little help with a home made delay
ok, so I'm making a delay object that uses wave~ so that I can manipulate the delayed sound in wierd ways by fiddling with the phasor signal. I am using poke~ to write to a buffer and then wave~ to play what is in the buffer shortly after it is recorded. This works well for an analog modeled delay type of thing; the pitch changes when delay time is changed and such.
What im having trouble with is that once I get to speeds over 1 hz I get a lot of undersampling distortion. I'm pretty sure that this happens because i have to multiply the phasor output by large numbers to get good enough values to record with poke~ and so some sample indexes are skipped. This is more apparent at higher rates because some of the sample values aren't rewritten and just stay there until the buffer is cleared.
If anyone could take a look or just tell me how to get smoother ramp values (at an adjustable rate, count and line are out of the question) I would greatly appreciate it.
running max 5 on windows xp
this is my patch. The issue is highlighted
just out of curiosity? why do you not use tapin~ tapout~?
jrp
i already said, I am modulating the phasor signal with wave~ to get different effects. I am also modelling an analog delay
dude, this patch is crazy!
i actually like the undersampling effect. but i have no idea what part of the sound you're trying to get and what part you're trying not to get...
a) what's wrong with record~?
b) have you looked at rampsmooth~?
c) have you tried rounding the output of the *~ 44100 to integers? it's spraying float sample values at the moment which probably aren't automatically rounded by poke~
d) it's not just at speed 1.0, it's related to the sample playback speed - i had your playback phasor at 0.23 hz (to get the sound at the right pitch, it was longer than 1 second...) and the undersampling was happening at 0.023 hz and above on the poke/delay phasor.
e) your -~ 0.5/pong~ is an interesting effect but is it actually what you want? i dunno quite how to fix it, try reducing it to 0.1 and see what happens...
f) where did you get *~ 2.2 from? couldn't tell why it should be scaled like that...
g) what gave you this idea of using poke~ in the first place?
i reckon there's always going to be undersampling using poke~ because it only writes one sample at a time and doesn't interpolate. if your sample index is going around at any speed faster than 1 buffersample per timesample, there are going to be samples in the buffer~ left unwritten, "unpoked"...
so to be honest i'd say that this undersampling is just the sound of poke~, like it or lump it or use record~ (i like it!)
i'd be interested to see how this develops...
nice fixing raja, but now it's just a rather clicky pitch shifter... i liked it better before. if that is all you want to do blackpeacock, record~ will be much less of a headache.
Quote: Zh wrote on Thu, 18 December 2008 17:22
----------------------------------------------------
> a) what's wrong with record~?
i cant syncronize it with my playback head
> b) have you looked at rampsmooth~?
no, but i used it and it helped a bit. thanks!
> c) have you tried rounding the output of the *~ 44100 to integers? it's spraying float sample values at the moment which probably aren't automatically rounded by poke~
this helped too, once again thanks.
> d) it's not just at speed 1.0, it's related to the sample playback speed - i had your playback phasor at 0.23 hz (to get the sound at the right pitch, it was longer than 1 second...) and the undersampling was happening at 0.023 hz and above on the poke/delay phasor.
yeah, i guess thats a good way to get aliasing. but when I have the same phasor controlling both playback and recording it doesn't make a lot of sense.
> e) your -~ 0.5/pong~ is an interesting effect but is it actually what you want? i dunno quite how to fix it, try reducing it to 0.1 and see what happens...
i did and it just kindof choruses, .5 keeps each head evenly spaced.
> f) where did you get *~ 2.2 from? couldn't tell why it should be scaled like that...
i was sampling at 44100 but then i switched to 96000. I guess that was an important detail...
> g) what gave you this idea of using poke~ in the first place?
once again, I want to be able to manipulate the recording/playback head, which requires that they are syncronized in some manner.
> i reckon there's always going to be undersampling using poke~ because it only writes one sample at a time and doesn't interpolate. if your sample index is going around at any speed faster than 1 buffersample per timesample, there are going to be samples in the buffer~ left unwritten, "unpoked"...
could you explain this a little more? This could easily be the source of my problem.
----------------------------------------------------
ok, check it out. I changed the buffer size to 500 (change 2.2 to 1.1) and now undersampling only happens over 2. I change it to 250 (.55) and undersampling only happens above 4. Wierd huh?
The audio signal flow is always going to be at 44.1 khz (or 96 kHz if
you changed it to that) in your patch regardless of the rate your
phasor is running at. poke~ will only write one data value into
buffer~ per sample of this samplerate - you can't make poke~ write
more quickly or slowly. When I was learning Max, and I figured that
out, I realized that it's better to drive poke~ with a count~, or
better still just use record~, for a buffer-based delay. In digital,
you can vary the playback rate, but the record rate should always be
locked to the sample-rate to avoid distortion. This doesn't mean you
can't get the analog delay effect you're after, but you need to
switch metaphors from the physical motors of the tape-delay box, to
the virtual space of the apparent tape-length.
Think of it this way - instead of the tape moving around the heads,
hold the tape steady and move the read & write heads along the tape.
Constrain the record head to only move at a fixed rate. Now the delay
length is the space between the read & write heads. You can adjust
the delay length by adjusting the rate of the play head *relative to*
the record head. But if they should ever meet or cross each other, or
you'll get a discontinuity in the sound. Try driving your poke~ with
a count~ (with a maximum set to the buffer~ size), and driving your
wave~ with
It's part of the nature of digital audio that a certain length of
memory always has the same number of sample points in it, which is
the big difference with analog tape. If you slow down the analog
tape, there is no loss of resolution (since it is continuous, not
discrete), but effectively the length of memory is expanded (relative
to our thresholds of perception). As you change between one speed and
another, there is a shift in apparent playback 'pitch' because of the
'stretching' of the tape-memory-space, akin to Doppler shift in a
way, but once you stop changing, the rate returns to normal. So, the
pitch-change (which is the phasor driving the wave~ in your patch)
should be relative not to the tape velocity, but to the change of
tape velocity, the tape acceleration.
Something like this:

And you can go further - adding different distortions to the relative
playback offset, placing things in the feedback path etc. But more -
since the tape velocity (which in digital is fixed to the sample
rate) determines the loop length (different to the delay length!) -
we can change the loop length by moving the loop start/end points
(i.e. make them different to the first & last sample of the buffer).
To do this, you must scale and offset (multiply and add) the signal
driving the wave~, and the min/max values for record~ (or count-poke
combo). What's magic about digital compared to analog, is that you
can change the size of the loop at any time, without having to get
scissors and glue out.
Since, to avoid clicking, you need to make sure that the playback
index and the record index never cross each other - this puts a
maximum on the amount by which the heads can move (just as the length
of the buffer~ determines the lowest rate of playback).
I hope this helps somehow.
BTW this is more-or-less what tapin/tapout are doing (tapout can take
a signal rate delay length), but yes, you can't access the internal
ringbuffer.
> once again, I want to be able to manipulate the recording/playback
> head, which requires that they are syncronized in some manner.
>
>> i reckon there's always going to be undersampling using poke~
>> because it only writes one sample at a time and doesn't
>> interpolate. if your sample index is going around at any speed
>> faster than 1 buffersample per timesample, there are going to be
>> samples in the buffer~ left unwritten, "unpoked"...
>
> could you explain this a little more? This could easily be the
> source of my problem.
> ----------------------------------------------------
>
>
> --
> www.myspace.com/theblackpeacock NOISE BIATCH!
Be seeing you
grrr waaa
www.grahamwakefield.net
dang, that explanation was really helpfull. Unfortunately, my patch kind of depends on the fact that my play and record heads will at some point have to cross eachother, as the playhead sometimes skips or goes back & forth. I guess i've just got to live with clicks and imperfections, but I've decided to use different phasors for record and playback, just going at the same speed. You guys can check it out if youd like, i think i fixed my bug last night.
thanks guys, huge help once again.
> poke~ will only write one data value into buffer~ per sample of
> this samplerate - you can't make poke~ write more quickly or slowly.
ipoke~ is great for this sort of thing:
http://pierrealexandretremblay.com/no-tv//MaxMSP/
Theres a delay example in the helpfile that does fantastic things when
you drive read and write independently.
also note that with tapin~ and tapout~ you can modulate the read
position at signal rate too, and you will never have the read/
writehead crossing. You can also use one tapin and 2 tapouts and
crossfade between the tapouts.
g, g.
Quote: jayrope wrote on Thu, 18 December 2008 15:33
----------------------------------------------------
> just out of curiosity? why do you not use tapin~ tapout~?
>
> jrp
he could play it slower, faster, or backwards with tapout, but as soon as you want to read files from disk or convert the tapping buffers content to video the use of a regular buffer object such as wave seems to make more sense.
the only thing is that i wouldnt call it a delay anymore, maybe "stream sampler" is more appropiate.:)
distortion? hm well, upsampling and dithering seems to complicated, that will only get you sidetracked from the creative part.
just to tap into that interesting discussion and in particular to Grahams comment.
I do understand that the "record" rate is fixed and therefore shouldn't be driven with a variable phasor etc. My playback though is driven by a phasor (using wave).
Does that mean that whatever phasor rate the wave is playing at, *every* sample will be processed and therefore will be delivered to the poke~ which is supposed to write it back to a second buffer ?
cheers, nick