Read/Write buffer contents in same external?
I’ve been using an MSP based tape style looper patch for performance over the last couple of years, and it’s evolution has orignally gone from simple MSP objects, next to Gen~, and recently I’ve resorted to modifying some of the third-party externals I’m using (xsample, ipoke~) now that I’ve learned enough C to be slightly dangerous.
Since I’ve already recompiled some of this stuff with my own modifications, I’m wondering if it would be theoretically possible to combine the two processes in a single external, thus writing an input signal to a buffer~ (with interpolation) on the same cycle as reading from that same buffer~’s contents. Is this even feasible, or possibly undesirable for some reason? It seems like it would be easier to maintain offset correction this way, and perhaps write to a secondary buffer for undo capabilities.
I’d love to hear some thoughts, since I don’t really know what I’m doing yet (and less time wasted is more time playing).
It should be possible to write to and read from the buffer~ in the same signal loop, yes; just needs care that the writing & reading happens in the order you need. I wouldn’t recommend writing with interpolation for a tape looper though; better to do the interpolation at read time if possible. What problem needed an interpolating write?
It is possible to do this in gen~ too, though to obtain an explicit order of operation (e.g. write before read) it needs to use GenExpr code.
Thanks Graham :)
Interpolation was a solution for skipped frames when varispeeding > 1x., especially while overdubbing…possibly there was a better way to do things, but at the time I made that decision, [ipoke~] seemed like the most obvious solution. It also offers an internal overdub w/feedback setting which prevents the need for synchronizing offsets between [groove~] and [poke~]/[ipoke~]. I was still having problems with it smearing the entire buffer when traversing between loop end/begin points, so I added some code to deal with that. I also switched from [groove~] to [xgroove~] over the weekend, and timing seems much more precise for the patch now.
I can’t interpolate at read since there are multiple record passes being placed in the same buffer via overdub, and the buffer’s playrate isn’t necesarily moving at the same speed between each pass (which is keying the referencing index to the write process)…ipoke~ fills every frame based on (what was there * feedback ration) + what is input, filling in skipped frames. Am I perhaps missing something? Or is there a more direct approach I’m just missing that would make it immaterial? I’ve been around with this so many times at length it’s possible my eyes are a bit crossed ;)
I started doing all this in gen~ before for() loops were possible, and since [splat] doesn’t do interpolation when reading in reverse, I found other ways of dealing with it. I’d like to do something large like this in gen~ just to get a feel for it’s capabilities, but since this code-base already exists and is OS I figured it might be a good opportunity to learn some C. gen~ has been instrumental for me doing small things on a day to day basis, especially prototyping timing algorithms, but I tend to think it would take me a while to port this much code over to gen~ and have it perform right. Still, I haven’t ruled it out….it would be nice to have something that is completely cross-platform and freezable in a m4l patch, not to mention easily editable. The killjoy for me was not having for() loops (and thus being able to write a custom interpolation method that splat didn’t include), and I haven’t revisited this project since then.
I’d still recommend writing at 1x sample rate and interpolating on the read. The problem with interpolating write is that you are losing information, especially above 2x; the smearing you hear may be due to this.
I’m not sure what features you need, maybe it’s not possible, but ideally it should be. One way to do it is to use multiple buffers and ping-ponging. Overdub by mixing the current output with the current input, rather than += on the source buffer itself. I.e. when making a new take, choose a new buffer (or buffer region, or buffer channel) as destination, and write at sampling rate, mixing in the currently playing source buffer. The new loop can now play back at 1x, or shifted dynamically, but no input information was lost.
Need to run, but maybe later if I have time I’ll throw something together in gen~.
BTW peek/splat will introduce some additional overdub mixing modes in 6.1.