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. | |
Typedefs | |
typedef void(* | audio_fill_buffer_callback) (short *buffer, size_t numsamples) |
Will be called periodically when more sample data is needed. | |
Functions | |
void | audio_init (const int frequency, int numbuffers) |
Initialize the audio subsystem. | |
void | audio_set_buffer_callback (audio_fill_buffer_callback fill_buffer_callback) |
Install a audio callback to fill the audio buffer when required. | |
void | audio_pause (bool pause) |
Pause or resume audio playback. | |
volatile int | audio_can_write () |
Return whether there is an empty buffer to write to. | |
void | audio_write_silence () |
Write a chunk of silence. | |
void | audio_close () |
Close the audio subsystem. | |
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. | |
short * | audio_write_begin (void) |
Start writing to the first free internal buffer. | |
void | audio_write_end (void) |
Complete writing to an internal buffer. | |
int | audio_push (const short *buffer, int nsamples, bool blocking) |
Push a chunk of audio data (high-level function) | |
void | audio_write (const short *const buffer) |
Write a chunk of audio data. | |
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.
typedef void(* audio_fill_buffer_callback) (short *buffer, size_t numsamples) |
Will be called periodically when more sample data is needed.
[in] | buffer | The address to write the sample data to |
[in] | numsamples | The number of samples to write to the buffer |
NOTE: This is the number of samples per channel, so clients should write twice this number of samples (interleaved).
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_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.
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.
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.
void audio_close | ( | ) |
Close the audio subsystem.
This function closes the audio system and cleans up any internal memory allocated by audio_init.
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.
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.
int audio_push | ( | const short * | buffer, |
int | nsamples, | ||
bool | blocking | ||
) |
Push a chunk of audio data (high-level function)
This function is an easy-to-use, higher level alternative to all the audio_write* functions. It pushes audio samples into output hiding the complexity required to match the fixed-size audio buffers.
The function accepts a buffer
of stereo interleaved audio samples; nsamples
is the number of samples in the buffer. The function will push the samples into output as much as possible.
If blocking
is true, it will stop and wait until all samples have been pushed into output. If blocking
is false, it will stop as soon as there are no more free buffers to push samples into, and will return the number of pushed samples. It is up to the caller to then take care of this and later try to call audio_push again with the remaining samples.
buffer | Buffer containing stereo samples to be played |
nsamples | Number of stereo samples in the buffer |
blocking | If true, wait until all samples have been pushed |
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 |