Example #1
0
        int[] ReadResidual( FlacBitReader bitReader, int predictorOrder, int blockSize )
        {
            int encodingMethod = bitReader.ReadBits( 2 );
            if( !( encodingMethod == 0 || encodingMethod == 1 ) ) {
                throw new InvalidDataException( "Invalid rice encoding method." );
            }
            bool extended = encodingMethod == 1;
            int partitionOrder = bitReader.ReadBits( 4 );
            int partitionsCount = 1 << partitionOrder; // 2^x.
            int partitionSamples = partitionOrder > 0 ? blockSize >> partitionOrder : blockSize - predictorOrder;
            int paramLength = extended ? rice2ParamLength : riceParamLength;
            int escapeParam = extended ? rice2EscapeParam : riceEscapeParam;

            int sample = 0;
            int[] residual = new int[blockSize - predictorOrder];
            for( int partition = 0; partition < partitionsCount; partition++ ) {
                int riceParam = bitReader.ReadBits( paramLength );
                if( riceParam < escapeParam ) {
                    int n = ( partitionOrder == 0 || partition > 0 ) ? partitionSamples : partitionSamples - predictorOrder;
                    for( int i = 0; i < n; i++ ) {
                        residual[sample + i] = bitReader.ReadRice( riceParam );
                    }
                    sample += n;
                } else {
                    int rawParamLength = bitReader.ReadBits( riceEscapeParamLength );
                    int n = ( partitionOrder == 0 || partition > 0 ) ? partitionSamples : partitionSamples - predictorOrder;
                    for( int i = 0; i < n; i++ ) {
                        residual[sample + i] = bitReader.ReadBits( rawParamLength );
                    }
                    sample += n;
                }
            }
            return residual;
        }
Example #2
0
        public IEnumerable<AudioChunk> StreamData( Stream source )
        {
            PrimitiveReader reader = new PrimitiveReader( source );
            reader.BigEndian = true;
            while( true ) {

                #region Frame header

                FlacBitReader bitReader = new FlacBitReader( reader );
                bitReader.BigEndian = true;
                int syncCode = bitReader.ReadBits( 14 );
                if( syncCode != 0x3FFE ) {
                    throw new InvalidDataException( "Invalid synchronisation code." );
                }
                int reserved = bitReader.ReadBit();
                bool variableBlockSize = bitReader.ReadBit() != 0;
                int blockSizeFlags = bitReader.ReadBits( 4 );
                int sampleRateFlags = bitReader.ReadBits( 4 );
                int channelAssignment = bitReader.ReadBits( 4 );
                int sampleSizeFlags = bitReader.ReadBits( 3 );
                if( bitReader.ReadBit() != 0 )
                    throw new InvalidDataException( "Reserved bit is not 0." );

                byte[] numberData = ReadRawUTF8Char( reader );
                /*int frameNumber = numberData[0];
                for( int i = 1; i < numberData.Length; i++ ) {
                    frameNumber <<= 6;
                    frameNumber |= numberData[i];
                }
                Console.WriteLine( frameNumber );*/

                int blockSize = 0;
                if( blockSizeFlags == 0x0 ) {
                    throw new InvalidDataException( "0 is reserved for block sizes." );
                } else if( blockSizeFlags == 0x1 ) {
                    blockSize = 192;
                } else if( blockSizeFlags >= 0x2 && blockSizeFlags <= 0x5 ) {
                    blockSize = 576 * ( 1 << ( blockSizeFlags - 2 ) ); // 2^x.
                } else if( blockSizeFlags == 0x6 ) {
                    blockSize = reader.ReadByte() + 1;
                } else if( blockSizeFlags == 0x7 ) {
                    blockSize = reader.ReadUInt16() + 1;
                } else {
                    blockSize = 256 * ( 1 << ( blockSizeFlags - 8 ) ); // 2^x.
                }

                int sampleRate = 0;
                if( sampleRateFlags == 0x0 ) {
                    sampleRate = metaSampleRate;
                } else if( sampleRateFlags >= 0x01 && sampleRateFlags <= 0xB ) {
                    sampleRate = sampleRates[sampleRateFlags];
                } else if( sampleRateFlags == 0xC ) {
                    sampleRate = reader.ReadByte();
                } else if( sampleRateFlags == 0xD ) {
                    sampleRate = reader.ReadUInt16();
                } else if( sampleRateFlags == 0xE ) {
                    sampleRate = reader.ReadUInt16() * 10;
                } else {
                    throw new InvalidDataException( "Invalid sample rate flag." );
                }

                int bitsPerSample;
                if( sampleSizeFlags == 0 ) {
                    bitsPerSample = metaBitsPerSample;
                } else if( sampleSizeFlags == 0x3 || sampleRateFlags == 0x7 ) {
                    throw new InvalidDataException( "Sample size is reserved." );
                } else {
                    bitsPerSample = bitSampleSizes[sampleSizeFlags];
                }

                int channelsCount;
                ChannelAssignment soundAssignment = (ChannelAssignment)channelAssignment;
                if( channelAssignment < 0x08 ) {
                    channelsCount = channelAssignment + 1;
                } else if( channelAssignment < 0x0B ) {
                    channelsCount = 2;
                } else {
                    throw new InvalidDataException( "Channel assignment values > 1010 are reserved." );
                }
                byte crc8 = reader.ReadByte();

                #endregion

                #region Subframe

                int[][] channelsData = new int[channelsCount][];
                for( int i = 0; i < channelsCount; i++ ) {
                    if( bitReader.ReadBit() != 0 ) {
                        throw new InvalidDataException( "Padding bit should be 0." );
                    }
                    int[] channelData = null;
                    int subframeType = bitReader.ReadBits( 6 );
                    bool wastedBitsPerSampleFlag = bitReader.ReadBit() != 0;

                    int adjustedBitsPerSample = bitsPerSample;
                    switch( soundAssignment ) {
                        case ChannelAssignment.LeftSide:
                            if( i == 1 ) adjustedBitsPerSample++;
                            break;

                        case ChannelAssignment.RightSide:
                            if( i == 0 ) adjustedBitsPerSample++;
                            break;

                        case ChannelAssignment.MidSide:
                            if( i == 1 ) adjustedBitsPerSample++;
                            break;
                    }

                    int wastedBitsPerSample = 0;
                    if( wastedBitsPerSampleFlag ) {
                        wastedBitsPerSample = 1 + bitReader.ReadUnary();
                    }
                    if( subframeType == 0x00 ) {
                        channelData = ProcessConstantSubframe( bitReader, adjustedBitsPerSample, blockSize );
                    } else if( subframeType == 0x01 ) {
                        channelData = ProcessVerbatimSubframe( bitReader, adjustedBitsPerSample, blockSize );
                    } else {
                        if( ( subframeType & 0x20 ) != 0 ) {
                            int order = ( subframeType & 0x1F ) + 1;
                            channelData = ProcessLpcSubframe( bitReader, adjustedBitsPerSample, order, blockSize );
                        } else if( ( subframeType & 0x08 ) != 0 ) {
                            int order = subframeType & 0x07;
                            channelData = ProcessFixedSubframe( bitReader, adjustedBitsPerSample, order, blockSize );
                        }
                    }
                    channelsData[i] = channelData;
                }
                bitReader.SkipRemainingBits();

                #endregion

                // Transform the samples into left right
                switch( soundAssignment ) {
                    case ChannelAssignment.LeftSide:
                        TransformSamplesLS( channelsData[0], channelsData[1] );
                        break;

                    case ChannelAssignment.RightSide:
                        TransformSamplesSR( channelsData[0], channelsData[1] );
                        break;

                    case ChannelAssignment.MidSide:
                        TransformSamplesMS( channelsData[0], channelsData[1] );
                        break;
                }

                int bytesPerSample = (int)Math.Ceiling( bitsPerSample / 8.0 );
                byte[] data = new byte[channelsCount * bytesPerSample * blockSize];
                bool use16Bits = bitsPerSample <= 16;
                bool use8Bits = bitsPerSample <= 8;
                int offset = 0;
                for( int i = 0; i < blockSize; i++ ) {
                    for( int ch = 0; ch < channelsCount; ch++ ) {
                        int[] channelData = channelsData[ch];
                        if( use16Bits ) {
                            ushort sample = (ushort)channelData[i];
                            data[offset++] = (byte)( sample );
                            data[offset++] = (byte)( sample >> 8 );
                        } else if( use8Bits ) {
                            data[offset++] = (byte)channelData[i];
                        }
                    }
                }

                // Read frame footer
                ushort crc16 = reader.ReadUInt16();

                AudioChunk chunk = new AudioChunk();
                chunk.Frequency = sampleRate;
                chunk.Channels = channelsCount;
                chunk.BitsPerSample = bitsPerSample;
                chunk.Data = data;
                yield return chunk;
            }
        }
Example #3
0
 int[] ProcessVerbatimSubframe( FlacBitReader bitReader, int bitsPerSample, int blockSize )
 {
     int[] data = new int[blockSize];
     for( int i = 0; i < data.Length; i++ ) {
         data[i] = bitReader.ReadSignedBits( bitsPerSample );
     }
     return data;
 }
Example #4
0
        int[] ProcessLpcSubframe( FlacBitReader bitReader, int bitsPerSample, int lpcOrder, int blockSize )
        {
            int[] warmUpSamples = new int[lpcOrder];
            for( int i = 0; i < warmUpSamples.Length; i++ ) {
                warmUpSamples[i] = bitReader.ReadSignedBits( bitsPerSample );
            }

            int lpcPrecision = bitReader.ReadBits( 4 ) + 1;
            if( lpcPrecision == 16 ) {// 1111 + 1
                throw new InvalidDataException( "Invalid lpc precision." );
            }

            int lpcShift = bitReader.ReadSignedBits( 5 );
            int[] coefficients = new int[lpcOrder];
            for( int i = 0; i < coefficients.Length; i++ ) {
                coefficients[i] = bitReader.ReadSignedBits( lpcPrecision );
            }

            int[] residual = ReadResidual( bitReader, lpcOrder, blockSize );
            int[] data = new int[lpcOrder + blockSize];
            Buffer.BlockCopy( warmUpSamples, 0, data, 0, lpcOrder * sizeof( int ) );

            if( bitsPerSample + lpcPrecision + ilog2( lpcOrder ) <= 32 ) {
                LpcRestoreSignal( residual, blockSize - lpcOrder, coefficients, lpcOrder, lpcShift, data );
            } else {
                LpcRestoreSignal64( residual, blockSize - lpcOrder, coefficients, lpcOrder, lpcShift, data );
            }
            return data;
        }
Example #5
0
 int[] ProcessFixedSubframe( FlacBitReader bitReader, int bitsPerSample, int predictorOrder, int blockSize )
 {
     int[] warmUpSamples = new int[predictorOrder];
     for( int i = 0; i < predictorOrder; i++ ) {
         warmUpSamples[i] = bitReader.ReadSignedBits( bitsPerSample );
     }
     int[] residual = ReadResidual( bitReader, predictorOrder, blockSize );
     int[] data = new int[blockSize];
     Buffer.BlockCopy( warmUpSamples, 0, data, 0, predictorOrder * sizeof( int ) );
     FixedSignalRestore( residual, blockSize - predictorOrder, predictorOrder, data );
     return data;
 }
Example #6
0
 int[] ProcessConstantSubframe( FlacBitReader bitReader, int bitsPerSample, int blockSize )
 {
     int constantValue = bitReader.ReadSignedBits( bitsPerSample );
     int[] data = new int[blockSize];
     for( int i = 0; i < data.Length; i++ ) {
         data[i] = constantValue;
     }
     return data;
 }
        void ProcessMetadataStreamInfo( int len, PrimitiveReader reader )
        {
            short minBlockSize = reader.ReadInt16();
            short maxBlockSize = reader.ReadInt16();
            int minFrameSize = reader.ReadUInt24();
            int maxFrameSize = reader.ReadUInt24();

            FlacBitReader bitReader = new FlacBitReader( reader );
            bitReader.BigEndian = true;
            int sampleRate = bitReader.ReadBits( 20 );
            Metadata[MetadataKeys.SampleRate] = sampleRate.ToString();
            int channels = bitReader.ReadBits( 3 ) + 1;
            Metadata[MetadataKeys.Channels] = channels.ToString();
            int bitsPerSample = bitReader.ReadBits( 5 ) + 1;
            Metadata[MetadataKeys.BitsPerSample] = bitsPerSample.ToString();
            long totalSamples = bitReader.ReadBits64( 36 );
            Metadata["Total samples"] = totalSamples.ToString();

            channelCount = channels;
            metaSampleRate = sampleRate;
            metaBitsPerSample = bitsPerSample;
            byte[] md5hash = reader.ReadBytes( 16 );
        }