|
|
Line 1: |
Line 1: |
− | ==What is this?==
| + | I was serisoluy at DefCon 5 until I saw this post. |
− | An audio library for the homebrew on Nintendo DS. When adding sound to games may also want to consider [[Thmp3|thmp3]] for mp3 playback, [http://www.devkitpro.org/ maxmod] with .mod/sfx/etc formats, and/or [http://meraman.dip.jp/index.php?NDS_BGMDRV_ENG Meraman's NDS_BGMDRV] which includes a software mml/midi sequencer, synth, and special effects facilities.
| + | |
− | | + | |
− | Features thsound:
| + | |
− | * Playback of 8bit, 16bit pcm, ICM-ADPCM
| + | |
− | * Looping
| + | |
− | * Noise generation
| + | |
− | * Tone generation using the PSG (Square wave, adjustable duty cycle, Equal Temperment tuning)
| + | |
− | * Arm7's audio registers accessible via arm9
| + | |
− | * Adjustable fade out of individual channels
| + | |
− | * Audio sample manager (to simplify playback)
| + | |
− | * Samples loadable from .wav files on nitrofs, fat-fs, etc..
| + | |
− | * Dynamic manipulation of playing samples.. (stopping playing samples, pitch, volume, pan, etc can all be manipulated)
| + | |
− | * Playback channel is selectable
| + | |
− | * Presetable defaults for sample rate, volume, and pan.
| + | |
− | | + | |
− | Todo:
| + | |
− | * Add auto channel selection
| + | |
− | * Make a list of resources used (memory, fifo channels, etc etc)
| + | |
− | | + | |
− | '''Dependencies'''<br>
| + | |
− | This library requires the [[Thfifo|thfifo]] library for inter-processor communications. It also requires libfat and possibly [[Nitrofs|nitrofs]] for loading .wav files.
| + | |
− | | + | |
− | ==Where to get it==
| + | |
− | Currently the sources for this are part of [http://blea.ch/wiki/index.php/Category:LIBTHDS LibThds] and is probably the easiest to use due to its dependence on [[Thfifo]]. The latest version of the source can be downloaded via SVN (see libthds page) or directly from the svn httpd:<br>
| + | |
− | * [http://svn.blea.ch/thdslib/trunk/thdslib/source/shared/include/thsound.h thsound.h] (This file is for both arm7 and arm9 sides)
| + | |
− | * [http://svn.blea.ch/thdslib/trunk/thdslib/source/arm7/source/thaudio7.c thaudio7.c]
| + | |
− | * [http://svn.blea.ch/thdslib/trunk/thdslib/source/arm9/source/thaudio9.c thaudio9.c]
| + | |
− | | + | |
− | Note: [[Thfifo]] is required for interprocessor communications.
| + | |
− | | + | |
− | ==Functions common to both CPU==
| + | |
− | '''thSndInit'''<br>
| + | |
− | This needs to be called at startup on both CPU before any other audio functions in order to allocate memory, and create a fifo channel.
| + | |
− | <source lang="c">
| + | |
− | void thSndInit(void);
| + | |
− | </source>
| + | |
− | | + | |
− | ==Sample loading and management functions==
| + | |
− | Sample management functions are provided to allowing loading of .wav data and to simplify playback by eliminating the need to specify start, length, loop point, sample rate, and format.
| + | |
− | | + | |
− | Creation functions return (or in case of thSampleDestroy take) a pointer to a structure of the thSample_t type. (todo: add macros for returning/manipulating values in this structure)
| + | |
− | | + | |
− | Loading sample via .wav files is prolly the simplest way to add audio to a project. :D
| + | |
− | | + | |
− | '''thSampleLoadWav'''<br>
| + | |
− | Load a sample from .wav file. Supported formats are 8bit mono, 16bit mono, and IMA-ADPCM. Stereo sample support MAY be added later.
| + | |
− | * name - name of file to load
| + | |
− | Returns pointer to newly created sample.
| + | |
− | <source lang="c">
| + | |
− | thSample_t *thSampleLoadWav(const char *name);
| + | |
− | </source>
| + | |
− | | + | |
− | '''thSampleCreate'''<br>
| + | |
− | Create a sample from raw audio data.
| + | |
− | * start - pointer to start of sample in memory
| + | |
− | * len - length of sample (in samples)
| + | |
− | * loopstart - Loop point of sample. in number of samples from start.
| + | |
− | * rate - sample rate in hertz (44100, 11025, etc etc)
| + | |
− | * opts - options. Should include one each of: SNDPCM8, SNDPCM16, SNDADPCM. Additionally may OR on SNDLOOP (or even specify a default volume, pan, but wont get into this yet.. :P)
| + | |
− | Returns Pointer to newly created sample.
| + | |
− | <source lang="c">
| + | |
− | thSample_t *thSampleCreate(void *start, int len, void *loopstart, int rate, u8 opts);
| + | |
− | </source>
| + | |
− | | + | |
− | '''thSampleDestroy'''<br>
| + | |
− | Unloads a sample freeing up any used memory. If it was loaded from .wav file will automagically unload that as well. :p
| + | |
− | <source lang="c">
| + | |
− | void thSampleDestroy(thSample_t *thSample);
| + | |
− | </source>
| + | |
− | | + | |
− | '''Wave loading/playing example'''
| + | |
− | <source lang="c">
| + | |
− | thSample_t *mysample;
| + | |
− | mysample=thSampleLoadWav("nitro:/test.wav");
| + | |
− | thSndPlaySample(4, mysample, 127, 64); //thSndPlaySample(char chan, thSample_t *sample, char vol, char pan)
| + | |
− | </source>
| + | |
− | | + | |
− | ==General Sound Functions==
| + | |
− | '''thPlayDefaults'''<br>
| + | |
− | Sets default sample playback options.
| + | |
− | <source lang="c">
| + | |
− | void thPlayDefaults(int rate, char level, char pan, u32 flags);
| + | |
− | </source>
| + | |
− | | + | |
− | '''thSndPlaySample'''<br>
| + | |
− | Starts playing a previously loaded sample.
| + | |
− | * chan - channel to use for playback
| + | |
− | * sample - previously loaded sample
| + | |
− | * vol - playback volume (0 to 127)
| + | |
− | * pan - playback pan (0 to 127, 0 = left, 127 = right, 64 = center)
| + | |
− | <source lang="c">
| + | |
− | void thSndPlaySample(char chan, thSample_t *sample, char vol, char pan);
| + | |
− | </source>
| + | |
− | | + | |
− | '''thSndPlaySampleRate'''<br>
| + | |
− | Starts playing a previously loaded sample at specified rate.
| + | |
− | * chan - channel to use for playback
| + | |
− | * sample - previously loaded sample
| + | |
− | * rate - sample playback rate (in hz)
| + | |
− | * vol - playback volume (0 to 127)
| + | |
− | * pan - playback pan (0 to 127, 0 = left, 127 = right, 64 = center)
| + | |
− | <source lang="c">
| + | |
− | void thSndPlaySampleRate(char chan, thSample_t *sample, u16 rate, char vol, char pan);
| + | |
− | </source>
| + | |
− | | + | |
− | '''thSndPlayRaw'''<br>
| + | |
− | Plays a sound in raw format from memory on the specified channel.
| + | |
− | * chan - channel to use for playback (0 to 15)
| + | |
− | * start - pointer to start of audio data in memory
| + | |
− | * len - length of sample (in samples)
| + | |
− | * vol - playback volume (0 to 127)
| + | |
− | * pan - playback pan (0 to 127, 0 = left, 127 = right, 64 = center)
| + | |
− | * loopstart - position to start looping sound (in samples)
| + | |
− | * opts - options (such as SNDPCM16, SNDPCM8, etc... see options sections)
| + | |
− | <source lang="c">
| + | |
− | void thSndPlayRaw(char chan, void *start, int len, int rate, char vol, char pan, u32 loopstart, u32 opts);
| + | |
− | </source>
| + | |
− | | + | |
− | '''thSndRegDirect'''<br>
| + | |
− | Direct manipulation of the arm7's audio registers from the arm9
| + | |
− | * chan - channel to manipulate (0 to 15)
| + | |
− | * start - start register
| + | |
− | * len - length register
| + | |
− | * rate - rate register
| + | |
− | * loopstart - loopstart register
| + | |
− | * opt - channel's CR register
| + | |
− | <source lang="c">
| + | |
− | void thSndRegDirect(char chan, u32 start, int len, int rate, u32 loopstart, u32 opts);
| + | |
− | </source>
| + | |
− | | + | |
− | '''thSndDefPlaySample'''<br>
| + | |
− | Playback a sample use default volume and pan settings
| + | |
− | * chan - channel to manipulate (0 to 15)
| + | |
− | * sample - pointer to previously loaded audio sample
| + | |
− | <source lang="c">
| + | |
− | void thSndDefPlaySample(char chan, thSample_t *sample);
| + | |
− | </source>
| + | |
− | | + | |
− | '''thSndDefPlayRaw'''<br>
| + | |
− | Playback a sample using default volume, pan, and rate settings
| + | |
− | * chan - channel to manipulate (0 to 15)
| + | |
− | * start - pointer to start of audio data
| + | |
− | * len - length of audio data (in samples)
| + | |
− | <source lang="c">
| + | |
− | void thSndDefPlayRaw(char chan, void *start, int len);
| + | |
− | </source>
| + | |
− | | + | |
− | '''thSndPlayNote'''<br>
| + | |
− | Plays a note on the specified channel via the PSG. Note is a square wave with adjustable duty cycle when using channels 8 thru 13, and noise when using channels 14 or 15.
| + | |
− | * chan - channel to play note (8 to 15 only!)
| + | |
− | * note - note to play 0 = c, 1 = c#, 2 = d, 3 = d#, 4 = e, 5 = f, etc etc up to 64 or so (range depends on tuning)
| + | |
− | * duty - duty cycle of PSG (0 to 7, use 4 if in doubt ?_?)
| + | |
− | * duration - fade out time, in milliseconds * 1000, for instance 1000 = 1 second, 500 = .5 seconds, etc. 0 = no fadeout note must be stopped manually with thSndStop().
| + | |
− | * vol - playback volume (0 to 127)
| + | |
− | * pan - playback pan (0 to 127, 0 = left, 127 = right, 64 = center)
| + | |
− | <source lang="c">
| + | |
− | void thSndPlayNote(char chan, char note, char duty, u16 duration, char vol, char pan);
| + | |
− | </source>
| + | |
− | | + | |
− | '''thSndStop'''<br>
| + | |
− | Immediately stops playing sample, note, noise, or raw data the specified channel.
| + | |
− | * chan - channel to stop
| + | |
− | <source lang="c">
| + | |
− | void thSndStop(char chan);
| + | |
− | </source>
| + | |
− | | + | |
− | ==Changing Active Parameters==
| + | |
− | These functions change various attributes after sound has already began playing.
| + | |
− | | + | |
− | '''thSndSetVol'''<br>
| + | |
− | Change channel's volume.
| + | |
− | * chan - channel to change (0-15)
| + | |
− | * vol - playback volume (0 to 127)
| + | |
− | <source lang="c">
| + | |
− | void thSndSetVol(char chan, char vol);
| + | |
− | </source>
| + | |
− | | + | |
− | '''thSndSetPan'''<br>
| + | |
− | Change channel's Pan..
| + | |
− | * chan - channel to change (0-15)
| + | |
− | * pan - playback pan (0 to 127, 0 = left, 127 = right, 64 = center)
| + | |
− | <source lang="c">
| + | |
− | void thSndSetPan(char chan, char pan);
| + | |
− | </source>
| + | |
− | | + | |
− | '''thSndSetRate'''<br>
| + | |
− | Change channel's sample rate. Usefull for special effects! :p
| + | |
− | * chan - channel to change (0-15)
| + | |
− | * rate - new channel frequency (in hertz)
| + | |
− | <source lang="c">
| + | |
− | void thSndSetRate(char chan, u32 rate);
| + | |
− | </source>
| + | |
− | | + | |
− | Change PSG's duty cycle.
| + | |
− | '''thSndSetDuty'''<br>
| + | |
− | * chan - channel to play note (8 to 13 only!)
| + | |
− | * duty - duty cycle of PSG (0 to 7, use 4 if in doubt ?_?)
| + | |
− | <source lang="c">
| + | |
− | void thSndSetDuty(char chan, char duty);
| + | |
− | </source>
| + | |
− | | + | |
− | '''thSndFade'''<br>
| + | |
− | Initiate a fadeout on specified channel. Useful for fading out repeating wavforms, mp3s, or even can be used with PSG note generation for rudamentary synth effects. Once volume reaches 0 audio playback is stopped on specified channel
| + | |
− | * chan - channel to change (0-15)
| + | |
− | * faderate - time to take fading out. (ms * 1000) for instance 1000 = 1 second, 2000 = 2 seconds, 500 = .5 seconds, etc.. up to 65535 :D
| + | |
− | <source lang="c">
| + | |
− | void thSndFade(char chan, u16 faderate);
| + | |
− | </source>
| + | |
− | | + | |
− | [[Category:NDS]]
| + | |
− | [[Category:C]]
| + | |
− | [[Category:LIBTHDS]]
| + | |
I was serisoluy at DefCon 5 until I saw this post.