I would like to take an mp3 (or ogg or whatever) and decode it in realtime, so that I can start/stop it on a specific sample in a read callback. I have a couple questions.
Must I stream it? Can I open it and let fmod allocate the memory for it as well as keep it compressed, and still have some method akin to readData where I can retrieve decompressed data from sample to sample as I need it? If not directly, is there a better method besides copying the file to memory and using FMOD_OPENMEMORY_POINT and FMOD_CREATESTREAM? I don’t want to keep it in a file, because there might be a few of these open at once, or would that actually be preferrable?
- popsoftheyear asked 10 years ago
OK here are my results… And keep in mind this is what I came up with for the specific scenerio that I am in. I need to play 1 or more of any audio file (mp3, wav, whatever) with sample accurate start and finish. This allows me to have multiple layers of sounds that are cued and stopped seemlessly. You could, for example, take an mp3 with recognizable patterns in it and play them back to back in any order as well as mix them together simultaneously.
So, for anyone interested, what I did was
1) Load audio files’ raw data into memory
2) createSound with the memory location and FMOD_2D | FMOD_OPENMEMORY_POINT | FMOD_SOFTWARE | FMOD_CREATESTREAM | FMOD_ACCURATETIME (at the least – I also used FMOD_LOOP_NORMAL but they’re not as important I don’t think)
2.5) I am also synthesizing some sounds into memory myself, and just used createSound with FMOD_2D | FMOD_OPENMEMORY_POINT | FMOD_OPENRAW | FMOD_CREATESTREAM | FMOD_SOFTWARE for these, as to "open" a raw audio file in memory as a stream (as opposed to creating a user sample… there is a good reason for this!)
3) I then create a user stream with FMOD_2D | FMOD_OPENUSER | FMOD_LOOP_NORMAL | FMOD_SOFTWARE | FMOD_CREATESTREAM and have a pcmreadcallback
4) In the pcmreadcallback, I just track my current position in each loaded sound that I am "playing", and I use seekData and readData to manually mix these sounds together. This works with any format that is supported by fmod, whether compressed or not! (Also, that’s why my user sample was loaded as a raw file stream positioned in memory…otherwise there would be no support for seekData and readData)
Now obviously I simplified things and didn’t include a bunch of intermediate stuff…but that is all personal implementation details. If anyone has any questions just reply to this post. Also, if all you need is to start and stop on a specific sample (and WHEN you start and stop isn’t as important, just as long as the sound starts and stops at the right place), use the method recommended in the post linked above by a1psx, as it is not nearly as complicated.
Also if anyone has a better way to accomplish what I’m trying to do please let me know!
See this topic, it would be the recommended way if you want precise sample control [url:3batclji]http://www.fmod.org/forum/viewtopic.php?t=9172[/url:3batclji]
Sorry, ignore that, I see you are the OP of that topic.
You can open it and keep it compressed with createcompressed sample when opening.
- a1psx answered 10 years ago
Yeah but then I can’t use readData… Is there an alternative that will work on samples (since CREATECOMPRESSEDSAMPLE loads it as a sample, not a stream).
Plus he’s saying use a DSP callback to get that effect. But to use a DSP callback I need to actually play the sound and aquire a channel for it. Problem is I need to START segments of audio at a specific time, lined up to the sample with other layers that are playing. So, I believe I will be doing my own mixing of these segments, which is why I believe I need to mix them without actually playing them individually (they would be mixed then played through 1 streaming user buffer). So that eliminates the DSP callback method right? All I can think of is load the mp3/ogg file into memory, and load that with CREATE_STREAM and OPENMEMORY_POINT, so that I can decompress what segments I need while I’m mixing them using readData. I guess I’m just trying to see if there is any other way to do it. Once I get this working right I’ll post some example code if anyone is interested.
Please login first to submit.