Hi,
I have made a script that records sound in my Unity game and I want to save the recording to a .wav file
I found a solution regarding this but that is in C language, so can you help me in converting the C script to a C# script.
This is the script I used for recording.
RecordMic.txt (4.2 KB)
solution in C language
Thanks
Hi, @Connor_FMOD
I am facing a major bottleneck can you please help me by providing a solution for how to save a sound to a .wav file. Is it possible to do this using C# language?
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));
}
}
}
Thank you for the solution @jeff_fmod
Newbie here, but how do you specify a new file path other than the project root to save the file?
Hi,
To set a location you can pass it into the extra driver data: FMOD Engine | Core API Data.
This will also require using a callback handler to assign the extra driver data before the FMOD system has been initialized, we have an example of how to implement that here: Unity integration | Scripting Examples: Callback Handler.
If you have followed the tutorial then you will pass the extra driver data here:
ERRCHECK( wavWriterSystem.init(100, INITFLAGS.NORMAL, /*ExtraDriverData*/) );
Hope this helps!