Esempio n. 1
0
 private uint ReadUInt32()
 {
     byte[] x = new byte[4];
     _fs.Read(x, 0, 4);
     _fileOffset += 4;
     return(BitConverterBE.ToUInt32(x, 0));
 }
        public void WriteChunk(byte[] chunk, uint timeStamp)
        {
            if (chunk.Length < 1)
            {
                return;
            }

            if (chunk[0] == 0)
            { // Header
                if (chunk.Length < 3)
                {
                    return;
                }

                ulong bits = (ulong)BitConverterBE.ToUInt16(chunk, 1) << 48;

                _aacProfile      = BitHelper.Read(ref bits, 5) - 1;
                _sampleRateIndex = BitHelper.Read(ref bits, 4);
                _channelConfig   = BitHelper.Read(ref bits, 4);

                if ((_aacProfile < 0) || (_aacProfile > 3))
                {
                    throw new Exception("Unsupported AAC profile.");
                }
                if (_sampleRateIndex > 12)
                {
                    throw new Exception("Invalid AAC sample rate index.");
                }
                if (_channelConfig > 6)
                {
                    throw new Exception("Invalid AAC channel configuration.");
                }
            }
            else
            { // Audio data
                int   dataSize = chunk.Length - 1;
                ulong bits     = 0;

                // Reference: WriteADTSHeader from FAAC's bitstream.c

                BitHelper.Write(ref bits, 12, 0xFFF);
                BitHelper.Write(ref bits, 1, 0);
                BitHelper.Write(ref bits, 2, 0);
                BitHelper.Write(ref bits, 1, 1);
                BitHelper.Write(ref bits, 2, _aacProfile);
                BitHelper.Write(ref bits, 4, _sampleRateIndex);
                BitHelper.Write(ref bits, 1, 0);
                BitHelper.Write(ref bits, 3, _channelConfig);
                BitHelper.Write(ref bits, 1, 0);
                BitHelper.Write(ref bits, 1, 0);
                BitHelper.Write(ref bits, 1, 0);
                BitHelper.Write(ref bits, 1, 0);
                BitHelper.Write(ref bits, 13, 7 + dataSize);
                BitHelper.Write(ref bits, 11, 0x7FF);
                BitHelper.Write(ref bits, 2, 0);

                _fs.Write(BitConverterBE.GetBytes(bits), 1, 7);
                _fs.Write(chunk, 1, dataSize);
            }
        }
 private void WriteVBRHeader(bool isPlaceholder)
 {
     byte[] buff = new byte[GetFrameLength(_mpegVersion, 64000, _sampleRate, 0)];
     if (!isPlaceholder)
     {
         uint header     = _firstFrameHeader;
         int  dataOffset = GetFrameDataOffset(_mpegVersion, _channelMode);
         header &= 0xFFFE0DFF;                                                                        // Clear CRC, bitrate, and padding fields
         header |= (uint)((_mpegVersion == 3) ? 5 : 8) << 12;                                         // 64 kbit/sec
         General.CopyBytes(buff, 0, BitConverterBE.GetBytes(header));
         General.CopyBytes(buff, dataOffset, BitConverterBE.GetBytes((uint)0x58696E67));              // "Xing"
         General.CopyBytes(buff, dataOffset + 4, BitConverterBE.GetBytes((uint)0x7));                 // Flags
         General.CopyBytes(buff, dataOffset + 8, BitConverterBE.GetBytes((uint)_frameOffsets.Count)); // Frame count
         General.CopyBytes(buff, dataOffset + 12, BitConverterBE.GetBytes((uint)_totalFrameLength));  // File length
         for (int i = 0; i < 100; i++)
         {
             int frameIndex = (int)((i / 100.0) * _frameOffsets.Count);
             buff[dataOffset + 16 + i] = (byte)((_frameOffsets[frameIndex] / (double)_totalFrameLength) * 256.0);
         }
     }
     _fs.Write(buff, 0, buff.Length);
 }
        private void ParseMP3Frames(byte[] buff)
        {
            int[] MPEG1BitRate     = new int[] { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 };
            int[] MPEG2XBitRate    = new int[] { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 };
            int[] MPEG1SampleRate  = new int[] { 44100, 48000, 32000, 0 };
            int[] MPEG20SampleRate = new int[] { 22050, 24000, 16000, 0 };
            int[] MPEG25SampleRate = new int[] { 11025, 12000, 8000, 0 };

            int offset = 0;
            int length = buff.Length;

            while (length >= 4)
            {
                ulong header;
                int   mpegVersion, layer, bitRate, sampleRate, padding, channelMode;
                int   frameLen;

                header = (ulong)BitConverterBE.ToUInt32(buff, offset) << 32;
                if (BitHelper.Read(ref header, 11) != 0x7FF)
                {
                    break;
                }
                mpegVersion = BitHelper.Read(ref header, 2);
                layer       = BitHelper.Read(ref header, 2);
                BitHelper.Read(ref header, 1);
                bitRate    = BitHelper.Read(ref header, 4);
                sampleRate = BitHelper.Read(ref header, 2);
                padding    = BitHelper.Read(ref header, 1);
                BitHelper.Read(ref header, 1);
                channelMode = BitHelper.Read(ref header, 2);

                if ((mpegVersion == 1) || (layer != 1) || (bitRate == 0) || (bitRate == 15) || (sampleRate == 3))
                {
                    break;
                }

                bitRate = ((mpegVersion == 3) ? MPEG1BitRate[bitRate] : MPEG2XBitRate[bitRate]) * 1000;

                if (mpegVersion == 3)
                {
                    sampleRate = MPEG1SampleRate[sampleRate];
                }
                else if (mpegVersion == 2)
                {
                    sampleRate = MPEG20SampleRate[sampleRate];
                }
                else
                {
                    sampleRate = MPEG25SampleRate[sampleRate];
                }

                frameLen = GetFrameLength(mpegVersion, bitRate, sampleRate, padding);
                if (frameLen > length)
                {
                    break;
                }

                bool isVBRHeaderFrame = false;
                if (_frameOffsets.Count == 0)
                {
                    // Check for an existing VBR header just to be safe (I haven't seen any in FLVs)
                    int o = offset + GetFrameDataOffset(mpegVersion, channelMode);
                    if (BitConverterBE.ToUInt32(buff, o) == 0x58696E67)
                    { // "Xing"
                        isVBRHeaderFrame = true;
                        _delayWrite      = false;
                        _hasVBRHeader    = true;
                    }
                }

                if (isVBRHeaderFrame)
                {
                }
                else if (_firstBitRate == 0)
                {
                    _firstBitRate     = bitRate;
                    _mpegVersion      = mpegVersion;
                    _sampleRate       = sampleRate;
                    _channelMode      = channelMode;
                    _firstFrameHeader = BitConverterBE.ToUInt32(buff, offset);
                }
                else if (!_isVBR && (bitRate != _firstBitRate))
                {
                    _isVBR = true;
                    if (_hasVBRHeader)
                    {
                    }
                    else if (_delayWrite)
                    {
                        WriteVBRHeader(true);
                        _writeVBRHeader = true;
                        _delayWrite     = false;
                    }
                    else
                    {
                        _warnings.Add("Detected VBR too late, cannot add VBR header.");
                    }
                }

                _frameOffsets.Add(_totalFrameLength + (uint)offset);

                offset += frameLen;
                length -= frameLen;
            }

            _totalFrameLength += (uint)buff.Length;
        }