Apologies for the delay, we somehow missed this post.The C++ example you’ve linked to is probably a little more low-level than you need- that is for manually creating a wav file whereas you can just use the WAVWRITER
output type in a separate system object.
We had a similar question recently where @Connor_FMOD provided a solution in Unity using two system objects; one to record mic input and one to output the wav file. Here is that example again, pared back a bit more just to have the basics of starting and stopping a recording. Use “R” to start the recording and “S” to stop, at which point a file called “fmodoutput.wav” will appear in the root of your Unity project.
RecordMicOutputWav.cs
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using UnityEngine;
using FMOD;
public class RecordMicOutputWav : MonoBehaviour
{
public float Latency = 0.2f;
public int RecordingDeviceIndex = 0;
public string RecordingDeviceName = null;
public List<string> ConnectedDevices = new List<string>();
private Sound sound;
private CREATESOUNDEXINFO exinfo;
private Channel channel;
private Channel wavChannel;
private ChannelGroup channelGroup;
private FMOD.System micRecordSystem, wavWriterSystem;
private bool recording = false;
private int SampleRate = 0;
private int NumChannels = 0;
private float time = 0.0f;
private void Start()
{
ERRCHECK( Factory.System_Create(out micRecordSystem) );
ERRCHECK( Factory.System_Create(out wavWriterSystem) );
ERRCHECK( micRecordSystem.init(100, INITFLAGS.NORMAL, System.IntPtr.Zero) );
ERRCHECK( wavWriterSystem.init(100, INITFLAGS.NORMAL, System.IntPtr.Zero) );
ERRCHECK( wavWriterSystem.setOutput(OUTPUTTYPE.NOSOUND) );
InitRecordingDevices();
InitExInfo();
}
private void OnDestroy()
{
if(recording)
{
StopRecording();
}
ERRCHECK( micRecordSystem.release() );
ERRCHECK( wavWriterSystem.release() );
}
private void Update()
{
if (recording)
{
time += Time.deltaTime;
if (time >= Latency)
{
ERRCHECK( micRecordSystem.update() );
ERRCHECK( wavWriterSystem.update() );
}
}
if (Input.GetKeyDown(KeyCode.R))
{
StartRecording();
}
if (Input.GetKeyDown(KeyCode.S))
{
StopRecording();
}
}
private void StartRecording()
{
recording = true;
ERRCHECK( micRecordSystem.createSound(exinfo.userdata, MODE.LOOP_NORMAL | MODE.OPENUSER, ref exinfo, out sound) );
ERRCHECK( micRecordSystem.recordStart(RecordingDeviceIndex, sound, true) );
ERRCHECK( wavWriterSystem.setOutput(OUTPUTTYPE.WAVWRITER) );
ERRCHECK( micRecordSystem.playSound(sound, channelGroup, false, out channel) );
ERRCHECK( wavWriterSystem.playSound(sound, channelGroup, false, out wavChannel) );
}
private void StopRecording()
{
recording = false;
time = 0.0f;
ERRCHECK( micRecordSystem.recordStop(RecordingDeviceIndex) );
ERRCHECK( wavChannel.stop() );
ERRCHECK( channel.stop() );
ERRCHECK( sound.release() );
ERRCHECK( wavWriterSystem.setOutput(OUTPUTTYPE.NOSOUND) );
}
private void InitExInfo()
{
exinfo.cbsize = Marshal.SizeOf(typeof(CREATESOUNDEXINFO));
exinfo.numchannels = NumChannels;
exinfo.format = SOUND_FORMAT.PCM16;
exinfo.defaultfrequency = SampleRate;
exinfo.length = (uint)SampleRate * sizeof(short) * (uint)NumChannels;
}
private void InitRecordingDevices()
{
ERRCHECK( micRecordSystem.getRecordNumDrivers(out int numdDrivers, out _) );
for (int i = 0; i < numdDrivers; ++i)
{
ERRCHECK( micRecordSystem.getRecordDriverInfo(i, out string name, 64, out _, out int sampleRate, out _, out int numChannels, out _) );
ConnectedDevices.Add(name);
if (i == RecordingDeviceIndex)
{
RecordingDeviceName = name;
SampleRate = sampleRate;
NumChannels = numChannels;
}
}
}
private void ERRCHECK(RESULT result, [CallerLineNumber] int lineNumber = 0, [CallerMemberName] string failed = null)
{
if (result != RESULT.OK)
{
UnityEngine.Debug.LogError(lineNumber + "(" + failed + "): " + Error.String(result));
}
}
}