public WaveInMeter(int samples) { _args = new WaveLevelEventArgs(); var format = new WaveFormatPcm(44100, 16, 1); _waveIn = new WaveIn(new MeterStream(this), format, format.FrameSize * samples); _waveIn.Start(); }
private static Sound WaveLoadFromStream(BinaryReader reader, BinaryReaderExtensions.Endianness endianness, uint fileSize) { long stopPosition = Math.Min(fileSize, reader.BaseStream.Length); WaveFormatEx format = null; byte[] dataBytes = null; while (reader.BaseStream.Position + 8 <= stopPosition) { uint ckID = reader.ReadUInt32(endianness); uint ckSize = reader.ReadUInt32(endianness); // "fmt " if (ckID == 0x20746D66) { if (ckSize < 16) { throw new InvalidDataException("Unsupported fmt chunk size"); } ushort wFormatTag = reader.ReadUInt16(endianness); if (wFormatTag == 0x0001 || wFormatTag == 0x0003) { format = new WaveFormatPcm { wFormatTag = wFormatTag }; } else if (wFormatTag == 0x0002) { format = new WaveFormatAdPcm { wFormatTag = wFormatTag }; } else if (wFormatTag == 0x0050 || wFormatTag == 0x0055) { format = new WaveFormatMp3 { wFormatTag = wFormatTag }; } else { // unsupported format throw new InvalidDataException("Unsupported wFormatTag"); } format.nChannels = reader.ReadUInt16(endianness); format.nSamplesPerSec = reader.ReadUInt32(endianness); format.nAvgBytesPerSec = reader.ReadUInt32(endianness); format.nBlockAlign = reader.ReadUInt16(endianness); format.wBitsPerSample = reader.ReadUInt16(endianness); if (!(format is WaveFormatAdPcm)) { if (ckSize > 16) { format.cbSize = reader.ReadUInt16(endianness); // This is a countermeasure to the cbSize is not correct file. reader.BaseStream.Position += Math.Min(format.cbSize, ckSize - 18); } if (format is WaveFormatPcm) { if (format.wBitsPerSample < 1) { throw new InvalidDataException("Unsupported wBitsPerSample"); } if (format.nBlockAlign != format.nChannels * format.wBitsPerSample / 8) { throw new InvalidDataException("Unexpected wBlockAlign"); } if (format.nAvgBytesPerSec != format.nChannels * format.nSamplesPerSec * format.wBitsPerSample / 8) { throw new InvalidDataException("Unexpected nAvgBytesPerSec"); } } } else { WaveFormatAdPcm adPcmFormat = (WaveFormatAdPcm)format; if (ckSize <= 16) { throw new InvalidDataException("Unsupported fmt chunk size"); } adPcmFormat.cbSize = reader.ReadUInt16(endianness); long readerPrevPos = reader.BaseStream.Position; if (adPcmFormat.cbSize < 32) { throw new InvalidDataException("Unsupported fmt chunk size"); } adPcmFormat.nSamplesPerBlock = reader.ReadUInt16(endianness); adPcmFormat.nNumCoef = reader.ReadUInt16(endianness); adPcmFormat.aCoeff = new WaveFormatAdPcm.CoefSet[adPcmFormat.nNumCoef]; for (int i = 0; i < adPcmFormat.nNumCoef; i++) { adPcmFormat.aCoeff[i].iCoef1 = reader.ReadInt16(endianness); adPcmFormat.aCoeff[i].iCoef2 = reader.ReadInt16(endianness); } reader.BaseStream.Position += adPcmFormat.cbSize - (reader.BaseStream.Position - readerPrevPos); if (adPcmFormat.wBitsPerSample != 4) { throw new InvalidDataException("Unsupported wBitsPerSample"); } if (adPcmFormat.nSamplesPerBlock != (adPcmFormat.nBlockAlign - 7 * adPcmFormat.nChannels) * 8 / (adPcmFormat.wBitsPerSample * adPcmFormat.nChannels) + 2) { throw new InvalidDataException("Unexpected nSamplesPerBlock"); } } } // "data" else if (ckID == 0x61746164) { if (format == null) { // invalid throw new InvalidDataException("No fmt chunk before the data chunk"); } if (!(format is WaveFormatAdPcm)) { dataBytes = reader.ReadBytes((int)ckSize); break; } { WaveFormatAdPcm adPcmFormat = (WaveFormatAdPcm)format; uint blocks = ckSize / adPcmFormat.nBlockAlign; dataBytes = new byte[adPcmFormat.nChannels * 2 * blocks * adPcmFormat.nSamplesPerBlock]; using (MemoryStream stream = new MemoryStream(dataBytes)) using (BinaryWriter writer = new BinaryWriter(stream)) { for (int i = 0; i < blocks; i++) { WaveFormatAdPcm.BlockData blockData = new WaveFormatAdPcm.BlockData(adPcmFormat.nChannels); long readerPrevPos = reader.BaseStream.Position; // get first data from this block header for (int j = 0; j < adPcmFormat.nChannels; j++) { blockData.bPredictor[j] = reader.ReadByte(); } for (int j = 0; j < adPcmFormat.nChannels; j++) { blockData.iDelta[j] = reader.ReadInt16(endianness); } for (int j = 0; j < adPcmFormat.nChannels; j++) { blockData.iSamp1[j] = reader.ReadInt16(endianness); } for (int j = 0; j < adPcmFormat.nChannels; j++) { blockData.iSamp2[j] = reader.ReadInt16(endianness); } // set first coefficients for (int j = 0; j < adPcmFormat.nChannels; j++) { if (blockData.bPredictor[j] >= adPcmFormat.nNumCoef) { throw new InvalidDataException("Invalid bPredictor"); } blockData.CoefSet[j] = adPcmFormat.aCoeff[blockData.bPredictor[j]]; } // the first two samples are already decoded for (int j = 0; j < adPcmFormat.nChannels; j++) { writer.Write(blockData.iSamp2[j]); } for (int j = 0; j < adPcmFormat.nChannels; j++) { writer.Write(blockData.iSamp1[j]); } byte nibbleByte = 0; bool nibbleFirst = true; for (int j = 0; j < adPcmFormat.nSamplesPerBlock - 2; j++) { for (int k = 0; k < adPcmFormat.nChannels; k++) { int lPredSamp = (blockData.iSamp1[k] * blockData.CoefSet[k].iCoef1 + blockData.iSamp2[k] * blockData.CoefSet[k].iCoef2) / 256; int iErrorDeltaUnsigned; if (nibbleFirst) { nibbleByte = reader.ReadByte(); nibbleFirst = false; iErrorDeltaUnsigned = nibbleByte >> 4; } else { nibbleFirst = true; iErrorDeltaUnsigned = nibbleByte & 15; } int iErrorDeltaSigned = iErrorDeltaUnsigned >= 8 ? iErrorDeltaUnsigned - 16 : iErrorDeltaUnsigned; int lNewSampInt = lPredSamp + blockData.iDelta[k] * iErrorDeltaSigned; short lNewSamp; if (lNewSampInt > short.MaxValue) { lNewSamp = short.MaxValue; } else if (lNewSampInt < short.MinValue) { lNewSamp = short.MinValue; } else { lNewSamp = (short)lNewSampInt; } writer.Write(lNewSamp); blockData.iDelta[k] = (short)(blockData.iDelta[k] * WaveFormatAdPcm.AdaptionTable[iErrorDeltaUnsigned] / 256); if (blockData.iDelta[k] < 16) { blockData.iDelta[k] = 16; } blockData.iSamp2[k] = blockData.iSamp1[k]; blockData.iSamp1[k] = lNewSamp; } } reader.BaseStream.Position += adPcmFormat.nBlockAlign - (reader.BaseStream.Position - readerPrevPos); } } break; } } // unsupported chunk else { reader.BaseStream.Position += ckSize; } // pad byte if ((ckSize & 1) == 1) { reader.BaseStream.Position++; } } // finalize if (dataBytes == null) { throw new InvalidDataException("No data chunk before the end of the file"); } if (format is WaveFormatMp3) { using (MemoryStream dataStream = new MemoryStream(dataBytes)) { return(Mp3LoadFromStream(dataStream)); } } int bytesPerSample; if (!(format is WaveFormatAdPcm)) { bytesPerSample = format.wBitsPerSample / 8; } else { bytesPerSample = 2; } // The size of the data chunk may not be correct, so we use sampleCount as the standard thereafter. int sampleCount = dataBytes.Length / (format.nChannels * bytesPerSample); byte[][] buffers = new byte[format.nChannels][]; for (int i = 0; i < format.nChannels; i++) { buffers[i] = new byte[sampleCount * bytesPerSample]; } for (int i = 0; i < sampleCount; i++) { for (int j = 0; j < format.nChannels; j++) { for (int k = 0; k < bytesPerSample; k++) { buffers[j][i * bytesPerSample + k] = dataBytes[i * bytesPerSample * format.nChannels + bytesPerSample * j + k]; } } } return(ChangeBitDepth(format.wFormatTag, (int)format.nSamplesPerSec, bytesPerSample, sampleCount, buffers)); }