1 /* ASNDLIB -> accelerated sound lib using the DSP
3 Copyright (c) 2008 Hermes <www.entuwii.net>
6 Redistribution and use in source and binary forms, with or without modification, are
7 permitted provided that the following conditions are met:
9 - Redistributions of source code must retain the above copyright notice, this list of
10 conditions and the following disclaimer.
11 - Redistributions in binary form must reproduce the above copyright notice, this list
12 of conditions and the following disclaimer in the documentation and/or other
13 materials provided with the distribution.
14 - The names of the contributors may not be used to endorse or promote products derived
15 from this software without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
25 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 #define ASND_LIB 0x100
42 #define SND_LIB (ASND_LIB+2)
50 /*! \addtogroup sndretvals SND return values
54 #define SND_INVALID -1
55 #define SND_ISNOTASONGVOICE -2
59 /*! \addtogroup sndiavretvals SND_IsActiveVoice additional return values
62 #define SND_UNUSED 0 /*!< This voice is available for use. */
63 #define SND_WORKING 1 /*!< This voice is currently in progress. */
64 #define SND_WAITING 2 /*!< This voice is currently in progress and waiting to one SND_AddVoice() function (the voice handler is called continuously) */
67 /*! \addtogroup sndsetvoiceformats Voice format
70 #define VOICE_MONO_8BIT 0
71 #define VOICE_MONO_16BIT 1
72 #define VOICE_STEREO_8BIT 2
73 #define VOICE_STEREO_16BIT 3
76 /*! \addtogroup voicevol Voice volume
80 #define MID_VOLUME 127
81 #define MAX_VOLUME 255
84 /*! \addtogroup pitchrange Pitch Range
87 #define MIN_PITCH 1 /*!< 1Hz */
88 #define F44100HZ_PITCH 44100 /*!< 44100Hz */
89 #define MAX_PITCH 144000 /*!< 144000Hz (more process time for pitch>48000) */
90 #define INIT_RATE_48000
93 /*! \addtogroup notecode Note codification
138 #define NOTE(note,octave) (note+(octave<<3)+(octave<<2)) /*!< Final note codification. Used in Note2Freq(). */
141 /*------------------------------------------------------------------------------------------------------------------------------------------------------*/
143 /*! \addtogroup sndlibcompat SNDLIB compatibility macros
144 * \details These defines are for compatability with SNDLIB functions.
147 #define Note2Freq ANote2Freq
148 #define SND_Init ASND_Init
149 #define SND_End ASND_End
150 #define SND_Pause ASND_Pause
151 #define SND_Is_Paused ASND_Is_Paused
152 #define SND_GetTime ASND_GetTime
153 #define SND_GetSampleCounter ASND_GetSampleCounter
154 #define SND_GetSamplesPerTick ASND_GetSamplesPerTick
155 #define SND_SetTime ASND_SetTime
156 #define SND_SetCallback ASND_SetCallback
157 #define SND_GetAudioRate ASND_GetAudioRate
158 #define SND_SetVoice ASND_SetVoice
159 #define SND_AddVoice ASND_AddVoice
160 #define SND_StopVoice ASND_StopVoice
161 #define SND_PauseVoice ASND_PauseVoice
162 #define SND_StatusVoice ASND_StatusVoice
163 #define SND_GetFirstUnusedVoice ASND_GetFirstUnusedVoice
164 #define SND_ChangePitchVoice ASND_ChangePitchVoice
165 #define SND_ChangeVolumeVoice ASND_ChangeVolumeVoice
166 #define SND_ChangeVolumeVoice ASND_ChangeVolumeVoice
167 #define SND_GetTickCounterVoice ASND_GetTickCounterVoice
168 #define SND_GetTimerVoice ASND_GetTimerVoice
169 #define SND_TestPointer ASND_TestPointer
172 /*------------------------------------------------------------------------------------------------------------------------------------------------------*/
174 /** \brief Callback type for ASND_SetVoice(). */
175 typedef void (*ASNDVoiceCallback
)(s32 voice
);
177 /*------------------------------------------------------------------------------------------------------------------------------------------------------*/
179 /** \brief Initializes the SND lib and fixes the hardware sample rate.
180 * \param[in] note \ref notecode to play. for example: NOTE(C,4) for note C and octave 4.
181 * \param[in] freq_base Frequency base of the sample. For example 8000Hz.
182 * \param[in] note_base \ref notecode of the sample. For example: NOTE(L, 3) for note L and octave 3 (LA 3).
183 * \return Frequency, in Hz. */
184 int ANote2Freq(int note
, int freq_base
,int note_base
);
186 /*------------------------------------------------------------------------------------------------------------------------------------------------------*/
188 /*! \addtogroup General sound functions
192 /*! \brief Initializes the ASND lib and fixes the hardware sample rate to 48000.
196 /*! \brief De-initializes the ASND lib.
200 /*! \brief Used to pause (or unpause) the sound.
201 * \note The sound starts paused when ASND_Init() is called.
202 * \param[in] paused If 1, sound is paused; sound can be unpaused with 0.
204 void ASND_Pause(s32 paused
);
206 /*! \brief Returns sound paused status.
207 * \return 1 if paused, 0 if unpaused. */
208 s32
ASND_Is_Paused();
210 /*! \brief Returns the global time.
211 * \details The time is updated from the IRQ.
212 * \return The current time, in milliseconds. */
215 /*! \brief Retrieves the global sample counter.
216 * \details This counter is updated from the IRQ in steps of ASND_GetSamplesPerTick().
217 * \note You can use this to implement one timer with high precision.
218 * \return Current sample. */
219 u32
ASND_GetSampleCounter();
221 /*! \brief Retrieves the samples sent from the IRQ in one tick.
222 * \return Samples per tick. */
223 u32
ASND_GetSamplesPerTick();
225 /*! \brief Set the global time.
226 * \details This time is updated from the IRQ.
227 * \param[in] time Fix the current time, in milliseconds.
229 void ASND_SetTime(u32 time
);
231 /*! \brief Sets a global callback for general purposes.
232 * \details This callback is called from the IRQ.
233 * \param[in] callback Callback function to assign.
235 void ASND_SetCallback(void (*callback
)());
237 /*! \brief Returns the current audio rate.
238 * \note This function is implemented for compatibility with SNDLIB.
239 * \return Audio rate (48000). */
240 s32
ASND_GetAudioRate();
244 /*! \addtogroup voicefuncs Voice functions
248 // NOTE: I'm keeping this description around because I couldn't fully understand it; if someone else knows exactly what it's doing, they can come around
249 // and make sure the description is correct.
250 /* callback: can be NULL or one callback function is used to implement a double buffer use. When the second buffer is empty, the callback is called sending
251 the voice number as parameter. You can use "void callback(s32 voice)" function to call ASND_AddVoice() and add one voice to the second buffer.
252 NOTE: When callback is fixed the voice never stops and it turn in SND_WAITING status if success one timeout condition.
255 /*! \brief Sets a PCM voice to play.
256 * \details This function stops one previous voice. Use ASND_StatusVoice() to test the status condition.
257 * \note The voices are played in 16-bit stereo, regardless of the source format.<br><br>
259 * \note \a callback is used to implement a double buffer. When the second buffer is empty, the callback function is called with the voice number
260 * as an argument. You can use <tt>void <i>callback</i> (s32 voice)</tt> to call ASND_AddVoice() and add one voice to the second buffer. When the callback
261 * is non-NULL the, the voice never stops and returns SND_WAITING if successful on timeout condition.
262 * \param[in] voice Voice slot to use for this sound; valid values are 0 to (MAX_SND_VOICES-1).
263 * \param[in] format \ref sndsetvoiceformats to use for this sound.
264 * \param[in] pitch Frequency to use, in Hz.
265 * \param[in] delay Delay to wait before playing this voice; value is in milliseconds.
266 * \param[in] snd Buffer containing samples to play back; the buffer <b>must</b> be aligned and padded to 32 bytes!
267 * \param[in] size_snd Size of the buffer samples, in bytes.
268 * \param[in] volume_l \ref voicevol of the left channel; value can be 0 - 255 inclusive.
269 * \param[in] volume_r \ref voicevol of the right channel; value can be 0 - 255 inclusive.
270 * \param[in] callback Optional callback function to use; set to NULL for no callback. See the note above for details.
271 * \return SND_OK or SND_INVALID. */
272 s32
ASND_SetVoice(s32 voice
, s32 format
, s32 pitch
,s32 delay
, void *snd
, s32 size_snd
, s32 volume_l
, s32 volume_r
, ASNDVoiceCallback callback
);
274 /*! \brief Sets a PCM voice to play infinitely.
275 * \note See ASND_SetVoice() for a detailed description, as it is largely identical. */
276 s32
ASND_SetInfiniteVoice(s32 voice
, s32 format
, s32 pitch
,s32 delay
, void *snd
, s32 size_snd
, s32 volume_l
, s32 volume_r
);
278 /*! \brief Adds a PCM voice to play from the second buffer.
279 * \note This function requires a call to ASND_SetVoice() and its subsequent return value to be a status other than SND_UNUSED prior to calling this one.
280 * \param[in] voice Voice slot to attach this buffer to; value must be 0 to (MAX_SND_VOICES-1).
281 * \param[in] snd Buffer containing the samples; it <b>must</b> be aligned and padded to 32 bytes AND have the same sample format as the first buffer.
282 * \param[in] size_snd Size of the buffer samples, in bytes.
283 * \return SND_OK or SND_INVALID; it may also return SND_BUSY if the second buffer is not empty and the voice cannot be added. */
284 s32
ASND_AddVoice(s32 voice
, void *snd
, s32 size_snd
);
286 /*! \brief Stops the selected voice.
287 * \details If the voice is used in song mode, you need to assign the samples with ASND_SetSongSampleVoice() again. In this case, use ANS_PauseSongVoice()
288 * to stop the voice without loss of samples.
289 * \param[in] voice Voice to stop, from 0 to (MAX_SND_VOICES-1).
290 * \return SND_OK or SND_INVALID. */
291 s32
ASND_StopVoice(s32 voice
);
293 /*! \brief Pauses the selected voice.
294 * \param[in] voice Voice to pause, from 0 to (MAX_SND_VOICES-1).
295 * \return SND_OK or SND_INVALID. */
296 s32
ASND_PauseVoice(s32 voice
, s32 pause
);
298 /*! \brief Returns the status of the selected voice.
299 * \param[in] voice Voice slot to get the status from, from 0 to (MAX_SND_VOICES-1).
300 * \return SND_INVALID if invalid, else a value from \ref sndiavretvals. */
301 s32
ASND_StatusVoice(s32 voice
);
303 /*! \brief Returns the first unused voice.
304 * \note Voice 0 is the last possible voice that can be returned. The idea is that this voice is reserved for a MOD/OGG/MP3/etc. player. With this in mind,
305 * you can use this function to determine that the rest of the voices are working if the return value is < 1.
306 * \return SND_INVALID or the first free voice from 0 to (MAX_SND_VOICES-1). */
307 s32
ASND_GetFirstUnusedVoice();
309 /*! \brief Changes the voice pitch in real-time.
310 * \details This function can be used to create audio effects such as Doppler effect emulation.
311 * \param[in] voice Voice to change the pitch of, from 0 to (MAX_SND_VOICES-1).
312 * \return SND_OK or SND_INVALID. */
313 s32
ASND_ChangePitchVoice(s32 voice
, s32 pitch
);
315 /*! \brief Changes the voice volume in real-time.
316 * \details This function can be used to create audio effects like distance attenuation.
317 * \param[in] voice Voice to change the volume of, from 0 to (MAX_SND_VOICES-1).
318 * \param[in] volume_l \ref voicevol to set the left channel to, from 0 to 255.
319 * \param[in] volume_r \ref voicevol to set the right channel to, from 0 to 255.
320 * \return SND_OK or SND_INVALID. */
321 s32
ASND_ChangeVolumeVoice(s32 voice
, s32 volume_l
, s32 volume_r
);
323 /*! \brief Returns the voice tick counter.
324 * \details This value represents the number of ticks since this voice started to play, sans delay time. It uses the same resolution as the internal
325 * sound buffer. For example, if the lib is initialized with INIT_RATE_48000, a return value of 24000 is equal to 0.5 seconds. This value can be used, for
326 * example, to synchronize audio and video.
327 * \note This function does not return error codes.
328 * \param[in] voice Voice to retrieve the counter value from, from 0 to (MAX_SND_VOICES-1).
329 * \return Number of ticks since this voice started playing. */
330 u32
ASND_GetTickCounterVoice(s32 voice
);
332 /*! \brief Returns the voice playback time.
333 * \details This value represents the time, in milliseconds, since this voice started playing, sans delay time. This value can be used, for example, to
334 * synchronize audio and video.
335 * \note This function does not return error codes.
336 * \param[in] voice Voice to retrieve the time value from, from 0 to (MAX_SND_VOICES-1).
337 * \return Amount of time since this voice has started playing. */
338 u32
ASND_GetTimerVoice(s32 voice
);
340 /*! \brief Tests if \a pointer is in use by \a voice as a buffer.
341 * \param[in] voice Voice to test, from 0 to (MAX_SND_VOICES-1).
342 * \param[in] pointer Address to test. This must be the same pointer sent to ASND_AddVoice() or ASND_SetVoice().
343 * \return SND_INVALID if invalid
344 * \return 0 if the pointer is unused
345 * \return 1 if the pointer used as a buffer. */
346 s32
ASND_TestPointer(s32 voice
, void *pointer
);
348 /*! \brief Tests to determine if the \a voice is ready to receive a new buffer sample with ASND_AddVoice().
349 * \details You can use this function to block a reader when double buffering is used. It works similarly to ASND_TestPointer() without needing to pass a
351 * \param[in] voice Voice to test, from 0 to (MAX_SND_VOICES-1).
352 * \return SND_INVALID
353 * \return 0 if voice is NOT ready to receive a new voice.
354 * \return 1 if voice is ready to receive a new voice with ASND_AddVoice(). */
355 s32
ASND_TestVoiceBufferReady(s32 voice
);
359 /*! \addtogroup dspfuncs DSP functions
363 /*! \brief Returns the DSP usage.
364 * \details The value is a percentage of DSP usage.
365 * \return DSP usage, in percent. */
366 u32
ASND_GetDSP_PercentUse();
368 u32
ASND_GetDSP_ProcessTime();