On Sat, Jun 9, 2012 at 5:18 PM, Matt Barber brbrofsvl@gmail.com wrote:
Csound has a variable write delay opcode that would be worth looking at - the csound website has just been flagged by google for having malicious content so I can't link to the manual page, but the opcode is called "vdelayxw."
Unfortunately I can not understand the c code of vdelayxw. There's comments for the obvious things but not for the magic numbers and other tricks. But it may be a method for sinc-interpolated resampling.
James Fenn pointed to Julius O. Smith's pages on resampling and sinc-interpolation:
https://ccrma.stanford.edu/~jos/resample/
After reading the pages and experimenting with the proposed sinc tables, I noticed that proper sinc-interpolation would be fairly cpu-intensive. It is much less effective than [tabread4~], because 4 point sinc-interpolation would not even work for the simplest resampling job. Compare with a FIR filter, which should be up to a few dozen points per octave resampling.
In addition to that, an object like [ipoke~] or [tabwrite4~] implies a continuously variable resampling factor, which depends on the distances between consecutive float indexes received at the index inlet. Should the interpolation order grow according to distance? If so, what would be the limit?
On the other hand, think of [tabread4~]: it's interpolation scheme is fixed, no matter what resampling factor. With extreme resampling, aliases may be noticeable. But what the hell, it doesn't sound like the original music anyway, when sped up or down to extremes. That is the difference with an offline resampling job, when the original sound must be preserved insofar the new frequency range allows. In that sense, an interpolation scheme like in [tabread4~] could be used for realtime variable speed writing, leaving the consequences for the user. For example, if you make large jumps through the table, many old samples would simply not be rewritten.
But even with interpolation quality requirements so relaxed, it is not by itself clear how the samples should be written. Using sinc-interpolation, each input sample could be written as many samples of a (eventually phase-shifted) sinc function, with amplitude compensation for the overlap. The interpolation scheme of [tabread4~] however can not calculate four output samples based on one input sample, it could only calculate one output sample based on four input samples.
Imagine how one would do this with a fixed resampling factor. For example with resampling factor 0.75 (downsampling) you would write 64
samples, while incrementing the read index by 1 / 0.75 = 1.3333333. Another example, with resampling factor 1.5 (upsampling) you would write 64 * 1.5 = 96 samples into the array for each block of 64 input samples, while incrementing the read index with 1 / 1.5 = 0.6666666. The perform loop would not iterate over an integer n (= blocksize), but it would just break when the float read index exceeds n. To accommodate for interpolation, and for index increments larger than one, a few samples of fixed delay 'headroom' must be introduced.
In a [tabwrite4~], resampling factor would follow from index increments calculated from float index values received at the inlet. But what to do with large increments, exceeding the delay 'headroom' at the end of the input buffer? And another question: what to do with very small increments, leading to massive amounts of written samples and possibly to cpu overload? When starting on [tabwrite4~] a few months ago, I stumbled upon these problems. I then considered a version where you don't enter a float index at signal rate, but a resampling factor at message rate which can be checked for bad values, and set the delay 'headroom' as needed. But such a write object would need another method to optionally synchronize with a read object, and I have not worked that out either. Suggestions or comments are appreciated.
Katja