Audio mixer (WAV effects)

If you’ve read the other pages about libdragon audio, it’s possible to play music and sound effects on your Nintendo 64 project. However, if you want to have some more control over how the audio is played, we’ll need to involve some of the more complex audio mixer functionality.

Note that these functions only seem to work with WAV files, they won’t work with YM or XM playback. You’ll have to add in the effects for those in the files themselves.

WAV looping

Something that is pretty useful for working with WAV files is to enable looping. This makes the WAV audio start playing back from the beginning without interruption. Useful when playing something like a repeating gunshot from an automatic gun, looping a music track or keeping a steady wave tone.

void wav64_set_loop(wav64_t *wav, bool loop);

Setting the volume

There are a few different ways to adjust the volume.

// Set the master volume. This affects all channels.
void mixer_set_vol (float vol);

// Set the volume for an individual channel
void mixer_ch_set_vol (int ch, float lvol, float rvol);

// Set the volume and panning. Same effect as above but with different parameters
void	mixer_ch_set_vol_pan (int ch, float vol, float pan);

// Set volume with Dolby Pro Logic II
void mixer_ch_set_vol_dolby(int ch, float fl, float fr, float c, float sl, float sr);

I found that only the mixer_set_vol() function seems to work with XM and YM files, all of them work fine with WAV.

Setting the frequency and position

You can modify the frequency and position of a waveform in the mixer by using the following functions:

// Set the channel to a certain frequency (in hz)
void mixer_ch_set_freq(int ch, float frequency);

// Make the WAV skip to a certain position in the track (in sample count)
void mixer_ch_set_pos(int ch, float pos);

This is particularly useful if you want to use one waveform but give it a different flavour. For example, you might have an explosion sound effect and want to change the way it sounds by stretching it out or by only playing the tail end of it.

Other mixer functions

Here are some miscellaneous mixer functions that can help out in some situations.

// Play a waveform in a particular channel
void mixer_ch_play(int ch, waveform_t *wave);

// Stop playing on a particular channel
void mixer_ch_stop(int ch);

// Check if a channel is currently playing
bool mixer_ch_playing(int ch);

// Set upper limits for bits per sample, playback frequency and buffer size
void mixer_ch_set_limits(int ch, int max_bits, float max_frequency, int max_buf_sz);

Mixer events

Basically, it adds a callback function called MixerEvent cb which is triggered after delay samples. The callback is a function that has a single parameter ctx which is a void pointer (can be assigned a type in-function) and returns an int which is 0 upon success.

I’m not 100% sure what to make of these since it doesn’t seem like it is used very much. I think it can be used to amend the sample or the buffer mid-read.

// Callback function
typedef int (*MixerEvent)(void* ctx);

// Add/remove events
void mixer_add_event(int64_t delay, MixerEvent cb, void *ctx);
void mixer_remove_event(MixerEvent cb, void *ctx);


If you really don’t want to use uncompressed WAV files, you can use Libdragon’s custom waveform functionality to create your own audio file processor.

// Callback function
// ctx     Opaque pointer that is provided as context to the function, and is specified in the waveform.
// sbuf    Samplebuffer into which read samples should be stored.
// wpos    Absolute position in the waveform to read from (in samples).
// wlen    Minimum number of samples to read (in samples).
// seeking True if this call requires seeking in the waveform, false if this read is consecutive to the last one
typedef void (*WaveformRead)(void *ctx, samplebuffer_t *sbuf, int wpos, int wlen, bool seeking);

// Structure to hold a the waveform
typedef struct waveform_s {
	const char *name;
	uint8_t bits;
	uint8_t channels;
	float frequency;
	int len;
	int loop_len;
	WaveformRead read;
	void *ctx;
} waveform_t;


Subscribe to the mailing list

Follow N64 Squid

  • RSS Feed
  • YouTube

Random featured posts