Artekit PropBoard: Advanced Audio API


WavChainPlayer Class

class WavChainPlayer : public RawChainPlayer

There are some sound fonts that are meant to be played a WAV file at the time. These WAV files never interpolate themselves and they already contain an audible transition from one WAV file to the other. Mostly used in the lightsaber prop industry, these sound fonts usually come pre-mixed in a way that, for example, a swing WAV file already contains the hum sound in the background and a there is smooth transition to the real hum sound towards the end. These kind of audio files are also known as monophonic fonts.

This kind of audio playback requires a mixing procedure that, due to the nature of the PropBoard Audio module implementation, cannot be cleanly achieved with a WavPlayer object. For WAV files where different sounds come in separated files (polyphonic fonts, for example, a WAV file for a hum sound and a WAV file for a swing sound) the WavPlayer object works just fine since the Audio module takes care of the mixing in real time. But for sound fonts that are pre-mixed, the WavChainPlayer is the best object to use.

The WavChainPlayer object (and so RawChainPlayer) practically combines two WavPlayer objects into one, and manages the transition from one WAV file to the other without missing a single sample, achieving this way a clean, gapless, clickless transition. We call this sequence a WAV chain.

The WavChainPlayer object is initialized by passing a WAV file name to the WavChainPlayer::begin function. We call this WAV file the main track, that is played in loop mode and could be, as for the above example, the hum sound. When another WAV file has to be played (for example a swing) you call the WavChainPlayer::chain function (or WavChainPlayer::chainRandom) and pass to it the file name of the WAV file to play. This is the chained track. When the swing sound is done playing (and you hear the transition), the WavChainPlayer goes back to seamlessly play the main track.

Of course, you can still use any other “audio object” in combination with WavChainPlayer objects, for example a WavPlayer to play background music.

Examples

WavChainPlayer myPlayer;
WavPlayer myMusicPlayer;

volatile bool on_swing = false;
volatile bool on_hit = false;

void setup()
{
    Audio.begin();
    
    // Play some background music in loop mode.
    myMusicPlayer.play("music.wav", PlayModeLoop);
    
    // set the main track
    myPlayer.begin("hum.wav");      

    // Start playing
    myPlayer.play();

    // you can hear the hum sound
}

void loop()
{
    // detect swing
    if (on_swing)
    {
        on_swing = 0;

        // chain swing
        myPlayer.chain("swing.wav");
    }
    
    // detect hit
    if (on_hit)
    {
        on_hit = 0;

        // chain random hit
        myPlayer.chainRandom("hit.wav", 0, 16);
    }
}

The WavChainPlayer starts playing only when the WavChainPlayer::play functions is called. This means that you can prepare a chain and play it in a delayed fashion. For example, in an ignition sequence:

WavChainPlayer myPlayer;

void setup()
{
    Audio.begin();
    
    // set the main track   
    myPlayer.begin("hum.wav");
    
    // prepare the chain
    myPlayer.chain("ignition.wav", PlayModeBlocking);
    
    // play
    myPlayer.play();
    
    // At this point you can hear ignition.wav
    // and when it's over, the hum.wav file
    // takes over in loop mode.
}

If you need to interrupt the chained WAV file, you can call the WavChainPlayer::restart function to go back and start playing the main track again. That would be the case for a lock-up sequence:

void loop()
{
    // lock-up condition is detected
    if (on_lock_up)
    {
        // Play the lockup.wav file in loop mode
        myPlayer.chain("lockup.wav", PlayModeLoop);
        
        // wait for lock-up condition to end
        while (on_lock_up);
        
        // lock-up ended, go back to the hum sound
        myPlayer.restart();
    }
}

There is only one constraint when using the WavChainPLayer (and RawChainPlayer) object, and is that the WAV (and raw PCM) files involved must have the same sampling frequency, bit depth and quantity of channels: all files must be either stereo or mono. Usually these sound fonts files have all the same format.

The WavChainPlayer class inherits from the RawChainPlayer class. In this guide we will document only the WavChainPlayer class since it is the most commonly used one. The functions of the parent class RawChainPlayer that are different from the child class are at the end of this document.

WavChainPlayer::begin

This function initializes the WavChainPlayer object and sets a WAV file as the main track.

Syntax

bool begin(const char* filename);

Parameters

The filename parameter is a string containing the name of the WAV file.

Returns

Returns true on success, false otherwise.

Example

See example for WavChainPlayer class.

WavChainPlayer::chain

This function sets a WAV file as the chained track. If the WavChainPlayer object is playing, the main track is interrupted and the chained track is played.

Syntax

bool chain(const char* filename, PlayMode mode = PlayModeNormal);

Parameters

The filename parameter is the name of the WAV file to chain.

The mode parameter indicates the playback mode and can be one of the following values:

  • PlayModeNormal: the WAV file is played once.
  • PlayModeLoop: the WAV file is played in loop mode. Once it finishes, it will start playing again.
  • PlayModeBlocking: the WAV file is played once and the function returns after the WAV file is done playing.

Returns

Returns true on success, false otherwise.

Example

See the examples for the WavChainPlayer class.

WavChainPlayer::chainRandom

This function sets a WAV file as the chained track by randomly choosing a file name among those specified with the min and max parameters, much like the WavPlayer::playRandom function does with regular WAV files.

If the WavChainPlayer object is playing, the main track is interrupted and the chained track is played.

Syntax

bool chainRandom(const char* filename, uint32_t min, uint32_t max, PlayMode mode = PlayModeNormal);

Parameters

The filename parameter is a string that indicates the WAV file to play without extension.

The min parameter is the minimum possible number that will be appended to the filename parameter, for example 0.

The max parameter is the maximum possible number that will be appended to the filename parameter, for example 10.

The mode parameter indicates the playback mode and can be one of the following values:

  • PlayModeNormal: the WAV file is played once.
  • PlayModeLoop: the WAV file is played in loop mode. Once it finishes, it will start playing again.
  • PlayModeBlocking: the WAV file is played once and the function returns after the WAV file is done playing.

If the mode parameter is omitted, it is defaulted to PlayModeNormal.

Returns

Returns true on success, false otherwise.

Example

WavChainPlayer myPlayer;

void setup()
{
    Audio.begin();
    
    // set the main track
    myPlayer.begin("hum.wav");

    // start playing
    myPlayer.play();

    // play a random swing between swing0.wav and swing14.wav
    myPlayer.chainRandom("swing", 0, 14);
}

WavChainPlayer::play

The WavChainPlayer::play function starts playing the main track or the chained track, if any.

Syntax

bool play();

Parameters

None.

Returns

The function returns true on success, false otherwise.

Example

See the examples for the WavChainPlayer class.

WavChainPlayer::stop

The WavChainPlayer::stop function stop any audio playback from the WavChainPlayer object (main track and chained track).

Syntax

bool stop();

Parameters

None.

Returns

The function returns true on success, false otherwise.

Example

void loop()
{
    // power off condition is detected
    if (on_power_off)
    {
        // Play the off.wav file in blocking mode
        myPlayer.chain("off.wav", PlayModeBlocking);
        
        // When finished, stop all playback
        myPlayer.stop();
        
        on_power_off = false;
    }
}

WavChainPlayer::pause

This functions pauses the playback of the WavChainPlayer object. To resume playback you need to call the WavChainPlayer::resume function.

Syntax

bool pause();

Parameters

None.

Returns

The function returns true on success, false otherwise.

WavChainPlayer::resume

This functions resumes the playback of a WavChainPlayer object previously paused with the WavChainPlayer::pause function.

Syntax

bool resume();

Parameters

None.

Returns

The function returns true on success, false otherwise.

WavChainPlayer::restart

This function restarts the playback of the main track and plays it from the beginning. If a chained track is playing, it is stopped.

Syntax

bool restart();

Parameters

None

Returns

Returns true on success, false otherwise.

Example

See the examples for the WavChainPlayer class.

WavChainPlayer::getChainStatus

The WavChainPlayer::getChainStatus function returns the current playback status of the WavChainPlayer object.

Syntax

ChainPlayStatus getChainStatus();

Parameters

None.

Returns

The function returns one of the following values:

  • PlayingNone: The WavChainPlayer object is stopped.
  • PlayingMain: The WavChainPlayer object is playing the main track.
  • PlayingChained: The WavChainPlayer object is playing the chained track
  • PlayingTransition: The WavChainPlayer object is playing the last samples of the chained track and soon will start playing the main track.

RawChainPlayer Class

class RawChainPlayer : public AudioSource

The RawChainPlayer is the base class for WavChainPlayer. It does what WavChainPlayer does for WAV files, but using raw PCM files that have a known format. The format is specified by initializing the object with the RawChainPlayer.begin function.

See the WavChainPlayer for details about sound files chaining.

RawChainPlayer::begin

Initializes the RawChainPlayer object and sets the file name and characteristics of the main track audio file.

Syntax

bool begin(const char* filename, uint32_t fs, uint8_t bps, bool mono, uint32_t hdrsize);

Parameters

The filename parameter is a string containing the name of the raw PCM file.

The fs parameter is the sampling frequency, and can be one of the following values:

  • 22050
  • 32000
  • 44100
  • 48000
  • 96000

The bps is the bit depth, and must be the following value:

  • 16

Set the mono parameter to true if the audio file is mono, otherwise set it to false.

The hdrsize parameter indicates the quantity of bytes to skip from the beginning of the file. Useful if you want to skip the header present in some raw PCM files.

Returns

Returns true on success, false otherwise.

RavChainPlayer::chainRandom

This function sets a raw PCM file as the chained track by randomly choosing a file name among those specified with the min and max parameters and with ext extension, much like the WavChainPlayer::chainRandom function does with regular WAV files.

If the WavChainPlayer object is playing, the main track is interrupted and the chained track is played.

Syntax

bool chainRandom(const char* filename, const char* ext, uint32_t min, uint32_t max, PlayMode mode = PlayModeNormal);

Parameters

The filename parameter is a string that indicates the WAV file to play without extension.

The ext parameter is the extension of the file. For example “raw”.

The min parameter is the minimum possible number that will be appended to the filename parameter, for example 0.

The max parameter is the maximum possible number that will be appended to the filename parameter, for example 10.

The mode parameter indicates the playback mode and can be one of the following values:

  • PlayModeNormal: the WAV file is played once.
  • PlayModeLoop: the WAV file is played in loop mode. Once it finishes, it will start playing again.
  • PlayModeBlocking: the WAV file is played once and the function returns after the WAV file is done playing.

If the mode parameter is omitted, it is defaulted to PlayModeNormal.

Returns

Returns true on success, false otherwise.

Example

RawChainPlayer myPlayer;

void setup()
{
    Audio.begin();
    
    // set the main track
    myPlayer.begin("hum.raw", 22050, 16, true, 0);

    // start playing
    myPlayer.play();

    // play a random swing between swing0.raw and swing14.raw
    myPlayer.chainRandom("swing", "raw", 0, 14);
}