0
0

In trying to get a dynamic kind of music going, I got a large soundtrack file and wanted to loop selectively in sections of it.

For example, if I had a sound 120 seconds long, start playing at 0 sec and when I notice it passing 45 seconds using getPosition(), trap it by using setLoopPoints() to loop from 30 seconds to 60 seconds, so that it would keep looping there. Then when some flag is raised, set the loop points to 30 to 120 and turn off looping so it would get the rest of the audio.

I couldn’t quite get it to work that way. As I call Channel->setLoopPoints(), it ignores the new settings. Stopping and starting the audio isn’t an option since, [b:3ny8biij]if I’m not mistaken[/b:3ny8biij], setPosition() using PCM_BYTES would require me to load the entire sound into memory as an uncompressed sample… while the example above is nice numbers I’m looking at, in reality, maybe 11 minutes of OGG and many, many dynamic loop points.

Any hints on that technique, BTW?

Anyway, an alternative method I experimented with is splitting the large file into separate sound files for each dynamic loop. So now I’ve got an intro, loop1, bridge, loop2, outro. One benefit so far is that I can load later parts in the background myself and then give FMOD the user memory as the reads are finished.

I set callbacks for the end of a sound every time I play them on a channel and, deciding from raised flags, to either replay or play the next part. So my callback function basically looks like this:

[code:3ny8biij]
FMOD_RESULT F_CALLBACK cb_AfterIntro_and_Loop1(FMOD_CHANNEL channel, FMOD_CHANNEL_CALLBACKTYPE type, int command, unsigned int commanddata1, unsigned int commanddata2)
{
FMOD::Channel
lchannel;
if (SIG_loop1) {
audio_system->playSound(FMOD_CHANNEL_FREE, bridge, false, &lchannel);
lchannel->setCallback(FMOD_CHANNEL_CALLBACKTYPE_END, cb_AfterBridge_and_Loop2, 0);
} else {
audio_system->playSound(FMOD_CHANNEL_FREE, loop1, false, &lchannel);
lchannel->setCallback(FMOD_CHANNEL_CALLBACKTYPE_END, cb_AfterIntro_and_Loop1, 0);
}
return FMOD_OK;
}
[/code:3ny8biij]

Right now it works really good in my test program, but it’s also hitting 100% CPU usage since it’s basically in a spin lock calling update() all the time. I’m worried how it’s going to scale when I end up integrating this in my game where I’ll only manage to call update() every 10 ms or so.

Will this result in heartbreak? Or is there an obvious 3rd method that eludes me? Thanks!!

  • You must to post comments
0
0

Hello boys and girls,

Currently I’m developing a DJ looptool with FMOD.
Basically it reads in the markers embedded in the .wav-file, and manually can switch between loop-regions (while playing) by calling something like

[code:37uvmnys]
FMOD_Channel_GetPos( &currentPos, FMOD_TIMEUNIT_PCMBYTES);
if( currentPos >= nextMarker )
FMOD_Channel_SetPos( currentMarker, FMOD_TIMEUNIT_PCMBYTES );
[/code:37uvmnys]

What I’ve noticed, that sometimes this is a bit jiggly when a lot of stuff is going on….thats why the ‘>=’ is sitting there.
I wonder if there can be a more accurate timing of calling SetPos(), because it seems that constantly calling GetPos() will cause some missed opportunities.

I wonder if you people have any tips to make this looping more stable.
Maybe events?
I really need tight loops because else it can’t be mixed correctly.
The music should be playing while this happens.

kind regards

  • You must to post comments
0
0

funny. i’m planning to do something similar (no code but have a design). FMOD follows the standard that an audio file (WAV/AIF etc) allows for a single loop. So, multiple loops is not supported (to my knowledge). To solve this problem (and to also stream the audio) i’m planning to have my own MySound Class. This class has an FMOD::Sound & FMOD::Channel, start and end points. These points are a selection/part of the sound you want to play. The other class is a MySoundList. The idea is that each MySound is played in the list, one after the other. When adding a new MySound, i was planning to
load up the stream ready to play (playSound paused)
set the sound to loop,
set loop count to 1…n,
set the setPosition to MySound.start,
set the loopPoints to MySound.start MySound.end position

so the FMOD::Sound will play from MySound.start and stop when it reaches MySound.end. Then play next MySound in MySoundList.

i think this will work but like i say, no code yet. And i might be missing something. This design has some nice features such as streaming of disk and each MySound can be the same file or a different one. The objective for me is to be able to "vamp" different parts of an audio file. They do this in musicals/theatre where the band/orchestra play a set number of bars and repeat until the conductor gives a cue to go on. And now we’re writing code to do it for us :)
cheers

  • You must to post comments
0
0

you should be using setLoopPoints not setPosition. getpos/setpos will not be accurate because it relies on polling speed, is not accurate because getpos gives you a buffered ‘audible’ result, and setpos will have a latency as well.

  • You must to post comments
0
0

Yeah, ultimately some kind of array of loop points would find itself in actual production code. It really is a shame it can’t change on the fly which is sure a lot cleaner than chopping things into separate files.

Imagine a list of those loop point structures also containing heuristics over the musical content, keeping track of comedic and dramatic (and other type) scores so it will dynamically select the tone for how a player would play a game.

While lurking on this board for a long while I seem to recall that dynamic loop points were on the FMOD wishlist. I, for one, eagerly await that.

  • You must to post comments
0
0

[quote:16ehqsym]The music should be playing while this happens. [/quote:16ehqsym]

hmmm…bummer, I already tried setLoopPoints before, but it requires a restart of the sound when changing the looppoints right? :(

This weekend I also discovered the ‘setCallback’-function for channels, it enables you to do a callback when the audio encounters a syncpoint.
Isn’t this a perfect timing to call setPosition()?

EDIT:

calling setLoopPoints while playing WORKS!
everybody should forget about making manual loops with setCallback(..) or Get/SetPosition(..)

  • You must to post comments
0
0

Well, I am quite sure it’s not really safe to change the callback while it’s used. It looks to my like a hen/egg relationship 😉 The real implementation will end up in some kind of recursion.
Playing a bit with fmodex’s looping stuff led me the intention that fmod has bigger problems when it comes to things like multiple loopings, changing the loop points while playing and accuracy of the loop (just do a loop for 10ms … it will sound sometimes pretty weird). I hope it will be investigated some time. I would like to use some stuff like this in my small synthesizer.

cheers Martin

  • You must to post comments
0
0

Hi!
I’m kinda new to fmod but I recently ran into the same thing and this is how I solved it:

  • Register a callback function to receive channel callbacks.
  • For each subsection of the sound you want to loop through, set 2 syncpoints in fmod.
  • When the syncpoint for the end of the section is reached, setPosition using the current section start (I keep track of all section boundaries in an array).
  • If I want to jump to a new section, I simply increase the "current section" index (basically an index into that section array) and leave it at that. What happens is when the section end syncpoint is reached, I will setPosition to the current section (step 3) so the sound will start looping on that section.

I’ve tried this out and it works fine. I didn’t hear any artifacts from using setPosition (I do it with the sound paused, but also tried with it running and no problem).

I didn’t have lots of sounds though, just that main music track (streaming, by the way) and some machine gun shots.

Am I going to run into problems later on by doing it this way?

  • You must to post comments
0
0

After re-reading,

[quote:2c32sj2n]if I’m not mistaken, setPosition() using PCM_BYTES would require me to load the entire sound into memory[/quote:2c32sj2n]

In the doc’s it states under Channel::setPosition

[quote:2c32sj2n]Note that if you are calling this function on a stream, it has to possibly reflush its buffer to get zero latency playback when it resumes playing, therefore it could potentially cause a stall or take a small amount of time to do this. [/quote:2c32sj2n]

now i haven’t tried this, but will be to see how far i can push fmod and too re-create this re-flush issue. But, you can call this function on a stream.

As for dynamic loop-points, the only restriction in my design is (as you say) cannot change the loop-points while that loop is being played. But selection of loop regions can change on the fly. You just need to set the next loop-region (where loopCount >= 1) while another loop-region is playing and before it finishes. And as for MySoundList, it could be another structure with some AI to "choose" which bit of music to play next. And all these loop-regions can be pointing at the same audio file or different audio files. You can add features such as dividing an audio file up into beats (as finer detail as needed). Now you can decide in which order you would like to play these regions in real-time.

The other alternative is to take a step back, design a new DSP unit (similar to wavetable unit) so i have access to the stream buffer and implement my own playBuffer routines with dynamic loop points. But i don’t need (or can think of a reason) to be moving loop-points around.

One way to help would be perhaps to add to FMOD wishlist a function such as

[code:2c32sj2n]playSound(channelId,sound,paused,channel,startPoint,endPoint);[/code:2c32sj2n]

start/end points MUST be within range of sound file.

and

setLoopPoints MUST be within the range of startPoint and endPoint.

cheers

  • You must to post comments
0
0

sounds ok to me.

  • You must to post comments
0
0

update…..

i have tried several approaches to creating multiple loop points, none of which work as well as i would like. The problem i am facing (i think) has to do with the internal buffering system of FMOD. So, i would like to ask some questions:

  1. using getPosition() can only produce an accuracy resolution of buffer size (while streaming and using FMOD_SOFTWARE) ?

  2. sub-sound mechanism (which is a great idea btw). When the sound has finished playing, FMOD moves to the next sub-sound. I assume the channel buffer is NOT flushed?

  3. after exploring many techniques including double channel buffering, sub-sound mechanism, channel callback (with markers), i come up with the same issue. This may not be possible but would like some info. on this. Is there a way to play a sound (streaming) and setting the end point of the sound?

  4. the issue for me is that FMOD trigger’s sub-sounds and channel internal de-allocation (therefore buffer) when it reaches the end of the file. Is there a way to avoid this, or to set a marker in the file to trigger this behaviour?

What i am trying to achieve is a way of chopping a stream up (ie. 1 audio file) into regions and to play each region in a particular order. The real test is to play the regions in order with the result: the whole sound file (without any "clicks" ie. accuracy of bytes).

The best solution i believe is using the sub-sound mechanism. Using 2 sub-sounds (just like a double buffer) and switching between the 2. Using setPosition() should be fine but detecting a position in the file (to then make the sub-sound switch) also needs to be byte accurate. And there lies my problem.

thanx

  • You must to post comments
0
0

Hmmm..I have some very strange behaviour using looppoints while playing:

[b:1qjge6i3]CASE:[/b:1qjge6i3]
I’m jumping back and forth between loop regions, first I do channel::setLoopPoint() and when I receive a syncpoint callback, I set the next.

[b:1qjge6i3]PROBLEM:[/b:1qjge6i3]
At first sight it looks like it works…but sometimes syncpoints aren’t fired consistent while playing looppoints.
Take a look at this wav and psuedocode :)

[code:1qjge6i3]
wav file with 4 markers :

[————|————|————-]
1 2 3 4
[/code:1qjge6i3]

if I use setLoopPoint(1,2) or (3,4)…..syncpoint 2 or 4 fires an callback correctly (it tells us the loop finished).
However once I do setLoopPoint(2,3)…then syncpoint 3 doesn’t fire an callback.

[b:1qjge6i3]I TRIED:[/b:1qjge6i3]
I tried to create some fake syncpoints, just BEFORE the actual syncpoint (so I could cheat a bit), but this ends up in inaccurate timing.
And this necessary because I use my software to do beatmixing.
The looppoints work except the syncpoints ‘in the middle’ don’t fire callbacks!

[b:1qjge6i3]TEMPORARY FIX:[/b:1qjge6i3]
As a backup-routine I do some GetPosition checking, and manually do SetPosition when the callback isn’t fired…but this is inaccurate and ugly.
If you know a better solution please let me know

  • You must to post comments
0
0

New technique….

In my exploring of FMOD i’ve discovered a neat way of getting accurate positioning using markers (sync points) and the channel callback. I have also been able to add and remove markers on the fly. This allows me create my own multi-looping behavior on a stream with byte accuracy. I am also going to try using the sub-sound mechanism, where the channel callback moves the position of the stream to the end thus starting the new sub-sound.

  • You must to post comments
0
0

update on multi-loops using FMOD’s loop mechanism.
after trying different approaches to this i went back to FMOD’s looping mechanism and came up with a logic that allowed for multi-loop points on a stream. there are some limitations but very usefull for phrases of music for looping. and using FMOD mechanism means its byte accurate.
limitations are: can not change current loop points (ie the loop FMOD is currently playing), limited size of first loop point (can be resolved by decreasing decode buffer size), loop-points must be ordered (no going back but you can use setPosition) and last loop-point is 1 sample short (i guess so not to trip the end of stream flag for the channel to release).

  • You must to post comments
0
0

In a future release we’ll be introducing the concept of ‘sound shaders’ which will allow things like command lists to be placed into a sound to allow logic for looping (multiple loops, jumping from one sample point to another with sample accuracy, volume ramps etc)

  • You must to post comments
0
0

[quote="brett":ycu4ist8]In a future release we’ll be introducing the concept of ‘sound shaders’ which will allow things like command lists to be placed into a sound to allow logic for looping (multiple loops, jumping from one sample point to another with sample accuracy, volume ramps etc)[/quote:ycu4ist8]

That sounds fantastic. I eagerly anticipate that release!

  • You must to post comments
0
0

great! this feature would really provide extra control over a single stream (including stopping a stream) adding flexibility to an already great audio engine. cheers

  • You must to post comments
Showing 16 results
Your Answer

Please first to submit.