Transpose contents of buffer~ as a process

Mark Durham's icon

Not sure if this is possible or not. I want to transpose the contents of a buffer~ ie change the length and alter the pitch, so if I have a note in the buffer~ which is 2000ms long and a C4 I want to change it to 1000ms long at C5, 4000ms at C4 etc. I'm thinking I might be able to do this in real-time by using two buffer~s, and playing the sample into the currently unused buffer before switching to it but this is rather clunky. Is there a way of doing this offline? ie faster than real-time?

If you're wondering why the convoluted route, it's because I'm loading them as impulse responses not using them for playback.

Thanks,

Mark

Christopher Dobrian's icon

To do that task in better-than-real time, you could write the operation in Java.file://localhost/Applications/Max%206.1/java-doc/api/com/cycling74/msp/MSPBuffer.html
All the work for programming rate-change, interpolation, etc. has already been done in the play~ and groove~ objects, though, so I'd advise trying to leverage that work rather than starting from scratch.

Mark Durham's icon

So presumably I can't achieve this using standard Max objects. Is this in any way a beginner project? I don't know Java, but am not averse to learning some. Any pointers appreciated.

Christopher Dobrian's icon

You could do something comparable using gen~. The same caveats apply about duplicating work that's already been done for realtime rate-change with play~ and groove~. Changing the increment rate to achieve the desired transposition, and interpolating between samples so as not to introduce unwanted distortion are both common computer music programming operations, but are not, imho, a "beginner project".

Mark Durham's icon

Fair enough, I'll continue with my convoluted solution unless anyone has already done this, and I'll try to put some effort in learning java later... it's on the to-do list but I never quite get there!

Peter McCulloch's icon

You could also do this faster than real time inside an upsampled poly~, if you want to do it in straight max.

I'd prefer java myself, but this should work. How much of a speed up do you need?

Mark Durham's icon

Well.. as fast as possible really. Ideally the user could just click to transpose the buffer~, but the samples are usually only 3 seconds max. So if I put my buffer and a playback object inside poly| and upsample the lot it will speed up the process by whatever the sample rate increase is, so if Max is at 48khz and i up it to 192 it will run 4x faster? I also take it I would need 2 buffer objects, one to play from and another to copy into?

Peter McCulloch's icon

Yup, that's pretty much it. Also, you can use the mute 1/mute 0 message with thispoly~ so you don't have to run it when you're not resampling.

If you do it in gen~ inside of poly~, you can also use fancier interpolation modes.

Mark Durham's icon

Thanks Peter, will give it a go.

Roman Thilenius's icon

if you want to switch as fast as possible and you are fine with per-key resolution for 2 or 3 octaves, why not use 30 buffers with 30 samples?

Mark Durham's icon

It's a good idea, but there are no samples to start with - the user copies them to the buffer from an existing sample of their choice. It's like an IR instrument where you can quickly design new IRs using existing samples - not for the purpose of reverb but more for general sound design. Will post it up when it's finished.

Mark Durham's icon
Max Patch
Copy patch and select New From Clipboard in Max.

So I've got the patch working outside of poly~. It's not my most elegant creation, but it works. I'm just unsure of how to put it inside a poly~, ie what needs to go in. I've used line~ and wave~, but don't understand how the timing will work when upsampled in poly - do I need divide my playback times?