0
0

I’m getting ERR_CHANNEL_STOLEN or ERR_INVALID_HANDLE errors after re-playing new sounds in my game engine for a few seconds (at about 3 to 10 new sounds per second (sounds that are about 1 second long)). I can’t tell why one error or the other occurs, it just seems to be randomly one or the other. Do I have to make some explicit call to free up a channel. I thought the channel would be freed up when the sound finished playing. I get the error during a call to channel.isPlaying. I can post a link to source code later, but if anyone has any preliminary thoughts on attacking this problem, I might be able to skip that. I’m writing in C# using fmodex.dll version 0.4.6.1. The channel number parameter I’m using in sound.play is FMOD.CHANNELINDEX.FREE. The error seems to happen after approximately the number of channels I reserved (32) but I think sometimes I get a few extra in.

  • You must to post comments
0
0

Why is Channel.getRaw not documented? I think I’ll need to be using it.

  • You must to post comments
0
0

Are you using the update function?

[quote:2a22d084]FMOD_RESULT System::update();

Updates the FMOD system. This should be called once per ‘game’ tick, or once per frame in your application.[/quote:2a22d084]

I remember getting a similar issue until I added this into the mix.

To my understanding, channels which have been played on won’t be flagged as ‘free’ (even if a sound on a channel has ended) unless this function is called to ‘update’ the channel status.

~Brandon

  • You must to post comments
0
0

I think I finally got it. I had to add all the sounds that might be playing to a list so I could reset their channels when they stop playing so I don’t look at that channel any more:

[code:1v9znt2p]
...
ERRCHECK(system.playSound(FMOD.CHANNELINDEX.FREE, Sound.sound, false, ref Sound.channel));
FMOD.CHANNEL_CALLBACK cb = (FMOD.CHANNEL_CALLBACK)Delegate.CreateDelegate(typeof(FMOD.CHANNEL_CALLBACK), Sound, "Channel_Callback");
ERRCHECK(Sound.channel.setCallback(FMOD.CHANNEL_CALLBACKTYPE.END, cb, 0));
ERRCHECK(Sound.channel.setVolume(Sound.Volume));
ERRCHECK(system.update());
...

  private FMOD.RESULT Channel_Callback(IntPtr channelraw, FMOD.CHANNEL_CALLBACKTYPE type, int command, uint commanddata1, uint commanddata2)
  {
     for(int i=0; i<soundList.Count; i++)
     {
        FMODBase snd = (FMODBase)soundList[i];
        if ((snd.channel != null) && (snd.channel.getRaw() == channelraw))
           snd.channel = null;
     }
     return FMOD.RESULT.OK;
  }

[/code:1v9znt2p]

Still have to find a better place to call system.update, but this works at least.

  • You must to post comments
0
0

Cool, an easy fix! I’ll try it when I get home and hope for the best. How did you learn that you needed to call update? Forums or documentation or… ?

  • You must to post comments
0
0

There appears to be a gotcha with making the FMOD.CHANNEL_CALLBACK instance a local variable. When it gets passed to unmanaged code, and the local reference goes out of scope, a reference is no longer held by .NET, so in the next garbage collection, delegate will be garbage collected, and next time FMOD attempts to call the callback, a NullReferenceException occurs. At least this is my guess at the reasoning behind the NullReferenceException I’m seeing. It’s occurring in the fmod.cs implementation of system.update (when system.update gets called) and the call stack shows that the next level below FMOD_System_Update is 00000000(). My solution was to keep a reference to the callback delegate as a module level variable associated with each instance of my sound class. That seemed to fix my NullReferenceException. Since I never used that member again, I gotta believe the problem had something to do with .NET reference tracking. That would have been a real pain for someone who doesn’t understand Managed code and .NET reference tracking to figure out. Is there a proper way for unmanaged code to track references to managed callbacks?

  • You must to post comments
0
0

From the documentation:

System::update
Updates the FMOD system. This should be called once per ‘game’ tick, or once per frame in your application.

  • You must to post comments
0
0

Yes, I saw the note about the documentation above. I’m just wondering if in fact that’s where most people find out about this. One might have to read the description of every function to stumble accross this if that’s how you learn about it.

I tried calling update, but then my problem is that I can’t call isPlaying to see if a channel is playing any more because it’s no longer valid when it’s not playing. So I’m looking into callbacks. But I suspect update had the desired effect as far as releasing the channels. Maybe I should manually stop them when isPlaying turns to false if I care to know when they stop?

Any more thoughts?

  • You must to post comments
0
0

I have the same problem, I’m getting the occasional invalid handle, and am planning to try and get a callback system in to clear my pointers the the handles, as I don’t really like any errors being generated from FMOD calls.

I’ll let you know how I get on with it (probably a few days/weeks away with my schedule :) )

  • You must to post comments
0
0

Read

"Getting Started" tutorial instead of stumbling onto function docs. You should have read this if you haven’t used fmod before.
It has a large bolded header.

[quote:1fcivzlb]
Update. (This is important!)
It is important that System::update be called once per frame. Do not call this more than once per frame, as this is not necessary and is just inefficient.
This function updates the following aspects of FMOD Ex.
[/quote:1fcivzlb]

  • You must to post comments
0
0

Thanks for the tip on the getting started tutorial.

I’m still getting ERR_INVALID_HANDLE (and I think some ERR_CHANNEL_STOLEN) errors even when calling system.update(). I can tell that the channel usage is improved when calling update (which is strange because the update documentation doesn’t say anything about freeing channels, and the getting started documentation says you don’t have to worry about freeing channels). The error always seems to happen when calling isPlaying on the channel to determine if a sound is still playing. How’s this supposed to work? Am I supposed to be able to call isPlaying on a channel that has stopped playing after update has been called? I tried only doing it before update was called, but I still get errors… perhaps because between the time that I checked and the update, it finished playing, resulting in my code thinking that it’s still playing when it’s not. How’s this supposed to work? How can I possibly use isPlaying reliably?

  • You must to post comments
0
0

Read what the error for stolen actually means.
It probably means you have played more sounds than you have specified voices in system::init and when voices you have handles to get stolen, those handles become invalid.

  • You must to post comments
0
0

Oh, I already know what those errors mean. I just don’t know how to design my software to get around them because, although FMOD knows which channels are playing which sounds, it won’t tell me without returning errors. After I call update, there doesn’t seem to be a way to determine which sounds have stopped, so I can’t clean up my own references to channels that just became invalid. So they continue to remain active, sometimes until another sound is played on the same channel. So I think I pretty well understand the problem, and the only soluiton I can think of is eliminating my call to update and manually checking all the channels myself and calling stop on them so I can synchonize the channel management with my own code.

The problem used to be because I ran out of channels, as you suggest, but it’s not any more. I’m calling GetChannelsPlaying to see how many channels are playing, and it confirms that I’m only using 5 or so of my 32 channels. But there’s no way to determine which channels are playing, because FMOD just returns a count. And if I try to get a channel that’s not playing and call isPlaying on it, it tells me the channel handle is invalid.

  • You must to post comments
0
0

After some further searching, I see two things that might help that I’m going to look into further. channel->setCallback and channel->getCurrentSound.

  • You must to post comments
Showing 13 results
Your Answer

Please first to submit.