little help with a home made delay

Dec 18, 2008 at 9:40pm

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

– Pasted Max Patch, click to expand. –
#41405
Dec 18, 2008 at 10:33pm

just out of curiosity? why do you not use tapin~ tapout~?

jrp

#147403
Dec 18, 2008 at 10:55pm

i already said, I am modulating the phasor signal with wave~ to get different effects. I am also modelling an analog delay

#147404
Dec 19, 2008 at 12:22am

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…

#147405
Dec 19, 2008 at 1:25am

Hi, I took out the “-~ 0.5″ and “pong~ 1 0 1″ and replaced them with a simple delay~ object which is great for that sort of thing(by using pong~ you were effectively dividing phasor~ into 2 sub-cycles causing pong~ to output at twice the rate of the phasor~). If you want the exact offset you had(phase offset by 0.5), then simply set the argument for delay~ to 22050.(at a sampling rate of 44.1kHz). In addition, poke~ does write by sample-index so you will get truncation, however this was not the reason for your “undersampling” sound when moving the speed above 1. What you needed to do was make sure the speed also changes the multiplication by 44100. so that 44100. is scaled appropriately. Anyways, see this mod of your patch for further details. Not sure if it solves all your problems(due to the possibility of truncation in sending floating-point sample-indexes to poke~, you may get a bit of degradation in audio quality). Hopefully it helps with some of it:

– Pasted Max Patch, click to expand. –
#147406
Dec 19, 2008 at 1:57am

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.

#147407
Dec 19, 2008 at 2:58am

sorry, just noticed some errors in my speed-of-record/speed-of-playback calculation. Here it is again with a windowing function for some of the clicks, but there is still a slight-click when changing above a delay speed of 1 which should be easier to figure out. But ya, there’s just that little complicatedness of poke~ which might make record~ an easier/better option. Still, record~ can never become sample-accurate so if you really want to model an analog-delay, you may want to write your own external because you’ll always be limited by the vector size as well in these cases or look into putting this in a poly~ with a different vector-size. anyways, here’s further mods on it:

– Pasted Max Patch, click to expand. –
#147408
Dec 19, 2008 at 4:08am

ok, sorry again, this time for obsessing so much over the patch when i obviously don’t have an ultimate solution, but here it is again with more amp-windowing on the recording-stage which takes care of further clicks. In addition, I set it up to clear the buffer~ whenever you change the speed which seems to clear up further clicks. Maybe it’s a good starting point. Or else, maybe I’ve gone completely mad and on a different tangent which has nothing to do with what you wanted originally. In any case, it was fun:

– Pasted Max Patch, click to expand. –
#147409
Dec 19, 2008 at 4:09am

and now i will quit while i am still far far behind ;)

#147410
Dec 19, 2008 at 7:50am

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.
—————————————————-

#147411
Dec 19, 2008 at 8:03am

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?

#147412
Dec 19, 2008 at 6:25pm

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.
> —————————————————-
>
>
> –
> http://www.myspace.com/theblackpeacock NOISE BIATCH!

Be seeing you

grrr waaa
http://www.grahamwakefield.net

#147413
Dec 19, 2008 at 7:38pm

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.

– Pasted Max Patch, click to expand. –
#147414
Dec 20, 2008 at 10:08pm

> 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.

#147415
Dec 22, 2008 at 1:32pm

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.

#147416
Mar 13, 2009 at 12:49pm

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

#147417

You must be logged in to reply to this topic.