libdragon
Files | Defines | Functions | Variables
Audio Subsystem
libdragon

Interface to the N64 audio hardware. More...

Files

file  audio.c
 

Audio Subsystem.


file  audio.h
 

Audio Subsystem.


Defines

#define TV_TYPE_LOC   0x80000300
 Memory location to read which determines the TV type.
#define NUM_BUFFERS   4
 Number of buffers the audio subsytem allocates and manages.
#define CALC_BUFFER(x)   ( ( ( ( x ) / 25 ) >> 3 ) << 3 )
 Macro that calculates the size of a buffer based on frequency.

Functions

static volatile int __busy ()
 Return whether the AI is currently busy.
static volatile int __full ()
 Return whether the AI is currently full.
static void audio_callback ()
 Send next available chunks of audio data to the AI.
void audio_init (const int frequency, int numbuffers)
 Initialize the audio subsystem.
void audio_init_ex (const int frequency, int numbuffers, int maxsamples, void(*cb)())
 Initialize the audio subsystem (extended)
void audio_close ()
 Close the audio subsystem.
void audio_write (const short *const buffer)
 Write a chunk of audio data.
void audio_write_silence ()
 Write a chunk of silence.
volatile int audio_can_write ()
 Return whether there is an empty buffer to write to.
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.
void audio_set_num_samples (int numsamples)
 Change the number of stereo samples to write to each buffer.
short * audio_get_next_buffer (int *lastbuf)
 Return the address of the next buffer to fill.
volatile int audio_send_buffer (int lastbuf)
 Start audio DMA on buffer.

Variables

static void(* _callback )() = NULL
 The actual frequency the AI will run at.
static int _frequency = 0
 The actual frequency the AI will run at.
static int _num_buf = NUM_BUFFERS
 The number of buffers currently allocated.
static int _num_samp = 0
 The number of samples to write into each buffer.
static int _buf_size = 0
 The buffer size in bytes for each buffer allocated.
static short ** buffers = NULL
 Array of pointers to the allocated buffers.
static volatile int now_playing = 0
 Index of the current playing buffer.
static volatile int now_writing = 0
 Index pf the currently being written buffer.
static volatile int buf_full = 0
 Bitmask of buffers indicating which buffers are full.
static struct AI_regs_s *const AI_regs = (struct AI_regs_s *)0xa4500000
 Structure used to interact with the AI registers.

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.

Detailed Description

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 master clock of the N64, the audio subsystem needs to know what region the N64 is from. This is due to the fact that the master 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 Documentation

#define CALC_BUFFER (   x)    ( ( ( ( x ) / 25 ) >> 3 ) << 3 )

Macro that calculates the size of a buffer based on frequency.

Parameters:
[in]xFrequency the AI is running at
Returns:
The size of the buffer in bytes rounded to an 8 byte boundary
#define TV_TYPE_LOC   0x80000300

Memory location to read which determines the TV type.

Values read include 0 for PAL, 1 for NTSC and 2 for MPAL


Function Documentation

static volatile int __busy ( ) [inline, static]

Return whether the AI is currently busy.

Returns:
nonzero if the AI is busy, zero otherwise
static volatile int __full ( ) [inline, static]

Return whether the AI is currently full.

Returns:
nonzero if the AI is full, zero otherwise
static void audio_callback ( ) [static]

Send next available chunks of audio data to the AI.

This function is called whenever internal buffers are running low. It will send as many buffers as possible to the AI until the AI is full.

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_close ( )

Close the audio subsystem.

This function closes the audio system and cleans up any internal memory allocated by audio_init.

Get the number of stereo samples that fit into an allocated buffer.

Note:
To get the number of bytes to allocate, multiply the return by 2 * sizeof( short )
Returns:
The number of stereo samples in an allocated buffer

Return actual frequency of audio playback.

Returns:
Frequency in Hz of the audio playback
short* audio_get_next_buffer ( int *  lastbuf)

Return the address of the next buffer to fill.

This function returns a pointer to the next buffer to fill with stereo 16-bit samples. The number of stereo samples to write may be found by calling audio_get_buffer_length. Pointer is uncached.

Parameters:
[in]lastbufpointer to previous buffer index
Returns:
Uncached pointer to the next available sample buffer
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.

Note:
Before re-initializing the audio subsystem to a new playback frequency, remember to call audio_close.
Parameters:
[in]frequencyThe frequency in Hz to play back samples at
[in]numbuffersThe number of buffers to allocate internally
void audio_init_ex ( const int  frequency,
int  numbuffers,
int  maxsamples,
void(*)()  cb 
)

Initialize the audio subsystem (extended)

This function will set up the AI to play at a given frequency, allocate a number of back buffers to write data to using the specified max number of stereo samples, and set the provided callback function. Max samples must be even, and if the callback is NULL, the built-in callback is used.

Note:
Before re-initializing the audio subsystem to a new playback frequency, remember to call audio_close.
Parameters:
[in]frequencyThe frequency in Hz to play back samples at
[in]numbuffersThe number of buffers to allocate internally
[in]maxsamplesThe max number of stereo 16-bit samples each buffer will hold
[in]cbThe callback function for audio interrupts
volatile int audio_send_buffer ( int  lastbuf)

Start audio DMA on buffer.

This function sets the audio DMA for the indexed buffer (should be the same as set by audio_get_next_buffer), and starts the DMA.

Parameters:
[in]lastbuflast buffer index returned by audio_get_next_buffer
Returns:
0 if audio DMA is full, or 1 if indexed buffer queued
void audio_set_num_samples ( int  numsamples)

Change the number of stereo samples to write to each buffer.

This function sets how many stereo samples to write to the audio buffers. It should be even so that the buffer length is divisible by eight bytes for DMA restrictions. It MUST be smaller than the max number of samples passed to audio_init_ex, but is not checked.

Parameters:
[in]numsamplesnumber of stereo samples to write to each buffer
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.

Note:
This function will block until there is room to write an audio sample. If you do not want to block, check to see if there is room by calling audio_can_write.
Parameters:
[in]bufferBuffer containing stereo samples to be played

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.

Note:
This function will block until there is room to write an audio sample. If you do not want to block, check to see if there is room by calling audio_can_write.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines