I made my own sound player using the Unity version of FMOD’s core system.
However, some functionalities are seemingly not working and it feels really weird.
- I’ve set a SYNCPOINT callback and it seems to be called normally. But I can’t get its info with getSyncPointInfo() function. The syncpoint index is always 0 and the name in string type is empty.
- I can’t stop the playback of my sound’s channel with the channel’s stop() function. Whenever I call that, [FMOD] assert : assertion: ‘mUserCallbackThreadId == 0’ failed occurs and the playback continues until it reaches the end. I found a workaround using setPaused(false) function instead but it doesn’t seem legit.
Why do these happen and what can I do?
Below is the entire source code I’m currenty tackling.
public class DirectSoundPlayer : MonoBehaviour
{
private FMOD.System coreSystem;
private Sound sound;
private Channel channel;
private ChannelGroup masterGroup;
private uint syncPointIndex;
private void Start()
{
coreSystem = RuntimeManager.CoreSystem;
coreSystem.getMasterChannelGroup(out masterGroup);
}
public void PlayAudioSegment(string filePath, uint startPos, uint endPos, float pitch = 1.0f)
{
// Stop and release any previously playing sound
StopAudio();
// Create the sound
var exInfo = new CREATESOUNDEXINFO
{
cbsize = Marshal.SizeOf(typeof(CREATESOUNDEXINFO))
};
coreSystem.createSound(filePath, MODE.CREATESTREAM, ref exInfo, out sound);
// Play the sound
coreSystem.playSound(sound, masterGroup, true, out channel);
// Set the playback position
channel.setPosition(startPos, TIMEUNIT.MS);
// Set up DSP effect for pitch shifting
coreSystem.createDSPByType(DSP_TYPE.PITCHSHIFT, out var pitchShift);
pitchShift.setParameterFloat((int)DSP_PITCHSHIFT.PITCH, pitch);
channel.addDSP(0, pitchShift);
// Sync point approach to stop at a specific point of the audio clip
sound.addSyncPoint(endPos, FMOD.TIMEUNIT.MS, "StopPoint", out var syncPoint);
channel.setCallback(ChannelStopCallback);
channel.setPaused(false);
}
RESULT ChannelStopCallback(IntPtr channelcontrol, CHANNELCONTROL_TYPE controltype, CHANNELCONTROL_CALLBACK_TYPE callbacktype, IntPtr commanddata1, IntPtr commanddata2)
{
if (callbacktype == FMOD.CHANNELCONTROL_CALLBACK_TYPE.SYNCPOINT)
{
// The "syncPointOffset" is always 0 and the other debug info is empty
/*sound.getSyncPointInfo(commanddata1, out var syncPointName, "StopPoint".Length, out var syncPointIndex, TIMEUNIT.MS);*/
/*sound.getSyncPointInfo(commanddata1, out var syncPointOffset, TIMEUNIT.MS);*/
/*Debug.LogWarning($"syncPointOffset: {syncPointOffset}, syncPointIndex: {syncPointIndex}, raw commanddata1: {commanddata1}");*/
// "[FMOD] assert : assertion: 'mUserCallbackThreadId == 0' failed" error occurs
/*channel.stop();*/
var newChannel = new FMOD.Channel(channelcontrol);
newChannel.setPaused(true); // Workaround. This is the only working way.
}
return RESULT.OK;
}
// Following thread error occurs:
// [FMOD] assert : assertion: 'mUserCallbackThreadId == 0' failed
public void StopAudio()
{
if (channel.hasHandle())
{
channel.stop();
}
if (sound.hasHandle())
{
sound.release();
}
}
public void SetPitch(float pitch)
{
if (channel.hasHandle())
{
channel.getDSP(0, out var pitchShift);
pitchShift.setParameterFloat((int)DSP_PITCHSHIFT.PITCH, pitch);
}
}
private void OnDestroy()
{
StopAudio();
}
}