コード例 #1
0
ファイル: Mp3FileStream.cs プロジェクト: derrickcreamer/Floe
		public Mp3FileStream(Stream stream)
		{
			_stream = stream;
			var bytes = new byte[10];
			_stream.Read(bytes, 0, 10);
			if (bytes[3] != 0x03 || bytes[4] != 0x00) // v2.3.0
			{
				throw new FileFormatException("Unsupported ID3 version.");
			}
			if (bytes[5] != 0x00)
			{
				throw new FileFormatException(string.Format("Unsupported ID3 flags ({0})", bytes[5]));
			}

			_stream.Seek((bytes[6] << 21) | (bytes[7] << 14) | (bytes[8] << 7) | bytes[9], SeekOrigin.Current);

			int channels, bitRate, sampleRate;
			int size = this.ReadFrameHeader(out channels, out sampleRate, out bitRate);
			_format = new WaveFormatMp3((short)channels, sampleRate, bitRate * 1000);
		}
コード例 #2
0
ファイル: Mp3FileStream.cs プロジェクト: ryanflannery/Floe
        public Mp3FileStream(Stream stream)
        {
            _stream = stream;
            var bytes = new byte[10];

            _stream.Read(bytes, 0, 10);
            if (bytes[3] != 0x03 || bytes[4] != 0x00)             // v2.3.0
            {
                throw new FileFormatException("Unsupported ID3 version.");
            }
            if (bytes[5] != 0x00)
            {
                throw new FileFormatException(string.Format("Unsupported ID3 flags ({0})", bytes[5]));
            }

            _stream.Seek((bytes[6] << 21) | (bytes[7] << 14) | (bytes[8] << 7) | bytes[9], SeekOrigin.Current);

            int channels, bitRate, sampleRate;
            int size = this.ReadFrameHeader(out channels, out sampleRate, out bitRate);

            _format = new WaveFormatMp3((short)channels, sampleRate, bitRate * 1000);
        }
コード例 #3
0
        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));
        }