Mic state when recording

Hey there,

I recently posted a question and kept digging further. I now got a mic working with FMOD in Unity, and am able to hear myself. There is some weird stuff happening still though.
When I talk thru the microphone, it sounds very distorted. Another odd thing that happens is the recording looping back. So after a little while, I hear the recording of before basically.

Feel like I’m getting closer to my endpoint, but currently stuck on the mic sounding distorted and the looping.

A complete different question, is there a way to tell if a microphone is picking up sounds? Like is there a possibility to just add a boolean that reacts to input to the microphone? I know it’s a possibility with just playing back sounds, I did it with the getPlaybackState in another script that reads data from an audio clip.

Hope to hear from you guys,
Niels :slight_smile:

using UnityEngine;
using System;
using System.Text;  
using System.Runtime.InteropServices;

public class MicSound : MonoBehaviour
{
public bool m_isrecording;
public FMOD.Sound m_Sound;
public string mic;
public int systemRate, speakerModeChannels;
public FMOD.SPEAKERMODE speakerMode = FMOD.SPEAKERMODE.RAW;
public FMOD.DRIVER_STATE driverState = FMOD.DRIVER_STATE.DEFAULT;

public int numDriv, numCon;

FMOD.RESULT m_Result;
FMOD.MODE soundMode = FMOD.MODE.OPENUSER | FMOD.MODE.LOOP_NORMAL;
FMOD.CREATESOUNDEXINFO exinfo;
public byte[] m_Bytes;
public FMOD.ChannelGroup channelGroup;
public FMOD.Channel channel;

void Start()
{
    FMODUnity.RuntimeManager.CoreSystem.getRecordDriverInfo(0, out mic, 1, out Guid guid, out systemRate, out speakerMode, out speakerModeChannels, out driverState);
    FMODUnity.RuntimeManager.CoreSystem.getRecordNumDrivers(out numDriv, out numCon);

    exinfo.cbsize = Marshal.SizeOf(exinfo);
    exinfo.numchannels = speakerModeChannels;
    exinfo.format = FMOD.SOUND_FORMAT.PCM16;
    exinfo.defaultfrequency = systemRate;
    exinfo.length = (uint)(exinfo.defaultfrequency * exinfo.numchannels * sizeof(short)) * 8;

    byte[] m_Bytes = new byte[exinfo.length + 1];

    m_Result = FMODUnity.RuntimeManager.CoreSystem.createSound(m_Bytes, soundMode, ref exinfo, out m_Sound);

    if (m_Result != FMOD.RESULT.OK)
    {
        UnityEngine.Debug.Log("failed to createSound: " + m_Result);
        return;
    }

    m_Result = FMODUnity.RuntimeManager.CoreSystem.recordStart(0, m_Sound, false);

    if (m_Result != FMOD.RESULT.OK)
    {
        UnityEngine.Debug.Log("failed to startrecord: " + m_Result);
    }
    else
    {
        m_isrecording = true;
        UnityEngine.Debug.Log("Recording " + m_Result);
    }

    //test play
    FMODUnity.RuntimeManager.CoreSystem.playSound(m_Sound, channelGroup, false, out channel);
}

This might help someone who has more knowledge about all the FMOD stuff, haha.

This sounds like it is because there is no latency between recording and playback.

https://fmod.com/resources/documentation-api?version=2.1&page=core-guide.html#recording-record-to-a-sound-from-microphone-or-line-in

The sound can also be played while it is recording, to allow realtime effects. A simple technique to achieve this is to start recording, then wait a small amount of time, like 50ms, then play the sound. This will keep the play cursor just behind the record cursor. See the record example for source and information on how to do this.

The record example can be found in the API download.

Hey,

Thans for your reply! It really helps.
Can you maybe paste the link for the API download? I can’t seem to find it on the Download page. Went thru the entire Unity Feature Demo, and there’s nothing like a record example in there.

Thanks again,
Niels :slight_smile:

Sorry it’s called the “FMOD Engine”, under “FMOD Studio Suite”.

Hey,

Thanks again for the help. Found the download with the examples you were talking about. Not something that will solve my problem, but that’s alright.
I added a delay on the moment the sound starts playing, and it now works fluently. There is only one thing left to do for me, and that’s to either get data out of my sound, or get like a status if sound is being made (like talking into the mic, or not).
I looked at the documentation, and tried to make my script work with readData, lock, unlock on the sound, but didn’t get the result I expected. Also tried to use the DSP_FFT.SPECTRUMDATA function, which I’m familiar with due to reading from a sound file, and making objects scale based on it’s volume. Also couldn’t get it to work properly.

Do you have an idea of what function to use, or is there an other simple solution for this?

Thanks again, already helped me a ton :slight_smile:
Niels

I know it won’t work with all the functions active, but here is the lines I used to test it out, for testing purposes, I activated them, but manually commented them out to actually test them.

void Update()
{
m_Sound.readData(buffer, length, out read);
m_Sound.@lock(offset, length, out ptr1, out ptr2, out len1, out len2);
m_Sound.unlock(ptr1, ptr2, len1, len2);
if (channelGroup.hasHandle())
{
channelGroup.isPlaying(out m_isPlaying);
}
if (m_isPlaying && m_dspAdded)
{
m_Result = m_DataDsp.getParameterData((int)FMOD.DSP_FFT.SPECTRUMDATA, out unmanagedData, out length);
m_DataParam = (FMOD.DSP_PARAMETER_FFT)Marshal.PtrToStructure(unmanagedData, typeof(FMOD.DSP_PARAMETER_FFT));
for (int bin = 1; bin < WINDOWSIZE; bin++)
{
float temp = lin2DB(m_DataParam.spectrum[0][bin]);
temp = ((temp + 80.0f) * (1 / 80.0f));
m_DataArray[bin] = Mathf.Lerp(m_DataArray[bin], temp, 0.6f);
}
}
}

There isn’t an api to find out the status of the sound being recorded, but using the spectrum data should work. What about it isn’t working? The code looks fine from what you have shown.

So, which method should I use? The spectrumdata one?
I’ve been trying to make it work properly, but can’t wrap my hands around it just yet.

if (m_dspAdded)
{
m_Result = m_DataDsp.getParameterData((int)FMOD.DSP_FFT.SPECTRUMDATA, out unmanagedData, out length);
Debug.Log("unmangData " + unmanagedData + " length " + length); //passes
m_DataParam = (FMOD.DSP_PARAMETER_FFT)Marshal.PtrToStructure(unmanagedData, typeof(FMOD.DSP_PARAMETER_FFT));
if (m_DataParam.numchannels < 1)
{
Debug.Log(“Failure”);
return;
}
Debug.Log("DataParam " + m_DataParam.spectrum[1][1]); //error
for (int bin = 1; bin < WINDOWSIZE; bin++)
{
float temp = lin2DB(m_DataParam.spectrum[0][bin]);
temp = ((temp + 80.0f) * (1 / 80.0f));
m_DataArray[bin] = Mathf.Lerp(m_DataArray[bin], temp, 0.6f);
}
}

Tried this, just to see where my problem occurs, and I guess it’s in the numChannels.
Since I’m asking for the script to debug, this is what it looks like as of right now:

Looks like it passes the getParameterData function, but gets stuck at the PtrToStructure function.
If I remove the numChannels check, it gives me the ‘Out of bounds error’, but that’s probably caused by the parameter not being set up properly. Do you have any idea on how to move on? Feel like I’m almost there!

Thanks :slight_smile: