gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Audio streamer v2.0.1 /w source

#165392 - DiscoStew - Fri Dec 19, 2008 7:22 am

Here it is. Version 2. The decoder has been converted into assembly, and processing time have been reduced, with stereo by about half of prior c++ implementations. Still only regular PCM and IMA-ADPCM formats. eKid allowed me to use his decoder/player template from his ms-adpcm decoder, so credit to him on that, but I made some extra adjustments with it. The interface is therefore different from the prior version, so update your code.

http://www.mediafire.com/?dubioj42m4e

Decoding times (not including read times):

22kHz Mono - 4 scanlines decode (~1.5% CPU)
22kHz Stereo - 6-7 scanlines decode (~2.5% CPU)
44Khz Stereo - 13 scanlines decode (~5% CPU)

NOTE:
Decoder supports both manual and auto mode, but auto mode sometimes suffers from audio cutoff due to a bug in Maxmod. eKid fixed this issue in the newest Maxmod svn, so unless you've compiled the newest svn yourself (or until it is compiled into the new build), just stick with the manual mode.

Latest changes/fixes:
    Fixed pcm loop streaming


EDIT:

3/23/10 - Re-uploaded to MediaFire with link fixed.
_________________
DS - It's all about DiscoStew


Last edited by DiscoStew on Wed Mar 31, 2010 6:50 pm; edited 9 times in total

#165404 - a128 - Fri Dec 19, 2008 5:55 pm

thanks. but with source the community would kiss you :-)

Last edited by a128 on Sat Dec 20, 2008 9:25 am; edited 1 time in total

#165406 - DiscoStew - Fri Dec 19, 2008 6:48 pm

I am planning to release the code, but first, I need to add a lot of comments as to how it works, because right now, it practically has none, and some of the optimizations to the ADPCM decoder look rather odd without them.

EDIT:

Commenting of the streaming code is done, but not for the directory code that allows scanning of folders and files. Should get it all done by tonight or tomorrow morning.
_________________
DS - It's all about DiscoStew

#165413 - DiscoStew - Fri Dec 19, 2008 9:56 pm

Ok, I did a good amount of commenting on the stream portion, and just a little with the directory stuff, but it should all be there for people to tinker with. The main focus of this whole thing was the audio streaming.

Because of a few problems related to using the filesystem with both the audio playback and scanning directories, I locked out scanning until the user stops playback. If someone else has a better way to do this (or can get both to work much better together), I'd appreciate your input.
_________________
DS - It's all about DiscoStew

#165419 - JYC376 - Fri Dec 19, 2008 11:46 pm

DiscoStew wrote:
Ok, I did a good amount of commenting on the stream portion, and just a little with the directory stuff, but it should all be there for people to tinker with. The main focus of this whole thing was the audio streaming.

Because of a few problems related to using the filesystem with both the audio playback and scanning directories, I locked out scanning until the user stops playback. If someone else has a better way to do this (or can get both to work much better together), I'd appreciate your input.


Do NOT use the POSIX opendir...There's some problems in libfat, with that. Use diropen instead: http://chishm.drunkencoders.com/libfat/

Thanks for the streaming, though! Came just in time for my project =)

#165422 - DiscoStew - Sat Dec 20, 2008 12:19 am

JYC376 wrote:
DiscoStew wrote:
Ok, I did a good amount of commenting on the stream portion, and just a little with the directory stuff, but it should all be there for people to tinker with. The main focus of this whole thing was the audio streaming.

Because of a few problems related to using the filesystem with both the audio playback and scanning directories, I locked out scanning until the user stops playback. If someone else has a better way to do this (or can get both to work much better together), I'd appreciate your input.


Do NOT use the POSIX opendir...There's some problems in libfat, with that. Use diropen instead: http://chishm.drunkencoders.com/libfat/

Thanks for the streaming, though! Came just in time for my project =)


Interesting. Perhaps the libfat example in the toolchain should be updated to reflect this as well, because I started the directory code with that example as a template, and it had opendir in there instead of diropen. I'll get to uploading a fixed version of the project tonight.
_________________
DS - It's all about DiscoStew

#165424 - wintermute - Sat Dec 20, 2008 2:04 am

JYC376 wrote:


Do NOT use the POSIX opendir...There's some problems in libfat, with that. Use diropen instead: http://chishm.drunkencoders.com/libfat/



what kind of problems?

hint: if you found a bug, use the tracker on SF and report it. Please don't just post random messages in forums telling people not to use stuff.

http://sourceforge.net/tracker2/?group_id=114505&atid=668551
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#165425 - wintermute - Sat Dec 20, 2008 2:09 am

DiscoStew wrote:

I only have 2 formats available for playback atm, one being uncompressed PCM, and the other is IMA-ADPCM, which is software decompressed unfortunately, as the hardware limitation screws over streaming it that way.


Not to rain on your parade here or anything but I'm pretty sure eKid has IMA-ADPCM decoding built into maxmod somewhere. I know he was working on it prior to release but I'm not sure if the interface was exposed yet.


Quote:

with the way I did the simple interface, the audio would bleep and freeze while scanning the files and such, so I locked out that until the user stops the audio playback.


Are you attempting file IO in interrupts, cos that *really* isn't going to work.

As for releasing source, get eKid to check it over & we can maybe shove it in the official example set, if you're willing.
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#165428 - JYC376 - Sat Dec 20, 2008 2:27 am

wintermute wrote:
JYC376 wrote:


Do NOT use the POSIX opendir...There's some problems in libfat, with that. Use diropen instead: http://chishm.drunkencoders.com/libfat/



what kind of problems?

hint: if you found a bug, use the tracker on SF and report it. Please don't just post random messages in forums telling people not to use stuff.

http://sourceforge.net/tracker2/?group_id=114505&atid=668551


Completely no idea...Ask chishm: http://chishm.drunkencoders.com/libfat/

Quote:
Directory functions do not follow POSIX standards. Custom functions are used for various reasons.


Last edited by JYC376 on Sat Dec 20, 2008 2:29 am; edited 1 time in total

#165429 - wintermute - Sat Dec 20, 2008 2:29 am

JYC376 wrote:


Completely no idea...Ask chishm: http://chishm.drunkencoders.com/libfat/


Then don't make assumptions based on old web pages :p

opendir wasn't available on the DS when that page was written. It is now.
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#165430 - JYC376 - Sat Dec 20, 2008 2:30 am

wintermute wrote:
JYC376 wrote:


Completely no idea...Ask chishm: http://chishm.drunkencoders.com/libfat/


Then don't make assumptions based on old web pages :p

opendir wasn't available on the DS when that page was written. It is now.


Oh, serious?! Awesome.

#165434 - DiscoStew - Sat Dec 20, 2008 3:26 am

wintermute wrote:
Not to rain on your parade here or anything but I'm pretty sure eKid has IMA-ADPCM decoding built into maxmod somewhere. I know he was working on it prior to release but I'm not sure if the interface was exposed yet.

He posted here about it with a test program for us to try, but I don't think that was related to streaming, but with the sequenced music. He commented out the two ADPCM enums in the mm_types header, because "adpcm streaming is not supported by the ds hardware (the loop point data gets recorded so ring buffers are not possible)". I believe that the initial sample and step index are kept internally when a channel "activates", so even if you got everything working, every block of data after the first would be corrupted because each block has it's own initial sample and step index that may not be the same as with the first block. Because of this, I wanted to try it myself with external decoding, which is how this little program came about.


Quote:
Are you attempting file IO in interrupts, cos that *really* isn't going to work.

As for releasing source, get eKid to check it over & we can maybe shove it in the official example set, if you're willing.

I haven't had a lot of exposure with file IO and interrupts, so this was one way to get my hands dirty. The problem with the audio freezing isn't as bad now because of moving mmStreamUpdate() into a function that gets called via interrupt once per frame, whereas before, it was still left in the infinite loop of the main function, sharing a place with my other crap that would take quite a few frames to finish. There is still some freezing, and if anyone would like to share how to prevent that, then I'm all ears.

By all means though, if there is anything useful in the source I posted, then grab what you want.
_________________
DS - It's all about DiscoStew

#165465 - eKid - Mon Dec 22, 2008 8:39 am

I was working on an MS-ADPCM decoder, right now it works OK at about 9 scanlines of cpu usage for 32khz stereo decoding (but I haven't tested when it reads data from the cart). I'm not really sure what to do with it yet... I was thinking maybe it could be part of a lib that supports multiple wav formats for streaming, or just add support in the maxmod streaming code.

#165481 - DiscoStew - Mon Dec 22, 2008 8:40 pm

Updated the audio streamer. Max allowable format for IMA-ADPCM playback (44kHz stereo) went from 22% CPU usage to 15% CPU usage. Other IMA-ADPCM formats have scaled down as well.

eKid wrote:
I was working on an MS-ADPCM decoder, right now it works OK at about 9 scanlines of cpu usage for 32khz stereo decoding (but I haven't tested when it reads data from the cart). I'm not really sure what to do with it yet... I was thinking maybe it could be part of a lib that supports multiple wav formats for streaming, or just add support in the maxmod streaming code.


Well, that's much better than what I would be getting with IMA-ADPCM decoding at 32kHz stereo. Are you using Assembly or C/C++ for that?
_________________
DS - It's all about DiscoStew

#165495 - eKid - Tue Dec 23, 2008 4:47 am

Before, everything was a c++ class and the load was like 24 scanlines, I converted the main decoding routine to asm and it dropped down to 9.

#166395 - hacker013 - Sat Feb 07, 2009 9:56 am

can you please release the source?
_________________
Website / Blog

Let the nds be with you.

#166451 - Odorules - Sun Feb 08, 2009 11:53 am

The Discotew's code is very good but there is a small glitch when the music starts :(

#166478 - DiscoStew - Sun Feb 08, 2009 7:15 pm

On No$GBA, the audio can sound crappy when just starting (must be a timing issue), but on hardware, I haven't been able to reproduce that same glitch.
_________________
DS - It's all about DiscoStew

#166484 - hacker013 - Sun Feb 08, 2009 8:18 pm

Odorules wrote:
The Discotew's code is very good but there is a small glitch when the music starts :(


I have that problem on the hardware
_________________
Website / Blog

Let the nds be with you.

#166486 - Odorules - Sun Feb 08, 2009 8:25 pm

Me too.

#166511 - DiscoStew - Mon Feb 09, 2009 10:04 am

I was given a little info about what problem people were experiencing, and it wasn't the problem I thought it was originally (which was possible static when starting the audio on an emulator). The two might be linked though, but nonetheless, when I have time this week, I'll look over it and see if I can do something about it.
_________________
DS - It's all about DiscoStew

#166543 - hacker013 - Mon Feb 09, 2009 5:18 pm

thx :)
_________________
Website / Blog

Let the nds be with you.

#166573 - DiscoStew - Mon Feb 09, 2009 11:09 pm

I quick question to all that are having this bug with it cutting off some audio when it first starts playing.

How are you all calling mmStreamUpdate(), or is it set for auto-mode? Also, was there any editing done to the code when used in your own projects?

As the code stands unaltered in form, it seems to play the audio just fine, but when I swapped these two lines in STREAM_PlayFile().....
Code:
mmStreamOpen( &Stream_Mystream );
Stream_Active = true;
...I began experiencing this problematic situation at the start of playback (but it plays fine afterwards, and when looping).
_________________
DS - It's all about DiscoStew

#166584 - hacker013 - Tue Feb 10, 2009 4:35 pm

've changed nothing on your source. if only written a wrapper around it so i can use it in my projects.
_________________
Website / Blog

Let the nds be with you.

#166586 - Odorules - Tue Feb 10, 2009 5:43 pm

I was calling mmStreamUpdate like in the vcount handler. But now I call it in the main loop and I haven't this bug anymore. Except a little "crash" when some musics start.
Thanks :)

#166663 - DiscoStew - Fri Feb 13, 2009 8:48 am

I can only imagine that there is that audio cut off from the very beginning of playback is because by the time the stream is set up, the point where the VCount interrupt activates would have already passed, therefore doesn't do anything with mmStreamUpdate, so by the time it got back to that point for updating, there would be much more data that needed to be decoded, and let's not forget that it uses a buffer with a limited size, further preventing the entire set from being decoded at once, so it could only decode in limited chunks until it finally caught up.

The reason why it didn't happen with my example is because there isn't anything else that could happen that would put it into this problematic situation.

While I don't have a solid fix for this *yet*, I would like everyone who is having this problem to try this simple change with their projects that use this decoder. Remove mmStreamUpdate completely, and in the STREAM_PlayFile function, change the line....
Code:
Stream_Mystream.manual = true;
....to....
Stream_Mystream.manual = false;


....and see if this helps. I'd like feedback concerning this, because by doing this, Maxmod will get the data required when it needs to, rather than waiting for the program to tell it that it can.

While this may break up the audio streaming in emulators, it seems to run fine on hardware, and that's where it counts, right?
_________________
DS - It's all about DiscoStew

#166672 - Odorules - Fri Feb 13, 2009 7:44 pm

I tried this but I have the same cut off sound when the song start.
Moreover, it works on emulator with Stream_Mystream.manual = false.

#166693 - DiscoStew - Sat Feb 14, 2009 10:25 pm

From the many tests that I have done, I can only conclude that it is a problem from the time it takes from calling mmStreamOpen to the next mmStreamUpdate. I'm also thinking that if you are to try having it update by itself as described in my last post, you may also want to move "Stream_Active = true" to before mmStreamOpen, as it might want to try and update itself right after finishing the mmStreamOpen call (and when it does that, it goes into the STREAM_Update function, where it is ended quickly for not having the actual stream active).

Also, while it runs fine with no errors or crashes on hardware and emulators, it still brings up static on No$GBA for me. While it's designed to work specifically on hardware, it can get a little irritating when developing with it. If anyone knows how to fix this, please let me know.

While being on this code-hunt, I decided to see if I could squeeze out any more juice from the decoding portion, and it appears that I have. The code is a little larger as it is expanded. I'll be updating the comments to it before I upload the new version which will be a little faster in decoding.

I should probably start putting up version numbers or something. I never had any in the past for all my other projects.....because I never got to a point of getting this far, lol. Guess starting with v1.0 will work.

EDIT:

New version is uploaded. The internals for the decoding and processing are different from the previous release. The only change made to interfacing with it is the addition to setting it to automatically update. Please give feedback, such as if there are still bugs and overall problems with the audio decoding/playback. The rest are just extras, and are not meant to be perfect, only usable.
_________________
DS - It's all about DiscoStew

#166699 - hacker013 - Sun Feb 15, 2009 10:39 am

i dont't get any sound at all now and yes i tryed all 2 modes and by manual mmStreamUpdate in the vblankhandler.
_________________
Website / Blog

Let the nds be with you.

#166729 - DiscoStew - Mon Feb 16, 2009 3:25 am

Seems some bugs snuck in that I didn't account for. The bug that everyone seemed to get before (with audio being cut off) finally revealed itself to me completely, but the simple change I made (without altering any of the decoding routines) makes it much like the previous version, and that was when people began experiencing the problem in the first place. I'll look into it more, as well as anything else I can find. This isn't a good start for this project. :P

hacker013,

Since you aren't getting any sound whatsoever, I'd like you to do something for me. I need you to examine the 'length' and 'Stream_CurPos' variables in the STREAM_Update function with both modes, and tell me what you get.
_________________
DS - It's all about DiscoStew

#166737 - DiscoStew - Mon Feb 16, 2009 7:03 am

I would like everyone that is trying this decode functionality in their projects to try this new files...

Link removed by Discostew. New version is up

Because I don't have anything running along side this that is intensive, I need help from you all. This file includes the stream files and a new main.c file. The stream file changes are little alterations to the stream loader, a different initial checker in the callback function, and a temporary function that displays a few status values for the user to see. The main.c file just has the addition of the stream status function. The main reason why I added that was for people who had problems that wanted to examine the data themselves, but didn't want to tamper with anything. If you want, you can add more values to look at (but be mindful that it's set at row 21, so change that if you add more).
_________________
DS - It's all about DiscoStew


Last edited by DiscoStew on Wed Mar 18, 2009 8:05 am; edited 1 time in total

#166774 - Odorules - Tue Feb 17, 2009 4:31 pm

I did some tests and your code works fine (there is not "crash" sound when at starting). I copied stream.h and strem.c in my code and there is this bug. It seems it's because of my code :(

I don't know what could cause this. Any idea ?

EDIT : This bug is here when I call STREAM_PlayFile() for the first time. I reload the level, I re-call STREAM_PlayFile() and there is not the bug.

#166785 - Emmanuel - Tue Feb 17, 2009 7:42 pm

I downloaded your files in the first post... they work perfectly for me...
Great work

#166788 - DiscoStew - Tue Feb 17, 2009 8:29 pm

That is just odd. When everyone else is getting no problems with the code (with the except of hacker013), I get problems, but when I don't get problems, everyone else does.

Emmanuel,

Are you using the files in a project of yours, or are just trying out the example program? No audio cut-off when switching between different files?

EDIT:

So is everyone having no problems with the "manual" version? From the looks of it, it appeared that after I posted the v1.0 release, I only checked the "auto" mode on my own NDS, and the cut-off was resulting on it. Instead of checking the "manual" version too, I assumed it had the same fate, so I went about trying to fix something that didn't necessarily have any problems. If no one is having problems with the manual version (hacker013, I need more information from you concerning why you aren't getting any audio at all), then I'll just remove the auto-mode portions until I figure out the cut-off from that.
_________________
DS - It's all about DiscoStew

#166789 - Emmanuel - Tue Feb 17, 2009 9:40 pm

DiscoStew wrote:
Emmanuel,

Are you using the files in a project of yours, or are just trying out the example program? No audio cut-off when switching between different files?

EDIT:

So is everyone having no problems with the "manual" version? From the looks of it, it appeared that after I posted the v1.0 release, I only checked the "auto" mode on my own NDS, and the cut-off was resulting on it. Instead of checking the "manual" version too, I assumed it had the same fate, so I went about trying to fix something that didn't necessarily have any problems. If no one is having problems with the manual version (hacker013, I need more information from you concerning why you aren't getting any audio at all), then I'll just remove the auto-mode portions until I figure out the cut-off from that.

I'm using them in a project of mine, with the one in your first post, working fine with both versions, but I prefer auto...
Also, testing it on No$Gba in auto I did found some "interference" that occured in a timely manner, but on manual that interference totally vanishes...
Hardware doesn't have any of this problems altogether...
I'm using C++, Arm7 in the combined template with slight modifications, and EFS to load the sounds

#166803 - hacker013 - Wed Feb 18, 2009 4:49 pm

DiscoStew wrote:
That is just odd. When everyone else is getting no problems with the code (with the except of hacker013), I get problems, but when I don't get problems, everyone else does.

Emmanuel,

Are you using the files in a project of yours, or are just trying out the example program? No audio cut-off when switching between different files?

EDIT:

So is everyone having no problems with the "manual" version? From the looks of it, it appeared that after I posted the v1.0 release, I only checked the "auto" mode on my own NDS, and the cut-off was resulting on it. Instead of checking the "manual" version too, I assumed it had the same fate, so I went about trying to fix something that didn't necessarily have any problems. If no one is having problems with the manual version (hacker013, I need more information from you concerning why you aren't getting any audio at all), then I'll just remove the auto-mode portions until I figure out the cut-off from that.


When i load a .wav it doesn't return NULL so i think that's not the problem. I've monitored some vars:
CurrentPos - 0;
Length Request - 0 (0)
Buffer length - 0
Is Active - 0
_________________
Website / Blog

Let the nds be with you.

#166808 - DiscoStew - Wed Feb 18, 2009 7:27 pm

You're getting those values after not getting NULL from STREAM_PlayFile? Looking over my code, I don't see how that is possible, not without changing something in the code itself, because when the function returns non-zero is when code execution also passes by Stream_Active and buffer_length, making them non-zero.
_________________
DS - It's all about DiscoStew

#167051 - DiscoStew - Fri Feb 27, 2009 8:33 pm

Expect a new version to be released within the next week or two. I took eKid's approach, and converted my decoding routine into assembly (only stereo atm). Getting about 16 scanlines for 44kHz stereo (as opposed to the 26 from c/c++ implementation), but I'm hoping the routine can be improved.

The decoding code is in the ASM forums if anyone wants to contribute to improving it, but it is not compatible with either my current release here or even eKid's release (even though the format is similar to his) because of other changes made outside of it to make it work with ima-adpcm.
_________________
DS - It's all about DiscoStew

#167128 - Odorules - Mon Mar 02, 2009 7:18 pm

Okay :)
I'll use it when you'll release it.
I had solved my bug by adding "soundDisable();" when I call STREAM_PlayFile and call soundEnable(); 5 frames after.

It's not a good fix at all but it works.

#167200 - Emmanuel - Thu Mar 05, 2009 3:34 pm

Has anyone gotten any problems with the latest libnds?
It just freezes when it comes the moment the play function is called... both in my project and the demo...
in the demo, same goes for auto and manual, I select the file: freeze...
In my project when I call stream_playFile....

#167268 - iainprice - Sat Mar 07, 2009 4:12 pm

I want to put the streaming audio into my game.... i am trying to load an mp3 from efsroot but am having no luck, has anyone else modified this to work for a libfat mp3 file?

#167274 - hacker013 - Sat Mar 07, 2009 5:36 pm

this is for wav files xD
_________________
Website / Blog

Let the nds be with you.

#167276 - DiscoStew - Sat Mar 07, 2009 5:59 pm

As hacker013 said, it only supported "wav" files, and limited in that range as well for only PCM and IMA-ADPCM.

One reason why people might be having problems with this is that the toolkit has been updated, and possible conflicts have occurred since then. I only updated last night, and found the most recent compiled version of my streamer to crash on-play with No$GBA, so I'll be working to fix that.
_________________
DS - It's all about DiscoStew

#167553 - DiscoStew - Wed Mar 18, 2009 7:32 am

Ok, new version is up, and should be working with the newest toolkit. As noted, auto-mode doesn't work correctly because of a bug in Maxmod, but has been fixed in the newest svn, so either update to that, or wait till it gets compiled with the toolkit.
_________________
DS - It's all about DiscoStew

#167557 - hacker013 - Wed Mar 18, 2009 2:50 pm

I hope this version works for me :)

EDIT: can you release a c version?
_________________
Website / Blog

Let the nds be with you.

#167568 - Emmanuel - Wed Mar 18, 2009 6:37 pm

Great, it's working awesome... save one little strange thing, which may actually be my file:
When I set loop mode, the first run works fine, second run ends, and then sound like screeches... starts sounding awful... but, the DS doesn't freeze, in fact, I can play the sound again with A button, and the same happens... awful sound until the second loop ends

Tried with a different, and smaller file, but same occurs, except the screech sounds different... but it's an awful sound nonetheless

#167575 - DiscoStew - Wed Mar 18, 2009 8:09 pm

Emmanuel wrote:
Great, it's working awesome... save one little strange thing, which may actually be my file:
When I set loop mode, the first run works fine, second run ends, and then sound like screeches... starts sounding awful... but, the DS doesn't freeze, in fact, I can play the sound again with A button, and the same happens... awful sound until the second loop ends

Tried with a different, and smaller file, but same occurs, except the screech sounds different... but it's an awful sound nonetheless


It sounds like this?

Anyways, I doubt it is your file(s). With looping, there is one of two things that the decoder will do. Either it takes looping information from what is called the "sampler" (if it exists), or the loop markers would get set at the start and end of the audio data block. I currently can't check through my code since I'm not at home, but I believe it might have something to do with the loop markers, and something being altered with the "capture_frame" when it loops back the first time, affecting it the next time it loops around.

But just so I understand how you are experiencing this, this corruption happens after it streams through the audio twice (meaning it starts when it should begin streaming through it the third time?). Is the audio PCM or IMA-ADPCM? Does it have a sampler block? And you said that when you replay the audio, it plays fine until it gets to that point again?


hacker013,

I had thought about converting just the decoder to regular C, because the prior versions were like that and people had already adapted their projects with that in mind. I'll see what I can do, but it might be a while before I can truly set aside some time to deal with it.
_________________
DS - It's all about DiscoStew

#167577 - Emmanuel - Wed Mar 18, 2009 9:08 pm

DiscoStew wrote:

But just so I understand how you are experiencing this, this corruption happens after it streams through the audio twice (meaning it starts when it should begin streaming through it the third time?).

Yeah, I don't know if it's when the second loop ends, or when the third loop is beginning though...

Quote:
Is the audio PCM or IMA-ADPCM?

PCM, 2 channel aka stereo, 16-bit, 44 KHz

Quote:
Does it have a sampler block?

what's a sampler block? ok, it's the block of the file with info about somethings... how do I set one, or check to see if it's correct?
Doesn't look like it has one though...

Quote:
And you said that when you replay the audio, it plays fine until it gets to that point again?

Yes, the first loop is totally perfect, however, on close inspection, the second time plays perfect too, but the start of the third time is the bad one... noticed that because I managed to hear a bit of the third time in a recent test (nothing fancy, just decided to pay more attention at the timing)

Btw, I'm clueless about ASM... so, I have no idea of how your code goes, for the ASM part.. which since it's the main part, I haven't even looked at it too much...

Btw, I'm using the already compiled nds file, no edition nor recompilations on my side... later I'll try to recompile it, and perhaps toy a little more with the file, about this sample block for example

#167580 - DiscoStew - Wed Mar 18, 2009 11:12 pm

Ok, after checking my own PCM wavs on the DS (I bring my DS to work to use on my breaks), it appears that I was right in my assumption. There is a problem with the loop markers, specifically the end marker. The "screech" you are hearing is data being read from past the end of the audio file.

When I get home today, I'll do a quite sweep over the code, get it fixed, and upload the new version.

EDIT:

I was right that it had something to do with the looping values, but wrong that it wasn't the start/end markers. Nevertheless, the problem is fixed. Go ahead and grab it.
_________________
DS - It's all about DiscoStew

#167603 - hacker013 - Thu Mar 19, 2009 7:36 pm

DiscoStew wrote:

hacker013,

I had thought about converting just the decoder to regular C, because the prior versions were like that and people had already adapted their projects with that in mind. I'll see what I can do, but it might be a while before I can truly set aside some time to deal with it.


How long do you think it would take to convert it?
_________________
Website / Blog

Let the nds be with you.

#167649 - Emmanuel - Sat Mar 21, 2009 8:34 am

ok, it looks perfect so far... now the prob is when adding it... I'm given an error at linking when I copy paste into my project... seems the linker is detecting the decode mono and decode stereo functions twice...
Code:
ima_adpcm_decode.o: In function `decode_mono_ima_adpcm':
c:/source/SSBClash/arm9/source/DStew/ima_adpcm_decode.s:56: multiple definition of `decode_mono_ima_adpcm'
ima_adpcm_decode.o:c:/source/SSBClash/arm9/source/DStew/ima_adpcm_decode.s:56: first defined here
ima_adpcm_decode.o: In function `decode_stereo_ima_adpcm':
c:/source/SSBClash/arm9/source/DStew/ima_adpcm_decode.s:110: multiple definition of `decode_stereo_ima_adpcm'
ima_adpcm_decode.o:c:/source/SSBClash/arm9/source/DStew/ima_adpcm_decode.s:110: first defined here


It says it's first defined... exactly in the same place the error occurs... I don't know what's the problem, all I know is this is the first .s file I add, all the rest are .cpp

When I remove just that file... the function is not found, and when I leave it, it's found twice...

#167651 - DiscoStew - Sat Mar 21, 2009 9:21 am

I did a little research on this, and the only thing I could find related to this problem is this...

In the compiler output, is the problematic file being listed twice? The source of this information that had the same problem also reported that the next day, there weren't having any problems associated with multiple definitions from the same line of code, so it could just be a small compiler hiccup. Are you cleaning out the prior build before the next build?
_________________
DS - It's all about DiscoStew

#167676 - Emmanuel - Sat Mar 21, 2009 10:05 pm

Lol... I found the problem... in the Arm9 makefile I had export OFILES for S files twice...

#167680 - Emmanuel - Sun Mar 22, 2009 5:02 am

So, now I added it to my project... but, ram usage keeps increasing... it seems whenever I call the player's play function RAM increases... and it doesn't decrease ever.... I think it may be the datacache... but since the source isn't mine, and I don't know a thing about ASM, I'm not completly sure...
I haven't had the time to test for RAM in your example though... but I don't think it's my project... it only happens when player.play(arguments) is called... and the increase happens each time it's called... though I haven't overload it yet... too lazy to do it...

#167683 - DiscoStew - Sun Mar 22, 2009 6:33 am

I'm pretty sure it's that "datacache", since the only time it ever frees that memory is when the Stream class is destroyed. Unfortunately, the place that I thought it would do that is when "active_player = this", but maybe it doesn't destroy the previous stream from right there?

In the stream's "reset" function, try adding...
Code:
if( datacache )
            delete [] datacache;

...just before it calls to allocate memory, and see if that fixes the memory leak. Please get back to me if it does, and I'll add the fix into the example.
_________________
DS - It's all about DiscoStew

#167696 - Emmanuel - Sun Mar 22, 2009 1:34 pm

Still, no use... this is the function whole... I tried to add it at the very start, no use either
Code:
int IMA_Adpcm_Stream::reset( const char *wav_file, bool loop )
{
   if( fin ) {
      close();
   }
   fin = fopen(wav_file, "rb");
   
   if( !fin )
      return IMA_ADPCM_ERROR_CANNOTOPEN;

   if( fget32() != 0x46464952 )      // "RIFF"
   {
      fclose( fin );
      return IMA_ADPCM_ERROR_NOTRIFFWAVE;
   }
   int size = fget32();
   if( fget32() != 0x45564157 )      // "WAVE"
   {
      fclose( fin );
      return IMA_ADPCM_ERROR_NOTRIFFWAVE;
   }
   
   // parse WAV structure
   while( tell() < size )
   {
      u32 code = fget32();
      u32 csize = fget32();
      switch( code )
      {
      case 0x20746D66:    // format chunk
         
         // catch invalid format
         format = fget16();
         if(( format != WAV_FORMAT_PCM ) && ( format != WAV_FORMAT_IMA_ADPCM ))
         {
            fclose( fin );
            return IMA_ADPCM_ERROR_UNSUPPORTED;
         }
         
         channels = fget16();
         
         // catch invalid channels
         if(( channels < 1 ) || ( channels > 2 ))
         {
            fclose( fin );
            return IMA_ADPCM_ERROR_INVALIDCHANNELS;
         }
            
         sampling_rate = fget32();// sample rate
         skip( 4 );   // avg bytes/second
         
         block = fget16();
         
-------------------if( datacache )
            delete [] datacache;
         
         datacache = new u8[block];

         sampBits = fget16();

         if((( format == WAV_FORMAT_PCM ) && (( sampBits != 8 ) && ( sampBits != 16 ))) ||
            (( format == WAV_FORMAT_IMA_ADPCM ) && ( sampBits != 4 )))
         {
            fclose( fin );
            return IMA_ADPCM_ERROR_UNSUPPORTED;
         }
         
         skip( csize - 0x10 );

         break;
         
      case 0x61746164:   // data chunk
         wave_data = tell();
         loop1 = 0;
         skip( csize );
         wave_end = tell();
         if( format == WAV_FORMAT_PCM )
            loop2 = csize >> ( sampBits == 16 ? channels : ( channels - 1 ));
         else
            loop2 = csize << ( 2 - channels );
         break;
         
      case 0x6C706D73:   // sampler chunk
      {
         int s;
         skip( 28 );
         int nl = fget32();
         skip(4);
         s = 36;
         if( nl && loop)
         {
            skip( 8 );
            loop1 = fget32() >> ( 2 - channels );
            loop2 = fget32() >> ( 2 - channels );
            s += 8+4+4;
         }
         skip( csize - s );
      }
         break;
      default:
         skip( csize );
      }
   }
   wave_loop = loop;
   oddnibble = 0;
   data.curSamps = 0;
   position = 0;
   seek( wave_data );
   currentblock = tell();
   state = state_beginblock;
   return IMA_ADPCM_OKAY;
}

I tried deleting the player completely when changing music or stopping it, and that didn't work either...

I test using this: (being called on every frame)
Code:
struct mallinfo info = mallinfo();
        iprintf("\x1b[10;0HMemory in use  : %d bytes \n", info.usmblks + info.uordblks);
        iprintf("\x1b[11;0HTotal heap size: %d bytes \n", info.arena);
        iprintf("\x1b[12;0HMemory in free : %d bytes \n", info.fsmblks + info.fordblks);

#167712 - DiscoStew - Mon Mar 23, 2009 6:17 am

I believe I may have found where the problem lies, but I want to check with eKid about it, as it may be another problem related to Maxmod.

eKid, you got mail. :P
_________________
DS - It's all about DiscoStew

#167721 - DiscoStew - Mon Mar 23, 2009 7:29 pm

Ok, the problem did lie in mmStreamClose(). So until it gets updated, the only thing I can think of to fix the problem would be to put the player into a special pause mode when notifying it to stop, where the stream continues to run, but nothing is done in the callback function except to fill in the buffer with 0s. Starting another stream would then release it from this special pause mode, and stuff would continue as normal.

I may do that as a temporary fix for now, but it will use some processing time in that standby mode because of having to still fill the buffer.

EDIT:

Forget it. The temporary fix works fine.......if all of your stream files are of the same sample rate, have the same number of channels, etc. It may work for some people, but I would say it's better to wait for Maxmod to be updated.
_________________
DS - It's all about DiscoStew

#167772 - Michoko - Thu Mar 26, 2009 9:22 pm

Hi,

This seems quite interesting! I have two question, please.

1) Until now I was using ASlib, for MP3 replay. There is an issue with this lib though: when streaming MP3 from fat, if you also load other games assets, it's likely that glitches or even crashes will occur (more info here, if you're interested: http://forum.gbadev.org/viewtopic.php?t=14987).
Is your streaming code concerned by the same issue?

2) I'd like to test ADPCM compression and audio quality. Please could you recommend an audio app that would produce an audio file compatible with your code?

Thank you! :)
Michoko

#167785 - hacker013 - Fri Mar 27, 2009 3:45 pm

I think I can answer is, but it isn't my project :)

1. the bug in the wavstreamer has to do with a bug in maxmod (ASLib doesn't use maxmod)

2. Every basic mp3 to wav converter should work :)
_________________
Website / Blog

Let the nds be with you.

#167791 - Michoko - Fri Mar 27, 2009 5:41 pm

Thanks hacker013, but I think you read my message a bit too fast ;)

I was referring to the fact that libfat is not very interrupts friendly, as explained in the link I gave. So if the ADPCM data is streamed using interrupts, and you load another file at the same time (like game assets), it is likely to crash. At least it's the case with ASlib, which uses interrupts to refill its buffer.
I was wondering if MaxMod had the same issue?

Thanks!

#167793 - DiscoStew - Fri Mar 27, 2009 7:14 pm

While I can't speak for loading/reading a file during playback, the streamer hasn't crashed (yet) when reading directory contents that have a good number of files in them. That's not to say that there aren't any side effects.

Obviously in manual mode, if mmStreamUpdate isn't called once per frame, you'll experience repeating because the buffer hasn't been updated with new data, and you'll experience that in the example project that comes with the decoder if you enter a directory containing a lot of files. My guess would be in this mode, as long as mmStreamUpdate is called once per frame, and there isn't anything else that would prevent this from happening (whether from reading a different file, or just too much processing), then you'll have no problems.

Auto-mode is another story because it updates when it needs to, which can be at any time. When the example project, in auto-mode, is under the same situation when reading from a file-heavy directory, the audio will sharply crackle, but will continue playing normally once that process is done.

So, I would have to say that no, Maxmod won't crash in this scenario, but that is just my opinion based on what I've tested, so it may or may not in a similar, but different scenario.

#167826 - hacker013 - Mon Mar 30, 2009 6:42 am

are you already working on a c version? I have tried it by myself but I don't get it working :(

#168054 - hacker013 - Wed Apr 08, 2009 3:05 pm

bump, any updates yet? or maybe a c version (desperate).

#168055 - kusma - Wed Apr 08, 2009 3:39 pm

hacker013 wrote:bump, any updates yet? or maybe a c version (desperate).
Why do you need a C-version?

#168056 - hacker013 - Wed Apr 08, 2009 3:43 pm

because my whole game is in c and if I compile it in c++ I have to fix to many errors. -_-

#168072 - kusma - Thu Apr 09, 2009 12:21 am

hacker013 wrote:because my whole game is in c and if I compile it in c++ I have to fix to many errors. -_-
Then write a C++ to C wrapper around it.

#168125 - hacker013 - Fri Apr 10, 2009 5:14 pm

how do I do that?

#168213 - Apollo - Wed Apr 15, 2009 3:52 pm

Create a file with a set of functions where you handle the C++ specific things of this library but without being "nested" into a class. Just "pure" functions. Compile this file as a C++ file (meaning the file should have a .cpp postfix) and then call the functions from C as usual.

#168244 - kusma - Thu Apr 16, 2009 9:34 pm

also remember to specify the functions as 'extern "C"' to make sure the C-side can call them.

#168276 - hacker013 - Sat Apr 18, 2009 11:52 am

I think i can do that, I will give it a try.

#168594 - hacker013 - Fri May 08, 2009 6:26 pm

I have tried it. I have changed ima_adpcm.h to ima_adpcm.hpp but I still get this error in my c++ 2 c wrapper for this library:

Code: Select all

E&#58;\UZProject\UZEngine>make
make -C arm7
make&#91;1&#93;&#58; Entering directory `/e/UZProject/UZEngine/arm7'
make&#91;2&#93;&#58; `/e/UZProject/UZEngine/UZEngine.arm7' is up to date.
make&#91;1&#93;&#58; Leaving directory `/e/UZProject/UZEngine/arm7'
make -C arm9
make&#91;1&#93;&#58; Entering directory `/e/UZProject/UZEngine/arm9'
template.c
arm-eabi-gcc -MMD -MP -MF /e/UZProject/UZEngine/arm9/build/template.d -g -Wall -
O2 -march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math -mthumb -mth
umb-interwork -I/e/UZProject/UZEngine/arm9/include -I/e/UZProject/UZEngine/arm9/
../common -I/e/UZProject/UZEngine/arm9/source/UZ -I/e/UZProject/UZEngine/arm9/so
urce/NE -I/e/UZProject/UZEngine/arm9/source/UZ/saving -I/e/UZProject/UZEngine/ar
m9/source/UZ/menu -I/e/UZProject/UZEngine/arm9/source/GModules -I/e/UZProject/UZ
Engine/arm9/source/MyEngine -I/e/UZProject/UZEngine/arm9/source/Sound -I/c/devki
tPro/libnds/include -I/e/UZProject/UZEngine/arm9/build -DARM9 -DNDS_DEBUG -DERRO
R_CHECKING -c /e/UZProject/UZEngine/arm9/source/template.c -o template.o
In file included from e&#58;/UZProject/UZEngine/arm9/source/Sound/sound_wrapper.h&#58;4,

                 from e&#58;/UZProject/UZEngine/arm9/source/GModules/menu.h&#58;8,
                 from e&#58;/UZProject/UZEngine/arm9/source/template.c&#58;23&#58; e&#58;/UZProject/UZEngine/arm9/source/Sound/ima_adpcm.hpp&#58;31&#58; error&#58; expected '=', ',', ';', 'asm' or '__attribute__' before 'IMA_Adpcm_Stream'
e&#58;/UZProject/UZEngine/arm9/source/Sound/ima_adpcm.hpp&#58;105&#58; error&#58; expected '=',',', ';', 'asm' or '__attribute__' before 'IMA_Adpcm_Player'
make&#91;2&#93;&#58; *** &#91;template.o&#93; Error 1
make&#91;1&#93;&#58; *** &#91;build&#93; Error 2
make&#91;1&#93;&#58; Leaving directory `/e/UZProject/UZEngine/arm9'
make&#58; *** &#91;arm9/UZEngine.elf&#93; Error 2

#168599 - Mighty Max - Sat May 09, 2009 3:42 am

Not very surprisingly if you try to compile c++ with the c compiler.

If you include a hpp into a c file (which is compiled as c by the ruleset in devkitpro) it will still be parsed as c and not cpp code.

#168601 - hacker013 - Sat May 09, 2009 11:23 am

any suggestions how to fix that?

#168604 - Mighty Max - Sat May 09, 2009 1:47 pm

Either change the rules to compile c as cpp (not that good of an idea) or well make them cpp :-P

I'm not sure however why to create a copy of existing source (thus increase the effort to maintain it) when you just can just use them extern "C" where you need them. So there is no messup with the original code involved

#168605 - hacker013 - Sat May 09, 2009 3:18 pm

but my whole program is in c -_- zo that are a lot of extern "C"
_________________
Website / Blog

Let the nds be with you.

#169330 - a128 - Fri Jul 03, 2009 7:03 pm

DiscoStew wrote:
On No$GBA, the audio can sound crappy when just starting (must be a timing issue), but on hardware, I haven't been able to reproduce that same glitch.


I also have an issue with NO$GBA ....I just used the stream MM example from libnds and streamed a WAV sample....instead of the sinus wave

on hardware it sounded good...on the emu it sounded distorted....

no I know why: the buffer size was 1200...rising the buffer to 32767 with playing rate 44100 worked on emu...I guess it's mutch slower then hardware so the emu did not make it in time with a small buffer ?!
_________________
"Hey! It compiles! Ship it!"

#173305 - protomank - Tue Mar 30, 2010 10:45 pm

Does anyone still have the source for this? The mediafire link is broken...
_________________
Iuri Fiedoruk
http://rockbot.upperland.net

#173306 - DiscoStew - Tue Mar 30, 2010 11:42 pm

yeah, when I had put it up some time ago, I didn't realize that letting it go inactive would wipe it. If I can find it in my backups, I'll re-upload it.
_________________
DS - It's all about DiscoStew

#173307 - headspin - Tue Mar 30, 2010 11:51 pm

I can host it for you DS if you like.
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game

#173319 - wintermute - Wed Mar 31, 2010 9:35 am

a128 wrote:

on hardware it sounded good...on the emu it sounded distorted....

no I know why: the buffer size was 1200...rising the buffer to 32767 with playing rate 44100 worked on emu...I guess it's mutch slower then hardware so the emu did not make it in time with a small buffer ?!


timing is all over the place on emulators, we found it almost impossible to get something that sounded good on both simultaneously.
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#173322 - DiscoStew - Wed Mar 31, 2010 6:57 pm

Ok, it's re-uploaded to MediaFire, and link is fixed. It's been a while since I last touched it, and I haven't had the time to test if it still works, though I would assume it should. It compiles fine at least.

headspin,

You and anyone else can go right ahead and host it.
_________________
DS - It's all about DiscoStew

#173323 - protomank - Wed Mar 31, 2010 7:42 pm

Thanks, I'll try it tomorrow, as today my football (aka soccer) team will play for Libertadores da Am?rica, and I'll go to the stadium :)
Looking at the code, it looks nice. Probally I'll run on a problem I have already: using sound (maxmod) with SDL, all timers junt went zero, so I can't control events speed and all runs crazy fast.
_________________
Iuri Fiedoruk
http://rockbot.upperland.net

#173333 - protomank - Fri Apr 02, 2010 12:46 am

Well it worked.. kinda.
It seems like maxmod update (manual or automatica) have some problem that freezes an SDL apps. Any chance of you guys know anything about it?
_________________
Iuri Fiedoruk
http://rockbot.upperland.net

#173335 - sverx - Fri Apr 02, 2010 10:14 am

mmm... you mean you're using cpu timers? Maybe MaxMod uses them too...

#173340 - protomank - Fri Apr 02, 2010 11:34 am

Yeah, I think that the problem is that. Both SDL and Maxmod use the same interrupts to control time, so, probally there is a conflict between them.

So, in the end I'll have to try to fix SDL_Mixer or leave my game without any sound :-(
_________________
Iuri Fiedoruk
http://rockbot.upperland.net

#173423 - sverx - Tue Apr 06, 2010 9:29 am

libxm7 uses only ARM7 resources... ;)

#173426 - protomank - Tue Apr 06, 2010 12:59 pm

And what is libmx7, and where I can get it? :)
(looking at the source, I saw that SDL also uses arm7, but I can hope it does not matter)
_________________
Iuri Fiedoruk
http://rockbot.upperland.net

#173452 - sverx - Wed Apr 07, 2010 9:06 am

uh-oh... I overlooked the topic... you need to stream music? Then sorry for the misleading suggestion, I just read you had some problems with MaxMod and I thought you were searching a replacement for XM/MOD reproduction...

#177556 - Kasumi - Wed Aug 22, 2012 1:13 am

Bumping an old topic.

I used this (with some modifications) to throw together a simple movie player. I'm getting seemingly random crashes, and I'm hoping the answer is something simple.

Edit 2: The answer seems pretty simple. CycloDS iEvolution isn't very good. I guess I'll leave this post in case my hacked in seeking function is useful to someone.

For instance, I realized that having player.update() in a function set to fire on IRQ_vblank makes it crash. I'm hoping there's just something like that about this player or about maxmod I'm not aware of, like I can't read files during the scanlines this could update, or whatever.

I made two "big" changes changes to the original player. I'm using nitrofs instead of standard FAT. And I added seeking to the player, in an admittedly hacky way. (Details to the specifics of changes for that are at the end of the post.)

My crash occurs during regular playing with this streamer. I don't have to use my added seek function/pause for it to occur. In fact, I originally thought the issue was just that my flash card was losing contact but I no longer think that's the case. If I completely remove the cart from the system while this is running the music and video obviously get extremely messed up, but I can actually still interact with the GUI on the touch screen. (Buttons still light up, etc.) When this crash happens, it cycles through the same part of the song over and no input does anything.

The weird thing is that this has worked forever, but then I decided to try new media files (converted in the exact same way), and I get crashes even on ones that have worked before. So maybe one of the new files changed the timing just enough that two interrupts are now interfering with each other?

Here's an outline of my program structure:

I've got an endless while loop that doesn't wait for vblank or anything else. It calls player.update(), and changes which media file is playing. (I think this is because I also discovered changing media in a vblank function causes this to crash. Otherwise, I'd probably be doing this in an easier way :) ).

The endless while loop also does one of the following things each frame.

1. Gets an offset for the specific frame in the movie file. The movies are nothing more than uncompressed 128x96 BGR frames stored in sequential order in a single file. The audio actually comes from a separate file which this player reads.

2. Uses the offset to load a frame to RAM with fopen, fseek, fread, fclose.

3. Works with the frame in RAM to double its resolution and copy it to RAM that will be DMA copied to the top screen.

4. Updates the GUI on the bottom screen if the frame hasn't been drawn yet.

Then, I have an function set to run on vblank via IRQ that does the following:

1. Reads and process input. This means it will set RAM to change movies that the endless while loop will pick up on when the interrupt returns. It also allows pausing and resuming the player directly, rather than passing a signal to the endless loop. (Could this cause a problem as well?)

2. Copies the frame to the top screen with a DMA OR copies the GUI from a RAM buffer to the bottom screen.

3. This also reads from the player's data to get the current block and total blocks in the wav. It does this and so that the movie frames can actually sync. Is reading this stuff safe in the vblank?

As of writing this post, I noticed I had an extra fread function for my movie frames. (left over from a test. Oops... Also discovered one other issue with how my frames are handled. I'll have to see if those things fix it, but I'm still making this post in case there are some not obvious gotchas with using vblank_IRQ and maxmod/this player.)

Edit: Fixed those. Still crashes, at least on one card. Another weird thing is that it doesn't seem to crash on a CycloDS, but it does on a CycloDS ievolution. This is with the same microsd card and everything. I realize the iEvolution isn't well recommended, but might anyone know why this is or how I might be able to fix it for a finicky card? I find it especially odd since I'd think they'd handle DS homebrew about the same...

Also, here is a (I think) complete list of changes for how I added seeking. (Yes, I realize one should not move private variables to public. If there are specific times I should not read from this data, let me know and I'll try to do it at a safe time.)

Moved the following to public in class IMA_Adpcm_Stream

int wave_data;
int wave_end;
int currentblock;

void capture_frame();
void restore_frame();

Added the following to public in class IMA_Adpcm_Stream

int seeking;
int seekpos;

Added the following to class IMA_Adpcm_Player

void seekfunc(int seekpos);

int pseeking;

int waveend();
int wavedata();


Added the following after stop(); in IMA_Adpcm_Player::play

stream.seeking = 0;
stream.seekpos = 0;

Added

stream.capture_frame();

before return 0 in in IMA_Adpcm_Player::play

Here is my IMA_Adpcm_Player::i_stream_request with all my sloppy edits to allow seeking:


Code:
mm_word IMA_Adpcm_Player::i_stream_request( mm_word length, mm_addr dest, mm_stream_formats format ) {   
   if(stream.seeking){
      if(stream.seekpos < stream.currentblock){
         stream.restore_frame();
      }
      int countiterations = 0;
      while(stream.currentblock <= stream.seekpos && countiterations < 40){
         resume();
         countiterations++;
         if( !paused ) {
            if( !stream.stream( (s16*)dest, length ))
            {
               // apply volume scaler
               if( volume != 256 ) {
                  s16 *d = (s16*)dest;
                  int i = length;
                  for( ; i; i-- ) {
                     *d = ((*d) * volume) >> 8; *d++;
                     *d = ((*d) * volume) >> 8; *d++;
                  }
               }
            }
            else{
               stop();
               stream.seeking = 0;
            }
         } else {
            s16 *d = (s16*)dest;
            int i = length * 2;
            for( ; i; i-- ) {
               *d++ = 0;
            }
         }
      }
      
      if(stream.currentblock >= stream.seekpos){
         stream.seeking = 0;
      }
   }else{
      if( !paused ) {
         if( !stream.stream( (s16*)dest, length ))
         {
            // apply volume scaler
            if( volume != 256 ) {
               s16 *d = (s16*)dest;
               int i = length;
               for( ; i; i-- ) {
                  *d = ((*d) * volume) >> 8; *d++;
                  *d = ((*d) * volume) >> 8; *d++;
               }
            }
         }
         else
            stop();
      } else {
         s16 *d = (s16*)dest;
         int i = length * 2;
         for( ; i; i-- ) {
            *d++ = 0;
         }
      }
   }

   return length;
}


Essentially it checks if it's seeking. If it does, it checks if we're trying to seek to a block that is before the current. If it does, it restores the frame. (Why I added stream.capture_frame() to the beginning of in IMA_Adpcm_Player::play). Then it just runs the logic that was there before 40 times to quickly play through it.

I changed IMA_Adpcm_Player::update() to this to detect seeking

Code:
void IMA_Adpcm_Player::update() {
   pseeking = stream.seeking;
   if( active && !autofill ) {
      mmStreamUpdate();
   }
}

And added the following functions:
Code:

void IMA_Adpcm_Player::seekfunc(int seekpos) {
   if(stream.seeking == 0){
      stream.seeking = 1;
      stream.seekpos = seekpos;
   }
}

int IMA_Adpcm_Player::waveend() {
   return stream.wave_end;
}

int IMA_Adpcm_Player::wavedata() {
   return stream.currentblock;
}


I could live without seeking, but would like a crash free way to report the current and last blocks so I can at least sync my video frames if that's all that can be done. Sorry for the long post, and here's hoping someone out there can provide some insight!