FMOD pcmreadcallback never is called while playing audio from a microphone source

621 Views Asked by At

I'm writing a Unity class to capture and playback audio data from a microphone. Playback part works fine I can hear my voice in the headphones but I cannot access audio samples because pcmsetposcallback is never called during playback. It is called only once inside createSound method. I think i'm missing some setting , also tried several OR combinations for FMOD.MODE flag but with no luck. I'm using fmodstudio10510.unitypackage and testing under windows 7 but it should have fully croos-platform support. Thanks in advance. Walter

public class AudioInit : MonoBehaviour {

    FMOD.System lowlevel = null;
    FMOD.Sound snd = null;

    // callbacks delegates
    FMOD.SOUND_PCMREADCALLBACK pcmreadcallbackPtr = new FMOD.SOUND_PCMREADCALLBACK (pcmreadcallbackFunc);
    int driverId;

    void Start () {

        int channels = 1;
        int sampleRate = 8000;
        float recordTime = 1.0f;

        // get low level instance
        FMOD_StudioSystem.instance.System.getLowLevelSystem(out lowlevel);

        // fill sound info struct
        FMOD.CREATESOUNDEXINFO soundInfo = new FMOD.CREATESOUNDEXINFO ();       
        soundInfo.cbsize = System.Runtime.InteropServices.Marshal.SizeOf (typeof(FMOD.CREATESOUNDEXINFO));
        soundInfo.length  = (uint)(sampleRate * channels * sizeof(byte) * recordTime);      
        soundInfo.numchannels       = channels;
        soundInfo.defaultfrequency  = sampleRate;
        soundInfo.format            = FMOD.SOUND_FORMAT.PCM8;
        soundInfo.pcmreadcallback = pcmreadcallbackPtr;
        soundInfo.pcmsetposcallback = pcmsetposcallbackPtr;
        soundInfo.dlsname = IntPtr.Zero;

        // FMODE MODE flag
        FMOD.MODE mode = FMOD.MODE.OPENUSER | FMOD.MODE.LOOP_NORMAL;

        // create sound
        FMOD.RESULT res = lowlevel.createSound((string)null, mode, ref soundInfo, out snd);

        if (res != FMOD.RESULT.OK) {
            Debug.Log ("ERROR snd " + res.ToString ());
            return;
        }

        // get driver
        res = lowlevel.getDriver (out driverId);        
        if (res != FMOD.RESULT.OK) {
            Debug.Log ("ERROR getDriver " + res.ToString ());
            return;
        }

        // start record from microphone
        res = lowlevel.recordStart (driverId, snd, true);       
        if (res != FMOD.RESULT.OK) {
            Debug.Log ("ERROR recordStart " + res.ToString ());
            return;
        }

        uint pos = 0;
        uint tries = 10;
        // wait for a valid record position
        while ( !(pos > 0) && (tries--) > 0 ) {

            if ( lowlevel.getRecordPosition(driverId, out pos) == FMOD.RESULT.OK ){
                System.Threading.Thread.Sleep(100);
            } else { break; }
        }
        if ( !( pos > 0 )) {
            Debug.Log ("ERROR invalid record position");
            return;
        }

        // start playback
        FMOD.Channel chn;
        res = lowlevel.playSound (snd, new FMOD.ChannelGroup (IntPtr.Zero), false, out chn);

        if (res != FMOD.RESULT.OK) {
            Debug.Log ("ERROR recordStart " + res.ToString ());
            return;
        }
    }

    // only called once during lowlevel.createSound execution 
    static FMOD.RESULT pcmreadcallbackFunc (IntPtr sound, IntPtr data, uint len){

        Debug.Log("pcmreadcallback sample size " + len.ToString());
        return FMOD.RESULT.OK;
    }

    // Update is called once per frame
    void Update () {
    }

}
1

There are 1 best solutions below

0
On

The recording system doesn't go via pcmreadcallback, that's why you aren't getting those callbacks.

To access the microphone data use Sound::lock and Sound::unlock.