Page 1 of 1

Question about possible ADPCM streaming

Posted: Mon Jul 16, 2012 8:56 pm
by Discostew
If I understand the way Maxmod works, ADPCM cannot be streamed because streaming uses a ring-buffer, which would interfere with how ADPCM audio is played (which is having an initial sample and table index, followed by 4-bit values that contribute to the decoding process to 16-bit samples).

My question is when looping ADPCM audio, is the SAD actually reloaded, or does that value become stored internally? I ask this because if the SAD does get reloaded from that point in memory, would changing that affect the resulting ADPCM audio? If so, then maybe we could get ADPCM streaming working with this idea I have. Instead of having the ADPCM audio as one single entity (with one header + data), make the ADPCM audio split into multiple entities (each with their own header + data), concatenated together in a sequence, and make the length of each equal to the buffer length to be used for the stream? I would assume that Maxmod would have to compensate for that initial sample/index since it isn't the same size as the individual compressed data that follows.

Of course, this type of format would be different from what the normal ADPCM format for the DS is stored as.

Re: Question about possible ADPCM streaming

Posted: Wed Jul 18, 2012 7:08 pm
by Discostew
Well, I decided that if I wanted to see if it were possible, then I'd try it myself. I looked into the IMA-ADPCM format specifically used by Microsoft in their WAVE format, and I found something quite convenient. The format that Microsoft IMA-ADPCM data is stored is based on sequential block chunks, each having a header and data, which exactly matches with the design the NDS works with. If the buffer were the length of these static-sized chunks, then the function that streamed in data could simply copy the data in. So, working with Mono ADPCM streaming, I messed with the maxmod source code, arranged the way the channel is initialized with that format (setting loop point 1 word from beginning as instructed by GBATek, as well as using the chunk size), compiled, and gave it a try.

The result? Well, I can't say if it is truly working, because I'm not getting the same result from both emulators and hardware, the former sounding like it's working better. With the emulator (DeSmuME), I can hear it along with popping and such one would get if timing is not correct for both playback and emulator inconsistencies. On hardware, the audio is extremely faint, full of static, yet I can make out some of the audio. I uploaded my compiled version here on MediaFire (23MB). The audio is Track 15 from MDK2 (4min 4sec length). Pressing B (or do nothing when it is loaded) plays back the 16bit stereo PCM version (20.5MB). Pressing A plays back the IMA-ADPCM mono version (2.58MB). No, the ADPCM version is not fully loaded into RAM. It is streamed just like the PCM version. Again, you can hear it on an emulator, but not really on hardware.

One annoying error that has keep creeping up is "invalid offset, value too big (...)", which if I interpret it correctly, is that it has reached its limit for how much code can exist. I had to comment out some sections that I wouldn't be using at the time (8bit audio, for instance) just so I could keep working on this one part. Is there a way around that?

Re: Question about possible ADPCM streaming

Posted: Thu Jul 19, 2012 5:34 am
by Discostew
An update.

I have stereo ADPCM streaming working. I tweaked the asm code and stream-loading code, so the audio should be a bit more fluid. Clicks and popping that remain are probably due to timing issues when dealing with the format ADPCM is enclosed in ('1' 32-bit header + 'n' 4-bit data samples in sequential blocks instead of just 'n' 8-bit/16-bit data samples). As before, it works to this extend in emulators, but not in hardware. However, after getting stereo adpcm streaming working, I listened in, and it seemed that the volume is just really low. Not sure why it is doing that on hardware. I initially suspected that it could be due to the header being stored and re-used during looping instead of reloaded each loop (as my test audio starts off quiet), but after testing the same audio, and forcing the first couple of block headers to full blast (0x7FFF), the audio started from being soft to initially being loud for a split second before being quiet again. That, plus I would imagine that if it didn't reload and instead re-used what it stored, the audio itself would be garbled, but I could hear the audio as it would be if it were quiet.

Link to newer binary here.