public static bool ConvertToValidWav(string inputFile, out string outputFile, ref int sampleRate) { try { RiffTags riff = new RiffTags(inputFile); // Remove unnecissary tags foreach (string key in riff.Keys.ToArray()) { if (key != "fmt " && key != "data") { riff.Remove(key); } } if (riff.FileType != "WAVE") { throw new Exception("Input is not a WAVE file!"); } WaveFmt fmt = WaveFmt.Read(riff["fmt "].Data); if (fmt.Format != 1) { throw new Exception("Input is not PCM format!"); } if (fmt.Channels != 2) { throw new Exception("Input does not have 2 channels!"); } if (fmt.BitsPerSample != 16) { throw new Exception("Input does not have 16 bits per sample!"); } if (fmt.SampleRate > 5000) { throw new Exception("Sample rate must be 5000Hz or less!"); } sampleRate = fmt.SampleRate; outputFile = inputFile; return(false); } catch (Exception) { outputFile = Path.Combine(Directory.GetCurrentDirectory(), "wiimote.converted.wav"); ProcessStartInfo startInfo = new ProcessStartInfo { FileName = FFMpeg, Arguments = $"-i \"{inputFile}\" -y -acodec pcm_s16le -ar {sampleRate} -ac 2 \"{outputFile}\"", //RedirectStandardOutput = true, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true, WorkingDirectory = Directory.GetCurrentDirectory(), }; Process process = Process.Start(startInfo); process.WaitForExit(); if (process.ExitCode != 0) { throw new Exception($"FFMpeg exited with {process.ExitCode}"); } return(true); } }
public static void ADPCM2Wav(Stream input, Stream output) { RiffTags riff = new RiffTags(input); // Remove unnecissary tags foreach (string key in riff.Keys.ToArray()) { if (key != "fmt " && key != "data") { riff.Remove(key); } } if (riff.FileType != "WAVE") { throw new Exception("Input is not a WAVE file!"); } WaveFmt fmt = WaveFmt.Read(riff["fmt "].Data); if (fmt.Format != 20) { throw new Exception("Input is not ADPCM format!"); } if (fmt.Channels != 2) { throw new Exception("Input does not have 2 channels!"); } if (fmt.BitsPerSample != 4) { throw new Exception("Input does not have 4 bits per sample!"); } byte[] data = riff["data"].Data; byte[] adpcm = new byte[data.Length]; short[] wavSamples = new short[data.Length * 2]; Buffer.BlockCopy(data, 0, adpcm, 0, data.Length); ADPCM2PCM2(wavSamples, 0, adpcm, 0); ADPCM2PCM(wavSamples, 0, adpcm, 0, adpcm.Length / 2); ADPCM2PCM(wavSamples, wavSamples.Length / 2, adpcm, adpcm.Length / 2, adpcm.Length / 2); //Interleave(wavSamples); byte[] wavData = new byte[wavSamples.Length * sizeof(short)]; Buffer.BlockCopy(wavSamples, 0, wavData, 0, wavData.Length); fmt.Format = 1; fmt.BitsPerSample = 16; fmt.UpdateValues(); riff["fmt "] = new RiffTag("fmt ", fmt.ToBytes()); riff["data"] = new RiffTag("data", wavData); riff.Save(output); }
public static byte[] Wav2ADPCMData(Stream input, out int sampleRate) { RiffTags riff = new RiffTags(input); // Remove unnecissary tags foreach (string key in riff.Keys.ToArray()) { if (key != "fmt " && key != "data") { riff.Remove(key); } } if (riff.FileType != "WAVE") { throw new Exception("Input is not a WAVE file!"); } WaveFmt fmt = WaveFmt.Read(riff["fmt "].Data); if (fmt.Format != 1) { throw new Exception("Input is not PCM format!"); } if (fmt.Channels != 2) { throw new Exception("Input does not have 2 channels!"); } if (fmt.BitsPerSample != 16) { throw new Exception("Input does not have 16 bits per sample!"); } byte[] data = riff["data"].Data; short[] wavSamples = new short[data.Length / 2]; byte[] adpcm = new byte[data.Length / 4]; Buffer.BlockCopy(data, 0, wavSamples, 0, data.Length); /*Deinterleave(wavSamples); * PCM2ADPCM(adpcm, 0, wavSamples, 0, adpcm.Length / 2); * PCM2ADPCM(adpcm, adpcm.Length / 2, wavSamples, wavSamples.Length / 2, adpcm.Length / 2);*/ PCM2ADPCM2(adpcm, 0, wavSamples, 0); sampleRate = fmt.SampleRate; return(adpcm); }
public static byte[] Wav2PCMs8Data(Stream input, out int sampleRate) { RiffTags riff = new RiffTags(input); // Remove unnecissary tags foreach (string key in riff.Keys.ToArray()) { if (key != "fmt " && key != "data") { riff.Remove(key); } } if (riff.FileType != "WAVE") { throw new Exception("Input is not a WAVE file!"); } WaveFmt fmt = WaveFmt.Read(riff["fmt "].Data); if (fmt.Format != 1) { throw new Exception("Input is not PCM format!"); } if (fmt.Channels != 2) { throw new Exception("Input does not have 2 channels!"); } if (fmt.BitsPerSample != 16) { throw new Exception("Input does not have 16 bits per sample!"); } byte[] data = riff["data"].Data; short[] wavSamples = new short[data.Length / 2]; Buffer.BlockCopy(data, 0, wavSamples, 0, data.Length); int pcmLength = data.Length / 2; if (pf.HasFlag(PCMFlags.S16LE) || pf.HasFlag(PCMFlags.S16BE)) { pcmLength *= 2; } if (pf.HasFlag(PCMFlags.MonoL) || pf.HasFlag(PCMFlags.MonoR)) { pcmLength /= 2; } byte[] pcm = new byte[pcmLength]; if (pf.HasFlag(PCMFlags.Deinterleave)) { Deinterleave(wavSamples); } for (int w = 0, p = 0; w < wavSamples.Length; w += 2, p += 2) { short sample = 0; if (pf.HasFlag(PCMFlags.MonoLR)) { sample = (short)((wavSamples[w + 0] + wavSamples[w + 1]) / 2); } else if (pf.HasFlag(PCMFlags.MonoR)) { sample = wavSamples[w + 1]; } else if (pf.HasFlag(PCMFlags.MonoL)) { sample = wavSamples[w + 0]; } else { sample = wavSamples[w]; w--; } if (pf.HasFlag(PCMFlags.S16LE)) { //Signed 16-bit LITTLE ENDIAN: pcm[p + 0] = unchecked ((byte)(sample & 0xFF)); pcm[p + 1] = unchecked ((byte)((sample >> 8) & 0xFF)); } else if (pf.HasFlag(PCMFlags.S16BE)) { //Signed 16-bit BIG ENDIAN: pcm[p + 0] = unchecked ((byte)((sample >> 8) & 0xFF)); pcm[p + 1] = unchecked ((byte)(sample & 0xFF)); } else { //Signed 8-bit: pcm[p] = unchecked ((byte)((sample >> 8) & 0xFF)); p--; } } /*int outSampleCount = wavSamples * //byte[] pcm = new byte[data.Length / 2];//; * bool? s16e = true;// null; * //s16e (stereo) * if (s16e.HasValue) * pcm = new byte[data.Length]; * //pcm = new byte[data.Length]; * //s16e = true; * //s8 (stereo) * //pcm = new byte[data.Length / 2]; * //byte[] pcm = new byte[data.Length / 4]; * Buffer.BlockCopy(data, 0, wavSamples, 0, data.Length); * * //Deinterleave(wavSamples); * //PCM2ADPCM(adpcm, 0, wavSamples, 0, adpcm.Length / 2); * //PCM2ADPCM(adpcm, adpcm.Length / 2, wavSamples, wavSamples.Length / 2, adpcm.Length / 2); * PCM2PCMs82(pcm, 0, wavSamples, 0, s16e);*/ sampleRate = fmt.SampleRate; return(pcm); }
public static bool MaximizeWavVolume(string inputFile, out string outputFile) { RiffTags riff = new RiffTags(inputFile); // Remove unnecissary tags foreach (string key in riff.Keys.ToArray()) { if (key != "fmt " && key != "data") { riff.Remove(key); } } if (riff.FileType != "WAVE") { throw new Exception("Input is not a WAVE file!"); } WaveFmt fmt = WaveFmt.Read(riff["fmt "].Data); if (fmt.Format != 1) { throw new Exception("Input is not PCM format!"); } if (fmt.Channels != 2) { throw new Exception("Input does not have 2 channels!"); } if (fmt.BitsPerSample != 16) { throw new Exception("Input does not have 16 bits per sample!"); } if (fmt.SampleRate > 5000) { throw new Exception("Sample rate must be 5000Hz or less!"); } byte[] data = riff["data"].Data; short[] wavSamples = new short[data.Length / 2]; Buffer.BlockCopy(data, 0, wavSamples, 0, data.Length); short max = 0; short min = 0; for (int i = 0; i < wavSamples.Length; i++) { max = Math.Max(max, wavSamples[i]); min = Math.Min(min, wavSamples[i]); } // Silent File if (min == 0 && max == 0) { outputFile = inputFile; return(false); } // Lazy maximum volume checking const short range = 32; if (min <= (short.MinValue + range) || max >= (short.MaxValue - range)) { outputFile = inputFile; return(false); } double maxScale = (double)short.MaxValue / max; double minScale = (double)short.MinValue / min; double scale = Math.Min(maxScale, minScale); for (int i = 0; i < wavSamples.Length; i++) { wavSamples[i] = (short)(wavSamples[i] * scale); } byte[] wavData = new byte[wavSamples.Length * sizeof(short)]; Buffer.BlockCopy(wavSamples, 0, wavData, 0, wavData.Length); outputFile = Path.Combine(Directory.GetCurrentDirectory(), "wiimote.maximized.wav"); riff["data"] = new RiffTag("data", wavData); riff.Save(outputFile); return(false); }