• Audio
  • Simple Wav File Trigger

Anyone have a simple example or library for loading and playing sounds from .wav files? Something that handles the heavy lifting and all I need to do is stuff like:

Trigger trigger; // defines a trigger object

trigger.LoadWav("snaredrum.wav"); // sets a wav file to the trigger object

trigger.PlayOnce; // plays the solo shot sound one time through. Repeated plays inturupts existing hits.

And likewise a library that handles the button control, much like EasyButton does for Arduino. https://www.arduino.cc/reference/en/libraries/easybutton/

Essentially, who has built libraries that can get me making music/sounds faster in Bela?

Thanks.

If you are using C++, then check the on-board examples in the Audio section. Especially Audio/sample-loader, Audio/sample-piezo-trigger. For basic button interaction, check out Digital/digital-input. There is no exact reimplementation of EasyButton, but there's BelaDebounce for debouncing. I don't think we have a dedicated example, but it's documented here and it goes more or less:

// global
BelaDebounce button;

// in setup()
button.setup({
  .context = context,
  .channel = 0,
  .debounceMs = 3,
});

// in render(), outside any loops
bool debounced = button.process(context);

Tangential to your question, you can also consider using PureData for higher-level interaction: https://learn.bela.io/tutorials/pure-data/fundamentals/course-introduction/

Does Pure Data also work with RGB LEDs, rotary encoders, track balls, a mouse, trill craft?

Missing image is

To

drumminhands Can you help me have a button input from the GPIO to cause a loaded audio file to play once and then stop?

That should be

[r bela_digitalIn18]
|
[select 1]
|
[tabplay~]

Image link should be fixed now.

Thank you both.

For those who come across this in the future, here is my main program:

And here is a button abstraction:

It's working great. Any advice in making it better I'm all ears.

Looking good. Two small things: [sel 1] has no method for "bang". So you just want to send it a message [1( for triggering it manually. I would always work with [trigger] to make the dataflow order explicit, even if it doesn't make a difference here, just to get used to it. So after [r bela_digitalIn18] insert a [t b b].

Is there any way to make each button abstraction behave more like an object class in object-oriented programming? I'm going to have many buttons, and I don't want to rewrite each input pin, output pin, and wav file more than once per button. Does Pure Data have anything close to global variables that are scoped just inside the abstraction? And/or send/receive messages that only fire inside the abstraction and not in other instances?

Riffing on this a little bit. In the example for trill craft-pd, it includes playAudioFile~.pd. This is great for a sound that is a loop. But how do I modify so that it plays a sound file once, all the way through, and it not interruptible until the sound has finished?

    What you want is to ignore any user input while the soundfile is still playing, and then only resume to do so once the soundfile has finished playing.
    [spigot] can interrupt a message flow in such way.

    drumminhands But how do I modify so that it plays a sound file once, all the way through, and it not interruptible until the sound has finished?

    In [pd playRetrig], a [phasor~] is used to generate a sawtooth, whose range is expanded to cover all the indexes in the array and sent to [tabread~] that reads the table at a variable speed. You have several options:

    • if you want to read the file at the original speed, do not use [tabread~], instead simply send a bang into [tabplay~].
    • if you want to read the file once at a fixed speed that may be different from the original, send messages to a[line~] object to generate a single ramp and connect its outlet to [tabread~]. E.g.: [0, 100000 2000] will read 100000 samples in 2000 milliseconds
    • if you want to read the file once at a variable speed, I think you need to keep the [phasor~] approach (as that allows for continuous modulation of the playback rate) object to generate a single ramp and then "turn it off" once it ends. To turn it off, you can do something like this hack to set the [phasor~]'s frequency to 0 when it is towards the end of the ramp:

    Note: in the above screenshot, the phasor~ is stopped at some value between 0.999 and 1 so it doesn't accidentally restart before the [threshold~] has triggered. This means playback won't reach the very end of the file (less than the last 0.001 will be missing). Full-length playback can be achieved with a bit of extra work.