public static byte[] EncodeToADPCM(AudioClip source, IMAADPCM.ADPCMState[] states = null) { Debug.Log ("channels = " + source.channels); float[] data = new float[source.samples*source.channels]; source.GetData(data, 0); IMAADPCM.ADPCMState state = new IMAADPCM.ADPCMState(); state.valprev = 0; int count = source.samples; byte[] bytes = new byte[count/2]; for (int i = 0; i < count/2; i++) { int m1 = i*2; int m2 = i*2+1; //samples en entrée short i1 = (short)(data[i*2+0]*32768f); short i2 = (short)(data[i*2+1]*32768f); if (m1%1017 == 0 && states != null) { Debug.Log ("modulo1"); int stateindex = m1/1017; states[stateindex].valprev = state.valprev; states[stateindex].index = state.index; } byte b1 = IMAADPCM.encodeADPCM(i1, ref state); if (m2%1017 == 0 && states != null) { Debug.Log ("modulo2"); int stateindex = m2/1017; states[stateindex].valprev = state.valprev; states[stateindex].index = state.index; } byte b2 = IMAADPCM.encodeADPCM(i2, ref state); //Debug.Log (""+b1+" " + b2); //bytes[i] = (byte)(b1*16+b2); bytes[i] = (byte)(b1*16+b2); } return bytes; }
public static MemoryStream encodeCompressedFromWAV(string source) { WAVFile wav = new WAVFile(); MemoryStream ms = new MemoryStream(); wav.Open(source, WAVFile.WAVFileMode.READ); IMAADPCM.ADPCMState state = new IMAADPCM.ADPCMState(); byte enc1, enc2; for (long i = 0; i < wav.NumSamples / 2; i++) { enc1 = IMAADPCM.encodeADPCM(wav.GetNextSampleAs16Bit(), ref state); enc2 = IMAADPCM.encodeADPCM(wav.GetNextSampleAs16Bit(), ref state); ms.Write(BitConverter.GetBytes(Convert.ToInt32(Utils.binaryString(enc2, 4) + Utils.binaryString(enc1, 4), 2)), 0, 1); } wav.Close(); return(ms); }
public static bool replaceSample(int sampleIndex, string path) { long offset = IVAUDSingle.WIoffset[sampleIndex] + IVAUDSingle.headerSize; byte[] dataBefore = new byte[offset - IVAUDSingle.headerSize]; byte[] dataAfter = new byte[IVAUD.file.Length - (offset + IVAUDSingle.WInumSamplesInBytes_computed[sampleIndex])]; //Get data between header and replaced sample IVAUD.file.Seek(IVAUDSingle.headerSize, SeekOrigin.Begin); IVAUD.file.Read(dataBefore, 0, dataBefore.Length); //Get data between replaced sample and eof IVAUD.file.Seek(offset + IVAUDSingle.WInumSamplesInBytes_computed[sampleIndex], SeekOrigin.Begin); IVAUD.file.Read(dataAfter, 0, dataAfter.Length); //Close file IVAUD.close(); //Open WAV file and encode it WAVFile wav = new WAVFile(); wav.Open(path, WAVFile.WAVFileMode.READ); MemoryStream ms = new MemoryStream(); IMAADPCM.ADPCMState state = new IMAADPCM.ADPCMState(); //byte enc1, enc2; byte[] bytes = new byte[2]; int loopValue = ((wav.DataSizeBytes - 8) / wav.BytesPerSample); /*Debug.WriteLine((((wav.DataSizeBytes - 8) / wav.BytesPerSample)) / 2); * Debug.WriteLine(wav.NumSamples / 2); * Debug.WriteLine((((wav.DataSizeBytes - 8) / wav.BytesPerSample))); * Debug.WriteLine(wav.NumSamples);*/ //for (long i = 0; i < wav.NumSamples / 2; i++) { for (long i = 0; i < loopValue / 2; i++) { bytes[0] = IMAADPCM.encodeADPCM(wav.GetNextSampleAs16Bit(), ref state); bytes[1] = IMAADPCM.encodeADPCM(wav.GetNextSampleAs16Bit(), ref state); ms.Write(BitConverter.GetBytes(Convert.ToInt32(Utils.binaryString(bytes[1], 4) + Utils.binaryString(bytes[0], 4), 2)), 0, 1); } long originalOffset = offset + IVAUDSingle.WInumSamplesInBytes_computed[sampleIndex]; //Change header values IVAUDSingle.WInumSamplesInBytes[sampleIndex] = (int)ms.Length; IVAUDSingle.WInumSamplesInBytes_computed[sampleIndex] = Utils.getPaddedSize(IVAUDSingle.WInumSamplesInBytes[sampleIndex]); IVAUDSingle.WInumSamples16Bit[sampleIndex] = (int)(ms.Length * 2); IVAUDSingle.WIsamplerate[sampleIndex] = (ushort)wav.SampleRateHz; if (IVAUDSingle.WIHsize[sampleIndex] > 32) { IVAUDSingle.WInumSamples16Bit2[sampleIndex] = (uint)(ms.Length * 2); } //Change later offsets long newOffset = offset + IVAUDSingle.WInumSamplesInBytes_computed[sampleIndex]; long offsetChange = newOffset - originalOffset; for (int i = 0; i < IVAUDSingle.WIHoffset.Count; i++) { if ((IVAUDSingle.WIoffset[i] + IVAUDSingle.headerSize) > offset) { IVAUDSingle.WIoffset[i] += offsetChange; } } wav.Close(); //Get WAV data byte[] dataWAV = new byte[ms.Length]; ms.Seek(0, SeekOrigin.Begin); ms.Read(dataWAV, 0, (int)ms.Length); ms.Close(); //Write header FileStream fs = new FileStream(Environment.GetEnvironmentVariable("TEMP") + "\\IVATB\\Current" + Utils.sessionID + ".tmp", FileMode.Open, FileAccess.ReadWrite); fs.Seek(0, SeekOrigin.Begin); if (!IVAUDSingle.write(fs)) { return(false); } //Write before-data fs.Seek(IVAUDSingle.headerSize, SeekOrigin.Begin); fs.Write(dataBefore, 0, dataBefore.Length); //Write sample fs.Seek(offset, SeekOrigin.Begin); fs.Write(dataWAV, 0, dataWAV.Length); //Write after-data fs.Seek(offset + IVAUDSingle.WInumSamplesInBytes_computed[sampleIndex], SeekOrigin.Begin); fs.Write(dataAfter, 0, dataAfter.Length); //Fix file length if needed if (offsetChange < 0) { fs.SetLength(fs.Length + offsetChange); } fs.Close(); //Replace the file //IVAUD.close(); //File.Copy(Environment.GetEnvironmentVariable("TEMP") + "\\IVATB\\Replace" + Utils.sessionID + ".tmp", Environment.GetEnvironmentVariable("TEMP") + "\\IVATB\\Current" + Utils.sessionID + ".tmp", true); //Reload the file IVAUD.load(Environment.GetEnvironmentVariable("TEMP") + "\\IVATB\\Current" + Utils.sessionID + ".tmp"); return(true); }
public static byte[] GetADPCMWAVData(AudioClip clip, int maxsamples) { Debug.Log ("maxsamples="+maxsamples); int headersize = 60; float[] fdata = new float[clip.samples*clip.channels]; int rawdatasize = (clip.samples*clip.channels)/2; if (rawdatasize>maxsamples/2) rawdatasize = maxsamples/2; clip.GetData(fdata, 0); int SampleRate = 22050; int ByteRate = 11100; int blockalign = 1024; //taille d'un header ADPCM complet int blockdata = blockalign-4;//252; int blocks = rawdatasize/blockdata; int datasize = blocks * blockalign; //IMAADPCM.ADPCMState[] states = new IMAADPCM.ADPCMState[blocks+1]; //for (int i=0;i<blocks;++i) //{ // states[i] = new IMAADPCM.ADPCMState(); //} //byte[] data = EncodeToADPCM(record, states); uint totalsize = (uint)(datasize+headersize); Debug.Log ("total size = " + totalsize); byte[] total = new byte[totalsize]; byte[] b = null; b = System.Text.Encoding.UTF8.GetBytes("RIFF"); b.CopyTo(total, 0); b = System.BitConverter.GetBytes(total.Length-8); b.CopyTo(total, 4); b = System.Text.Encoding.UTF8.GetBytes("WAVE"); b.CopyTo(total, 8); //fmt CHUNK ======================= b = System.Text.Encoding.UTF8.GetBytes("fmt "); b.CopyTo(total, 12); //4 b = System.BitConverter.GetBytes(20); //taille du block fmt b.CopyTo(total, 16); //2 b = System.BitConverter.GetBytes((ushort)17); //FORMAT 0x11=INA ADPCM (17) OK !!! //b = System.BitConverter.GetBytes((ushort)57); //b = System.BitConverter.GetBytes((ushort)259); //FORMAT 0x11=INA ADPCM (17) b.CopyTo(total, 20); b = System.BitConverter.GetBytes((ushort)1); //CHANNELS OK !!! b.CopyTo(total, 22); b = System.BitConverter.GetBytes((uint)SampleRate); //SR b.CopyTo(total, 24); //byte rate = SR/2 + overhead //b = System.BitConverter.GetBytes((uint)(22050*1/2)); //byte rate //SR*channels*2 b = System.BitConverter.GetBytes((uint)(ByteRate)); //byte rate //SR*channels*2 b.CopyTo(total, 28); //block align b = System.BitConverter.GetBytes((ushort)blockalign); //2 : 16 bits mono 512 dans le fichier Audacity b.CopyTo(total, 32); b = System.BitConverter.GetBytes((ushort)4); //bits per samples, 4 b.CopyTo(total, 34); //taille de la zone extended b = System.BitConverter.GetBytes((ushort)2); b.CopyTo(total, 36); int samplesperblock = (blockalign-4)*2+1; b = System.BitConverter.GetBytes((ushort)samplesperblock); //nombre de samples par bloc : (512-4)*2+1 b.CopyTo(total, 38); //FACT CHUNK b = System.Text.Encoding.UTF8.GetBytes("fact"); b.CopyTo(total, 40); b = System.BitConverter.GetBytes(4); //taille du block fact : 4 octets b.CopyTo(total, 44); b = System.BitConverter.GetBytes((uint)datasize*2); //nombre de samples au total b.CopyTo(total, 48); //DATA CHUNK b = System.Text.Encoding.UTF8.GetBytes("data"); b.CopyTo(total, 52); b = System.BitConverter.GetBytes((uint)totalsize); b.CopyTo(total, 56); //on commence à header size //compression IMA ADPCM //Debug.Log("Samples per blocks = " + samplesperblock); IMAADPCM.ADPCMState state = new IMAADPCM.ADPCMState(); state.valprev = 0; state.index = 0; int count = (blocks-1) * samplesperblock; int dest = 0; bool first = true; for (int s=0;s<count;++s) //pour tous les samples en entrée { short input = (short)(fdata[s]*32768f); int m = s%samplesperblock; byte adpcm = IMAADPCM.encodeADPCM(input, ref state); if (m == 0) { //premier sample du bloc //il faut écrire un header mais ne pas émettre normalement le sample //s+=1; //byte adpcm = IMAADPCM.encodeADPCM(input, ref state); //Debug.Log ("write adpcm header at dest " + dest + " first="+first + " vals " + state.valprev + " " + state.index); b = System.BitConverter.GetBytes(state.valprev); total[headersize+dest+0] = b[0]; total[headersize+dest+1] = b[1]; total[headersize+dest+2] = state.index; total[headersize+dest+3] = 0;//adpcm; //hack pour avoir quand même le nible dans le header NON ! semble poser un problème sur la box dest += 4; first = true; //byte adpcm = IMAADPCM.encodeADPCM(input, ref state); } else { //byte adpcm = IMAADPCM.encodeADPCM(input, ref state); //cas normal, on écrit l'échantillon //byte adpcm = IMAADPCM.encodeADPCM(input, ref state); if (first) { total[headersize+dest] = (byte)(adpcm); first = false; } else { total[headersize+dest] += (byte)(adpcm*16); dest ++; first = true; } } } return total; }
static void Main(string[] args) { //Debug test //args = (@"E:\Mijn documenten\Visual Studio 2010\ADPCMEncoder\~24000HZTEST.wav|test").Split(Convert.ToChar("|")); //args = (@"E:\Mijn documenten\Visual Studio 2010\ADPCMEncoder\TestFiles\LoadingSNOW.wav|test").Split(Convert.ToChar("|")); //Print header Console.WriteLine("================="); Console.WriteLine("IMA ADPCM Encoder"); Console.WriteLine(" by Flitskikker"); Console.WriteLine("================="); Console.WriteLine(""); //Check args if (args.Length == 0) { //No args Console.WriteLine("ERROR: No command line arguments passed. Press any key to exit..."); Console.ReadLine(); Environment.Exit(1); } //Check file if (!File.Exists(args[0])) { //File not found Console.WriteLine("ERROR: File \"" + args[0] + "\" not found. Press any key to exit..."); Console.ReadLine(); Environment.Exit(2); } //Print file Console.WriteLine("File: " + args[0]); Console.WriteLine(""); //Load file WAVFile wav = new WAVFile(); wav.Open(args[0], WAVFile.WAVFileMode.READ); //Show WAV info Console.WriteLine("WAV Info:"); Console.WriteLine("\tBits per sample:\t" + wav.BitsPerSample.ToString() + " bits"); Console.WriteLine("\tBytes per sample:\t" + wav.BytesPerSample.ToString()); Console.WriteLine("\tBytes per second:\t" + wav.BytesPerSec.ToString()); Console.WriteLine("\tData size:\t\t" + wav.DataSizeBytes.ToString() + " bytes"); Console.WriteLine("\tDuration:\t\t" + Math.Round(Convert.ToDecimal((double)wav.NumSamples / (double)wav.SampleRateHz), 2).ToString() + " seconds (" + Utils.getDurationString(wav.NumSamples, wav.SampleRateHz) + ")"); Console.WriteLine("\tEncoding type:\t\t" + wav.EncodingType.ToString()); Console.WriteLine("\tFile size:\t\t" + wav.FileSizeBytes.ToString() + " bytes"); Console.WriteLine("\t# of channels:\t\t" + wav.NumChannels.ToString()); Console.WriteLine("\t# of samples:\t\t" + wav.NumSamples.ToString()); Console.WriteLine("\tRIFF type:\t\t" + wav.RIFFTypeString); Console.WriteLine("\tSample Rate:\t\t" + wav.SampleRateHz.ToString() + " Hz"); Console.WriteLine("\tWAV header:\t\t" + wav.WAVHeaderString); Console.WriteLine(""); //Check bits if (wav.BitsPerSample != 16) { //Not 16 bits Console.WriteLine("ERROR: WAV should have 16 bits per sample. Press any key to exit..."); Console.ReadLine(); Environment.Exit(1); } //Check bytes per sample if (wav.BytesPerSample / wav.NumChannels != 2) { //Not 2 bytes Console.WriteLine("ERROR: WAV should have (wav.NumChannels * 2) bytes per sample. Press any key to exit..."); Console.ReadLine(); Environment.Exit(1); } //Print message Console.WriteLine("Ready to go! Press any key when ready..."); //Wait for input Console.ReadLine(); if (wav.NumChannels > 1) { //Split channels Console.WriteLine(""); Console.WriteLine("Saving separate channels..."); Console.WriteLine(""); List <WAVFile> wavs = new List <WAVFile>(); for (int c = 0; c < wav.NumChannels; c++) { wavs.Add(new WAVFile()); wavs[c].Create(Path.GetDirectoryName(args[0]) + "\\" + Path.GetFileNameWithoutExtension(args[0]) + "_" + (c + 1).ToString() + ".wav", false, wav.SampleRateHz, wav.BitsPerSample, true); } int numSamplesCorrected = ((wav.DataSizeBytes - 8) / wav.BytesPerSample); //for (long i = 0; i < wav.NumSamples / wav.NumChannels; i++) { for (long i = 0; i < numSamplesCorrected; i++) { for (int c = 0; c < wav.NumChannels; c++) { wavs[c].AddSample_16bit(wav.GetNextSampleAs16Bit()); } } for (int c = 0; c < wav.NumChannels; c++) { wavs[c].Close(); } } //Encode Console.WriteLine(""); Console.WriteLine("Encoding file(s)..."); Console.WriteLine(""); IMAADPCM.ADPCMState state = new IMAADPCM.ADPCMState(); WAVFile cwav = new WAVFile(); int nc = wav.NumChannels; for (int c = 0; c < wav.NumChannels; c++) { Console.WriteLine("Encoding file: " + Path.GetDirectoryName(args[0]) + "\\" + Path.GetFileNameWithoutExtension(args[0]) + "_" + (c + 1).ToString() + ".bin"); MemoryStream ms = new MemoryStream(); cwav = new WAVFile(); // Open splitted WAV if (wav.NumChannels > 1) { cwav.Open(Path.GetDirectoryName(args[0]) + "\\" + Path.GetFileNameWithoutExtension(args[0]) + "_" + (c + 1).ToString() + ".wav", WAVFile.WAVFileMode.READ_WRITE); } else { cwav = wav; //wav.Close(); //cwav.Open(args[0], WAVFile.WAVFileMode.READ_WRITE); } byte[] bytes = new byte[2]; int loopValue = ((cwav.DataSizeBytes - 8) / cwav.BytesPerSample); //Actual encode for (long i = 0; i < loopValue / 2; i++) { bytes[0] = IMAADPCM.encodeADPCM(cwav.GetNextSampleAs16Bit(), ref state); bytes[1] = IMAADPCM.encodeADPCM(cwav.GetNextSampleAs16Bit(), ref state); ms.Write(BitConverter.GetBytes(Convert.ToInt32(Utils.binaryString(bytes[1], 4) + Utils.binaryString(bytes[0], 4), 2)), 0, 1); } //Get WAV data byte[] dataWAV = new byte[ms.Length]; ms.Seek(0, SeekOrigin.Begin); ms.Read(dataWAV, 0, (int)ms.Length); ms.Close(); //Create file FileStream fs = new FileStream(Path.GetDirectoryName(args[0]) + "\\" + Path.GetFileNameWithoutExtension(args[0]) + "_" + (c + 1).ToString() + ".bin", FileMode.Create, FileAccess.ReadWrite); //Write sample fs.Seek(0, SeekOrigin.Begin); fs.Write(dataWAV, 0, dataWAV.Length); //Close cwav.Close(); ms.Close(); fs.Close(); if (nc == 1) { break; } } //Close WAV file wav.Close(); //Print message Console.WriteLine(""); Console.WriteLine("Done! Press any key to exit..."); //Wait for input Console.ReadLine(); //Exit Environment.Exit(0); }