Hi everyone.
i’m working on a research project where i need to record multiple microphones simultaneousely in unity. I’ve decided to use FMOD for this. Now i’m running into the problem that, while the windows default microphone records fine, as soon as i select a mic with an index other than 0 (default recording device) it wont record.
i’m getting FMOD OK results all the way but the current record position of the sound i record into doesn’t move (stays at 0).
Has anyone had this Problem before?
i will add some of my code here
void StartRecording()
{
FMOD.RESULT result = RuntimeManager.CoreSystem.getRecordNumDrivers(out numofDrivers, out numOfDriversConnected);
if (result != FMOD.RESULT.OK)
{
UnityEngine.Debug.LogError("Failed to detect connected Microphones: " + result);
return;
}
if (numOfDriversConnected == 0)
{
UnityEngine.Debug.Log("No microphone detected!");
return;
}
else
// UnityEngine.Debug.Log($"{numOfDriversConnected} microphones available.");
result = RuntimeManager.CoreSystem.getRecordDriverInfo(recordingDeviceIndex, out recordingDeviceName, 50,
out micGUID, out micSampleRate, out FMODSpeakerMode, out micNumOfChannels, out FMODmicDriverState);
UnityEngine.Debug.Log($"Mic selected: micName {recordingDeviceName} micSampleRate {micSampleRate} FMODSpeakerMode: {FMODSpeakerMode} micNumOfChannels: {micNumOfChannels} micDriverState: {FMODmicDriverState}");
UnityEngine.Debug.Log("Starting FMOD recording...");
soundInfo.cbsize = Marshal.SizeOf(typeof(FMOD.CREATESOUNDEXINFO));
// Set the number of channels (1 for mono, 2 for stereo, etc.)
soundInfo.numchannels = channels;
// Set desired sample rate here
soundInfo.defaultfrequency = samplingFrequency;
// Set Format for the samples (16bit/short here)
soundInfo.format = FMOD.SOUND_FORMAT.PCM16;
// Calculate the buffer length in bytes (5 seconds)
soundInfo.length = (uint)(samplingFrequency * sizeof(short) * soundInfo.numchannels * FMODrollingBufferLength);
result = FMODUnity.RuntimeManager.CoreSystem.createSound("", FMOD.MODE.OPENUSER | FMOD.MODE.LOOP_NORMAL, ref soundInfo, out recSound);
if (result != FMOD.RESULT.OK)
{
UnityEngine.Debug.LogError("Failed to create sound for recording: " + result);
return;
}
result = FMODUnity.RuntimeManager.CoreSystem.recordStart(recordingDeviceIndex, recSound, true);
if (result != FMOD.RESULT.OK)
{
UnityEngine.Debug.LogError("Failed to start recording: " + result);
return;
}
else
{
UnityEngine.Debug.Log($"recording start result: {result}");
}
result = recSound.getLength(out recSoundLength, FMOD.TIMEUNIT.PCM);
if (result != FMOD.RESULT.OK)
{
UnityEngine.Debug.LogError("Failed to start recording: " + result);
return;
}
// recSoundLengthSamples = (uint)(recSoundLength / (sizeof(short) * channels));
UnityEngine.Debug.Log($"Recording started. Buffer Length: {recSoundLength} samples");
FMODUnity.RuntimeManager.CoreSystem.getRecordPosition(0, out lastReadPos);
}
public byte[] FetchAudioData(int bufferSize)
{
// Calculate the size in bytes (16-bit PCM = 2 bytes per sample)
// Prepare a buffer to hold the fetched audio data
byte[] audioData = new byte[bufferSize * 2];
uint currentRecordPos = 0;
FMOD.RESULT result = FMODUnity.RuntimeManager.CoreSystem.getRecordPosition(0, out currentRecordPos);
if (result != FMOD.RESULT.OK)
{
UnityEngine.Debug.LogError("Failed to get recording position: " + result);
return audioData;
}
// Calculate the amount of new data available since the last read position
uint availableSamples;
if (currentRecordPos >= lastReadPos) {
availableSamples = currentRecordPos - lastReadPos;
} else {
// When currentRecordPos has wrapped around and is less than lastReadPos,
// add recSoundLength to currentRecordPos before subtracting to get the correct distance
availableSamples = (currentRecordPos + recSoundLength) - lastReadPos;
}
// If there's enough data to read
if (availableSamples >= bufferSize) { // Example buffer size
// UnityEngine.Debug.Log($"Fetching audio data. Available Samples: {availableSamples}, Buffer Size: {bufferSize}, currentRecordPos: {currentRecordPos}, lastReadPos: {lastReadPos}, recSoundLength: {recSoundLength}");
//skip one buffer to catch up if needed
if (availableSamples > 2*bufferSize) {
buffersSkipped ++;
lastReadPos = (uint)((lastReadPos + bufferSize) % recSoundLength); // Update last read position
UnityEngine.Debug.LogWarning($"Skipping buffer to catch up with recorded real-time audio data. Sent: {buffersProcessed}, Skipped: {buffersSkipped}");
}
uint byteOffset = (uint)(lastReadPos * sizeof(short) * channels);
IntPtr dataPtr1, dataPtr2;
uint length1, length2;
uint lengthInBytes = (uint)(bufferSize * sizeof(short) * channels);
if (byteOffset > recSoundLength * sizeof(short))
{
UnityEngine.Debug.LogError($"byteOffset out of bounds: {byteOffset}");
return audioData;
}
result = recSound.@lock(byteOffset, lengthInBytes, out dataPtr1, out dataPtr2, out length1, out length2);
if (result != FMOD.RESULT.OK)
{
UnityEngine.Debug.LogError("Failed to lock recording buffer: " + result);
return audioData;
}
// Copy from the first block of data
if (dataPtr1 != IntPtr.Zero && length1 > 0)
{
Marshal.Copy(dataPtr1, audioData, 0, (int)length1);
}
// If there's a second block of data due to wrap-around, copy it immediately after the first block
if (dataPtr2 != IntPtr.Zero && length2 > 0)
{
Marshal.Copy(dataPtr2, audioData, (int)length1, (int)length2); // Notice how we start copying at the end of the first block
}
// Unlock the sound object
recSound.unlock(dataPtr1, dataPtr2, length1, length2);
buffersProcessed ++;
lastReadPos = (uint)((lastReadPos + bufferSize) % recSoundLength); // Update last read position
// audioData contains the left channel audio data in 16-bit PCM format
return audioData;
}
else
{
return null;
}
}
I would greatly appreciate any help i can get.