/// <summary> /// Parse the MsAdpcm format wav. /// </summary> private void ParseMsAdpcm() { int offset = Chunk_fmt_.Offset; Sanity.RequiresWave(Chunk_fmt_.Length >= 30, "fmt_ chunk is shorter than expected."); switch (SampleRate) { case 8000: case 11025: Sanity.RequiresWave(BlockAlign == 256, "MsAdpcm BlockAlign mismatch."); break; case 22050: Sanity.RequiresWave(BlockAlign == 512, "MsAdpcm BlockAlign mismatch."); break; case 44100: Sanity.RequiresWave(BlockAlign == 1024, "MsAdpcm BlockAlign mismatch."); break; default: break; } CbSize = BitConverter.ToInt16(WaveBytes, offset + 24); SamplesPerBlock = BitConverter.ToInt16(WaveBytes, offset + 26); NumCoef = BitConverter.ToInt16(WaveBytes, offset + 28); Sanity.RequiresWave(NumCoef * 4 + 4 == CbSize, "CbSize mismatch."); Sanity.RequiresWave(BitsPerSample == 4, "bits/sample should be 4 in MsAdpcm."); Sanity.RequiresWave(SampleRate * BlockAlign / SamplesPerBlock == ByteRate, "ByteRate equation error."); Sanity.RequiresWave((BlockAlign - 7 * NumChannels) * 8 / (BitsPerSample * NumChannels) + 2 == SamplesPerBlock, "SamplesPerBlock equation error."); CoefList = Enumerable.Range(0, NumCoef * 2).Select(x => BitConverter.ToInt16(WaveBytes, offset + 30 + x * 2)).ToList(); Sanity.RequiresWave(CoefStandardList.SequenceEqual(CoefList.Take(2 * NumCoef)), "Coef list mismatch."); }
public void ParseData() { Sanity.Requires(DeepFlag, "Parse data requires deep parse."); ParseDataFlag = true; AudioBits = BlockAlign / NumChannels * 8; DataValues = CalcValues().ToArray(); RMS = CalculateRms(); }
/// <summary> /// Parse the extra parts, typically for alaw and ulaw. /// </summary> private void ParseWaveFormatEx() { if (Chunk_fmt_.Length >= 18) { CbSize = BitConverter.ToInt16(WaveBytes, 24); } Sanity.RequiresWave(ByteRate == NumChannels * SampleRate * BitsPerSample / 8, "Byte rate equation error."); Sanity.RequiresWave(BlockAlign == NumChannels * BitsPerSample / 8, "BlockAlign equation error."); Sanity.RequiresWave(CbSize == Chunk_fmt_.Length - 16, "CbSize Error."); }
public static byte[] ReadBytes(string path, int n) { Sanity.Requires(File.Exists(path), "The file doesn't exist."); Sanity.Requires(n >= 0, "The bytes required cannot be negative."); using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(fs)) { return(br.ReadBytes(n)); } } }
/// <summary> /// Check the chunks after all the parsing are done. /// </summary> private void PostCheck() { Sanity.RequiresWave(!string.IsNullOrEmpty(Chunk_fmt_.Name), "Missing fmt_ chunk."); Sanity.RequiresWave(!string.IsNullOrEmpty(Chunk_data.Name), "Missing data chunk."); if (DeepFlag) { DataBytes = new byte[Chunk_data.Length]; DataBytes = WaveBytes.ArraySkip(Chunk_data.Offset + 8); //Array.Copy(WaveBytes, Chunk_data.Offset + 8, DataBytes, 0, Chunk_data.Length); } ParseFormat(); AudioLength = 1.0 * Chunk_data.Length / ByteRate; }
/// <summary> /// Parse the RIFF chunk. /// </summary> private void ParseRiff() { Sanity.RequiresWave(WaveBytes.Length >= 44, "Wave size is less than min requirement(44 bytes)."); string riffName = Encoding.ASCII.GetString(WaveBytes, 0, 4); Sanity.RequiresWave(riffName == "RIFF", "Riff header broken."); int length = BitConverter.ToInt32(WaveBytes, 4); Sanity.RequiresWave(!DeepFlag || length + 8 == WaveBytes.Length, "Riff length broken."); string waveName = Encoding.ASCII.GetString(WaveBytes, 8, 4); Sanity.RequiresWave(waveName == "WAVE", "Wave header broken."); ParseChunk(12); }
/// <summary> /// Parse the chunk. /// </summary> /// <param name="offset">The offset of the chunk</param> private void ParseChunk(int offset) { if (offset == WaveBytes.Length) { return; } if (offset + 8 > WaveBytes.Length) { Sanity.RequiresWave(!DeepFlag, "Wave is shorter than expected."); return; } string name = Encoding.ASCII.GetString(WaveBytes, offset, 4); int length = BitConverter.ToInt32(WaveBytes, offset + 4); if ((length & 1) == 1) { length++; } switch (name) { case "fmt ": Sanity.RequiresWave(string.IsNullOrEmpty(Chunk_fmt_.Name), "fmt_ chunk duplication."); Chunk_fmt_ = new Chunk { Name = name, Length = length, Offset = offset }; break; case "data": Sanity.RequiresWave(string.IsNullOrEmpty(Chunk_data.Name), "data chunk duplication."); Chunk_data = new Chunk { Name = name, Length = length, Offset = offset }; break; default: Chunks.Add(new Chunk() { Name = name, Length = length, Offset = offset }); break; } ParseChunk(offset + 8 + length); }
/// <summary> /// Calculate the root mean square of the audio. /// </summary> /// <returns>The RMS value</returns> private double CalculateRms() { Sanity.Requires(ParseDataFlag, "The wave data has to be parsed in order to get RMS."); return(Math.Sqrt(DataValues.Sum(x => x * x) / DataValues.Length)); }
public static int ToInt24(byte[] bytes, int offset) { Sanity.Requires(offset + 3 <= bytes.Length, "Offset exceeds array length."); return(ToInt24(bytes[offset], bytes[offset + 1], bytes[offset + 2])); }