libdragon
|
RSP Audio mixer. More...
Data Structures | |
struct | mixer_channel_t |
Mixer channel state - CPU side. More... | |
struct | rsp_mixer_channel_t |
Mixer channel state - RSP side. More... | |
struct | rsp_mixer_settings_t |
Mixer ucode settings. More... | |
struct | channel_limit_t |
Configured limits of a mixer channel. More... | |
struct | mixer_event_t |
A mixer event (synchronized with sample playback) More... | |
Macros | |
#define | MIXER_TRACE 0 |
Set to 1 to activate debug logs. | |
#define | tracef(fmt, ...) ({ }) |
like debugf(), but writes only if MIXER_TRACE is not 0 | |
#define | MAX_EVENTS 32 |
Maximum number of mixer events. | |
#define | MIXER_POLL_PER_SECOND 8 |
Number of expected mixer_poll calls per second. | |
#define | MIXER_STATE_SIZE 128 |
Size of the ucode state that is automatically persisted by rspq. | |
#define | CH_FLAGS_BPS_SHIFT (3<<0) |
BPS shift value. | |
#define | CH_FLAGS_16BIT (1<<2) |
Set if the channel is 16 bit. | |
#define | CH_FLAGS_STEREO (1<<3) |
Set if the channel is stereo (left) | |
#define | CH_FLAGS_STEREO_SUB (1<<4) |
The channel is the second half of a stereo (right) | |
#define | CH_FLAGS_STEREO_ALLOC (1<<5) |
The channel has a buffer sized for stereo. | |
#define | MIXER_FX64_FRAC 12 |
Number of fractional bits in mixer_fx64_t. | |
#define | MIXER_FX64(f) (int64_t)((f) * (1<<MIXER_FX64_FRAC)) |
Convert a floating point value to mixer_fx64_t. | |
#define | MIXER_FX15_FRAC 15 |
Number of fractional bits in mixer_fx15_t. | |
#define | MIXER_FX15(f) (int16_t)((f) * ((1<<MIXER_FX15_FRAC)-1)) |
Convert a floating point value to mixer_fx15_t. | |
#define | MIXER_FX16_FRAC 16 |
Number of fractional bits for a fixed 16.16 value. | |
#define | MIXER_FX16(f) (int16_t)((f) * ((1<<MIXER_FX16_FRAC)-1)) |
Convert a floating point value to a fixed 16.16 value. | |
AI Status Register Values | |
#define | AI_STATUS_BUSY ( 1 << 30 ) |
Bit representing that the AI is busy. | |
#define | AI_STATUS_FULL ( 1 << 31 ) |
Bit representing that the AI is full. | |
Typedefs | |
typedef uint64_t | mixer_fx64_t |
Fixed point value used in waveform position calculations. This is a signed 64-bit integer with the fractional part using MIXER_FX64_FRAC bits. You can use MIXER_FX64 to convert from float. | |
typedef int16_t | mixer_fx15_t |
Fixed point value used for volume and panning calculations. You can use MIXER_FX15 to convert from float. | |
Functions | |
DEFINE_RSP_UCODE (rsp_mixer) | |
void | mixer_init (int num_channels) |
Initialize the mixer. | |
void | mixer_set_vol (float vol) |
Set master volume. | |
void | mixer_close (void) |
Deinitialize the mixer. | |
void | mixer_ch_set_freq (int ch, float frequency) |
Change the frequency for the specified channel. | |
void | mixer_ch_set_vol (int ch, float lvol, float rvol) |
Set channel volume (as left/right). | |
void | mixer_ch_set_vol_pan (int ch, float vol, float pan) |
Set channel volume (as volume and panning). | |
void | mixer_ch_set_vol_dolby (int ch, float fl, float fr, float c, float sl, float sr) |
Set channel volume with Dolby Pro Logic II encoding. | |
void | mixer_ch_play (int ch, waveform_t *wave) |
Start playing the specified waveform on the specified channel. | |
void | mixer_ch_set_pos (int ch, float pos) |
Change the current playback position within a waveform. | |
float | mixer_ch_get_pos (int ch) |
void | mixer_ch_stop (int ch) |
Stop playing samples on the specified channel. | |
void | __mixer_wave_stopall (waveform_t *wave) |
bool | mixer_ch_playing (int ch) |
Return true if the channel is currently playing samples. | |
void | mixer_ch_set_limits (int ch, int max_bits, float max_frequency, int max_buf_sz) |
Configure the limits of a channel with respect to sample bit size, and frequency. | |
void | mixer_add_event (int64_t delay, MixerEvent cb, void *ctx) |
Register a time-based event into the mixer. | |
void | mixer_remove_event (MixerEvent cb, void *ctx) |
Deregister a time-based event from the mixer. | |
void | mixer_poll (int16_t *out16, int num_samples) |
Run the mixer to produce output samples. | |
Variables | |
int64_t | __mixer_profile_rsp = 0 |
Count of ticks spent in mixer RSP, used for debugging purposes. | |
uint32_t | __mixer_overlay_id |
RSPQ overlay ID assigned to the mixer ucode. | |
RSP Audio mixer.
struct mixer_channel_t |
Mixer channel state - CPU side.
Data Fields | ||
---|---|---|
mixer_fx64_t | pos | Current position within the waveform (in bytes) |
mixer_fx64_t | step | Step between samples (in bytes) to playback at the correct frequency. |
mixer_fx64_t | len | Length of the waveform (in bytes) |
mixer_fx64_t | loop_len | Length of the loop in the waveform (in bytes) |
void * | ptr | Pointer to the waveform. |
uint32_t | flags | Misc flags (see CH_FLAGS_*) |
struct rsp_mixer_channel_t |
Mixer channel state - RSP side.
This structure represents the state of a mixer channel as stored in RSP DMEM. Structure-wise, it is similar to mixer_channel_t, but waveform-related offsets are 32-bit wide rather than 64-bit, since RSP cannot easily work with 64-bit integers. Check mixer_poll to see how this difference is handled.
struct rsp_mixer_settings_t |
Mixer ucode settings.
This struct reflects the settings defined in rsp_mixer.S.
Data Fields | ||
---|---|---|
uint32_t | lvol[MIXER_MAX_CHANNELS/2] | |
uint32_t | rvol[MIXER_MAX_CHANNELS/2] | |
rsp_mixer_channel_t | channels[MIXER_MAX_CHANNELS] |
struct channel_limit_t |
Configured limits of a mixer channel.
This structure describes the playback limits for a mixer channel. The limits are used to avoid over-allocating memory via sample buffers.
Data Fields | ||
---|---|---|
int | max_bits | Maximum number of bits per channel. |
float | max_frequency | Maximum frequency. |
int | max_buf_sz | Maximum sample buffer size (bytes) |
struct mixer_event_t |
A mixer event (synchronized with sample playback)
Data Fields | ||
---|---|---|
int64_t | ticks | Absolute time at which the event will trigger (ticks = output samples) |
MixerEvent | cb | Callback for the event. |
void * | ctx | Opaque context pointer to pass to the callback. |
#define MIXER_POLL_PER_SECOND 8 |
Number of expected mixer_poll calls per second.
This is used to allocate memory for the sample buffers according to the expected number of samples that must be calculated and held in memory.
DEFINE_RSP_UCODE | ( | rsp_mixer | ) |
RSP mixer ucode (rsp_mixer.S)
void mixer_init | ( | int | num_channels | ) |
Initialize the mixer.
The mixer must be initialized after the audio subsystem (audio_init). The number of channels specified is the maximum number of channels used by the application. Specifying a higher number means using more memory as the mixer will allocate one sample buffer per channel, but it does not affect performance (which correlates to the actual number of simultaneously playing channels).
[in] | num_channels | Number of channels to initialize. |
void mixer_set_vol | ( | float | vol | ) |
Set master volume.
This is a global attenuation factor (range [0..1]) that will be applied to all channels and simplify implementing a global volume control.
[in] | vol | Master volume (range [0..1]) |
void mixer_ch_set_freq | ( | int | ch, |
float | frequency | ||
) |
Change the frequency for the specified channel.
By default, the frequency is the one required by the waveform associated to the channel, but this function allows to override.
This function must be called after mixer_ch_play, as otherwise the frequency is reset to the default of the waveform.
[in] | ch | Channel index |
[in] | frequency | Playback frequency (in Hz / samples per second) |
void mixer_ch_set_vol | ( | int | ch, |
float | lvol, | ||
float | rvol | ||
) |
Set channel volume (as left/right).
Configure channel volume for the specified channel, specifying two values: one for the left output and one for the right output.
The volume is an attenuation (no amplification is performed). Valid volume range in [0..1], where 0 is silence and 1 is original channel sample volume (no attenuation performed).
Notice that it's perfectly valid to set left/right volumes even if the channel itself will play a mono waveforms, as it allows to balance a mono sample between the two final output channels.
[in] | ch | Channel index |
[in] | lvol | Left volume (range [0..1]) |
[in] | rvol | Right volume (range [0..1]) |
void mixer_ch_set_vol_pan | ( | int | ch, |
float | vol, | ||
float | pan | ||
) |
Set channel volume (as volume and panning).
Configure the left and right channel volumes for the specified channel, Using a central volume value and a panning value to specify left/right balance.
Valid volume range in [0..1], where 0 is silence and 1 is maximum volume (no attenuation).
Valid panning range is [0..1] where 0 is 100% left, and 1 is 100% right.
Notice that panning 0.5 balance the sound but causes an attenuation of 50%.
[in] | ch | Channel index |
[in] | vol | Central volume (range [0..1]) |
[in] | pan | Panning (range [0..1], center is 0.5) |
void mixer_ch_set_vol_dolby | ( | int | ch, |
float | fl, | ||
float | fr, | ||
float | c, | ||
float | sl, | ||
float | sr | ||
) |
Set channel volume with Dolby Pro Logic II encoding.
Configure the volumes of the specified channel according to the Dolby Pro Logic II matrix encoding. This allows to encode samples with a virtual surround system, that can be decoded with a Dolby 5.1 compatible equipment.
The function accepts the volumes configured for the 5 channels: front left, front right, center, surround left, surround right. These values can be calculated from a 3D scene
[in] | ch | Channel index |
[in] | fl | Front left volume (range [0..1]) |
[in] | fr | Front right volume (range [0..1]) |
[in] | c | Central volume (range [0..1]) |
[in] | sl | Surround left volume (range [0..1]) |
[in] | sr | Surround right volume (range [0..1]) |
void mixer_ch_play | ( | int | ch, |
waveform_t * | wave | ||
) |
Start playing the specified waveform on the specified channel.
This function immediately begins playing the waveform, interrupting any other waveform that might have been reproduced on this channel.
Waveform settings are applied to the mixer channel; for instance, the frequency of the channel is modified to adapt to the frequency requested for correct playback of the waveform.
If the waveform is marked as stereo (channels == 2), the mixer will need two channels to play it back. "ch" will be used for the left samples, while "ch+1" will be used for the right samples. After this, it is forbidden to call mixer functions on "ch+1" until the stereo waveform is stopped.
If the same waveform (same pointer) was already being played or was the last one that was played on this channel, the channel sample buffer is retained, so that any cached samples might be reused.
[in] | ch | Channel index |
[in] | wave | Waveform to playback |
void mixer_ch_set_pos | ( | int | ch, |
float | pos | ||
) |
Change the current playback position within a waveform.
This function can be useful to seek to a specific point of the waveform. The position must be specified in number of samples (not bytes). Fractional values account for accurate resampling position.
This function must be called after mixer_ch_play, as otherwise the position is reset to the beginning of the waveform.
[in] | ch | Channel index |
[in] | pos | Playback position (in number of samples) |
float mixer_ch_get_pos | ( | int | ch | ) |
Read the current playback position of the waveform in the channel.
The position is returned as number of samples. Fractional values account for accurate resampling position.
[in] | ch | Channel index |
void __mixer_wave_stopall | ( | waveform_t * | wave | ) |
Check if a certain waveform is currently playing on some channel
void mixer_ch_set_limits | ( | int | ch, |
int | max_bits, | ||
float | max_frequency, | ||
int | max_buf_sz | ||
) |
Configure the limits of a channel with respect to sample bit size, and frequency.
This is an advanced function that should be used with caution, only in situations in which it is paramount to control the memory usage of the mixer.
By default, each channel in the mixer is capable of doing 16-bit playback with a frequency up to the mixer output sample rate (eg: 44100hz). This means that the mixer will allocate sample buffers required for this kind of capability.
If it is known that certain channels will use only 8-bit waveforms and/or a lower frequency, it is possible to call this function to inform the mixer of these limits. This will cause the mixer to reallocate the samplebuffers lowering its memory usage (note: multiple calls to this function for different channels will of course be batched to cause only one reallocation).
Note also that this function can be used to increase the maximum frequency over the mixer sample rate, in case this is required. This works correctly but since it causes downsampling, it is generally a waste of memory bandwidth and processing power.
"max_buf_sz" can be used to limit the maximum buffer size that will be allocated for this channel (in bytes). This is a hard cap, applied on top of the optimal buffer size that will be calculated by "max_bits" and "max_frequency", and can be used in situations where there are very strong memory constraints that must be respected. Use 0 if you don't want to impose a limit.
[in] | ch | Channel index |
[in] | max_bits | Maximum number of bits per sample (or 0 to reset this to default, which is currently 16). |
[in] | max_frequency | Maximum playback frequency for this channel in Hz / samples per seconds (or 0 to reset this to default, which is the output sample rate as specified in audio_init). |
[in] | max_buf_sz | Maximum buffer size in bytes (or 0 to reset this default, which is calculated using the other limits, the playback output rate, and the number of audio buffers specified in audio_init). |
void mixer_add_event | ( | int64_t | delay, |
MixerEvent | cb, | ||
void * | ctx | ||
) |
Register a time-based event into the mixer.
Register a new event into the mixer. "delay" is the number of samples to wait before calling the event callback. "cb" is the event callback. "ctx" is an opaque pointer that will be passed to the callback when invoked.
[in] | delay | Number of samples to wait before invoking the event. |
[in] | cb | Event callback to invoke |
[in] | ctx | Context opaque pointer to pass to the callback |
void mixer_remove_event | ( | MixerEvent | cb, |
void * | ctx | ||
) |
Deregister a time-based event from the mixer.
Deregister an event from the mixer. "cb" is the event callback, and "ctx" is the opaque context pointer. Notice that an event can also deregister itself by returning 0 when called.
[in] | cb | Callback that was registered via mixer_add_event |
[in] | ctx | Opaque pointer that was registered with the callback. |
void mixer_poll | ( | int16_t * | out, |
int | nsamples | ||
) |
Run the mixer to produce output samples.
This function will fetch the required samples from all the channels and mix them together according to each channel's settings. The output will be written into the specified buffer (out). nsamples is the number of samples that should be produced.
A common pattern would be to call audio_write_begin to obtain an audio buffer's pointer, and pass it to mixer_poll.
mixer_poll performs mixing using RSP. If RSP is busy, mixer_poll will spin-wait until the RSP is free, to perform audio processing.
Since the N64 AI can only be fed with an even number of samples, mixer_poll does not accept odd numbers.
[in] | out | Output buffer were samples will be written. |
[in] | nsamples | Number of stereo samples to generate. |