Hello,
In order to build a variable speed sound-on-sound looper I was looking for an object that can write at fractional speed, analogous to the interpolated reading of [tabread4~]. Indeed I found C code for [tabwrite4~] in ggee/experimental, but a quick test revealed that it doesn't work properly. In a flash of optimism, I planned to rewrite the code, but soon stumbled upon questions.
It seems to me that 4-point-interpolated writing would mean: write values to 4 indexes at a time, just like [tabread4~] reads from 4 indexes at a time. While writing 4 values, recently written values must be taken into account, not bluntly overwritten. So two existing values, x[n-2] and x[n-1], should be somehow integrated with new values, if the writing direction is positive. That should be a leaky integration. Imagine the write pointer doesn't move; the values should not build up then. But how much should it leak to get the right balance?
Does anyone have knowledge of this? It would be cool to have [tabwrite4~] in Pd-extended. I'm prepared to spend time on it, if someone can assure me that the concept is viable at all.
Katja
Le 2012-01-07 à 11:01:00, katja a écrit :
It seems to me that 4-point-interpolated writing would mean: write values to 4 indexes at a time, just like [tabread4~] reads from 4 indexes at a time.
I don't think that [tabread4~] can be reversed so easily. I think that the most appropriate antialiased [tabwrite4~] would not be a mirror image of what [tabread4~] is. It wouldn't necessarily write four values : making it write two values would be quite normal ; you'll want to tune its amount of «opaqueness» perhaps, and this will be a setting for which you will have no ideal default value ; and whatever it'll be, you probably won't like that it's not a mirror image of [tabread4~] or even of [tabread~].
This makes me think of [#remap_image] and [#store]. If I want to warp the coordinates of a picture in a nontrivial way, I can't loop over the source pixels and write them in the destination image, because this creates lots of holes. It doesn't tell what to fill the holes with. What [#remap_image] does (using the [#store] external) is to loop over destination pixels and choose where their data come from. This means that the warping function has to be inversed.
nontrivial examples : http://gridflow.ca/gallery/un_sur_z%C3%A8de.jpg http://gridflow.ca/gallery/patch_dans_patch_5.png http://gridflow.ca/gallery/patch_dans_patch_9.png
help : http://gridflow.ca/help/%23remap_image-help.html
But when the source data is a continuous flow, you can't index it as if it were a picture of pixels, because the flow of sound is unlimited and realtime.
IMHO, it's a hard problem. It looks like the kind of thing for which many situation-specific solutions are designed because there is no general way to make something that generally makes sense.
While writing 4 values, recently written values must be taken into account, not bluntly overwritten. So two existing values, x[n-2] and x[n-1], should be somehow integrated with new values, if the writing direction is positive.
Just think about constant speeds for now : if the index is a phasor moving at the same speed as [tabsend~] would, then it better act very similar to [tabsend~]. This is the first thing you ought to verify for any possible solution. Then you should look at what happens when using any other different constant speeds. Then if you are satisfied with what happens with all constant speeds, chances are that you will be satisfied with variable speeds.
| Mathieu BOUCHARD ----- téléphone : +1.514.383.3801 ----- Montréal, QC
On Sat, Jan 7, 2012 at 2:23 PM, Mathieu Bouchard matju@artengine.ca wrote:
I don't think that [tabread4~] can be reversed so easily. I think that the most appropriate antialiased [tabwrite4~] would not be a mirror image of what [tabread4~] is.
Admittedly I did not have a clear idea of how writing at fractional speed could be conceived. Your detailed answer helped me to concentrate on the issues. Thanks, Mathieu.
A [tabwrite4~] is not comparable to [tabread4~] indeed, because writing is much more obliging than reading. Like you can read and skip chapters in a book, but you can't publish a book with chapters or pages missing, or print the pages over each other.
So the issue of fractional-speed-writing should really be solved as fractional resampling. I've been experimenting with chirp z-transform some years ago, and was surprised by the perfect interpolation which it can do. A block of audio can be blown up alias-free to any length, like with zero-padding but without the power-of-two ratio restriction. Downsampling likewise. Maybe I should write it into a Pd class. Certainly it won't be an easy job though.
Katja
It wouldn't necessarily write four values : making it write two values would be quite normal ; you'll want to tune its amount of «opaqueness» perhaps, and this will be a setting for which you will have no ideal default value ; and whatever it'll be, you probably won't like that it's not a mirror image of [tabread4~] or even of [tabread~].
This makes me think of [#remap_image] and [#store]. If I want to warp the coordinates of a picture in a nontrivial way, I can't loop over the source pixels and write them in the destination image, because this creates lots of holes. It doesn't tell what to fill the holes with. What [#remap_image] does (using the [#store] external) is to loop over destination pixels and choose where their data come from. This means that the warping function has to be inversed.
nontrivial examples : http://gridflow.ca/gallery/un_sur_z%C3%A8de.jpg http://gridflow.ca/gallery/patch_dans_patch_5.png http://gridflow.ca/gallery/patch_dans_patch_9.png
help : http://gridflow.ca/help/%23remap_image-help.html
But when the source data is a continuous flow, you can't index it as if it were a picture of pixels, because the flow of sound is unlimited and realtime.
IMHO, it's a hard problem. It looks like the kind of thing for which many situation-specific solutions are designed because there is no general way to make something that generally makes sense.
While writing 4 values, recently written values must be taken into account, not bluntly overwritten. So two existing values, x[n-2] and x[n-1], should be somehow integrated with new values, if the writing direction is positive.
Just think about constant speeds for now : if the index is a phasor moving at the same speed as [tabsend~] would, then it better act very similar to [tabsend~]. This is the first thing you ought to verify for any possible solution. Then you should look at what happens when using any other different constant speeds. Then if you are satisfied with what happens with all constant speeds, chances are that you will be satisfied with variable speeds.
______________________________________________________________________ | Mathieu BOUCHARD ----- téléphone : +1.514.383.3801 ----- Montréal, QC
Hi all --
Peter Brinkmann and Michael Goggins did some related work recently:
http://nettoyeur.noisepages.com/2010/10/doppler-effects-without-equations/
but back in the dark ages Barry Vercoe made a Music 11 ugen called 'pipadv' that added a signal into a delay line assuming the write location was continuous and could be stably differentiated (so that for each point of the delay line you could associate a fractional pposition in the incoming signal. He then interpolated to get fractional-indexed values of the incoming signal to correspond with successive sample locations in the delay line, turning the problem around backward.)
I've thought about this for a few hours but so far my only conclusion is that it's very interesting :)
Miller
On Sat, Jan 07, 2012 at 05:48:04PM +0100, katja wrote:
On Sat, Jan 7, 2012 at 2:23 PM, Mathieu Bouchard matju@artengine.ca wrote:
I don't think that [tabread4~] can be reversed so easily. I think that the most appropriate antialiased [tabwrite4~] would not be a mirror image of what [tabread4~] is.
Admittedly I did not have a clear idea of how writing at fractional speed could be conceived. Your detailed answer helped me to concentrate on the issues. Thanks, Mathieu.
A [tabwrite4~] is not comparable to [tabread4~] indeed, because writing is much more obliging than reading. Like you can read and skip chapters in a book, but you can't publish a book with chapters or pages missing, or print the pages over each other.
So the issue of fractional-speed-writing should really be solved as fractional resampling. I've been experimenting with chirp z-transform some years ago, and was surprised by the perfect interpolation which it can do. A block of audio can be blown up alias-free to any length, like with zero-padding but without the power-of-two ratio restriction. Downsampling likewise. Maybe I should write it into a Pd class. Certainly it won't be an easy job though.
Katja
It wouldn't necessarily write four values : making it write two values would be quite normal ; you'll want to tune its amount of «opaqueness» perhaps, and this will be a setting for which you will have no ideal default value ; and whatever it'll be, you probably won't like that it's not a mirror image of [tabread4~] or even of [tabread~].
This makes me think of [#remap_image] and [#store]. If I want to warp the coordinates of a picture in a nontrivial way, I can't loop over the source pixels and write them in the destination image, because this creates lots of holes. It doesn't tell what to fill the holes with. What [#remap_image] does (using the [#store] external) is to loop over destination pixels and choose where their data come from. This means that the warping function has to be inversed.
nontrivial examples : http://gridflow.ca/gallery/un_sur_z%C3%A8de.jpg http://gridflow.ca/gallery/patch_dans_patch_5.png http://gridflow.ca/gallery/patch_dans_patch_9.png
help : http://gridflow.ca/help/%23remap_image-help.html
But when the source data is a continuous flow, you can't index it as if it were a picture of pixels, because the flow of sound is unlimited and realtime.
IMHO, it's a hard problem. It looks like the kind of thing for which many situation-specific solutions are designed because there is no general way to make something that generally makes sense.
While writing 4 values, recently written values must be taken into account, not bluntly overwritten. So two existing values, x[n-2] and x[n-1], should be somehow integrated with new values, if the writing direction is positive.
Just think about constant speeds for now : if the index is a phasor moving at the same speed as [tabsend~] would, then it better act very similar to [tabsend~]. This is the first thing you ought to verify for any possible solution. Then you should look at what happens when using any other different constant speeds. Then if you are satisfied with what happens with all constant speeds, chances are that you will be satisfied with variable speeds.
 ______________________________________________________________________ | Mathieu BOUCHARD ----- téléphone : +1.514.383.3801 ----- Montréal, QC
Pd-list@iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
On 1/8/12, Miller Puckette msp@ucsd.edu wrote:
Hi all --
Peter Brinkmann and Michael Goggins did some related work recently:
http://nettoyeur.noisepages.com/2010/10/doppler-effects-without-equations/
but back in the dark ages Barry Vercoe made a Music 11 ugen called 'pipadv' that added a signal into a delay line assuming the write location was continuous and could be stably differentiated (so that for each point of the delay line you could associate a fractional pposition in the incoming signal. He then interpolated to get fractional-indexed values of the incoming signal to correspond with successive sample locations in the delay line, turning the problem around backward.)
I've thought about this for a few hours but so far my only conclusion is that it's very interesting :)
Miller
The problems that I see are with orthogonality and reconstruction. A sample really just represents a sync that's centered on a point in time (in the easy case). Integer numbers of samples are orthogonal... but the fractionally-centered sample is not orthogonal to samples at all the integer indexes.
Then, the reconstruction problem follows from it. When you want to read a value from a table, does it exactly retrieve the value that was recorded there? It seems like the interpolator needs to be modified continuously with the spacing of adjacent samples.
All I know right now is, I can't spend my whole vacation on a math problem, even if it's good :)
Chuck
On Sun, Jan 8, 2012 at 9:01 PM, Miller Puckette msp@ucsd.edu wrote:
Hi all --
Peter Brinkmann and Michael Goggins did some related work recently:
http://nettoyeur.noisepages.com/2010/10/doppler-effects-without-equations/
but back in the dark ages Barry Vercoe made a Music 11 ugen called 'pipadv' that added a signal into a delay line assuming the write location was continuous and could be stably differentiated (so that for each point of the delay line you could associate a fractional pposition in the incoming signal. He then interpolated to get fractional-indexed values of the incoming signal to correspond with successive sample locations in the delay line, turning the problem around backward.)
Yes, PIPADV seems to be the process I'm looking for, so let me say [pipadv~] instead of [tabwrite4~]. Barry Vercoe describes a 'community of pipelines', forming a delay network for room acoustics simulation, to which PIPADV can add a signal 'whose distance is time-varying'.
http://web.media.mit.edu/~bv/papers/compsys%20&%20langs.pdf
But the article has no technical details, and Peter Brinkmann and Michael Goggins solve another problem, related to this topic of doppler shifts caused by moving positions of listeners and/or or sources.
If it is true that PIPADV could write to fractional indexes on a PDP-11 (though not quite in realtime yet), then it must be possible to make such a thing for Pd. Here's another brainstorm:
Writing at double speed would be done after upsampling/filtering. Writing at half speed would be done after filtering/downsampling.
Writing at speeds ratio's not some power of two could be done via chirp z-transform: resample the spectrum in forward chirp z-transform, and go back to time domain with regular IFFT. Illustrated here:
http://www.katjaas.nl/chirpZsampling/chirpZsampling.html
However this would still require an integer number of output samples every time, if the output blocks are to be neatly stitched together. The speed ratio would be forced to blocksize/n or n/blocksize, and the larger blocksize, the more options.
If this is not flexible enough for the purpose, it must be done different still. I am now thinking how it could be done as 'fractional-phase convolution'. A non-linear convolution where the filter kernel changes for every input sample. The change in the kernel is a phase rotation, such that the filter kernel's identity point coincides with the fractional index where the output sample should be located. This dynamic filter kernel would regulate the resampling amplitude filtering, plus a fractional delay needed to get the signal energy at the right position. Seen over time, the filter kernel would kind of undulate, like a snake moving forward.
To recalculate a filter kernel for every input sample is a CPU intensive matter, specially for substantial upsampling factors where the filter kernel must be long. So this is not a very practical concept yet. But there may be ways to make this idea more efficient. If it makes sense at all.
Katja
On 9 January 2012 12:05, katja katjavetter@gmail.com wrote:
On Sun, Jan 8, 2012 at 9:01 PM, Miller Puckette msp@ucsd.edu wrote:
Hi all --
Peter Brinkmann and Michael Goggins did some related work recently:
http://nettoyeur.noisepages.com/2010/10/doppler-effects-without-equations/
but back in the dark ages Barry Vercoe made a Music 11 ugen called 'pipadv' that added a signal into a delay line assuming the write location was continuous and could be stably differentiated (so that for each point of the delay line you could associate a fractional pposition in the incoming signal. He then interpolated to get fractional-indexed values of the incoming signal to correspond with successive sample locations in the delay line, turning the problem around backward.)
Yes, PIPADV seems to be the process I'm looking for, so let me say [pipadv~] instead of [tabwrite4~]. Barry Vercoe describes a 'community of pipelines', forming a delay network for room acoustics simulation, to which PIPADV can add a signal 'whose distance is time-varying'.
http://web.media.mit.edu/~bv/papers/compsys%20&%20langs.pdf
But the article has no technical details, and Peter Brinkmann and Michael Goggins solve another problem, related to this topic of doppler shifts caused by moving positions of listeners and/or or sources.
If it is true that PIPADV could write to fractional indexes on a PDP-11 (though not quite in realtime yet), then it must be possible to make such a thing for Pd. Here's another brainstorm:
Writing at double speed would be done after upsampling/filtering. Writing at half speed would be done after filtering/downsampling.
Writing at speeds ratio's not some power of two could be done via chirp z-transform: resample the spectrum in forward chirp z-transform, and go back to time domain with regular IFFT. Illustrated here:
http://www.katjaas.nl/chirpZsampling/chirpZsampling.html
However this would still require an integer number of output samples every time, if the output blocks are to be neatly stitched together. The speed ratio would be forced to blocksize/n or n/blocksize, and the larger blocksize, the more options.
If this is not flexible enough for the purpose, it must be done different still. I am now thinking how it could be done as 'fractional-phase convolution'. A non-linear convolution where the filter kernel changes for every input sample. The change in the kernel is a phase rotation, such that the filter kernel's identity point coincides with the fractional index where the output sample should be located. This dynamic filter kernel would regulate the resampling amplitude filtering, plus a fractional delay needed to get the signal energy at the right position. Seen over time, the filter kernel would kind of undulate, like a snake moving forward.
To recalculate a filter kernel for every input sample is a CPU intensive matter, specially for substantial upsampling factors where the filter kernel must be long. So this is not a very practical concept yet. But there may be ways to make this idea more efficient. If it makes sense at all.
Hi Katja,
Have you looked at: https://ccrma.stanford.edu/~jos/resample/ ? The algorithm he describes sounds like what you are talking about, if I understand correctly. He uses a massively oversampled filter kernel and linearly interpolates into it at different scales to get the filter coefficients.
James
On Tue, Jan 10, 2012 at 6:18 PM, James Fenn geekery@jamesfenn.com wrote:
Have you looked at: https://ccrma.stanford.edu/~jos/resample/ ? The algorithm he describes sounds like what you are talking about, if I understand correctly. He uses a massively oversampled filter kernel and linearly interpolates into it at different scales to get the filter coefficients.
Thanks so much for pointing to this article, James.
Earlier today I was thinking about a 512 pt or so sinc table, analogous to Pd's cosine table. The article speaks of ~13K pt tables... Anyway, a fractional resampling method is described which is used in several open source softwares. This is more detailed info and example code than I dared to hope for.
Hopefully this can be translated to a Pd class [tabwritev~]. The object shall write input samples into an array or table at fractional speed, and it shall be able to do so in circular buffer mode. Not the simplest of Pd classes, but it's at least worth a try.
Katja