#42455 - b0on - Wed May 11, 2005 7:26 pm
1) how do i load sound data?
2) what format can be loaded?
in ndslib
#42488 - josath - Thu May 12, 2005 12:49 am
http://drunkencoders.com/documents/DS/ndslib.htm#_Sound
One thing...in current ndslib, the values of SOUND_ENABLE and SCHANNEL_ENABLE are swapped. Don't know if this has been fixed. If sound isn't working, try swapping them.
#42509 - b0on - Thu May 12, 2005 6:44 am
thanks josath, but how do i load/get testwavdata?
#44603 - Herve13 - Fri Jun 03, 2005 12:50 pm
I've questions on soud too.
Is it possible to play music in loop ? Does it work perfectly ?
Is it possible to play a soudn effects on a music, or does it stop the background music ?
thanks in advance
herve
#44606 - Pacifist - Fri Jun 03, 2005 3:45 pm
there are 16 channels of sound so you can play up to 16 sounds (including music) at the same time.
You can repeat sounds and pan them between speakers.
A quick note: the version of the ndslib docs I have are ever so slightly faulty. The code in the docs miss the SOUND_ONE_SHOT flag when it loads a sound. Without it you'll start playing uninitialized memory.
Code: |
SCHANNEL_CR(0) = SOUND_ENABLE | SOUND_VOL(0x3F) | SOUND_ONE_SHOT;
|
Also, to answer b0on's question, which he has already probably answered for himself, you can download apps in the gba-dev tools section to convert from wav to bin (or c header files or whatever's your pleasure).
#44650 - Herve13 - Fri Jun 03, 2005 10:22 pm
thanks for your answers !
#44728 - Herve13 - Sat Jun 04, 2005 5:58 pm
Pacifist, can you send me please some (working) examples ?
#44733 - Pacifist - Sat Jun 04, 2005 7:14 pm
The current state of my code isn't really conducive to a simple example.
It's really not that hard. Just take the code from the ndslib docs:
Code: |
powerON(POWER_SOUND);
SOUND_CR = SCHANNEL_ENABLE | SOUND_VOL(0x3F);
SCHANNEL_TIMER(0) = SOUND_FREQ(22050);
SCHANNEL_SOURCE(0) = (u32)GETRAW( test_bin );
SCHANNEL_LENGTH(0) =GETRAWSIZE( test_bin )>>2;
SCHANNEL_CR(0) = SOUND_ENABLE | SOUND_VOL(0x3F) | SOUND_ONE_SHOT;
|
then go to the gbadev tools section and download wav2gba.
download a wav file.
note the wav must be in PCM format for wav2gba to work (right click the wav and check the 'properties' tab to find out what format it's in)
Use wav2gba to get your bin file. And then you just put the bin in your resources dir and include the resulting c header file.
#44740 - Herve13 - Sat Jun 04, 2005 9:50 pm
I didn't understand how to use wav2gba to get a c file
so I used wav2gbac toi get a c file
I put your code in arm7 side, but I don't success to heard something.
can you help me more than that please ?
I'm completely lost
(it's for OMalone :-))
#44742 - Maverick - Sat Jun 04, 2005 10:32 pm
Try this one:
http://www.double.co.nz/nintendo_ds/nds_develop4.html
It is a very good tutorial and will give you the tools you need.
#44743 - Herve13 - Sat Jun 04, 2005 10:38 pm
thanks but no, because it used libnds, and I don't !
#44757 - doublec - Sun Jun 05, 2005 2:18 am
The routines to use the sound are not really libnds specific. What toolkit are you using? The same basic code should work.
#44793 - dovoto - Sun Jun 05, 2005 10:04 am
I added a sound example to ndslib. It is in ndslib/examples/arm7/soundPlay. This might help a few people get sound up and running.
www.drunkencoders.com/tools/ds/ndslib.zip
_________________
www.drunkencoders.com
#44879 - Herve13 - Mon Jun 06, 2005 2:35 pm
thanks dovoto, everything works now : thanks a lot !
Is there a way to stop playing a sound ?
For now I just do a SCHANNEL_CR(channel) = 0;
is there a better way to do this ?
#45345 - Herve13 - Thu Jun 09, 2005 9:26 pm
Up !
I would like to stop playing a sound immediately now.
Because I've a background music (so, that plays continously) for one screen, and another one for another screen (same behaviour). When I go from one to another screen, I want
1.stop first background music
2.start the 2nd one
I'm able to start the 2nd one, but the first one doesn't stop immediately (it stops after a loop)
Does anyone tried this before ?
Thanks in advance.
I really need that feature.
Herve
#45346 - DekuTree64 - Thu Jun 09, 2005 9:31 pm
Ya, bit31 is the enable/disable bit, so clearing that is what you want. Just zeroing the whole register like you mentioned before is the easiest way to clear it, so do that.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku
#45347 - Herve13 - Thu Jun 09, 2005 9:33 pm
but it doesn't stop the sound immediately !!!
#45349 - DekuTree64 - Thu Jun 09, 2005 9:42 pm
It should... are you sending a command of some sort from the ARM9 to stop it? If you're only checking for commands on VBlank, then that would be your delay.
That would be what the IPC interrupt register talked about in my MOD player thread would help with, because you could interrupt ARM7 and tell it to stop immediately, and then safely overwrite that music data with the new song.
Unfortunately Dovoto seems to have lost his defines for it and hasn't made new ones yet...
If that's not your problem, would you explain exactly how your sound system works?
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku
#45350 - Herve13 - Thu Jun 09, 2005 10:00 pm
I'm exactly using sound system of "soundplay" example delivered in ndslib.
So, I try to stop arm7 from arm9.
But I didn't success.
Sorry, but I don't really understand what you told me with your "IPC interrupt register".
Else, Dovot told me that there is a way to interrupt arm7 directly, but didn't tell me how, and I didn't find anything by myself...
in all cases, thanks for helping.
If someone has some code that works, please put it here.
#45353 - doublec - Thu Jun 09, 2005 10:46 pm
Speaking of that interrupt, I notice the DSLinux project is using a 'FIFO' to pass data between the ARM9 and ARM7:
Code: |
#define REG_IPCFIFOSEND (*(volatile u32*) 0x04000188)
#define REG_IPCFIFORECV (*(volatile u32*) 0x04100000)
#define REG_IPCFIFOCNT (*(volatile u16*) 0x04000184)
#define IRQ_SEND 17 /* SEND FIFO empty */
#define IRQ_RECV 18 /* RECV FIFO non empty */
|
Is there any information about the or their usage (Apart from the DSLinux source code)?
#45354 - doublec - Thu Jun 09, 2005 11:01 pm
Herve13, can you post the code you are using to stop the sound? If you are trying to stop it by setting the sound registers in the ARM9 it won't work. You'll need to do that from the ARM7.
#45381 - doublec - Fri Jun 10, 2005 1:51 am
Nevermind about the Fifo details. Got pointed to dstek on IRC:
http://neimod.com/dstek.html
#45394 - Lino - Fri Jun 10, 2005 4:34 am
when does the cpu receive the irq 17? When has it stopped sending?
#45436 - dovoto - Fri Jun 10, 2005 6:06 pm
My notes disagree slightly with dstek for the sync register. Here are my IPC defines for sync
Code: |
// Synchronization register
#define IPC_SYNC (*(vuint16*)0x04000180)
#define IPC_SYNC_IRQ_ENABLE (1<<14)
#define IPC_SYNC_IRQ_REQUEST (1<<13)
#define IPC_SEND_COMMAND(n) ((IPC_SYNC & 0xF0FF) | (((n) & 0xF) << 8) | IPC_SYNC_IRQ_REQUEST)
#ifdef ARM7
#define IPC_GET_COMMAND (IPC_SYNC & 0xF)
#endif
#ifdef ARM9
#define IPC_GET_COMMAND ((IPC_SYNC & 0xF0) >> 4)
|
To use is rather simple. "Recieving" processor refers to the one you would like to send commands to, and "sending" the one you are sending commands from. You can send and recieve from either or both processors.:
1)Enable interupts on the recieving processor.
2)Un-mask the sync interupt (set bit 16 of IE) on the recieving processor.
3)Enable the interupt on the recieving processor (IPC_SYNC = IPC_SYNC_IRQ_ENABLE)
4)Install the irq handler for recieving the the command.
5)Send the command from the sending processor (IPC_SEND_COMMAND(n))
6)This should cause an interupt to occure on the recieving processor and you can grab the sent command with IPC_GET_COMMAND
These are limited to 4 bit commands. To send actual chunks of data the fifo would be a better option. But for a sound engine were you only have a limited number of commands to send this works great. These defines are not in the current cvs as I lost my origals and these have not quite been tested yet (the names may change slightly). I will try to get the cvs/zip updated this evening with an example.
_________________
www.drunkencoders.com
#45452 - Herve13 - Fri Jun 10, 2005 7:54 pm
nice to read this dovoto ;-)
thanks in advance for your example
#45471 - dovoto - Fri Jun 10, 2005 11:19 pm
Okay here are the final defines (the obove had a few errors ...thats what I get for working from memory)
Code: |
//////////////////////////////////////////////////////////////////////
// Synchronization register
#define IPC_SYNC (*(vuint16*)0x04000180)
#define IPC_SYNC_IRQ_ENABLE (1<<14)
#define IPC_SYNC_IRQ_REQUEST (1<<13)
#define IPC_SYNC_SEND_COMMAND(n) (IPC_SYNC = (IPC_SYNC & 0xF0FF) | (((n) & 0xF) << 8) | IPC_SYNC_IRQ_REQUEST)
#define IPC_SYNC_GET_COMMAND ((IPC_SYNC & 0xF) )
|
This code and the example were uploaded to cvs as well as to the zip file maintained on my site. The example sets up recieve irq on both processors. It sends a comand from arm9 to arm7 each vblank. The arm7 reads the comand then sends it back to the arm9 and the arm9 prints it. This may be helpfull..may not :)
Arm9 code
Code: |
void irqVblank(void)
{
static int heartbeat = 0;
heartbeat++;
//increment about once per second
IPC_SYNC_SEND_COMMAND(heartbeat >> 6);
IF = IRQ_VBLANK;
}
void irqRecieve(void)
{
consolePrintf("Command Recieved: %X\n", IPC_SYNC_GET_COMMAND);
IF = IRQ_SYNC;
}
int main(void)
{
videoSetMode(0);
videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);
vramSetBankC(VRAM_C_SUB_BG);
SUB_BG0_CR = BG_MAP_BASE(31);
BG_PALETTE_SUB[255] = RGB15(31,31,31);//by default font will be rendered with color 255
consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);
irqInitHandler(irqDefaultHandler);
irqSet(IRQ_VBLANK, irqVblank);
irqSet(IRQ_SYNC, irqRecieve);
IPC_SYNC = IPC_SYNC_IRQ_ENABLE;
while(1){}
return 0;
}
|
And the arm7 code
Code: |
void irqRecieve(void)
{
//just send it back
IPC_SYNC_SEND_COMMAND(IPC_SYNC_GET_COMMAND);
IF = IRQ_SYNC;
}
int main(int argc, char ** argv)
{
// Reset the clock if needed
rtcReset();
//enable sound
SOUND_CR = SCHANNEL_ENABLE | SOUND_VOL(0x7F);
IPC->soundData = 0;
// Set up the interrupt handler
irqInitHandler(irqDefaultHandler);
irqSet(IRQ_VBLANK, InterruptHandler);
irqSet(IRQ_SYNC, irqRecieve);
IPC_SYNC = IPC_SYNC_IRQ_ENABLE;
// Keep the ARM7 out of main RAM
while (1);
return 0;
}
|
The full source is under ndslib/examples/ipc
_________________
www.drunkencoders.com
#45493 - tepples - Sat Jun 11, 2005 5:38 am
dovoto wrote: |
These are limited to 4 bit commands. To send actual chunks of data the fifo would be a better option. But for a sound engine were you only have a limited number of commands to send this works great. |
But as you move to a more sophisticated sound engine, you may have to put the commands in the FIFO as well, using MIDI or a similar protocol, and collapse the IPC commands to just send() and recv().
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#45500 - DekuTree64 - Sat Jun 11, 2005 6:20 am
tepples wrote: |
dovoto wrote: | These are limited to 4 bit commands. To send actual chunks of data the fifo would be a better option. But for a sound engine were you only have a limited number of commands to send this works great. |
But as you move to a more sophisticated sound engine, you may have to put the commands in the FIFO as well, using MIDI or a similar protocol, and collapse the IPC commands to just send() and recv(). |
Yeah, my sound commands are up to 8 bytes. I'd planned on keeping the actual command buffer just like it is, and only use the register to tell ARM7 to execute all the commands immediately, instead of having to wait for the next VBlank.
I could also do it with the FIFO, but I like the idea of being able to queue up a bunch of commands, and then execute them all at once. Then there's only one interrupt, and ARM9 has the option of waiting for a reply from ARM7 to say that they've all been processed, or to just trigger the IRQ and call it a done deal, leaving ARM7 to process the commands while ARM9 does other things.
And Dovoto, thanks a lot for your work! I'll see if I can play with it some this weekend, tho things have been a bit hectic at work so I don't know if I'll get to it :)
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku
#45518 - Herve13 - Sat Jun 11, 2005 3:03 pm
thanks for your help.
but it's too complex for me this.
I d'ont know how to use it to stop soudn immediately on a channel.
could someone explain it to me please ?
soory, I'm a newbie !
#45594 - headspin - Sun Jun 12, 2005 2:52 pm
Thanks for the example dovoto, can you please tell me how I can find out when a sample has stopped playing in the main loop?
I need to play a few samples in succession, so I need to know when sound has finished playing.
Code: |
while(1)
{
scanKeys();
//move the cursor
consolePrintSet(0,10);
consolePrintf("Touch x = %04X\n", IPC->touchX);
consolePrintf("Touch y = %04X\n", IPC->touchY);
if(keysDown() & KEY_A) playGenericSound(AA, (u32)AA_size);
if(keysDown() & KEY_B) playGenericSound(AE, (u32)AE_size);
if(keysDown() & KEY_X) playGenericSound(AH, (u32)AH_size);
// Need to check if sound has finished playing
waitForVBlank();
} |
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game
#45615 - DekuTree64 - Sun Jun 12, 2005 8:02 pm
The enable bit in the channel control gets cleared automatically when the sample ends (in one-shot mode), so you'll need a way to check that.
Maybe make a command you can send with the IPC_SYNC to say "has this channel ended?", and then ARM7 checks it and sends a command back with true or false.
Or it might be even easier to write a back-to-back sample player thing on ARM7 itself.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku
#45621 - headspin - Sun Jun 12, 2005 9:20 pm
Thanks DekuTree, but a little more clarification would be great.
I know I need ARM9 to find out when the channel has finished.
if(SCHANNEL_CR(n) & SOUND_ENABLE) == 0) // finished
..should achieve that. But how can I set up a function to store this true/false, and how can I get ARM9 to read this using IPC so that ARM7 will relay the true/false state. Sorry I've just started coding DS today sheesh.. GBA seems so much nicer to code now ;)
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game
#45640 - headspin - Mon Jun 13, 2005 6:13 am