libpd-sys 0.3.4

Rust bindings for libpd
from pylibpd import *
from struct import unpack
import array
import pygame
import numpy

BUFFERSIZE = 4096
SAMPLERATE = 44100
BLOCKSIZE = 64

pygame.mixer.init(frequency=SAMPLERATE)

m = PdManager(1, 2, SAMPLERATE, 1)
patch = libpd_open_patch('bloopy.pd', '.')
print("$0: ", patch)

# this is basically a dummy since we are not actually going to read from the mic
inbuf = array.array('h', range(BLOCKSIZE))

# the pygame channel that we will use to queue up buffers coming from pd
ch = pygame.mixer.Channel(0)
# python writeable sound buffers
sounds = [pygame.mixer.Sound(numpy.zeros((BUFFERSIZE, 2), numpy.int16)) for s in range(2)]
samples = [pygame.sndarray.samples(s) for s in sounds]

# we go into an infinite loop selecting alternate buffers and queueing them up
# to be played each time we run short of a buffer
selector = 0
clock = pygame.time.Clock()
while(1):
	# we have run out of things to play, so queue up another buffer of data from Pd
	if not ch.get_queue():
		# make sure we fill the whole buffer
		for x in range(BUFFERSIZE):
			# let's grab a new block from Pd each time we're out of BLOCKSIZE data
			if x % BLOCKSIZE == 0:
				barray = m.process(inbuf)
				outbuf = unpack('h'*(len(barray)//2),barray)
			# de-interlace the data coming from libpd
			samples[selector][x][0] = outbuf[(x % BLOCKSIZE) * 2]
			samples[selector][x][1] = outbuf[(x % BLOCKSIZE) * 2 + 1]
		# queue up the buffer we just filled to be played by pygame
		ch.queue(sounds[selector])
		# next time we'll do the other buffer
		selector = int(not selector)
	# cap the framerate
	clock.tick(40)

libpd_release()