Playing a Buffer so that it ends on a beat?

Hey folks,
Is there a way to time the beginning of a Buffer played by PlayBuf in a Pbind so that the audio file ends on a given beat? For context, I’d like to play a number of different scraping sounds of varying lengths. I’m guessing this is probably pretty straightforward, but I can’t find any help for this in the help file.

one way to do it…


SynthDef(\player, {|buf| [Out.ar](http://Out.ar)(0, [PlayBuf.ar](http://PlayBuf.ar)(1, buf, doneAction:2)!2)}).add;

TempoClock.default.tempo= 0.8;

(
Pbind( //reference
\legato, 0.1,
\amp, 0.5,
).play;
Pbind( //buffer player
\instrument, \player,
\dur, Pseq([2, 2, 4], inf),
\buf, ~buffers[0],
\timingOffset, Pfunc({|ev|
var f= ev.buf.duration/TempoClock.default.beatDur;
f.ceil-f;
}),
).play;
)

the example expect ~buffers to be an array with mono soundfile(s).

with \timingOffset you can set a percentage how much the event should be delayed. 1.0 for a full beat. so we can calculate how much of a beat the buffer’s duration is, take the rest and use that as offset value. e.g. for a buffer that takes 30% of a beat’s duration in current tempo, 0.7 is how much we should offset the start with.

also, if your buffers are less than one beat long it’d be enough to do 1-f, but to deal with files that are longer than a single beat we use f.ceil-f.

give it a go - hope it works,
_f

23 juli 2021 kl. 19:37 skrev chaos_lloyd via scsynth <noreply@m.scsynth.org>:

| chaos_lloyd
July 23 |

  • | - |

Hey folks,
Is there a way to time the beginning of a Buffer played by PlayBuf in a Pbind so that the audio file ends on a given beat? For context, I’d like to play a number of different scraping sounds of varying lengths. I’m guessing this is probably pretty straightforward, but I can’t find any help for this in the help file.


Visit Topic or reply to this email to respond. Email replies to this address may be posted publicly and archived on scsynth.org (privacy policy).

You are receiving this because you enabled mailing list mode. To unsubscribe from these emails, click here.

#|
fredrikolofsson.com musicalfieldsforever.com

1 Like

Thank you so much. As a novice, I really appreciate the help. I’m pretty sure I understand that the Pfunc is more or less doing this:

TempoClock.default.tempo= 0.8;
~buffers[0].duration/TempoClock.default.beatDur;

and returning the difference, which we use as the value for \timingOffset.

Would you be willing to explain a couple of syntax elements to me? What exactly is the ev argument? Also, is the .buf method looking back at the value of the \buf key earlier in the Pbind?

Thanks in advance.

Would you be willing to explain a couple of syntax elements to me? What exactly is the ev argument? Also, is the .buf method looking back at the value of the \buf key earlier in the Pbind?

correct. it is looking back.

the argument i called ev will be the current ‘event’ - a kind of dictionary with key, value pairs that hold information about the note/event to be played.
so ev.buf is looking up the value for key buf. and this we’ve set just above.

the example could also have been written like this…


Pbind( //buffer player
\instrument, \player,
\dur, Pseq([2, 2, 4], inf),
\buf, ~buffers[0],
\timingOffset, Pfunc({
var f= ~buffers[0].duration/TempoClock.default.beatDur;
f.ceil-f;
}),
).play;

but then you’d have to match which buffer to use in two places. no good.
just imagine if you’d like to sequence or pick buffers at random… then querying the passed in event argument is best the way. it will know which buffer that was chosen.


Pbind( //buffer player
\instrument, \player,
\dur, Pseq([2, 2, 4], inf),
\buf, Prand(~buffers, inf).trace, //pick a buffer at random
\timingOffset, Pfunc({|ev|
var f= ev.buf.duration/TempoClock.default.beatDur;
f.ceil-f;
}),
).play;

there are in-depth tutorials on this if you search in the help system (Understanding Streams, Patterns and Events).
but feel free to ask again if something is unclear,
_f

#|
fredrikolofsson.com musicalfieldsforever.com

1 Like

Just a little potential gotcha, the current event contains all the keys in the Pbind before/above the Pfunc:

(
Pbind(
  \degree, Pbrown(0, 24, 2),
  \pan, Pbrown(-1, 1, 0.3),
  \dummy1, Pfunc { |event| Post << "dummy1 -> " << event << "\n"; 0 },
  \db, Pwhite(-30, 0),
  \dur, 0.1,
  \dummy2, Pfunc { |event| Post << "dummy2 -> " << event << "\n"; 0 }
).play
)
1 Like

Alternately, the Practical Guide to Patterns, which I wrote because I felt that the “Understanding Streams, Patterns and Events” series is a bit terse and difficult to follow.

hjh

1 Like