"Scrolling" Buffer~, or changing the recording behavior

peakssound's icon

Hi - I did a search and found an old thread that goes over this, but I wasn't able to reach a solution using it.

I am using a combination of Poke and Peek in gen to build a real-time granular effect inspired by Nobuyasu Sakonda's iconic SugarSynth. When the mouse is held down, the Poke's phasor is stopped and the effect is active, otherwise the dry audio input plays.

The issue is in the way audio is recorded to the buffer~. Poke's phasor is always wrapping from 0 to 1, and inherently creating a "break point", or interruption somewhere in the middle of the buffer that combines old and new data in a discontinuous way. When the effect is on, and Poke's phasor stops, Peek's phasor goes from 0 to 1, but will inevitably cross over this break point.

Is the issue in fact with the way it is recorded? Or perhaps it can be fixed with the way Peek's phasor is reading the data?

I'm sure some of the built-in modules could fix this problem for me, but please assume I am a masochist who wants to enjoy the pursuit of knowledge and building things from scratch.

Graham Wakefield's icon

Hi this is a common question, and really the problem is as you describe: when you are recording some sound into a buffer, there will always be a point where it jumps from the newest (most recently added) sample to the oldest. By analogy with a tape machine, this is where the "record head" is located. That point will likely cause a discontinuity if you read through it using a "play head". So, the trick is usually to find a way to play sound that makes the "play head" never cross over the "record head". If you can't ever truly avoid this by controlling where grains happen, e.g. for a looper, then one of the most common solutions is to use at least two play heads, and crossfade between them, so that you are never listening to any play head as it is passing the record head.

Another way is to never stop poking the buffer, but crossfade between the input source and a feedback delay loop when you enable/disable the effect. So, when the effect is engaged, you have crossfaded over to recording an infinite feedback loop, and when the effect is disengaged, you crossfade back to recording the new input again. This works better for the infinite looper kind of thing, and you can still treat this as raw material buffer for granulation.

BTW I recommend not using phasors to drive poke -- it's best to use a sample-counter here. That way you are more sure that you hit every sample index in the buffer in turn, with no floating point issues. E.g. you can use a [counter] and hook the last inlet to the first outlet of your [buffer], to set the loop size. Send a value of 1 to counter's first input to make it run, and a value of 0 to make it pause. The output will be a sample index that can go directly to [poke], and it tells you the location of the record head in samples.
You can also use sample indices for playback, e.g. for [peek @interp linear] or [sample @index samples].

peakssound's icon

Thanks much for the suggestions Graham. I'll investigate the methods you mentioned here.

Appreciate the recommendation for using sample-counter as well. I noticed when using phasors that it occasionally did not register things such as [==0] or more precise functions.