libdragon
|
Interface to the N64 audio hardware. More...
Modules | |
Audio mixer | |
Flexible, composable, fast, RSP-based audio mixer. | |
Files | |
file | audio.c |
Audio Subsystem. | |
file | audio.h |
Audio Subsystem. | |
Macros | |
#define | NUM_BUFFERS 4 |
Number of buffers the audio subsytem allocates and manages. | |
#define | BUFFERS_PER_SECOND 25 |
How many different audio buffers we want to schedule in one second. | |
#define | CALC_BUFFER(x) ( ( ( ( x ) / BUFFERS_PER_SECOND ) >> 3 ) << 3 ) |
Macro that calculates the size of a buffer based on frequency. More... | |
Functions | |
void | audio_init (const int frequency, int numbuffers) |
Initialize the audio subsystem. More... | |
void | audio_set_buffer_callback (audio_fill_buffer_callback fill_buffer_callback) |
Install a audio callback to fill the audio buffer when required. More... | |
void | audio_close () |
Close the audio subsystem. More... | |
void | audio_pause (bool pause) |
Pause or resume audio playback. More... | |
void | audio_write (const short *const buffer) |
Write a chunk of audio data. More... | |
short * | audio_write_begin (void) |
Start writing to the first free internal buffer. More... | |
void | audio_write_end (void) |
Complete writing to an internal buffer. More... | |
void | audio_write_silence () |
Write a chunk of silence. More... | |
volatile int | audio_can_write () |
Return whether there is an empty buffer to write to. More... | |
int | audio_get_frequency () |
Return actual frequency of audio playback. More... | |
int | audio_get_buffer_length () |
Get the number of stereo samples that fit into an allocated buffer. More... | |
DAC rates for different regions | |
#define | AI_NTSC_DACRATE 48681812 |
NTSC DAC rate. | |
#define | AI_PAL_DACRATE 49656530 |
PAL DAC rate. | |
#define | AI_MPAL_DACRATE 48628316 |
MPAL DAC rate. | |
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. | |
Interface to the N64 audio hardware.
The audio subsystem handles queueing up chunks of audio data for playback using the N64 audio DAC. The audio subsystem handles DMAing chunks of data to the audio DAC as well as audio callbacks when there is room for another chunk to be written. Buffer size is calculated automatically based on the requested audio frequency. The audio subsystem accomplishes this by interfacing with the audio interface (AI) registers.
Because the audio DAC is timed off of the system clock of the N64, the audio subsystem needs to know what region the N64 is from. This is due to the fact that the system clock is timed differently for PAL, NTSC and MPAL regions. This is handled automatically by the audio subsystem based on settings left by the bootloader.
Code attempting to output audio on the N64 should initialize the audio subsystem at the desired frequency and with the desired number of buffers using audio_init. More audio buffers allows for smaller chances of audio glitches but means that there will be more latency in sound output. When new data is available to be output, code should check to see if there is room in the output buffers using audio_can_write. Code can probe the current frequency and buffer size using audio_get_frequency and audio_get_buffer_length respectively. When there is additional room, code can add new data to the output buffers using audio_write. Be careful as this is a blocking operation, so if code doesn't check for adequate room first, this function will not return until there is room and the samples have been written. When all audio has been written, code should call audio_close to shut down the audio subsystem cleanly.
#define CALC_BUFFER | ( | x | ) | ( ( ( ( x ) / BUFFERS_PER_SECOND ) >> 3 ) << 3 ) |
Macro that calculates the size of a buffer based on frequency.
[in] | x | Frequency the AI is running at |
void audio_init | ( | const int | frequency, |
int | numbuffers | ||
) |
Initialize the audio subsystem.
This function will set up the AI to play at a given frequency and allocate a number of back buffers to write data to.
[in] | frequency | The frequency in Hz to play back samples at |
[in] | numbuffers | The number of buffers to allocate internally |
void audio_set_buffer_callback | ( | audio_fill_buffer_callback | fill_buffer_callback | ) |
Install a audio callback to fill the audio buffer when required.
This function allows to implement a pull-based audio system. It registers a callback which will be invoked under interrupt whenever the AI is ready to have more samples enqueued. The callback can fill the provided audio data with samples that will be enqueued for DMA to AI.
[in] | fill_buffer_callback | Callback to fill an empty audio buffer |
void audio_close | ( | ) |
Close the audio subsystem.
This function closes the audio system and cleans up any internal memory allocated by audio_init.
void audio_pause | ( | bool | pause | ) |
Pause or resume audio playback.
Should only be used when a fill_buffer_callback has been set in audio_init. Silence will be generated while playback is paused.
void audio_write | ( | const short *const | buffer | ) |
Write a chunk of audio data.
This function takes a chunk of audio data and writes it to an internal buffer which will be played back by the audio system as soon as room becomes available in the AI. The buffer should contain stereo interleaved samples and be exactly audio_get_buffer_length stereo samples long.
To improve performance and avoid the memory copy, use audio_write_begin and audio_write_end instead.
[in] | buffer | Buffer containing stereo samples to be played |
short * audio_write_begin | ( | void | ) |
Start writing to the first free internal buffer.
This function is similar to audio_write but instead of taking samples and copying them to an internal buffer, it returns the pointer to the internal buffer. This allows generating the samples directly in the buffer that will be sent via DMA to AI, without any subsequent memory copy.
The buffer should be filled with stereo interleaved samples, and exactly audio_get_buffer_length samples should be written.
After you have written the samples, call audio_write_end() to notify the library that the buffer is ready to be sent to AI.
void audio_write_end | ( | void | ) |
Complete writing to an internal buffer.
This function is meant to be used in pair with audio_write_begin(). Call this once you have generated the samples, so that the audio system knows the buffer has been filled and can be played back.
void audio_write_silence | ( | ) |
Write a chunk of silence.
This function will write silence to be played back by the audio system. It writes exactly audio_get_buffer_length stereo samples.
volatile int audio_can_write | ( | ) |
Return whether there is an empty buffer to write to.
This function will check to see if there are any buffers that are not full to write data to. If all buffers are full, wait until the AI has played back the next buffer in its queue and try writing again.
int audio_get_frequency | ( | ) |
Return actual frequency of audio playback.
int audio_get_buffer_length | ( | ) |
Get the number of stereo samples that fit into an allocated buffer.