-
-
Save BeatUpir/964eb4071ff21c585e4d6a72dc82c384 to your computer and use it in GitHub Desktop.
Unity3D: script to save an AudioClip as a .wav file.
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 System; | |
using System.IO; | |
using UnityEngine; | |
using System.Collections.Generic; | |
using System.Threading; | |
public class SavWav { | |
const int HEADER_SIZE = 44; | |
struct ClipData{ | |
public int samples; | |
public int channels; | |
public float[] samplesData; | |
} | |
public bool Save(string filename, AudioClip clip) { | |
if (!filename.ToLower().EndsWith(".wav")) { | |
filename += ".wav"; | |
} | |
var filepath = filename; | |
Debug.Log(filepath); | |
// Make sure directory exists if user is saving to sub dir. | |
Directory.CreateDirectory(Path.GetDirectoryName(filepath)); | |
ClipData clipdata = new ClipData (); | |
clipdata.samples = clip.samples; | |
clipdata.channels = clip.channels; | |
float[] dataFloat = new float[clip.samples*clip.channels]; | |
clip.GetData (dataFloat, 0); | |
clipdata.samplesData = dataFloat; | |
using (var fileStream = CreateEmpty(filepath)) { | |
MemoryStream memstrm = new MemoryStream (); | |
ConvertAndWrite(memstrm, clipdata); | |
memstrm.WriteTo (fileStream); | |
WriteHeader(fileStream, clip); | |
} | |
return true; // TODO: return false if there's a failure saving the file | |
} | |
public 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 AudioClip TrimSilence(List<float> samples, float min, int channels, int hz) { | |
return TrimSilence(samples, min, channels, hz, false, false); | |
} | |
public 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; | |
} | |
FileStream CreateEmpty(string filepath) { | |
var fileStream = new FileStream(filepath, FileMode.Create); | |
byte emptyByte = new byte(); | |
for(int i = 0; i < HEADER_SIZE; i++) //preparing the header | |
{ | |
fileStream.WriteByte(emptyByte); | |
} | |
return fileStream; | |
} | |
void ConvertAndWrite(MemoryStream memStream, ClipData clipData) | |
{ | |
float[] samples = new float[clipData.samples*clipData.channels]; | |
samples = clipData.samplesData; | |
Int16[] intData = new Int16[samples.Length]; | |
Byte[] bytesData = new Byte[samples.Length * 2]; | |
const float rescaleFactor = 32767; //to convert float to Int16 | |
for (int i = 0; i < samples.Length; i++) | |
{ | |
intData[i] = (short)(samples[i] * rescaleFactor); | |
//Debug.Log (samples [i]); | |
} | |
Buffer.BlockCopy(intData, 0, bytesData, 0, bytesData.Length); | |
memStream.Write(bytesData, 0, bytesData.Length); | |
} | |
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