I'm working on a Looper project using python and jackclient-python library. Keep a tab open for the code.
If you know what is a loop pedal and how it functions, you'll probably get it. A simple looper, without overdubbing. So there's a button for toggling recorder. User makes connections with a patchbay, hits record, starts playing something, hits it again and the recording is done. So the audio is recorded between two hits. That audio should be looped now.
As you would know, jack applications work with a process
function. So here's mine:
def process(self, frames):
current_blocks = [port.get_array() for port in self.input_ports]
if self.looper.mode == LoopMode.PLAY:
for outport, take, block in zip(
self.output_ports,
self.looper.get_next_takes(),
current_blocks):
outport.get_buffer()[:] = take + block
elif self.looper.mode == LoopMode.RECORD:
self.temp_take.append(current_blocks)
for outport, block in zip(self.output_ports, current_blocks):
outport.get_buffer()[:] = block
Each audio block is a numpy array here. There's a temporary list to save every audio block until recording is done. Here's what happens while toggling:
def switch_modes(self):
if self.looper.mode == LoopMode.PLAY:
# Record mode is on.
self.temp_take = []
self.looper.mode = LoopMode.RECORD
elif self.looper.mode == LoopMode.RECORD:
# This means the record is over,
# and we are ready to put it to our take.
blocks1 = list(map(lambda b: b[0], self.temp_take))
blocks2 = list(map(lambda b: b[1], self.temp_take))
self.looper.record_takes(blocks1, blocks2)
self.looper.mode = LoopMode.PLAY
Simple, right? So here's a summary: After recording begins, incoming audio blocks are played and saved to the temporary list.
When recording is done, toggler function writes the temporary list to the looper take. process
plays the every recorded
audio block in an order, rolls back when recorded blocks are over. Which is supposed to result in a simple looper that
functions correctly... Right...
I've created a youtube video and edited it to explain what happens when I run the code above. Nothing plays when I finish recording, and when I play hi-hat sound I hear it like twice.
ANY feedback that might help is appreciated. Thanks!
...
It's solved. It turned out that
get_array
was not copying the values of the memory area that contains the audio block. So, before appendingcurrent_blocks
to the temp list, I copied it usingcopy.deepcopy
and it just worked.