Code layout suggestion for a multi track sequencer and ensuring files play at the same time

Hello,

I am trying to decide how best to manage a couple of ideas in my code flow and could use some advice on how to create the sequencing for my multi track sequencer.

Should I have a ~gen for each track that has all of it’s own track data and I call ~gen track1, then ~gen track 2, etc? Or is it better to have a higher level setup that would consist of a main loop that contains: 1) global for all of the tracks, 2) get button / knob states, 3) process tracks, 4) set LEDs. And inside of the “process tracks” I would then sequence each track in that pass?

One last thought: How do I ensure that the sequencers start playing several samples at the same time? For example: if all sequencers were playing the same audio file they would all start at the same time? (if that is even possible).

overall I am asking these questions because I have the basics going for my single track sequencer and I would like to take the next steps to extend this to 2, then 4, then 8 tracks. Thus, arranging this in a reasonable way is somewhat of a mystery to me as I am not quite used to programming on a DSP.

Any thoughts, help, or suggestions would be greatly appreciated.

Thanks,
Brett

Hi

I’m not sure if this helps, but…

Yes, it generally makes sense to have each track be a sub-[gen] object subpatcher, but then to have some shared properties that come from outside these subpatchers. In particular I recommend having a shared timing source, probably based on a ramp signal, and feed that signal into all “tracks” subpatchers. (It doesn’t prevent you from doing polyrhythm or polymeter if you want to do that too – just add a [rate] object to each track re-time the ramp.) But having a shared timing source is the best way to ensure your events (e.g. staring a sample playback) are synchronized.

You can turn a ramp into a “step” by quantizing, e.g. if you have a ramp that goes from 0 to 1 over 1 bar, you can get 8 steps by multiplying the ramp by 8 and then using a [floor], so it will go 0, 1, 2, 3, 4, 5, 6, 7 and repeat. You can send that step function into a [change] to detect when the step changes. So e.g. to trigger a sample on step 3 you would check the [change] [and] step [== 3]. That will give a single-sample spike that you can use to reset a sample player’s counter, or a [latch] for a sample & hold, etc.

Similarly, the actual sample [data] objects should be outside the subpatcher, so that they only load once. The subpatcher’s code can still use them.

1 Like

@grrrwaaa,

Thank you, this is super helpful and I greatly appreciate that you took the time to write this up.

I do have one follow-on question:
How do I pass a data block it into a subpatcher?

Thank you again for taking the time to write this up.

Brett

Just use the same name.

Create [data foo] in the top patcher, use [peek foo], [dim foo], [poke foo], [sample foo] etc etc in the subpatcher.

@grrrwaaa,

Thank you, that makes it super simple, I tried using setparam and that wasn’t working. … turns out it is much simpler. :slight_smile:

Great to hear and thank you again for your time and help.
Brett