[PD] [PD-dev] Rewriting a unified phasor / metro object for reading tables
reduzent at gmail.com
Fri Mar 7 12:54:38 CET 2014
On Thu, 2014-03-06 at 19:22 -0500, Brian Fay wrote:
> On Tue, Mar 4, 2014 at 8:53 PM, Chris McCormick <chris at mccormick.cx>
> Not sure if this is relevant or already common knowledge but
> versions of Pd allow you to specify metro and delay tempo &
> including in samples. e.g. [metro 500 1 samp].
> Does anybody know if sample-accurate [metros] are available in libpd?
Assuming, that libpd uses the same code for [metro], I'd say yes.
> I'm making an application that allows for fairly arbitrary divisions
> of a tempo. Originally I was going to make clocks out of metros, but I
> wasn't aware that you could set a [metro] faster than one bang per ms.
[metro] used to have an artificial lower limit of 1ms. I assume this was
implemented in order to save Pd from freezing if a [metro] accidentally
received a '0' as interval. It seems that is not the case anymore in
0.45. The current behavior is that it allows any non-zero input, but
falls back to one unit as defined in the 'tempo' method when set to 0.
> If I wanted a bunch of different rhythms, not just eigths and
> sixteenths, but triplets and divisions of fives or sevens or whatever,
> I would need to make a bunch of [metro] objects (or maybe one running
> at the least common multiple of the various divisions).
> In the end, I settled on handling this logic in the Java side of my
> application by counting samples and doing some math.
This is still only sample precise, while you could make it sub-sample
precise in Pd.
This isn't addressed to you specifically, but it is a common
misconception to think of the audio domain as being precise and the
message domain as being rounded to vectors. This might apply to many
softwares, especially those that have two configured rates, one audio
sampling rate and one fixed control rate. However, there is no such
thing as a control rate in Pd. It is true, though, that many classes
with message inlets and signal outlets only evaluate the incoming
message only at block boundaries ([tabplay~], [line~] and more).
However, [vline~] is the __one__ class that connects the two worlds
(message and signal) without losing precision. But I'm getting off-topic
now, as your topic is about precision in the message domain only.
Anyway, the precision of [metro], [delay], [timer] and co is only
limited by the float type used in Pd.
> I can schedule bangs at arbitrary divisions of a base amount of time
> (so I can make seven-tuplets or fiftythree-uplets or whatever strange
> rhythm I want to). In theory my solution should be sample-accurate,
> and it sounds like it's working fine.
> But is there a straightforward way to do this in pd that I completely
It depends on what you consider straight-forward. It is certainly
possible to have many [metro]s with arbitrary divisions running in sync.
I still think the whole topic is very complex. I implemented something
like that in some of the netpd instruments. However, I figured the tick
rate of the master metro would be way too high, if I'd make it dividable
by all the possible divisions I can think of. I went for a different
strategy. The master metro ticks at 16th of the given BPM. I made an
[metro] replacement abstraction that takes divisor and dividend as
arguments. [polymetro 7 5] plays 7 ticks within the period of 5 ticks of
the master metro. [polymetro] is designed so that it runs on its own and
plays 7 ticks and then waits for every 5th master tick to start again.
The difficult part was to allow tempo changes without losing sync. Pd's
[metro] applies the new tempo only at the next tick. In order to be able
to run many [polymetro]s concurrently without them losing sync on tempo
changes, I had to create a [metro] replacement that allows for
in-interval tempo changes. By using that [metro] replacement in the
master metro and the [polymetro]s, it is possible to change tempo at any
time without losing sync. One issue, that I haven't solved yet is a
clean start at an arbitrary tick. [polymetro] doesn't immediately start
when master metro is started at a non-zero tick, but it waits for the
next sync tick of the master (any 5th master metro tick in the case of
[polymetro 7 5]).
More information about the Pd-list