Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ah1053 committed Dec 4, 2020
1 parent 443a67f commit 93e4b53
Show file tree
Hide file tree
Showing 10 changed files with 1,003 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Recorder.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

204 changes: 204 additions & 0 deletions Recorder/Recorder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
using System;
using System.IO;
using System.Text;
using UnityEngine;
using UnityEngine.UI;

namespace Recorder
{
/// <summary>
/// Add this component to a GameObject to Record Mic Input
/// </summary>
[AddComponentMenu("AhmedSchrute/Recorder")]
[RequireComponent(typeof(AudioSource))]
public class Recorder : MonoBehaviour
{
#region Constants & Static Variables
/// <summary>
/// Audio Source to store Microphone Input, An AudioSource Component is required by default
/// </summary>
static AudioSource audioSource;
/// <summary>
/// The samples are floats ranging from -1.0f to 1.0f, representing the data in the audio clip
/// </summary>
static float[] samplesData;
/// <summary>
/// WAV file header size
/// </summary>
const int HEADER_SIZE = 44;

#endregion

#region Editor Exposed Variables

/// <summary>
/// Set a keyboard key for saving the Audio File
/// </summary>
[Tooltip("Set a keyboard key for saving the Audio File")]
public KeyCode keyCode;
/// <summary>
/// Set a Button to trigger writing the WAV file and Saving the Audio
/// </summary>
public Button SaveButton;
/// <summary>
/// What should the saved file name be, the file will be saved in Streaming Assets Directory
/// </summary>
[Tooltip("What should the saved file name be, the file will be saved in Streaming Assets Directory, Don't add .wav at the end")]
public string fileName;

#endregion

#region MonoBehaviour Callbacks

void Start()
{
audioSource = GetComponent<AudioSource>();
audioSource.clip = Microphone.Start(Microphone.devices[0], true, 10, 44100);
if (SaveButton == null)
{
return;
}
SaveButton.onClick.AddListener(() =>
{
Save();
});
}

private void Update()
{
if (Input.GetKeyDown(keyCode))
{
Save();
}
}

#endregion

#region Recorder Functions

public static void Save(string fileName = "test")
{

while (!(Microphone.GetPosition(null) > 0)) { }
samplesData = new float[audioSource.clip.samples * audioSource.clip.channels];
audioSource.clip.GetData(samplesData, 0);
string filePath = Path.Combine(Application.streamingAssetsPath, fileName + ".wav");
// Delete the file if it exists.
if (File.Exists(filePath))
{
File.Delete(filePath);
}
try
{
WriteWAVFile(audioSource.clip, filePath);
Debug.Log("File Saved Successfully at StreamingAssets/" + fileName + ".wav");
}
catch (DirectoryNotFoundException)
{
Debug.LogError("Please, Create a StreamingAssets Directory in the Assets Folder");
}

}

public static byte[] ConvertWAVtoByteArray(string filePath)
{
//Open the stream and read it back.
byte[] bytes = new byte[audioSource.clip.samples + HEADER_SIZE];
using (FileStream fs = File.OpenRead(filePath))
{
fs.Read(bytes, 0, bytes.Length);
}
return bytes;
}

// WAV file format from http://soundfile.sapp.org/doc/WaveFormat/
static void WriteWAVFile(AudioClip clip, string filePath)
{
float[] clipData = new float[clip.samples];

//Create the file.
using (Stream fs = File.Create(filePath))
{
int frequency = clip.frequency;
int numOfChannels = clip.channels;
int samples = clip.samples;
fs.Seek(0, SeekOrigin.Begin);

//Header

// Chunk ID
byte[] riff = Encoding.ASCII.GetBytes("RIFF");
fs.Write(riff, 0, 4);

// ChunkSize
byte[] chunkSize = BitConverter.GetBytes((HEADER_SIZE + clipData.Length) - 8);
fs.Write(chunkSize, 0, 4);

// Format
byte[] wave = Encoding.ASCII.GetBytes("WAVE");
fs.Write(wave, 0, 4);

// Subchunk1ID
byte[] fmt = Encoding.ASCII.GetBytes("fmt ");
fs.Write(fmt, 0, 4);

// Subchunk1Size
byte[] subChunk1 = BitConverter.GetBytes(16);
fs.Write(subChunk1, 0, 4);

// AudioFormat
byte[] audioFormat = BitConverter.GetBytes(1);
fs.Write(audioFormat, 0, 2);

// NumChannels
byte[] numChannels = BitConverter.GetBytes(numOfChannels);
fs.Write(numChannels, 0, 2);

// SampleRate
byte[] sampleRate = BitConverter.GetBytes(frequency);
fs.Write(sampleRate, 0, 4);

// ByteRate
byte[] byteRate = BitConverter.GetBytes(frequency * numOfChannels * 2); // sampleRate * bytesPerSample*number of channels, here 44100*2*2
fs.Write(byteRate, 0, 4);

// BlockAlign
ushort blockAlign = (ushort)(numOfChannels * 2);
fs.Write(BitConverter.GetBytes(blockAlign), 0, 2);

// BitsPerSample
ushort bps = 16;
byte[] bitsPerSample = BitConverter.GetBytes(bps);
fs.Write(bitsPerSample, 0, 2);

// Subchunk2ID
byte[] datastring = Encoding.ASCII.GetBytes("data");
fs.Write(datastring, 0, 4);

// Subchunk2Size
byte[] subChunk2 = BitConverter.GetBytes(samples * numOfChannels * 2);
fs.Write(subChunk2, 0, 4);

// Data

clip.GetData(clipData, 0);
short[] intData = new short[clipData.Length];
byte[] bytesData = new byte[clipData.Length * 2];

int convertionFactor = 32767;

for (int i = 0; i < clipData.Length; i++)
{
intData[i] = (short)(clipData[i] * convertionFactor);
byte[] byteArr = new byte[2];
byteArr = BitConverter.GetBytes(intData[i]);
byteArr.CopyTo(bytesData, i * 2);
}

fs.Write(bytesData, 0, bytesData.Length);
}
}

#endregion
}
}
11 changes: 11 additions & 0 deletions Recorder/Recorder.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Recorder/Scenes.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 93e4b53

Please sign in to comment.