Exemple #1
0
        /// <summary>
        /// Creates a cue list from the cue RIFF chunk and the list RIFF chunk
        /// </summary>
        /// <param name="cueChunkData">The data contained in the cue chunk</param>
        /// <param name="listChunkData">The data contained in the list chunk</param>
        internal CueList(byte[] cueChunkData, byte[] listChunkData)
        {
            int cueCount = BitConverter.ToInt32(cueChunkData, 0);
            Dictionary <int, int> cueIndex = new Dictionary <int, int>();

            int[] positions = new int[cueCount];
            int   cue       = 0;

            for (int p = 4; cueChunkData.Length - p >= 24; p += 24, cue++)
            {
                cueIndex[BitConverter.ToInt32(cueChunkData, p)] = cue;
                positions[cue] = BitConverter.ToInt32(cueChunkData, p + 20);
            }

            string[] labels      = new string[cueCount];
            int      labelLength = 0;

            var labelChunkId = ChunkIdentifier.ChunkIdentifierToInt32("labl");

            for (int p = 4; listChunkData.Length - p >= 16; p += labelLength + labelLength % 2 + 12)
            {
                if (BitConverter.ToInt32(listChunkData, p) == labelChunkId)
                {
                    labelLength = BitConverter.ToInt32(listChunkData, p + 4) - 4;
                    var cueId = BitConverter.ToInt32(listChunkData, p + 8);
                    cue         = cueIndex[cueId];
                    labels[cue] = Encoding.Default.GetString(listChunkData, p + 12, labelLength - 1);
                }
            }

            for (int i = 0; i < cueCount; i++)
            {
                cues.Add(new Cue(positions[i], labels[i]));
            }
        }
Exemple #2
0
        internal byte[] GetRiffChunks()
        {
            if (this.Count == 0)
            {
                return(null);
            }
            int num  = 12 + 24 * this.Count;
            int num2 = 12;

            for (int i = 0; i < this.Count; i++)
            {
                int num3 = this[i].Label.Length + 1;
                num2 += num3 + num3 % 2 + 12;
            }
            byte[] array  = new byte[num + num2];
            int    value  = ChunkIdentifier.ChunkIdentifierToInt32("cue ");
            int    value2 = ChunkIdentifier.ChunkIdentifierToInt32("data");
            int    value3 = ChunkIdentifier.ChunkIdentifierToInt32("LIST");
            int    value4 = ChunkIdentifier.ChunkIdentifierToInt32("adtl");
            int    value5 = ChunkIdentifier.ChunkIdentifierToInt32("labl");

            using (MemoryStream memoryStream = new MemoryStream(array))
            {
                using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
                {
                    binaryWriter.Write(value);
                    binaryWriter.Write(num - 8);
                    binaryWriter.Write(this.Count);
                    for (int j = 0; j < this.Count; j++)
                    {
                        int position = this[j].Position;
                        binaryWriter.Write(j);
                        binaryWriter.Write(position);
                        binaryWriter.Write(value2);
                        binaryWriter.Seek(8, SeekOrigin.Current);
                        binaryWriter.Write(position);
                    }
                    binaryWriter.Write(value3);
                    binaryWriter.Write(num2 - 8);
                    binaryWriter.Write(value4);
                    for (int k = 0; k < this.Count; k++)
                    {
                        binaryWriter.Write(value5);
                        binaryWriter.Write(this[k].Label.Length + 1 + 4);
                        binaryWriter.Write(k);
                        binaryWriter.Write(Encoding.Default.GetBytes(this[k].Label.ToCharArray()));
                        if (this[k].Label.Length % 2 == 0)
                        {
                            binaryWriter.Seek(2, SeekOrigin.Current);
                        }
                        else
                        {
                            binaryWriter.Seek(1, SeekOrigin.Current);
                        }
                    }
                }
            }
            return(array);
        }
Exemple #3
0
        private void ReadRiffHeader(BinaryReader br)
        {
            int header = br.ReadInt32();

            if (header == ChunkIdentifier.ChunkIdentifierToInt32("RF64"))
            {
                this.isRf64 = true;
            }
            else if (header != ChunkIdentifier.ChunkIdentifierToInt32("RIFF"))
            {
                throw new FormatException("Not a WAVE file - no RIFF header");
            }
        }
        private void ReadDs64Chunk(BinaryReader reader)
        {
            int num = ChunkIdentifier.ChunkIdentifierToInt32("ds64");

            if (reader.ReadInt32() != num)
            {
                throw new FormatException("Invalid RF64 WAV file - No ds64 chunk found");
            }
            int num2 = reader.ReadInt32();

            this.riffSize        = reader.ReadInt64();
            this.dataChunkLength = reader.ReadInt64();
            reader.ReadInt64();
            reader.ReadBytes(num2 - 24);
        }
Exemple #5
0
        /// <summary>
        /// http://tech.ebu.ch/docs/tech/tech3306-2009.pdf
        /// </summary>
        private void ReadDs64Chunk(BinaryReader reader)
        {
            int ds64ChunkId = ChunkIdentifier.ChunkIdentifierToInt32("ds64");
            int chunkId     = reader.ReadInt32();

            if (chunkId != ds64ChunkId)
            {
                throw new FormatException("Invalid RF64 WAV file - No ds64 chunk found");
            }
            int chunkSize = reader.ReadInt32();

            this.riffSize        = reader.ReadInt64();
            this.dataChunkLength = reader.ReadInt64();
            long sampleCount = reader.ReadInt64(); // replaces the value in the fact chunk

            reader.ReadBytes(chunkSize - 24);      // get to the end of this chunk (should parse extra stuff later)
        }
Exemple #6
0
        internal CueList(byte[] cueChunkData, byte[] listChunkData)
        {
            int num = BitConverter.ToInt32(cueChunkData, 0);
            Dictionary <int, int> dictionary = new Dictionary <int, int>();

            int[] array = new int[num];
            int   num2  = 0;
            int   num3  = 4;

            while (cueChunkData.Length - num3 >= 24)
            {
                dictionary[BitConverter.ToInt32(cueChunkData, num3)] = num2;
                array[num2] = BitConverter.ToInt32(cueChunkData, num3 + 20);
                num3       += 24;
                num2++;
            }
            string[] array2 = new string[num];
            int      num4   = 0;
            int      num5   = ChunkIdentifier.ChunkIdentifierToInt32("labl");
            int      num6   = 4;

            while (listChunkData.Length - num6 >= 16)
            {
                if (BitConverter.ToInt32(listChunkData, num6) == num5)
                {
                    num4 = BitConverter.ToInt32(listChunkData, num6 + 4) - 4;
                    int key = BitConverter.ToInt32(listChunkData, num6 + 8);
                    num2         = dictionary[key];
                    array2[num2] = Encoding.Default.GetString(listChunkData, num6 + 12, num4 - 1);
                }
                num6 += num4 + num4 % 2 + 12;
            }
            for (int i = 0; i < num; i++)
            {
                this.cues.Add(new Cue(array[i], array2[i]));
            }
        }
Exemple #7
0
        /// <summary>
        /// Gets the cues as the concatenated cue and list RIFF chunks.
        /// </summary>
        /// <returns>RIFF chunks containing the cue data</returns>
        internal byte[] GetRiffChunks()
        {
            if (Count == 0)
            {
                return(null);
            }
            var cueChunkLength  = 12 + 24 * Count;
            var listChunkLength = 12;

            for (int i = 0; i < Count; i++)
            {
                var labelChunkLength = this[i].Label.Length + 1;
                listChunkLength += labelChunkLength + labelChunkLength % 2 + 12;
            }

            byte[] chunks       = new byte[cueChunkLength + listChunkLength];
            var    cueChunkId   = ChunkIdentifier.ChunkIdentifierToInt32("cue ");
            int    dataChunkId  = ChunkIdentifier.ChunkIdentifierToInt32("data");
            int    listChunkId  = ChunkIdentifier.ChunkIdentifierToInt32("LIST");
            int    adtlTypeId   = ChunkIdentifier.ChunkIdentifierToInt32("adtl");
            int    labelChunkId = ChunkIdentifier.ChunkIdentifierToInt32("labl");

            using (var stream = new MemoryStream(chunks))
            {
                using (var writer = new BinaryWriter(stream))
                {
                    writer.Write(cueChunkId);
                    writer.Write(cueChunkLength - 8);
                    writer.Write(Count);
                    for (int cue = 0; cue < Count; cue++)
                    {
                        int position = this[cue].Position;

                        writer.Write(cue);
                        writer.Write(position);
                        writer.Write(dataChunkId);
                        writer.Seek(8, SeekOrigin.Current);
                        writer.Write(position);
                    }
                    writer.Write(listChunkId);
                    writer.Write(listChunkLength - 8);
                    writer.Write(adtlTypeId);
                    for (int cue = 0; cue < Count; cue++)
                    {
                        writer.Write(labelChunkId);
                        writer.Write(this[cue].Label.Length + 1 + 4);
                        writer.Write(cue);
                        writer.Write(Encoding.Default.GetBytes(this[cue].Label.ToCharArray()));
                        if (this[cue].Label.Length % 2 == 0)
                        {
                            writer.Seek(2, SeekOrigin.Current);
                        }
                        else
                        {
                            writer.Seek(1, SeekOrigin.Current);
                        }
                    }
                }
            }
            return(chunks);
        }
Exemple #8
0
        public WaveFormat ReadWaveHeader(Stream stream)
        {
            this.dataChunkPosition = -1;
            this.riffChunks        = new List <RiffChunk>();
            this.dataChunkLength   = 0;

            var br = new BinaryReader(stream);

            ReadRiffHeader(br);
            this.riffSize = br.ReadUInt32(); // read the file size (minus 8 bytes)

            if (br.ReadInt32() != ChunkIdentifier.ChunkIdentifierToInt32("WAVE"))
            {
                throw new FormatException("Not a WAVE file - no WAVE header");
            }

            if (isRf64)
            {
                ReadDs64Chunk(br);
            }

            long length = stream.Length;

            int dataChunkId   = ChunkIdentifier.ChunkIdentifierToInt32("data");
            int formatChunkId = ChunkIdentifier.ChunkIdentifierToInt32("fmt ");

            // sometimes a file has more data than is specified after the RIFF header
            long stopPosition = Math.Min(riffSize + 8, length);

            // this -8 is so we can be sure that there are at least 8 bytes for a chunk id and length
            while (stream.Position <= stopPosition - 8)
            {
                Int32 chunkIdentifier = br.ReadInt32();
                var   chunkLength     = br.ReadUInt32();
                if (chunkIdentifier == dataChunkId)
                {
                    dataChunkPosition = stream.Position;
                    if (!isRf64) // we already know the dataChunkLength if this is an RF64 file
                    {
                        dataChunkLength = chunkLength;
                    }
                    stream.Position += chunkLength;
                }
                else if (chunkIdentifier == formatChunkId)
                {
                    if (chunkLength > Int32.MaxValue)
                    {
                        throw new InvalidDataException(string.Format("Format chunk length must be between 0 and {0}.", Int32.MaxValue));
                    }
                    return(WaveFormat.FromFormatChunk(br, (int)chunkLength));
                }
                else
                {
                    // check for invalid chunk length
                    if (chunkLength > length - stream.Position)
                    {
                        if (strictMode)
                        {
                            Debug.Assert(false, String.Format("Invalid chunk length {0}, pos: {1}. length: {2}",
                                                              chunkLength, stream.Position, length));
                        }
                        // an exception will be thrown further down if we haven't got a format and data chunk yet,
                        // otherwise we will tolerate this file despite it having corrupt data at the end
                        break;
                    }

                    /*if (storeAllChunks)
                     * {
                     *  if (chunkLength > Int32.MaxValue)
                     *      throw new InvalidDataException(string.Format("RiffChunk chunk length must be between 0 and {0}.", Int32.MaxValue));
                     *  riffChunks.Add(GetRiffChunk(stream, chunkIdentifier, (int)chunkLength));
                     * }*/
                    stream.Position += chunkLength;
                }
            }

            throw new FormatException("Invalid WAV file - No fmt chunk found");
        }
Exemple #9
0
        public void CanConvertChunkIndentiferToInt(string chunkIdentifier)
        {
            var x = WaveInterop.mmioStringToFOURCC(chunkIdentifier, 0);

            Assert.AreEqual(x, ChunkIdentifier.ChunkIdentifierToInt32(chunkIdentifier));
        }
        public void ReadWaveHeader(Stream stream)
        {
            this.dataChunkPosition = -1;
            this.waveFormat        = null;
            this.riffChunks        = new List <RiffChunk>();
            this.dataChunkLength   = 0;

            var br = new BinaryReader(stream);

            ReadRiffHeader(br);
            this.riffSize = br.ReadUInt32(); // read the file size (minus 8 bytes)

            if (br.ReadInt32() != ChunkIdentifier.ChunkIdentifierToInt32("WAVE"))
            {
                throw new FormatException("Not a WAVE file - no WAVE header");
            }

            if (isRf64)
            {
                ReadDs64Chunk(br);
            }

            int dataChunkId   = ChunkIdentifier.ChunkIdentifierToInt32("data");
            int formatChunkId = ChunkIdentifier.ChunkIdentifierToInt32("fmt ");

            // sometimes a file has more data than is specified after the RIFF header
            long stopPosition = Math.Min(riffSize + 8, stream.Length);

            // this -8 is so we can be sure that there are at least 8 bytes for a chunk id and length
            while (stream.Position <= stopPosition - 8)
            {
                Int32 chunkIdentifier = br.ReadInt32();
                var   chunkLength     = br.ReadUInt32();
                if (chunkIdentifier == dataChunkId)
                {
                    dataChunkPosition = stream.Position;
                    if (!isRf64) // we already know the dataChunkLength if this is an RF64 file
                    {
                        dataChunkLength = chunkLength;
                    }
                    stream.Position += chunkLength;
                }
                else if (chunkIdentifier == formatChunkId)
                {
                    if (chunkLength > Int32.MaxValue)
                    {
                        throw new InvalidDataException(string.Format("Format chunk length must be between 0 and {0}.", Int32.MaxValue));
                    }
                    waveFormat = WaveFormat.FromFormatChunk(br, (int)chunkLength);
                }
                else
                {
                    // check for invalid chunk length
                    if (chunkLength > stream.Length - stream.Position)
                    {
                        if (strictMode)
                        {
                            Debug.Assert(false, String.Format("Invalid chunk length {0}, pos: {1}. length: {2}",
                                                              chunkLength, stream.Position, stream.Length));
                        }
                        // an exception will be thrown further down if we haven't got a format and data chunk yet,
                        // otherwise we will tolerate this file despite it having corrupt data at the end
                        break;
                    }
                    if (storeAllChunks)
                    {
                        if (chunkLength > Int32.MaxValue)
                        {
                            throw new InvalidDataException(string.Format("RiffChunk chunk length must be between 0 and {0}.", Int32.MaxValue));
                        }
                        riffChunks.Add(GetRiffChunk(stream, chunkIdentifier, (int)chunkLength));
                    }
                    stream.Position += chunkLength;
                }

                // All Chunks have to be word aligned.
                // https://www.tactilemedia.com/info/MCI_Control_Info.html
                // "If the chunk size is an odd number of bytes, a pad byte with value zero is
                //  written after ckData. Word aligning improves access speed (for chunks resident in memory)
                //  and maintains compatibility with EA IFF. The ckSize value does not include the pad byte."
                if (((chunkLength % 2) != 0) && (br.PeekChar() == 0))
                {
                    stream.Position++;
                }
            }

            if (waveFormat == null)
            {
                throw new FormatException("Invalid WAV file - No fmt chunk found");
            }
            if (dataChunkPosition == -1)
            {
                throw new FormatException("Invalid WAV file - No data chunk found");
            }
        }
        public void ReadWaveHeader(Stream stream)
        {
            this.dataChunkPosition = -1L;
            this.waveFormat        = null;
            this.riffChunks        = new List <RiffChunk>();
            this.dataChunkLength   = 0L;
            BinaryReader binaryReader = new BinaryReader(stream);

            this.ReadRiffHeader(binaryReader);
            this.riffSize = (long)((ulong)binaryReader.ReadUInt32());
            if (binaryReader.ReadInt32() != ChunkIdentifier.ChunkIdentifierToInt32("WAVE"))
            {
                throw new FormatException("Not a WAVE file - no WAVE header");
            }
            if (this.isRf64)
            {
                this.ReadDs64Chunk(binaryReader);
            }
            int  num  = ChunkIdentifier.ChunkIdentifierToInt32("data");
            int  num2 = ChunkIdentifier.ChunkIdentifierToInt32("fmt ");
            long num3 = Math.Min(this.riffSize + 8L, stream.Length);

            while (stream.Position <= num3 - 8L)
            {
                int  num4 = binaryReader.ReadInt32();
                uint num5 = binaryReader.ReadUInt32();
                if (num4 == num)
                {
                    this.dataChunkPosition = stream.Position;
                    if (!this.isRf64)
                    {
                        this.dataChunkLength = (long)((ulong)num5);
                    }
                    stream.Position += (long)((ulong)num5);
                }
                else if (num4 == num2)
                {
                    if (num5 > 2147483647u)
                    {
                        throw new InvalidDataException(string.Format("Format chunk length must be between 0 and {0}.", int.MaxValue));
                    }
                    this.waveFormat = WaveFormat.FromFormatChunk(binaryReader, (int)num5);
                }
                else if ((ulong)num5 > (ulong)(stream.Length - stream.Position))
                {
                    if (this.strictMode)
                    {
                        break;
                    }
                    break;
                }
                else
                {
                    if (this.storeAllChunks)
                    {
                        if (num5 > 2147483647u)
                        {
                            throw new InvalidDataException(string.Format("RiffChunk chunk length must be between 0 and {0}.", int.MaxValue));
                        }
                        this.riffChunks.Add(WaveFileChunkReader.GetRiffChunk(stream, num4, (int)num5));
                    }
                    stream.Position += (long)((ulong)num5);
                }
            }
            if (this.waveFormat == null)
            {
                throw new FormatException("Invalid WAV file - No fmt chunk found");
            }
            if (this.dataChunkPosition == -1L)
            {
                throw new FormatException("Invalid WAV file - No data chunk found");
            }
        }
        public void ReadWaveHeader(Stream stream)
        {
            this.dataChunkPosition = -1;
            this.waveFormat        = null;
            this.riffChunks        = new List <RiffChunk>();
            this.dataChunkLength   = 0;

            var br = new BinaryReader(stream);

            ReadRiffHeader(br);
            this.riffSize = br.ReadUInt32(); // read the file size (minus 8 bytes)

            if (br.ReadInt32() != ChunkIdentifier.ChunkIdentifierToInt32("WAVE"))
            {
                throw new FormatException("Not a WAVE file - no WAVE header");
            }

            if (isRf64)
            {
                ReadDs64Chunk(br);
            }

            HashSet <int> knownChunkIds = new HashSet <int>(ChunkIdentifier.KnownChunkIdentifiers());

            int dataChunkId   = ChunkIdentifier.ChunkIdentifierToInt32("data");
            int formatChunkId = ChunkIdentifier.ChunkIdentifierToInt32("fmt ");

            // sometimes a file has more data than is specified after the RIFF header
            long stopPosition = Math.Min(riffSize + 8, stream.Length);

            // this -8 is so we can be sure that there are at least 8 bytes for a chunk id and length
            while (stream.Position <= stopPosition - 8)
            {
                Int32 chunkIdentifier = br.ReadInt32();

                if (knownChunkIds.Contains(chunkIdentifier) == false)
                {
                    //this chunk id isn't known, perhaps the previous chunk length was incorrect, lets look in nearby offsets
                    chunkIdentifier = LocalSeekForChunkIdentifier(stream, br, knownChunkIds);
                }

                var chunkLength = br.ReadUInt32();
                if (chunkIdentifier == dataChunkId)
                {
                    dataChunkPosition = stream.Position;
                    if (!isRf64) // we already know the dataChunkLength if this is an RF64 file
                    {
                        dataChunkLength = chunkLength;
                    }
                    stream.Position += chunkLength;
                }
                else if (chunkIdentifier == formatChunkId)
                {
                    if (chunkLength > Int32.MaxValue)
                    {
                        throw new InvalidDataException(string.Format("Format chunk length must be between 0 and {0}.", Int32.MaxValue));
                    }
                    waveFormat = WaveFormat.FromFormatChunk(br, (int)chunkLength);
                }
                else
                {
                    // check for invalid chunk length
                    if (chunkLength > stream.Length - stream.Position)
                    {
                        if (strictMode)
                        {
                            Debug.Assert(false, String.Format("Invalid chunk length {0}, pos: {1}. length: {2}",
                                                              chunkLength, stream.Position, stream.Length));
                        }
                        // an exception will be thrown further down if we haven't got a format and data chunk yet,
                        // otherwise we will tolerate this file despite it having corrupt data at the end
                        break;
                    }
                    if (storeAllChunks)
                    {
                        if (chunkLength > Int32.MaxValue)
                        {
                            throw new InvalidDataException(string.Format("RiffChunk chunk length must be between 0 and {0}.", Int32.MaxValue));
                        }
                        riffChunks.Add(GetRiffChunk(stream, chunkIdentifier, (int)chunkLength));
                    }
                    stream.Position += chunkLength;
                }
            }

            if (waveFormat == null)
            {
                throw new FormatException("Invalid WAV file - No fmt chunk found");
            }
            if (dataChunkPosition == -1)
            {
                throw new FormatException("Invalid WAV file - No data chunk found");
            }
        }