public WaveHeader(BinaryReader waveBinaryReader) { _riffChunkDescriptor = new RiffChunkDescriptor { ChunkID = waveBinaryReader.ReadBytes(TEXT_SIZE), ChunkSize = waveBinaryReader.ReadUInt32(), Format = waveBinaryReader.ReadBytes(TEXT_SIZE) }; _fmtSubChunk = new FmtSubChunk { Subchunk1ID = waveBinaryReader.ReadBytes(TEXT_SIZE), Subchunk1Size = waveBinaryReader.ReadUInt32(), AudioFormat = waveBinaryReader.ReadUInt16(), NumChannels = waveBinaryReader.ReadUInt16(), SampleRate = waveBinaryReader.ReadUInt32(), ByteRate = waveBinaryReader.ReadUInt32(), BlockAlign = waveBinaryReader.ReadUInt16(), BitsPerSample = waveBinaryReader.ReadUInt16() }; _dataSubChunk = new DataSubChunk { Subchunk2ID = waveBinaryReader.ReadBytes(TEXT_SIZE), Subchunk2Size = waveBinaryReader.ReadUInt32() }; }
private bool Read(BinaryReader br, ReadMode mode, long startFrame, long endFrame) { ErrorReason = string.Empty; bool riffChunkExist = false; bool fmtChunkExist = false; bool ds64ChunkExist = false; long offset = 0; try { do { var fourcc = br.ReadBytes(4); if (fourcc.Length < 4) { // ファイルの終わりに達した。 break; } offset += 4; long advance = 0; if (!riffChunkExist) { if (!PcmDataLib.PcmDataUtil.FourCCHeaderIs(fourcc, 0, "RIFF") && !PcmDataLib.PcmDataUtil.FourCCHeaderIs(fourcc, 0, "RF64")) { // ファイルの先頭がRF64でもRIFFもない。WAVではない。 ErrorReason = "File does not start with RIFF nor RF64."; return(false); } advance = ReadRiffChunk(br, fourcc); riffChunkExist = true; } else if (PcmDataLib.PcmDataUtil.FourCCHeaderIs(fourcc, 0, "fmt ")) { advance = ReadFmtChunk(br, fourcc); fmtChunkExist = true; } else if (PcmDataLib.PcmDataUtil.FourCCHeaderIs(fourcc, 0, "LIST")) { advance = ReadListChunk(br); } else if (PcmDataLib.PcmDataUtil.FourCCHeaderIs(fourcc, 0, "id3 ")) { advance = ReadId3Chunk(br); } else if (PcmDataLib.PcmDataUtil.FourCCHeaderIs(fourcc, 0, "ID3 ")) { advance = ReadId3Chunk(br); } else if (PcmDataLib.PcmDataUtil.FourCCHeaderIs(fourcc, 0, "ds64")) { advance = ReadDS64Chunk(br); ds64ChunkExist = true; } else if (PcmDataLib.PcmDataUtil.FourCCHeaderIs(fourcc, 0, "data")) { if (!fmtChunkExist) { // fmtチャンクがないと量子化ビット数がわからず処理が継続できない。 ErrorReason = "fmt subchunk is missing."; return(false); } if (ds64ChunkExist && 0 < mDscList.Count) { ErrorReason = "multiple data chunk in RF64. not supported format."; return(false); } int frameBytes = BitsPerSample / 8 * NumChannels; var dsc = new DataSubChunk(); advance = dsc.ReadDataChunkHeader(br, offset, fourcc, NumChannels, BitsPerSample); if (ds64ChunkExist) { // ds64チャンクが存在する場合(RF64形式) // dsc.ChunkSizeは正しくないので、そこから算出するdsc.NumFramesも正しくない。 // dsc.NumFrameをds64の値で上書きする。 dsc.NumFrames = Ds64DataSize / frameBytes; } else { const long MASK = UInt32.MaxValue; if (MASK < (br.BaseStream.Length - 8) && RiffChunkSize != MASK) { // RIFF chunkSizeが0xffffffffではないのにファイルサイズが4GB+8(8==RIFFチャンクのヘッダサイズ)以上ある。 // このファイルはdsc.ChunkSize情報の信憑性が薄い。 // dsc.ChunkSizeの上位ビットが桁あふれによって消失している可能性があるので、 // dsc.ChunkSizeの上位ビットをファイルサイズから類推して付加し、 // dsc.NumFrameを更新する。 long remainBytes = br.BaseStream.Length - (offset + advance); long maskedRemainBytes = remainBytes & 0xffffffffL; if (maskedRemainBytes <= dsc.ChunkSize && RiffChunkSize - maskedRemainBytes < 4096) { long realChunkSize = dsc.ChunkSize; while (realChunkSize + 0x100000000L <= remainBytes) { realChunkSize += 0x100000000L; } dsc.NumFrames = realChunkSize / frameBytes; } } } int peekBytes = 0; if (mode == ReadMode.OnlyHeader) { peekBytes = ScanDopMarker(br, dsc.NumFrames); } // マルチデータチャンク形式の場合、data chunkの後にさらにdata chunkが続いたりするので、 // 読み込みを続行する。 long skipBytes = (dsc.NumFrames * frameBytes - peekBytes + 1) & (~1L); if (0 < skipBytes) { PcmDataLib.PcmDataUtil.BinaryReaderSkip(br, skipBytes); } if (br.BaseStream.Length < (offset + advance) + skipBytes) { // ファイルが途中で切れている。 dsc.NumFrames = (br.BaseStream.Length - (offset + advance)) / frameBytes; } if (0 < dsc.NumFrames) { mDscList.Add(dsc); } else { // ファイルがDSCヘッダ部分を最後に切れていて、サンプルデータが1フレーム分すらも無いとき。 } advance += skipBytes; } else { advance = SkipUnknownChunk(br, fourcc); } if (0 == advance) { // 行儀が悪いWAVファイル。ファイルの最後に0がいくつか書き込まれている。 return(riffChunkExist && fmtChunkExist && mDscList.Count != 0); } offset += advance; } while (true); } catch (Exception ex) { ErrorReason = string.Format("E: WavRWLib2.WavData.ReadRiffChunk() {0}", ex); } if (mode == ReadMode.HeaderAndPcmData) { if (!ReadPcmDataInternal(br, startFrame, endFrame)) { return(false); } return(true); } return(riffChunkExist && fmtChunkExist && mDscList.Count != 0); }
private bool Read(BinaryReader br, ReadMode mode, long startFrame, long endFrame) { ErrorReason = string.Empty; bool riffChunkExist = false; bool fmtChunkExist = false; bool ds64ChunkExist = false; long offset = 0; try { do { var fourcc = br.ReadBytes(4); if (fourcc.Length < 4) { // ファイルの終わりに達した。 break; } offset += 4; long advance = 0; if (!riffChunkExist) { if (!PcmDataLib.Util.FourCCHeaderIs(fourcc, 0, "RIFF") && !PcmDataLib.Util.FourCCHeaderIs(fourcc, 0, "RF64")) { // ファイルの先頭がRF64でもRIFFもない。WAVではない。 ErrorReason = "File does not start with RIFF nor RF64."; return false; } advance = ReadRiffChunk(br, fourcc); riffChunkExist = true; } else if (PcmDataLib.Util.FourCCHeaderIs(fourcc, 0, "fmt ")) { advance = ReadFmtChunk(br, fourcc); fmtChunkExist = true; } else if (PcmDataLib.Util.FourCCHeaderIs(fourcc, 0, "LIST")) { advance = ReadListChunk(br); } else if (PcmDataLib.Util.FourCCHeaderIs(fourcc, 0, "id3 ")) { advance = ReadId3Chunk(br); } else if (PcmDataLib.Util.FourCCHeaderIs(fourcc, 0, "ds64")) { advance = ReadDS64Chunk(br); ds64ChunkExist = true; } else if (PcmDataLib.Util.FourCCHeaderIs(fourcc, 0, "data")) { if (!fmtChunkExist) { // fmtチャンクがないと量子化ビット数がわからず処理が継続できない。 ErrorReason = "fmt subchunk is missing."; return false; } if (ds64ChunkExist && 0 < mDscList.Count) { ErrorReason = "multiple data chunk in RF64. not supported format."; return false; } int frameBytes = BitsPerSample / 8 * NumChannels; var dsc = new DataSubChunk(); advance = dsc.ReadDataChunkHeader(br, offset, fourcc, NumChannels, BitsPerSample); if (ds64ChunkExist) { // ds64チャンクが存在する場合(RF64形式) // dsc.ChunkSizeは正しくないので、そこから算出するdsc.NumFramesも正しくない。 // dsc.NumFrameをds64の値で上書きする。 dsc.NumFrames = Ds64DataSize / frameBytes; } else { const long MASK = UInt32.MaxValue; if (MASK < (br.BaseStream.Length - 8) && RiffChunkSize != MASK) { // RIFF chunkSizeが0xffffffffではないのにファイルサイズが4GB+8(8==RIFFチャンクのヘッダサイズ)以上ある。 // このファイルはdsc.ChunkSize情報の信憑性が薄い。 // dsc.ChunkSizeの上位ビットが桁あふれによって消失している可能性があるので、 // dsc.ChunkSizeの上位ビットをファイルサイズから類推して付加し、 // dsc.NumFrameを更新する。 long remainBytes = br.BaseStream.Length - (offset + advance); long maskedRemainBytes = remainBytes & 0xffffffffL; if (maskedRemainBytes <= dsc.ChunkSize && RiffChunkSize - maskedRemainBytes < 4096) { long realChunkSize = dsc.ChunkSize; while (realChunkSize + 0x100000000L <= remainBytes) { realChunkSize += 0x100000000L; } dsc.NumFrames = realChunkSize / frameBytes; } } } // マルチデータチャンク形式の場合、data chunkの後にさらにdata chunkが続いたりするので、 // 読み込みを続行する。 long skipBytes = (dsc.NumFrames * frameBytes + 1) & (~1L); PcmDataLib.Util.BinaryReaderSkip(br, skipBytes); if (br.BaseStream.Length < (offset + advance) + skipBytes) { // ファイルが途中で切れている。 dsc.NumFrames = (br.BaseStream.Length - (offset + advance)) / frameBytes; } if (0 < dsc.NumFrames) { mDscList.Add(dsc); } else { // ファイルがDSCヘッダ部分を最後に切れていて、サンプルデータが1フレーム分すらも無いとき。 } advance += skipBytes; } else { advance = SkipUnknownChunk(br, fourcc); } if (0 == advance) { // 行儀が悪いWAVファイル。ファイルの最後に0がいくつか書き込まれている。 return riffChunkExist && fmtChunkExist && mDscList.Count != 0; } offset += advance; } while (true); } catch (Exception ex) { ErrorReason = string.Format("E: WavRWLib2.WavData.ReadRiffChunk() {0}", ex); } if (mode == ReadMode.HeaderAndPcmData) { if (!ReadPcmDataInternal(br, startFrame, endFrame)) { return false; } return true; } return riffChunkExist && fmtChunkExist && mDscList.Count != 0; }