Drum Machines: Timing and Polyphony

chthonic's icon

I have tried the following failed attempts at creating a drum machine with accurate timing (something that I have only ever experienced while using MIDI objects and when looping samples using wave~) and that is polyphonic.

I started by using a the phasor~ object and scaling it so that it would go from 0 to 16 (representing 16th notes) in a specified amount of time. I then subtracted a number from it's current value at the time so that it would ramp between 0 1. This is so I could place the samples in an arrangement (the wave~ that has a signal with 8. subtracted from it driving it plays in the middle of the bar, for example). This only allows me to play samples of all the same length and only play each sample one at a time, although the timing is perfect.

The only other way I can think of doing this is to make poly~s filled with multiple instances of a groove~ (or play~, which I would assume is just as bad) that are sent 0 messages to cause groove~ to begin from the beginning of the sample. But one will see that if you do this and drive it using a metro object or a phasor~ object that uses a comparison operator and then edge~ to send out bangs, both will have hiccups in a short period of time, and very often after that. Yes I have both "scheduler in overdrive" and "In Audio Interrupt" checked.

Is it possible to get accurate timing using bangs that cause objects to play samples? I am just very concerned because I think for almost all music that is played by humans, timing is one of the most important factors in making something musical, not to mention playable. Only in the very abstract scores that one must themselves interpret is timing of little importance. You would think that a mechanical machine could repetitively accomplish a task with an unfaltering period (Hundreds of companies make drum machines that are polyphonic and never skip a beat and the processors contained inside are hundreds of times slower than those in virtually all personal computers!).

This is a very long winded post, but in a way it is also a complaint. I think achieving accurate timing should be one of the easiest things to do with MaxMSP, but instead in the 2 years that I have used it I have only by using very complicated means attained it.

Any help would be appreciated.

Thank You.

Mehmet Can Ozer's icon

Hello,

As a a very simple suggestion for accurate timing is using play~ object. You can check the help and reference manual for using in depth.

Best,

Mehmet

Exit Only's icon

Here is a patch that uses scheduler rate timing to trigger two different sounds. If you wanted more sounds, simply create more instances of the sample playback patch. If you got creative, you could package something like this into a poly~ that would allow many instances of a sampler

I recorded a 16th note 120bpm hihat line from this and placed it in logic to analyze the timing, which was fine. Attached is a screenshot of the output as viewed in Logic with a 16th note grid.

Max Patch
Copy patch and select New From Clipboard in Max.

At first I was going to suggest searching the archives, but I tried and honestly it isn't very easy to find the best threads on timing issues and how to work around them.

You may or may not be aware but to get accurate timing in max you need to set the scheduler to overdrive and turn on audio interrupt. At this point your timing depends on the signal vector size. I have my signal vector size set to 64 and have no problems with timing in Max.

chthonic's icon

Thanks a lot. Changing the vector size helped and your use of the play~ object has inspired me to use it more often. It's too bad that groove~ has poor timing issues (it still hiccuped even with the changed vector size).

Exit Only's icon

I find that curve~ -> play~ or curve~ -> wave~ to be the most flexible ways of playing back "one shot" type samples.

groove~ seems more oriented towards playing back loops though I think 2d.wave with a couple of phasors attached is much more useful for that kind of thing

Grizzle's icon

I've been messing with Eric Lyons el.samm and el.player. There are problems like I have to turn off the dac before I can replace a sound (or crash) and there doesn't seem to be a way to trim the sample lenght but... it has sample accurate timing.

The timing is machine tight and it's the tightest I think I'ved ever heard coming from my pc. Even at ridiculous tempos well over 1000bpm. it is still locked completely solid and no glitches no matter what my computer is at.

cebec's icon

Ok, correct me if I'm wrong but if you run the above patch from Nick with Scheduler in Overdrive, in Audio Interrupt and with a Signal Vector Size of 1, doesn't that ensure 'sample accurate' timing?

chthonic's icon

the signal will probably break up if you set the signal vector to 1 unless you have an extremely fast computer. But a signal vector of 64 is good enough for virtually all applications, it seems.

ComfortableInClouds's icon

why curve~ to play? why not phasor/line?

Exit Only's icon

well, I meant that as a general personal preference for "play once" style sampling like drum hits etc. Of course whatever application one needs will involve a different set of objects!

ComfortableInClouds's icon

Curve~ is actually a really cool idea. just messing around with it and can get some interesting variations on ordinarily bland hits. thanks for that!

and to answer my own question: because phasor/line are boring! :-D

Stefan Tiedje's icon

matt schrieb:
> Ok, correct me if I'm wrong but if you run the above patch from Nick
> with Scheduler in Overdrive, in Audio Interrupt and with a Signal
> Vector Size of 1, doesn't that ensure 'sample accurate' timing?

Yes, but its not worth the cost. A signal vector of 1 sample is eating
CPU like a dinosaur is eating trees.
For me I never met a musician who was better than 1 ms (about a
scheduler tick) with drumming. If you want it sample accurate, you are
talking about sound, not rhythm or timing. If you want all polyphonic
hits to sound exactly the same (robotic) you can construct it still with
poly~ and the way Nick was showing it in his first reply, just put each
voice into a poly~, let the phasor~ run into all the voices, and only
control the volume with scheduler events...

Stefan

--
Stefan Tiedje------------x-------
--_____-----------|--------------
--(_|_ ----|-----|-----()-------
-- _|_)----|-----()--------------
----------()--------www.ccmix.com

Eric Lyon's icon

Quote: Grizzle wrote on Wed, 24 September 2008 18:57
----------------------------------------------------
> I've been messing with Eric Lyons el.samm and el.player. There
> are problems like I have to turn off the dac before I can
> replace a sound (or crash) and there doesn't seem to be a way
> to trim the sample lenght but... it has sample accurate timing.
>

I should mention that player~ was only written as s "proof of concept" object for samm~ and was never intended to compete with the many features of groove~. I can look into the crashes if you could post a simple patch that reliably produces them. However, it is inadvisable to switch buffers on the fly for player~ objects, as this instantly aborts any active notes in player~'s internal polyphony, which is likely to produce clicks even if crashes are averted. You can almost surely design a better solution if you need to swap in different sample sets, e.g. with poly~. You can also use groove~ with samm~, by converting clicks to bangs with edge~. The timing will not be be sample-accurate, but its indeterminacy will be limited to the signal vector size, and you will not experience the clock drift which I have observed with some Max control level timing. (I don't know if this is still an issue with the new transport system.)

Eric

cebec's icon

Compare the output of [curve~] to [line~]. It seems that [curve~]'s is not completely linear at a curve setting of 0.0 -- Martin Robinson's [mxj~ curve] takes care of this but I have asked Cycling if they could fix the native object. I haven't received any response so I'm not sure if it's a bug or a feature.

Grizzle's icon

Quote: Eric Lyon wrote on Thu, 25 September 2008 10:28
----------------------------------------------------
> Quote: Grizzle wrote on Wed, 24 September 2008 18:57
> ----------------------------------------------------
> > I've been messing with Eric Lyons el.samm and el.player. There
> > are problems like I have to turn off the dac before I can
> > replace a sound (or crash) and there doesn't seem to be a way
> > to trim the sample lenght but... it has sample accurate timing.
> >
>
>
> I should mention that player~ was only written as s "proof of concept" object for samm~ and was never intended to compete with the many features of groove~. I can look into the crashes if you could post a simple patch that reliably produces them. However, it is inadvisable to switch buffers on the fly for player~ objects, as this instantly aborts any active notes in player~'s internal polyphony, which is likely to produce clicks even if crashes are averted. You can almost surely design a better solution if you need to swap in different sample sets, e.g. with poly~. You can also use groove~ with samm~, by converting clicks to bangs with edge~. The timing will not be be sample-accurate, but its indeterminacy will be limited to the signal vector size, and you will not experience the clock drift which I have observed with some Max control level timing. (I don't know if this is still an issue with the new transport system.)
>
> Eric
----------------------------------------------------

Thanks for the response Eric. I wanted to check it out before I got back to you. The crashing was a fault on my end. One particular sample must be malformed and crashes the player~ object when loaded into it.

If I load the sample at the very start before the dac is on then it will play fine when I turn on the dac however if I load the sample while the dac is already on - crash. It only happens with that single sample and I happened to keep randomly failing on it when I was browsing through sample folders. Apologies for jumping the gun.

I'm sure I could use the groove~ or some other object but the simplicity and unbelievable tightness of player~ and samm~ is very very difficult to give up :)

thanks

Ken

david604's icon

Quote: Eric Lyon wrote on Thu, 25 September 2008 10:28
----------------------------------------------------
> Quote: Grizzle wrote on Wed, 24 September 2008 18:57
> ----------------------------------------------------
> > I've been messing with Eric Lyons el.samm and el.player. There
> > are problems like I have to turn off the dac before I can
> > replace a sound (or crash) and there doesn't seem to be a way
> > to trim the sample lenght but... it has sample accurate timing.
> >
>
>
> I should mention that player~ was only written as s "proof of concept" object for samm~ and was never intended to compete with the many features of groove~. I can look into the crashes if you could post a simple patch that reliably produces them. However, it is inadvisable to switch buffers on the fly for player~ objects, as this instantly aborts any active notes in player~'s internal polyphony, which is likely to produce clicks even if crashes are averted. You can almost surely design a better solution if you need to swap in different sample sets, e.g. with poly~. You can also use groove~ with samm~, by converting clicks to bangs with edge~. The timing will not be be sample-accurate, but its indeterminacy will be limited to the signal vector size, and you will not experience the clock drift which I have observed with some Max control level timing. (I don't know if this is still an issue with the new transport system.)
>
> Eric
----------------------------------------------------

Hi Eric,

Glad to find this post, I am trying to achieve the same thing as chthonic. My ideas was to populate a folder and fill up separate buffers with different names before turning on the DAC~, then just set the el.player~ to listen to the different buffer~ names while on performance to avoid crash.
My second idea was to use zigzag~, play~, poly~ etc...
Got the third idea from you using el.player~ and poly~.
While messing around with the possibilities here is a very simple patch that could easily reproduce the player~ crash:

Max Patch
Copy patch and select New From Clipboard in Max.

Cheers
David

david604's icon

meanwhile I tried to change only the buffer's name sending the [setbuf buffer-x] message to el.player~ but still crashes

Eric Lyon's icon

> here is a very simple patch that could easily reproduce the player~ crash:

Thanks, David.

That is a good example. I have a fix that seems to solve both this crash, and the crash when changing a buffer with "setbuf". The updated player~ will be included in the next release of LyonPotpourri.

Eric

david604's icon

Quote: Eric Lyon wrote on Sat, 11 October 2008 16:03
----------------------------------------------------
> > here is a very simple patch that could easily reproduce the player~ crash:
>
> Thanks, David.
>
> That is a good example. I have a fix that seems to solve both this crash, and the crash when changing a buffer with "setbuf". The updated player~ will be included in the next release of LyonPotpourri.
>
> Eric
>
----------------------------------------------------

This is really goods news. When are you planning to release the new version ? :)
It would be also wonderful if the player~ could handle better the stereo-mono issue, I mean if I give it a channel argument of 1 it will play both mono and stereo files(truncated), but if I set it to 2 and load a mono buffer then it stops playing at all. I would suggest it to duplicate the mono audio buffer to the second output or at least output it from the left outlet so a logic can be built around...

Eric Lyon's icon

> This is really goods news. When are you planning to release the new version ? :)

Sometime after c74 releases the Max 5 SDK.

>>
It would be also wonderful if the player~ could handle better the stereo-mono issue, I mean if I give it a channel argument of 1 it will play both mono and stereo files(truncated), but if I set it to 2 and load a mono buffer then it stops playing at all.
>>

That sounds about right. player~ was not designed to be especially accommodating to unusual requests, since I basically just needed it to demo samm~.

>>
I would suggest it to duplicate the mono audio buffer to the second output or at least output it from the left outlet so a logic can be built around...
>>

It's a nice idea to have a player~ that's smart enough to adjust to the number of channels in the current buffer. (groove~ can do that already.) I'm not sure your first suggestion scales well to channel numbers larger than 2. For example, what if you have a player~ with 4 output channels and your input buffer has 3 channels? Probably best to just output the 3 channels and zero out the last outlet.

If c74 chooses to significantly increase the channel capacity of buffer~ that would definitely increase my motivation to improve the multichannel design of my buffer-related objects :)

Eric