Answered
0
0

Hello Guys,

I’m writing a Unity class to playback and capture 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.

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);
FMOD.SOUND_PCMSETPOSCALLBACK pcmsetposcallbackPtr = new FMOD.SOUND_PCMSETPOSCALLBACK(pcmsetposcallbackFunc);
int driverId;

// Use this for initialization
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;
    }


}

// not used
static FMOD.RESULT pcmsetposcallbackFunc(IntPtr soundraw, int subsound, uint position, FMOD.TIMEUNIT postype)
{
    return FMOD.RESULT.OK;
}

// 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 () {
}

}

  • You must to post comments
Best Answer
0
0

Those callbacks aren’t what you want.

Each frame use System.getRecordPosition() to track how much audio has been recorded since the last frame, and then use Sound.@lock() to get a pointer to the data and copy it out. Be aware you’ll have to deal with the buffer wrapping around.

  • You must to post comments
Showing 1 result
Your Answer

Please first to submit.