Streaming sound on NDS
Posted: Mon Feb 15, 2010 6:49 pm
I'm working on porting some code to the NDS which plays sounds into an already-mixed buffer, but I'm getting sound/buffer glitches in playback in both various emulators and the actual hardware. I'm actually fairly knowledgable about sound and playback, and I've successfully written code to do streaming via DMA on the GBA using either the VBlank interrupt or a timer -- but I've been hacking at this for almost two days now and can't quite figure out what I'm doing wrong.
Since the NDS's VBlank timings are different than the GBA, I'm not using the VBlank method but using a timer for now (I would like to get this to work using the VBlank as well, but that can wait until later).
Basically I have two 2K buffers -- one for the left channel, and one for the right -- but for simplicity's sake I'm just trying to get mono working for now. I call soundPlaySample() and have it loop over the entire 2K block. I then set up a timer at Hz=(sampleRate/(bufSize >> 1)), where in this case if I'm playing at 16Khz, playback would interrupt every 1024 samples, or half the buffer size. In the timer interrupt, I simply update the 1K half portion that is not being played, and flip the index pointer. And yes, I made sure I wrote the data into uncached memory.
It's really quite simple, and I don't understand why I'm getting glitches in my playback.
I've even went so far as to generate a sine wave and sample the actual output from a real NDS, looking at the result, but aside from noticing that there are 8 glitches per second, it hasn't helped me figure out what's causing the problem.
I have also tried doubling and halving the timer rate just to see if I might have a bug somewhere else, but neither made it sound correct. Actually it made it sound worse, so I don't think my timer code is broken. I also have already tested the timers by setting up a 1Hz timer to count seconds, and it is working properly.
I'm completely at a loss at this point, and would be willing to post code/youtube video/etc. if desired. Any help or ideas at this point would be greatly appreciated.
Since the NDS's VBlank timings are different than the GBA, I'm not using the VBlank method but using a timer for now (I would like to get this to work using the VBlank as well, but that can wait until later).
Basically I have two 2K buffers -- one for the left channel, and one for the right -- but for simplicity's sake I'm just trying to get mono working for now. I call soundPlaySample() and have it loop over the entire 2K block. I then set up a timer at Hz=(sampleRate/(bufSize >> 1)), where in this case if I'm playing at 16Khz, playback would interrupt every 1024 samples, or half the buffer size. In the timer interrupt, I simply update the 1K half portion that is not being played, and flip the index pointer. And yes, I made sure I wrote the data into uncached memory.
It's really quite simple, and I don't understand why I'm getting glitches in my playback.
I've even went so far as to generate a sine wave and sample the actual output from a real NDS, looking at the result, but aside from noticing that there are 8 glitches per second, it hasn't helped me figure out what's causing the problem.
I have also tried doubling and halving the timer rate just to see if I might have a bug somewhere else, but neither made it sound correct. Actually it made it sound worse, so I don't think my timer code is broken. I also have already tested the timers by setting up a 1Hz timer to count seconds, and it is working properly.
I'm completely at a loss at this point, and would be willing to post code/youtube video/etc. if desired. Any help or ideas at this point would be greatly appreciated.