Esempio n. 1
0
        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()
            };
        }
Esempio n. 2
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.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;
        }