using FMODUnity; using UnityEngine; using System.Collections; using System.Runtime.InteropServices; using System.Collections.Generic; using System.IO; using TMPro; public class RecordMic : MonoBehaviour { //Retrieve file location [Header("File Path")] public TMP_InputField filePath; //public variables [Header("Choose A Microphone")] public int recordingDeviceIndex = 0; [TextArea] public string recordingDeviceName = null; //FMOD Objects private FMOD.Sound sound; private FMOD.CREATESOUNDEXINFO exinfo; private FMOD.Channel channel; private FMOD.Channel wavChannel; private FMOD.ChannelGroup channelGroup; //How many recording devices are plugged in for us to use. private int numOfDriversConnected = 0; private int numofDrivers = 0; //Info about the device we're recording with. private System.Guid MicGUID; private int SampleRate = 0; private FMOD.SPEAKERMODE FMODSpeakerMode; private int NumOfChannels = 0; private FMOD.DRIVER_STATE driverState; private FMOD.System micRecordSystem, wavWriterSystem; private string micRecordData = "MICTEST"; private string wavWiterData = "WAVWRITER"; //Display selectable drivers public List _connectedDevices = new List(); private bool killed = false; private bool recording = false; private bool stopped = false; private bool soundActive = true; void Start() { //Creating systems to record and output mic input ------------------------------------------------------------- GCHandle micRecordDataPtr = GCHandle.Alloc(micRecordData); GCHandle wavWriterDataPrt = GCHandle.Alloc(wavWiterData); FMOD.RESULT result; FMOD.OUTPUTTYPE currentOutput; //Creating the mic system solely for recording mic input result = FMOD.Factory.System_Create(out micRecordSystem); ERRCHEK(result, "Failed to create mic sysytem"); //Initialize mic record system result = micRecordSystem.init(100, FMOD.INITFLAGS.NORMAL, GCHandle.ToIntPtr(micRecordDataPtr)); ERRCHEK(result, "Mic system int failed"); //Checking current output for the system result = micRecordSystem.getOutput(out currentOutput); ERRCHEK(result, "Failed to check output", "Mic system current ouput " + currentOutput.ToString() + " with result "); //Creating the wav writter system result = FMOD.Factory.System_Create(out wavWriterSystem); ERRCHEK(result, "Failed to create wav system"); //Initialize wav writer sytem result = wavWriterSystem.init(100, FMOD.INITFLAGS.NORMAL, GCHandle.ToIntPtr(wavWriterDataPrt)); ERRCHEK(result, "Failed to init wav write system"); //Assigining output of Wav system to nosound, till we are ready to record sound result = wavWriterSystem.setOutput(FMOD.OUTPUTTYPE.NOSOUND); wavWriterSystem.getOutput(out currentOutput); ERRCHEK(result, "Failed to change wav output", "Wav system current output " + currentOutput.ToString() + " with result "); //------------------------------------------------------------------------------------------------------------- //Step 1: Check to see if any recording devices (or drivers) are plugged in and available for us to use. micRecordSystem.getRecordNumDrivers(out numofDrivers, out numOfDriversConnected); if (numOfDriversConnected == 0) { Debug.Log("Hey! Plug a Microhpone in ya dummy!!!"); micRecordSystem.release(); return; } else Debug.Log("You have " + numOfDriversConnected + " microphones available to record with."); //Step 2: Get all of the information we can about the recording device (or driver) that we're // going to use to record with. result = micRecordSystem.getRecordDriverInfo(recordingDeviceIndex, out recordingDeviceName, 50, out MicGUID, out SampleRate, out FMODSpeakerMode, out NumOfChannels, out driverState); ERRCHEK(result, "Failed to retrieve record driver info"); //Step 3: Store relevant information into FMOD.CREATESOUNDEXINFO variable. exinfo.cbsize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(FMOD.CREATESOUNDEXINFO)); exinfo.numchannels = NumOfChannels; exinfo.format = FMOD.SOUND_FORMAT.PCM16; exinfo.defaultfrequency = SampleRate; exinfo.length = (uint)SampleRate * sizeof(short) * (uint)NumOfChannels * 1000; Debug.Log("Assinged exit info"); //Step 4: Create an FMOD Sound "object". This is what will hold our voice as it is recorded. result = micRecordSystem.createSound("Sound", FMOD.MODE.LOOP_NORMAL | FMOD.MODE.OPENUSER, ref exinfo, out sound); ERRCHEK(result, "Failed to create sound"); } void Update() { //Updating both the create systems if (!killed) { micRecordSystem.update(); wavWriterSystem.update(); } //START RECORDING---------------------------------------------------------------------------------------------- if (Input.GetKeyDown(KeyCode.R) && !recording && soundActive) { SetState("Recording"); FMOD.RESULT result; result = micRecordSystem.recordStart(recordingDeviceIndex, sound, true); ERRCHEK(result, "Failed to start recording"); //Playing the sound to the mic record system result = micRecordSystem.playSound(sound, channelGroup, false, out channel); ERRCHEK(result, "Failed to play sound on mic system"); //Playing the sound on the wav system result = wavWriterSystem.playSound(sound, channelGroup, false, out wavChannel); ERRCHEK(result, "Failed to play sound on wav system"); //Start wav system writing to file, make sure this only happens once result = wavWriterSystem.setOutput(FMOD.OUTPUTTYPE.WAVWRITER); ERRCHEK(result, "Wav system failed to start writing to file", "Wav system now writting to file"); } //------------------------------------------------------------------------------------------------------------- //STOP RECORDING----------------------------------------------------------------------------------------------- if (Input.GetKeyDown(KeyCode.S) && !stopped && recording) { SetState("Stopped"); //Stopping the recording FMOD.RESULT result = micRecordSystem.recordStop(recordingDeviceIndex); ERRCHEK(result, "Failed to stop recording on mic system"); //Should stop WASAPI starving------------------------------------------------------------------------------ result = wavChannel.stop(); ERRCHEK(result, "Failed to stop wav channel"); result = channel.stop(); ERRCHEK(result, "Failed to stop mic channel"); //--------------------------------------------------------------------------------------------------------- result = sound.release(); ERRCHEK(result, "Failed to release sound"); //Stop the wav system writting to file result = wavWriterSystem.setOutput(FMOD.OUTPUTTYPE.NOSOUND); ERRCHEK(result, "Failed to chage wav system output"); } //------------------------------------------------------------------------------------------------------------- //RECREATE SOUND----------------------------------------------------------------------------------------------- if (Input.GetKeyDown(KeyCode.L) && killed && stopped) { SetState("Restart"); //Only need to recreate the sound FMOD.RESULT result = micRecordSystem.createSound("Sound", FMOD.MODE.LOOP_NORMAL | FMOD.MODE.OPENUSER, ref exinfo, out sound); ERRCHEK(result, "Failed to recreate sound"); //Removing old wav so that the new one can be recorded if (filePath.text.Length != 0) { File.Delete(filePath.text); #if UNITY_EDITOR Debug.Log("Deleted .wav file"); #endif } } //------------------------------------------------------------------------------------------------------------- } //REMEMBER TO RELEASE SYSTEMS SO THERE ARENT MEMORY LEAKS, this will get called if you stop play or if the object is destroyed private void OnDestroy() { micRecordSystem.release(); wavWriterSystem.release(); } /// /// Use to debug FMOD functions with explanation of what the function was doing with both success and failed messages /// /// /// /// private void ERRCHEK(FMOD.RESULT result, string failed, string success) { #if UNITY_EDITOR if (result.ToString().Length != 0) { if (result != FMOD.RESULT.OK) Debug.Log(failed + " " + result); else Debug.Log(success + " " + result); } #endif } /// /// Override of no success message is required /// /// /// private void ERRCHEK(FMOD.RESULT result, string failed) { //Will only call debugs if in editor to save on calls in build #if UNITY_EDITOR if (result.ToString().Length != 0) { if (result != FMOD.RESULT.OK) Debug.Log(failed + " " + result); } #endif } private void SetState(string currentState) { switch(currentState) { case "Recording": { recording = true; stopped = false; killed = false; #if UNITY_EDITOR Debug.Log("RECORDING"); #endif break; } case "Stopped": { recording = false; stopped = true; killed = true; soundActive = false; #if UNITY_EDITOR Debug.Log("STOPPED"); #endif break; } case "Restart": { recording = false; stopped = false; killed = false; soundActive = true; #if UNITY_EDITOR Debug.Log("RESTARTING"); #endif break; } } } }