Created
January 23, 2016 13:32
-
-
Save abhisuri97/4cb754c8c0990690e860 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
using System; | |
using System.IO; | |
using System.Collections.Generic; | |
using System.Security.Cryptography; | |
using System.Text; | |
[RequireComponent (typeof (AudioSource))] | |
public class SingleMicrophoneCapture : MonoBehaviour | |
{ | |
//A boolean that flags whether there's a connected microphone | |
private bool micConnected = false; | |
//The maximum and minimum available recording frequencies | |
private int minFreq; | |
private int maxFreq; | |
//A handle to the attached AudioSource | |
private AudioClip goAudioSource; | |
//Use this for initialization | |
void Start() | |
{ | |
//Check if there is at least one microphone connected | |
if(Microphone.devices.Length <= 0) | |
{ | |
//Throw a warning message at the console if there isn't | |
Debug.LogWarning("Microphone not connected!"); | |
} | |
else //At least one microphone is present | |
{ | |
//Set 'micConnected' to true | |
micConnected = true; | |
//Get the default microphone recording capabilities | |
Microphone.GetDeviceCaps(null, out minFreq, out maxFreq); | |
//According to the documentation, if minFreq and maxFreq are zero, the microphone supports any frequency... | |
if(minFreq == 0 && maxFreq == 0) | |
{ | |
//...meaning 44100 Hz can be used as the recording sampling rate | |
maxFreq = 44100; | |
} | |
//Get the attached AudioSource component | |
goAudioSource = this.GetComponent<AudioClip>(); | |
} | |
} | |
void OnGUI() | |
{ | |
//If there is a microphone | |
if(micConnected) | |
{ | |
//If the audio from any microphone isn't being captured | |
if(!Microphone.IsRecording(null)) | |
{ | |
//Case the 'Record' button gets pressed | |
if(Input.GetMouseButtonDown(0)) | |
{ | |
//Start recording and store the audio captured from the microphone at the AudioClip in the AudioSource | |
goAudioSource = Microphone.Start(null, true, 10, 8000); | |
} | |
} | |
else //Recording is in progress | |
{ | |
//Case the 'Stop and Play' button gets pressed | |
if (Input.GetMouseButtonUp (0)) { | |
print ("YESESES2"); | |
Microphone.End (null); //Stop the audio recording | |
Save(GetUniqueKey(10), goAudioSource); //Playback the recorded audio | |
} | |
GUI.Label(new Rect(Screen.width/2-100, Screen.height/2+25, 200, 50), "Recording in progress..."); | |
} | |
} | |
else // No microphone | |
{ | |
//Print a red "Microphone not connected!" message at the center of the screen | |
GUI.contentColor = Color.red; | |
GUI.Label(new Rect(Screen.width/2-100, Screen.height/2-25, 200, 50), "Microphone not connected!"); | |
} | |
} | |
public static string GetUniqueKey(int maxSize) | |
{ | |
maxSize = 10; | |
System.Random rnd = new System.Random (); | |
int num = rnd.Next (1, 100000); | |
return num.ToString(); | |
} | |
public static bool Save(string filename, AudioClip clip) { | |
if (!filename.ToLower().EndsWith(".wav")) { | |
filename += ".wav"; | |
print (filename); | |
} | |
var filepath = Path.Combine(Application.persistentDataPath, filename); | |
Debug.Log(filepath); | |
// Make sure directory exists if user is saving to sub dir. | |
Directory.CreateDirectory(Path.GetDirectoryName(filepath)); | |
clip = TrimSilence (clip, 0); | |
using (var fileStream = CreateEmpty(filepath)) { | |
ConvertAndWrite(fileStream, clip); | |
WriteHeader(fileStream, clip); | |
} | |
return true; // TODO: return false if there's a failure saving the file | |
} | |
public static AudioClip TrimSilence(AudioClip clip, float min) { | |
var samples = new float[clip.samples]; | |
clip.GetData(samples, 0); | |
return TrimSilence(new List<float>(samples), min, clip.channels, clip.frequency); | |
} | |
public static AudioClip TrimSilence(List<float> samples, float min, int channels, int hz) { | |
return TrimSilence(samples, min, channels, hz, false, false); | |
} | |
public static AudioClip TrimSilence(List<float> samples, float min, int channels, int hz, bool _3D, bool stream) { | |
int i; | |
for (i=0; i<samples.Count; i++) { | |
if (Mathf.Abs(samples[i]) > min) { | |
break; | |
} | |
} | |
samples.RemoveRange(0, i); | |
for (i=samples.Count - 1; i>0; i--) { | |
if (Mathf.Abs(samples[i]) > min) { | |
break; | |
} | |
} | |
samples.RemoveRange(i, samples.Count - i); | |
var clip = AudioClip.Create("TempClip", samples.Count, channels, hz, _3D, stream); | |
clip.SetData(samples.ToArray(), 0); | |
return clip; | |
} | |
static FileStream CreateEmpty(string filepath) { | |
var fileStream = new FileStream(filepath, FileMode.Create); | |
byte emptyByte = new byte(); | |
for(int i = 0; i < 44; i++) //preparing the header | |
{ | |
fileStream.WriteByte(emptyByte); | |
} | |
return fileStream; | |
} | |
static void ConvertAndWrite(FileStream fileStream, AudioClip clip) { | |
var samples = new float[clip.samples]; | |
clip.GetData(samples, 0); | |
Int16[] intData = new Int16[samples.Length]; | |
//converting in 2 float[] steps to Int16[], //then Int16[] to Byte[] | |
Byte[] bytesData = new Byte[samples.Length * 2]; | |
//bytesData array is twice the size of | |
//dataSource array because a float converted in Int16 is 2 bytes. | |
int rescaleFactor = 32767; //to convert float to Int16 | |
for (int i = 0; i<samples.Length; i++) { | |
intData[i] = (short) (samples[i] * rescaleFactor); | |
Byte[] byteArr = new Byte[2]; | |
byteArr = BitConverter.GetBytes(intData[i]); | |
byteArr.CopyTo(bytesData, i * 2); | |
} | |
fileStream.Write(bytesData, 0, bytesData.Length); | |
} | |
static void WriteHeader(FileStream fileStream, AudioClip clip) { | |
var hz = clip.frequency; | |
var channels = clip.channels; | |
var samples = clip.samples; | |
fileStream.Seek(0, SeekOrigin.Begin); | |
Byte[] riff = System.Text.Encoding.UTF8.GetBytes("RIFF"); | |
fileStream.Write(riff, 0, 4); | |
Byte[] chunkSize = BitConverter.GetBytes(fileStream.Length - 8); | |
fileStream.Write(chunkSize, 0, 4); | |
Byte[] wave = System.Text.Encoding.UTF8.GetBytes("WAVE"); | |
fileStream.Write(wave, 0, 4); | |
Byte[] fmt = System.Text.Encoding.UTF8.GetBytes("fmt "); | |
fileStream.Write(fmt, 0, 4); | |
Byte[] subChunk1 = BitConverter.GetBytes(16); | |
fileStream.Write(subChunk1, 0, 4); | |
UInt16 two = 2; | |
UInt16 one = 1; | |
Byte[] audioFormat = BitConverter.GetBytes(one); | |
fileStream.Write(audioFormat, 0, 2); | |
Byte[] numChannels = BitConverter.GetBytes(channels); | |
fileStream.Write(numChannels, 0, 2); | |
Byte[] sampleRate = BitConverter.GetBytes(hz); | |
fileStream.Write(sampleRate, 0, 4); | |
Byte[] byteRate = BitConverter.GetBytes(hz * channels * 2); // sampleRate * bytesPerSample*number of channels, here 44100*2*2 | |
fileStream.Write(byteRate, 0, 4); | |
UInt16 blockAlign = (ushort) (channels * 2); | |
fileStream.Write(BitConverter.GetBytes(blockAlign), 0, 2); | |
UInt16 bps = 16; | |
Byte[] bitsPerSample = BitConverter.GetBytes(bps); | |
fileStream.Write(bitsPerSample, 0, 2); | |
Byte[] datastring = System.Text.Encoding.UTF8.GetBytes("data"); | |
fileStream.Write(datastring, 0, 4); | |
Byte[] subChunk2 = BitConverter.GetBytes(samples * channels * 2); | |
fileStream.Write(subChunk2, 0, 4); | |
// fileStream.Close(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment