// --- functions --- /// <summary>Reads wave data from a WAVE file.</summary> /// <param name="fileName">The file name of the WAVE file.</param> /// <returns>The wave data.</returns> private static Sound LoadFromFile(string fileName) { byte[] fileBytes = File.ReadAllBytes(fileName); using (MemoryStream stream = new MemoryStream(fileBytes)) { using (BinaryReader reader = new BinaryReader(stream)) { // RIFF/RIFX chunk Endianness endianness; uint headerCkID = reader.ReadUInt32(); if (headerCkID == 0x46464952) { endianness = Endianness.Little; } else if (headerCkID == 0x58464952) { endianness = Endianness.Big; } else { throw new InvalidDataException("Invalid chunk ID"); } //Skip the header checksum ReadUInt32(reader, endianness); uint formType = ReadUInt32(reader, endianness); if (formType != 0x45564157) { throw new InvalidDataException("Unsupported format"); } // data chunks WaveFormat format = new WaveFormat(); FormatData data = null; byte[] dataBytes = null; while (stream.Position + 8 <= stream.Length) { uint ckID = reader.ReadUInt32(); uint ckSize = ReadUInt32(reader, endianness); if (ckID == 0x20746d66) { // "fmt " chunk if (ckSize < 14) { throw new InvalidDataException("Unsupported fmt chunk size"); } ushort wFormatTag = ReadUInt16(reader, endianness); ushort wChannels = ReadUInt16(reader, endianness); uint dwSamplesPerSec = ReadUInt32(reader, endianness); if (dwSamplesPerSec >= 0x80000000) { throw new InvalidDataException("Unsupported dwSamplesPerSec"); } //Skip the average bytes per second declaration ReadUInt32(reader, endianness); ushort wBlockAlign = ReadUInt16(reader, endianness); if (wFormatTag == 1) { // PCM if (ckSize < 16) { throw new InvalidDataException("Unsupported fmt chunk size"); } ushort wBitsPerSample = ReadUInt16(reader, endianness); stream.Position += ckSize - 16; if (wBitsPerSample < 1) { throw new InvalidDataException("Unsupported wBitsPerSample"); } if (wBlockAlign != ((wBitsPerSample + 7) / 8) * wChannels) { throw new InvalidDataException("Unexpected wBlockAlign"); } format = new WaveFormat((int)dwSamplesPerSec, (int)wBitsPerSample, wChannels); PcmData pcmData = new PcmData { BlockSize = (int)wBlockAlign }; data = pcmData; } else if (wFormatTag == 2) { // Microsoft ADPCM if (ckSize < 22) { throw new InvalidDataException("Unsupported fmt chunk size"); } ushort wBitsPerSample = ReadUInt16(reader, endianness); if (wBitsPerSample != 4) { throw new InvalidDataException("Unsupported wBitsPerSample"); } ReadUInt16(reader, endianness); MicrosoftAdPcmData adpcmData = new MicrosoftAdPcmData { SamplesPerBlock = ReadUInt16(reader, endianness) }; if (adpcmData.SamplesPerBlock == 0 | adpcmData.SamplesPerBlock > 2 * ((int)wBlockAlign - 6)) { throw new InvalidDataException("Unexpected nSamplesPerBlock"); } ushort wNumCoef = ReadUInt16(reader, endianness); if (ckSize < 22 + 4 * wNumCoef) { throw new InvalidDataException("Unsupported fmt chunk size"); } adpcmData.Coefficients = new short[wNumCoef][]; unchecked { for (int i = 0; i < wNumCoef; i++) { adpcmData.Coefficients[i] = new short[] { (short)ReadUInt16(reader, endianness), (short)ReadUInt16(reader, endianness) }; } } stream.Position += ckSize - (22 + 4 * wNumCoef); format = new WaveFormat((int)dwSamplesPerSec, 16, (int)wChannels); adpcmData.BlockSize = wBlockAlign; data = adpcmData; } else if (wFormatTag == 85) { //This is actually a WAV encapsulated mp3 file.... return(NlayerLoadFromFile(fileName)); } else { // unsupported format throw new InvalidDataException("Unsupported wFormatTag"); } } else if (ckID == 0x61746164) { // "data" chunk if (ckSize >= 0x80000000) { throw new InvalidDataException("Unsupported data chunk size"); } if (data is PcmData) { // PCM int bytesPerSample = (format.BitsPerSample + 7) / 8; int samples = (int)ckSize / (format.Channels * bytesPerSample); int dataSize = samples * format.Channels * bytesPerSample; dataBytes = reader.ReadBytes(dataSize); stream.Position += ckSize - dataSize; } else if (data != null) { // Microsoft ADPCM MicrosoftAdPcmData adpcmData = (MicrosoftAdPcmData)data; int blocks = (int)ckSize / adpcmData.BlockSize; dataBytes = new byte[2 * blocks * format.Channels * adpcmData.SamplesPerBlock]; int position = 0; for (int i = 0; i < blocks; i++) { unchecked { MicrosoftAdPcmData.ChannelData[] channelData = new MicrosoftAdPcmData.ChannelData[format.Channels]; for (int j = 0; j < format.Channels; j++) { channelData[j].bPredictor = (int)reader.ReadByte(); if (channelData[j].bPredictor >= adpcmData.Coefficients.Length) { throw new InvalidDataException("Invalid bPredictor"); } else { channelData[j].iCoef1 = (int)adpcmData.Coefficients[channelData[j].bPredictor][0]; channelData[j].iCoef2 = (int)adpcmData.Coefficients[channelData[j].bPredictor][1]; } } for (int j = 0; j < format.Channels; j++) { channelData[j].iDelta = (short)ReadUInt16(reader, endianness); } for (int j = 0; j < format.Channels; j++) { channelData[j].iSamp1 = (short)ReadUInt16(reader, endianness); } for (int j = 0; j < format.Channels; j++) { channelData[j].iSamp2 = (short)ReadUInt16(reader, endianness); } for (int j = 0; j < format.Channels; j++) { dataBytes[position] = (byte)(ushort)channelData[j].iSamp2; dataBytes[position + 1] = (byte)((ushort)channelData[j].iSamp2 >> 8); position += 2; } for (int j = 0; j < format.Channels; j++) { dataBytes[position] = (byte)(ushort)channelData[j].iSamp1; dataBytes[position + 1] = (byte)((ushort)channelData[j].iSamp1 >> 8); position += 2; } uint nibbleByte = 0; bool nibbleFirst = true; for (int j = 0; j < adpcmData.SamplesPerBlock - 2; j++) { for (int k = 0; k < format.Channels; k++) { int lPredSample = (int)channelData[k].iSamp1 * channelData[k].iCoef1 + (int)channelData[k].iSamp2 * channelData[k].iCoef2 >> 8; int iErrorDeltaUnsigned; if (nibbleFirst) { nibbleByte = (uint)reader.ReadByte(); iErrorDeltaUnsigned = (int)(nibbleByte >> 4); nibbleFirst = false; } else { iErrorDeltaUnsigned = (int)(nibbleByte & 15); nibbleFirst = true; } int iErrorDeltaSigned = iErrorDeltaUnsigned >= 8 ? iErrorDeltaUnsigned - 16 : iErrorDeltaUnsigned; int lNewSampInt = lPredSample + (int)channelData[k].iDelta * iErrorDeltaSigned; short lNewSamp = lNewSampInt <= -32768 ? (short)-32768 : lNewSampInt >= 32767 ? (short)32767 : (short)lNewSampInt; channelData[k].iDelta = (short)( (int)channelData[k].iDelta * (int)MicrosoftAdPcmData.AdaptionTable[iErrorDeltaUnsigned] >> 8 ); if (channelData[k].iDelta < 16) { channelData[k].iDelta = 16; } channelData[k].iSamp2 = channelData[k].iSamp1; channelData[k].iSamp1 = lNewSamp; dataBytes[position] = (byte)(ushort)lNewSamp; dataBytes[position + 1] = (byte)((ushort)lNewSamp >> 8); position += 2; } } } stream.Position += adpcmData.BlockSize - (format.Channels * (adpcmData.SamplesPerBlock - 2) + 1 >> 1) - 7 * format.Channels; } stream.Position += (int)ckSize - blocks * adpcmData.BlockSize; } else { // invalid throw new InvalidDataException("No fmt chunk before the data chunk"); } } else { // unsupported chunk stream.Position += (long)ckSize; } // pad byte if ((ckSize & 1) == 1) { stream.Position++; } } // finalize if (dataBytes == null) { throw new InvalidDataException("No data chunk before the end of the file"); } else if (format.Channels == 1) { return(new Sound(format.SampleRate, ((format.BitsPerSample + 7) >> 3) << 3, new byte[][] { dataBytes })); } else { byte[][] bytes = new byte[format.Channels][]; for (int i = 0; i < format.Channels; i++) { bytes[i] = new byte[dataBytes.Length / format.Channels]; } int bytesPerSample = (format.BitsPerSample + 7) >> 3; int samples = dataBytes.Length / (format.Channels * bytesPerSample); int pos1 = 0; int pos2 = 0; for (int i = 0; i < samples; i++) { for (int j = 0; j < format.Channels; j++) { for (int k = 0; k < bytesPerSample; k++) { bytes[j][pos1 + k] = dataBytes[pos2 + k]; } pos2 += bytesPerSample; } pos1 += bytesPerSample; } return(new Sound(format.SampleRate, ((format.BitsPerSample + 7) >> 3) << 3, bytes)); } } } }
// --- functions --- /// <summary>Reads wave data from a RIFF/WAVE/PCM file.</summary> /// <param name="fileName">The file name of the RIFF/WAVE/PCM file.</param> /// <returns>The wave data.</returns> /// <remarks>Both RIFF and RIFX container formats are supported by this function.</remarks> internal static WaveData LoadFromFile(string fileName) { string fileTitle = Path.GetFileName(fileName); byte[] fileBytes = File.ReadAllBytes(fileName); using (MemoryStream stream = new MemoryStream(fileBytes)) { using (BinaryReader reader = new BinaryReader(stream)) { // RIFF/RIFX chunk Endianness endianness; uint headerCkID = reader.ReadUInt32(); /* Chunk ID is character-based */ if (headerCkID == 0x46464952) { endianness = Endianness.Little; } else if (headerCkID == 0x58464952) { endianness = Endianness.Big; } else { throw new InvalidDataException("Invalid chunk ID in " + fileTitle); } uint headerCkSize = ReadUInt32(reader, endianness); uint formType = ReadUInt32(reader, endianness); if (formType != 0x45564157) { throw new InvalidDataException("Unsupported format in " + fileTitle); } // data chunks WaveFormat format = new WaveFormat(); FormatData data = null; byte[] dataBytes = null; while (stream.Position + 8 <= stream.Length) { uint ckID = reader.ReadUInt32(); /* Chunk ID is character-based */ uint ckSize = ReadUInt32(reader, endianness); if (ckID == 0x20746d66) { // "fmt " chunk if (ckSize < 14) { throw new InvalidDataException("Unsupported fmt chunk size in " + fileTitle); } ushort wFormatTag = ReadUInt16(reader, endianness); ushort wChannels = ReadUInt16(reader, endianness); uint dwSamplesPerSec = ReadUInt32(reader, endianness); if (dwSamplesPerSec >= 0x80000000) { throw new InvalidDataException("Unsupported dwSamplesPerSec in " + fileTitle); } uint dwAvgBytesPerSec = ReadUInt32(reader, endianness); ushort wBlockAlign = ReadUInt16(reader, endianness); if (wFormatTag == 1) { // PCM if (ckSize < 16) { throw new InvalidDataException("Unsupported fmt chunk size in " + fileTitle); } ushort wBitsPerSample = ReadUInt16(reader, endianness); stream.Position += ckSize - 16; if (wBitsPerSample < 1) { throw new InvalidDataException("Unsupported wBitsPerSample in " + fileTitle); } if (wBlockAlign != ((wBitsPerSample + 7) / 8) * wChannels) { throw new InvalidDataException("Unexpected wBlockAlign in " + fileTitle); } format.SampleRate = (int)dwSamplesPerSec; format.BitsPerSample = (int)wBitsPerSample; format.Channels = (int)wChannels; PcmData pcmData = new PcmData(); pcmData.BlockSize = (int)wBlockAlign; data = pcmData; } else if (wFormatTag == 2) { // Microsoft ADPCM if (ckSize < 22) { throw new InvalidDataException("Unsupported fmt chunk size in " + fileTitle); } ushort wBitsPerSample = ReadUInt16(reader, endianness); if (wBitsPerSample != 4) { throw new InvalidDataException("Unsupported wBitsPerSample in " + fileTitle); } ushort cbSize = ReadUInt16(reader, endianness); MicrosoftAdPcmData adpcmData = new MicrosoftAdPcmData(); adpcmData.SamplesPerBlock = ReadUInt16(reader, endianness); if (adpcmData.SamplesPerBlock == 0 | adpcmData.SamplesPerBlock > 2 * ((int)wBlockAlign - 6)) { throw new InvalidDataException("Unexpected nSamplesPerBlock in " + fileTitle); } ushort wNumCoef = ReadUInt16(reader, endianness); if (ckSize < 22 + 4 * wNumCoef) { throw new InvalidDataException("Unsupported fmt chunk size in " + fileTitle); } adpcmData.Coefficients = new short[wNumCoef][]; for (int i = 0; i < wNumCoef; i++) { unchecked { adpcmData.Coefficients[i] = new short[] { (short)ReadUInt16(reader, endianness), (short)ReadUInt16(reader, endianness) }; } } stream.Position += ckSize - (22 + 4 * wNumCoef); format.SampleRate = (int)dwSamplesPerSec; format.BitsPerSample = 16; format.Channels = (int)wChannels; adpcmData.BlockSize = wBlockAlign; data = adpcmData; } else { // unsupported format throw new InvalidDataException("Unsupported wFormatTag in " + fileTitle); } } else if (ckID == 0x61746164) { // "data" chunk if (ckSize >= 0x80000000) { throw new InvalidDataException("Unsupported data chunk size in " + fileTitle); } if (data is PcmData) { // PCM int bytesPerSample = (format.BitsPerSample + 7) / 8; int samples = (int)ckSize / (format.Channels * bytesPerSample); int dataSize = samples * format.Channels * bytesPerSample; dataBytes = reader.ReadBytes(dataSize); stream.Position += ckSize - dataSize; } else if (data is MicrosoftAdPcmData) { // Microsoft ADPCM MicrosoftAdPcmData adpcmData = (MicrosoftAdPcmData)data; int blocks = (int)ckSize / adpcmData.BlockSize; dataBytes = new byte[2 * blocks * format.Channels * adpcmData.SamplesPerBlock]; int position = 0; for (int i = 0; i < blocks; i++) { unchecked { MicrosoftAdPcmData.ChannelData[] channelData = new MicrosoftAdPcmData.ChannelData[format.Channels]; for (int j = 0; j < format.Channels; j++) { channelData[j].bPredictor = (int)reader.ReadByte(); if (channelData[j].bPredictor >= adpcmData.Coefficients.Length) { throw new InvalidDataException("Invalid bPredictor in " + fileTitle); } channelData[j].iCoef1 = (int)adpcmData.Coefficients[channelData[j].bPredictor][0]; channelData[j].iCoef2 = (int)adpcmData.Coefficients[channelData[j].bPredictor][1]; } for (int j = 0; j < format.Channels; j++) { channelData[j].iDelta = (short)ReadUInt16(reader, endianness); } for (int j = 0; j < format.Channels; j++) { channelData[j].iSamp1 = (short)ReadUInt16(reader, endianness); } for (int j = 0; j < format.Channels; j++) { channelData[j].iSamp2 = (short)ReadUInt16(reader, endianness); } for (int j = 0; j < format.Channels; j++) { dataBytes[position] = (byte)(ushort)channelData[j].iSamp2; dataBytes[position + 1] = (byte)((ushort)channelData[j].iSamp2 >> 8); position += 2; } for (int j = 0; j < format.Channels; j++) { dataBytes[position] = (byte)(ushort)channelData[j].iSamp1; dataBytes[position + 1] = (byte)((ushort)channelData[j].iSamp1 >> 8); position += 2; } uint nibbleByte = 0; bool nibbleFirst = true; for (int j = 0; j < adpcmData.SamplesPerBlock - 2; j++) { for (int k = 0; k < format.Channels; k++) { int lPredSample = (int)channelData[k].iSamp1 * channelData[k].iCoef1 + (int)channelData[k].iSamp2 * channelData[k].iCoef2 >> 8; int iErrorDeltaUnsigned; if (nibbleFirst) { nibbleByte = (uint)reader.ReadByte(); iErrorDeltaUnsigned = (int)(nibbleByte >> 4); nibbleFirst = false; } else { iErrorDeltaUnsigned = (int)(nibbleByte & 15); nibbleFirst = true; } int iErrorDeltaSigned = iErrorDeltaUnsigned >= 8 ? iErrorDeltaUnsigned - 16 : iErrorDeltaUnsigned; int lNewSampInt = lPredSample + (int)channelData[k].iDelta * iErrorDeltaSigned; short lNewSamp = lNewSampInt <= -32768 ? (short)-32768 : lNewSampInt >= 32767 ? (short)32767 : (short)lNewSampInt; channelData[k].iDelta = (short)( (int)channelData[k].iDelta * (int)MicrosoftAdPcmData.AdaptionTable[iErrorDeltaUnsigned] >> 8 ); if (channelData[k].iDelta < 16) { channelData[k].iDelta = 16; } channelData[k].iSamp2 = channelData[k].iSamp1; channelData[k].iSamp1 = lNewSamp; dataBytes[position] = (byte)(ushort)lNewSamp; dataBytes[position + 1] = (byte)((ushort)lNewSamp >> 8); position += 2; } } } stream.Position += adpcmData.BlockSize - (format.Channels * (adpcmData.SamplesPerBlock - 2) + 1 >> 1) - 7 * format.Channels; } stream.Position += (int)ckSize - blocks * adpcmData.BlockSize; } else { // invalid throw new InvalidDataException("No fmt chunk before the data chunk in " + fileTitle); } } else { // unsupported chunk stream.Position += (long)ckSize; } // pad byte if ((ckSize & 1) == 1) { stream.Position++; } } // finalize if (dataBytes == null) throw new InvalidDataException("No data chunk before the end of the file in " + fileTitle); return new WaveData(format, dataBytes); } } }
// --- functions --- /// <summary>Reads wave data from a RIFF/WAVE/PCM file.</summary> /// <param name="fileName">The file name of the RIFF/WAVE/PCM file.</param> /// <returns>The wave data.</returns> /// <remarks>Both RIFF and RIFX container formats are supported by this function.</remarks> internal static WaveData LoadFromFile(string fileName) { string fileTitle = Path.GetFileName(fileName); byte[] fileBytes = File.ReadAllBytes(fileName); using (MemoryStream stream = new MemoryStream(fileBytes)) { using (BinaryReader reader = new BinaryReader(stream)) { // RIFF/RIFX chunk Endianness endianness; uint headerCkID = reader.ReadUInt32(); /* Chunk ID is character-based */ if (headerCkID == 0x46464952) { endianness = Endianness.Little; } else if (headerCkID == 0x58464952) { endianness = Endianness.Big; } else { throw new InvalidDataException("Invalid chunk ID in " + fileTitle); } uint headerCkSize = ReadUInt32(reader, endianness); uint formType = ReadUInt32(reader, endianness); if (formType != 0x45564157) { throw new InvalidDataException("Unsupported format in " + fileTitle); } // data chunks WaveFormat format = new WaveFormat(); FormatData data = null; byte[] dataBytes = null; while (stream.Position + 8 <= stream.Length) { uint ckID = reader.ReadUInt32(); /* Chunk ID is character-based */ uint ckSize = ReadUInt32(reader, endianness); if (ckID == 0x20746d66) { // "fmt " chunk if (ckSize < 14) { throw new InvalidDataException("Unsupported fmt chunk size in " + fileTitle); } ushort wFormatTag = ReadUInt16(reader, endianness); ushort wChannels = ReadUInt16(reader, endianness); uint dwSamplesPerSec = ReadUInt32(reader, endianness); if (dwSamplesPerSec >= 0x80000000) { throw new InvalidDataException("Unsupported dwSamplesPerSec in " + fileTitle); } uint dwAvgBytesPerSec = ReadUInt32(reader, endianness); ushort wBlockAlign = ReadUInt16(reader, endianness); if (wFormatTag == 1) { // PCM if (ckSize < 16) { throw new InvalidDataException("Unsupported fmt chunk size in " + fileTitle); } ushort wBitsPerSample = ReadUInt16(reader, endianness); stream.Position += ckSize - 16; if (wBitsPerSample < 1) { throw new InvalidDataException("Unsupported wBitsPerSample in " + fileTitle); } if (wBlockAlign != ((wBitsPerSample + 7) / 8) * wChannels) { throw new InvalidDataException("Unexpected wBlockAlign in " + fileTitle); } format.SampleRate = (int)dwSamplesPerSec; format.BitsPerSample = (int)wBitsPerSample; format.Channels = (int)wChannels; PcmData pcmData = new PcmData(); pcmData.BlockSize = (int)wBlockAlign; data = pcmData; } else if (wFormatTag == 2) { // Microsoft ADPCM if (ckSize < 22) { throw new InvalidDataException("Unsupported fmt chunk size in " + fileTitle); } ushort wBitsPerSample = ReadUInt16(reader, endianness); if (wBitsPerSample != 4) { throw new InvalidDataException("Unsupported wBitsPerSample in " + fileTitle); } ushort cbSize = ReadUInt16(reader, endianness); MicrosoftAdPcmData adpcmData = new MicrosoftAdPcmData(); adpcmData.SamplesPerBlock = ReadUInt16(reader, endianness); if (adpcmData.SamplesPerBlock == 0 | adpcmData.SamplesPerBlock > 2 * ((int)wBlockAlign - 6)) { throw new InvalidDataException("Unexpected nSamplesPerBlock in " + fileTitle); } ushort wNumCoef = ReadUInt16(reader, endianness); if (ckSize < 22 + 4 * wNumCoef) { throw new InvalidDataException("Unsupported fmt chunk size in " + fileTitle); } adpcmData.Coefficients = new short[wNumCoef][]; for (int i = 0; i < wNumCoef; i++) { unchecked { adpcmData.Coefficients[i] = new short[] { (short)ReadUInt16(reader, endianness), (short)ReadUInt16(reader, endianness) }; } } stream.Position += ckSize - (22 + 4 * wNumCoef); format.SampleRate = (int)dwSamplesPerSec; format.BitsPerSample = 16; format.Channels = (int)wChannels; adpcmData.BlockSize = wBlockAlign; data = adpcmData; } else { // unsupported format throw new InvalidDataException("Unsupported wFormatTag in " + fileTitle); } } else if (ckID == 0x61746164) { // "data" chunk if (ckSize >= 0x80000000) { throw new InvalidDataException("Unsupported data chunk size in " + fileTitle); } if (data is PcmData) { // PCM int bytesPerSample = (format.BitsPerSample + 7) / 8; int samples = (int)ckSize / (format.Channels * bytesPerSample); int dataSize = samples * format.Channels * bytesPerSample; dataBytes = reader.ReadBytes(dataSize); stream.Position += ckSize - dataSize; } else if (data is MicrosoftAdPcmData) { // Microsoft ADPCM MicrosoftAdPcmData adpcmData = (MicrosoftAdPcmData)data; int blocks = (int)ckSize / adpcmData.BlockSize; dataBytes = new byte[2 * blocks * format.Channels * adpcmData.SamplesPerBlock]; int position = 0; for (int i = 0; i < blocks; i++) { unchecked { MicrosoftAdPcmData.ChannelData[] channelData = new MicrosoftAdPcmData.ChannelData[format.Channels]; for (int j = 0; j < format.Channels; j++) { channelData[j].bPredictor = (int)reader.ReadByte(); if (channelData[j].bPredictor >= adpcmData.Coefficients.Length) { throw new InvalidDataException("Invalid bPredictor in " + fileTitle); } channelData[j].iCoef1 = (int)adpcmData.Coefficients[channelData[j].bPredictor][0]; channelData[j].iCoef2 = (int)adpcmData.Coefficients[channelData[j].bPredictor][1]; } for (int j = 0; j < format.Channels; j++) { channelData[j].iDelta = (short)ReadUInt16(reader, endianness); } for (int j = 0; j < format.Channels; j++) { channelData[j].iSamp1 = (short)ReadUInt16(reader, endianness); } for (int j = 0; j < format.Channels; j++) { channelData[j].iSamp2 = (short)ReadUInt16(reader, endianness); } for (int j = 0; j < format.Channels; j++) { dataBytes[position] = (byte)(ushort)channelData[j].iSamp2; dataBytes[position + 1] = (byte)((ushort)channelData[j].iSamp2 >> 8); position += 2; } for (int j = 0; j < format.Channels; j++) { dataBytes[position] = (byte)(ushort)channelData[j].iSamp1; dataBytes[position + 1] = (byte)((ushort)channelData[j].iSamp1 >> 8); position += 2; } uint nibbleByte = 0; bool nibbleFirst = true; for (int j = 0; j < adpcmData.SamplesPerBlock - 2; j++) { for (int k = 0; k < format.Channels; k++) { int lPredSample = (int)channelData[k].iSamp1 * channelData[k].iCoef1 + (int)channelData[k].iSamp2 * channelData[k].iCoef2 >> 8; int iErrorDeltaUnsigned; if (nibbleFirst) { nibbleByte = (uint)reader.ReadByte(); iErrorDeltaUnsigned = (int)(nibbleByte >> 4); nibbleFirst = false; } else { iErrorDeltaUnsigned = (int)(nibbleByte & 15); nibbleFirst = true; } int iErrorDeltaSigned = iErrorDeltaUnsigned >= 8 ? iErrorDeltaUnsigned - 16 : iErrorDeltaUnsigned; int lNewSampInt = lPredSample + (int)channelData[k].iDelta * iErrorDeltaSigned; short lNewSamp = lNewSampInt <= -32768 ? (short)-32768 : lNewSampInt >= 32767 ? (short)32767 : (short)lNewSampInt; channelData[k].iDelta = (short)( (int)channelData[k].iDelta * (int)MicrosoftAdPcmData.AdaptionTable[iErrorDeltaUnsigned] >> 8 ); if (channelData[k].iDelta < 16) { channelData[k].iDelta = 16; } channelData[k].iSamp2 = channelData[k].iSamp1; channelData[k].iSamp1 = lNewSamp; dataBytes[position] = (byte)(ushort)lNewSamp; dataBytes[position + 1] = (byte)((ushort)lNewSamp >> 8); position += 2; } } } stream.Position += adpcmData.BlockSize - (format.Channels * (adpcmData.SamplesPerBlock - 2) + 1 >> 1) - 7 * format.Channels; } stream.Position += (int)ckSize - blocks * adpcmData.BlockSize; } else { // invalid throw new InvalidDataException("No fmt chunk before the data chunk in " + fileTitle); } } else { // unsupported chunk stream.Position += (long)ckSize; } // pad byte if ((ckSize & 1) == 1) { stream.Position++; } } // finalize if (dataBytes == null) { throw new InvalidDataException("No data chunk before the end of the file in " + fileTitle); } return(new WaveData(format, dataBytes)); } } }