예제 #1
0
        private IEnumerator <ArraySegment <byte> > ReadFlac(FlacReader reader)
        {
            try
            {
                while (reader.Read())
                {
                    if (reader.RecordType == FlacRecordType.MetadataBlock &&
                        reader.MetadataBlockType == FlacMetadataBlockType.Streaminfo)
                    {
                        streaminfo = reader.Streaminfo;
                        ValidateBitPerSample(streaminfo.BitsPerSample);
                        ValidateTotalSamples(streaminfo.TotalSampleCount);
                        InitializeHelpers(reader);

                        byte[] waveHeader = CreateWaveHeader();

                        yield return(new ArraySegment <byte>(waveHeader));
                    }
                    else if (reader.RecordType == FlacRecordType.Frame)
                    {
                        yield return(ReadFrame(reader));
                    }
                }
            }
            finally
            {
                reader.Close();
            }
        }
예제 #2
0
        private IEnumerator <ArraySegment <byte> > ReadFlacSpliter(FlacStreaminfo info, Stream body)
        {
            IFlacReader reader = null;

            try
            {
                streaminfo = info;
                ValidateBitPerSample(streaminfo.BitsPerSample);
                ValidateTotalSamples(streaminfo.TotalSampleCount);
                reader = new FlacSpliteReader(streaminfo, body, true);
                InitializeHelpers(reader);
                while (reader.Read())
                {
                    if (reader.RecordType == FlacRecordType.Frame)
                    {
                        yield return(ReadFrame(reader));
                    }
                }
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
            }
        }
예제 #3
0
        private void ReadStreaminfo(int metadataBlockLength)
        {
            const int Md5Length = FlacCommons.Md5Length;
            const int Md5Offset = FlacCommons.StreaminfoMetadataBlockLengh - Md5Length;

            if (metadataBlockLength < FlacCommons.StreaminfoMetadataBlockLengh)
            {
                throw new FlacException("Invalid STREAMINFO block size");
            }

            byte[] data = ReadExactly(metadataBlockLength);

            FlacStreaminfo streaminfo = new FlacStreaminfo();

            streaminfo.MinBlockSize = data[0] << 8 | data[1];
            streaminfo.MaxBlockSize = data[2] << 8 | data[3];
            streaminfo.MinFrameSize = data[4] << 16 | data[5] << 8 | data[6];
            streaminfo.MaxFrameSize = data[7] << 16 | data[8] << 8 | data[9];

            streaminfo.SampleRate    = (data[10] << 16 | data[11] << 8 | data[12]) >> 4;
            streaminfo.ChannelsCount = ((data[12] >> 1) & 0x07) + 1;

            streaminfo.BitsPerSample = ((data[12] & 0x01) << 4 | (data[13] >> 4)) + 1;

            streaminfo.TotalSampleCount = ((long)(data[13] & 0x0F)) << 32 |
                                          (long)data[14] << 24 | (uint)(data[15] << 16 | data[16] << 8 | data[17]);

            streaminfo.MD5 = new byte[Md5Length];
            Array.Copy(data, Md5Offset, streaminfo.MD5, 0, Md5Length);

            this.streaminfo = streaminfo;
        }
예제 #4
0
        public void EndStream()
        {
            if (bufferSize > 0)
            {
                FlushBuffer();
            }
            buffer = null;

            this.streaminfo = null;
        }
예제 #5
0
        public WaveOverFlacStream(FlacStreaminfo info, Stream Body)
        {
            if (Body == null)
            {
                throw new ArgumentNullException("reader");
            }

            this.dataSource = ReadFlacSpliter(info, Body);
            this.mode       = WaveOverFlacStreamMode.Decode;
        }
예제 #6
0
        public override void Write(byte[] buffer, int offset, int count)
        {
            int[] samples = new int[count * 8 / bitsPerSample];
            if (bitsPerSample == 8)
            {
                for (int i = 0; i < count; i++)
                {
                    samples[i] = buffer[offset + i];
                }
            }
            else
            {
                unsafe {
                    if (offset + count > buffer.Length)
                        throw new IndexOutOfRangeException();
                    fixed(byte *rawdata = buffer)
                    {
                        if (bitsPerSample == 16)
                        {
                            short *data = (short *)(rawdata + offset);
                            for (int i = 0; i < count / 2; i++)
                            {
                                samples[i] = data[i];
                            }
                        }
                        else if (bitsPerSample == 32)
                        {
                            int *data = (int *)(rawdata + offset);
                            for (int i = 0; i < count / 4; i++)
                            {
                                samples[i] = data[i];
                            }
                        }
                    }
                }
            }


            var streaminfo = new FlacBox.FlacStreaminfo();

            streaminfo.ChannelsCount = 1;
            streaminfo.SampleRate    = 44100;
            streaminfo.BitsPerSample = 16;
            streaminfo.MinBlockSize  = 4608;
            streaminfo.MaxBlockSize  = 4608;
            writer.StartStreamNoHeader(streaminfo);
            writer.WriteSamples(samples);
            writer.EndStream();
        }
예제 #7
0
        public void StartStream(FlacStreaminfo streaminfo, FlacEncodingPolicy policy)
        {
            if (policy == null)
            {
                throw new ArgumentNullException("policy");
            }
            policy.Validate();
            if (streaminfo == null)
            {
                throw new ArgumentNullException("baseStream");
            }

            this.streaminfo = streaminfo;

            InitializeEstimation(policy);
            InitializeBuffer();

            WriteFlacHeader();

            metaWriter = new StreaminfoWriter(streaminfo);
        }
예제 #8
0
 public StreaminfoWriter(FlacStreaminfo streaminfo)
 {
     this.streaminfo = streaminfo;
 }
예제 #9
0
        private IEnumerator<ArraySegment<byte>> ReadFlac(FlacReader reader)
        {
            try
            {
                while (reader.Read())
                {
                    if (reader.RecordType == FlacRecordType.MetadataBlock &&
                        reader.MetadataBlockType == FlacMetadataBlockType.Streaminfo)
                    {
                        streaminfo = reader.Streaminfo;
                        ValidateBitPerSample(streaminfo.BitsPerSample);
                        ValidateTotalSamples(streaminfo.TotalSampleCount);
                        InitializeHelpers(reader);

                        byte[] waveHeader = CreateWaveHeader();

                        yield return new ArraySegment<byte>( waveHeader );
                    }
                    else if (reader.RecordType == FlacRecordType.Frame)
                    {
                        yield return ReadFrame(reader);
                    }
                }
            }
            finally
            {
                reader.Close();
            }
        }
예제 #10
0
 public void StartStream(FlacStreaminfo streaminfo)
 {
     StartStream(streaminfo, FlacEncodingPolicy.CreateFromLevel(DefaultEncodingPolicyLevel));
 }
예제 #11
0
 public void StartStream(FlacStreaminfo streaminfo, int level)
 {
     StartStream(streaminfo, FlacEncodingPolicy.CreateFromLevel(level));
 }
예제 #12
0
 private static void EstimateMinAndMaxFrameSize(FlacStreaminfo streaminfo)
 {
     // unknown
     streaminfo.MinFrameSize = 0;
     streaminfo.MaxFrameSize = 0;
 }
예제 #13
0
 public StreaminfoWriter(FlacStreaminfo streaminfo)
 {
     this.streaminfo = streaminfo;
 }
예제 #14
0
        private void ReadStreaminfo(int metadataBlockLength)
        {
            const int Md5Length = FlacCommons.Md5Length;
            const int Md5Offset = FlacCommons.StreaminfoMetadataBlockLengh - Md5Length;

            if (metadataBlockLength < FlacCommons.StreaminfoMetadataBlockLengh)
                throw new FlacException("Invalid STREAMINFO block size");

            byte[] data = ReadExactly(metadataBlockLength);

            FlacStreaminfo streaminfo = new FlacStreaminfo();
            streaminfo.MinBlockSize = data[0] << 8 | data[1];
            streaminfo.MaxBlockSize = data[2] << 8 | data[3];
            streaminfo.MinFrameSize = data[4] << 16 | data[5] << 8 | data[6];
            streaminfo.MaxFrameSize = data[7] << 16 | data[8] << 8 | data[9];

            streaminfo.SampleRate = (data[10] << 16 | data[11] << 8 | data[12]) >> 4;
            streaminfo.ChannelsCount = ((data[12] >> 1) & 0x07) + 1;

            streaminfo.BitsPerSample = ((data[12] & 0x01) << 4 | (data[13] >> 4)) + 1;

            streaminfo.TotalSampleCount = ((long)(data[13] & 0x0F)) << 32 |
                (long)data[14] << 24 | (uint)(data[15] << 16 | data[16] << 8 | data[17]);

            streaminfo.MD5 = new byte[Md5Length];
            Array.Copy(data, Md5Offset, streaminfo.MD5, 0, Md5Length);

            this.streaminfo = streaminfo;
        }
예제 #15
0
        private IEnumerator<WriteRequest> WriteFlac(FlacWriter writer, int compressionLevel)
        {
            try
            {
                const int RiffHeaderLength = 12;
                const int RiffBlockHeaderLength = 8;
                const int MinFormatLength = 16;
                const int MaxFormatLength = 128;

                WriteRequest request = new WriteRequest();

                byte[] waveHeader = new byte[RiffHeaderLength];
                ArraySegment<byte> buffer = new ArraySegment<byte>(waveHeader);
                do
                {
                    yield return request;
                    if (!request.IsDataPresent)
                        throw new FlacException("RIFF header is expected");

                } while (FillBuffer(ref buffer, request));

                if (waveHeader[0] != 'R' || waveHeader[1] != 'I' || waveHeader[2] != 'F' || waveHeader[3] != 'F' ||
                    waveHeader[8] != 'W' || waveHeader[9] != 'A' || waveHeader[10] != 'V' || waveHeader[11] != 'E')
                    throw new FlacException("RIFF and WAVE header are expected");

                long totalStreamLength = BitConverter.ToUInt32(waveHeader, 4);

                do
                {
                    byte[] blockHeader = new byte[RiffBlockHeaderLength];
                    buffer = new ArraySegment<byte>(blockHeader);
                    while (FillBuffer(ref buffer, request))
                    {
                        yield return request;
                        if (!request.IsDataPresent)
                            throw new FlacException("RIFF block expected");
                    }

                    if (blockHeader[0] == 'f' && blockHeader[1] == 'm' && blockHeader[2] == 't' && blockHeader[3] == ' ')
                    {
                        int formatBlockSize = BitConverter.ToInt32(blockHeader, 4);
                        if (formatBlockSize < MinFormatLength || formatBlockSize > MaxFormatLength)
                            throw new FlacException("Invalid format block size");

                        byte[] formatBlock = new byte[formatBlockSize];
                        buffer = new ArraySegment<byte>(formatBlock);

                        while (FillBuffer(ref buffer, request))
                        {
                            yield return request;
                            if (!request.IsDataPresent)
                                throw new FlacException("format block expected");
                        }

                        if(BitConverter.ToUInt16(formatBlock, 0) != 1)
                                throw new FlacException("Unsupported alignment in WAVE");

                        FlacStreaminfo streaminfo = new FlacStreaminfo();
                        streaminfo.ChannelsCount = BitConverter.ToUInt16(formatBlock, 2);
                        streaminfo.SampleRate = BitConverter.ToInt32(formatBlock, 4);
                        streaminfo.BitsPerSample = BitConverter.ToUInt16(formatBlock, 14);
                        streaminfo.MinBlockSize = FlacCommons.DefaultBlockSize;
                        streaminfo.MaxBlockSize = FlacCommons.DefaultBlockSize;

                        EstimateMinAndMaxFrameSize(streaminfo);

                        this.streaminfo = streaminfo;
                    }
                    else if (blockHeader[0] == 'd' && blockHeader[1] == 'a' && blockHeader[2] == 't' && blockHeader[3] == 'a')
                    {
                        uint dataBlockSize = BitConverter.ToUInt32(blockHeader, 4);
                        if (streaminfo == null)
                            throw new FlacException("Format block was not found");

                        int bytesPerInterChannelSample = (streaminfo.ChannelsCount * streaminfo.BitsPerSample) >> 3;

                        long totalSamples = dataBlockSize / bytesPerInterChannelSample;
                        streaminfo.TotalSampleCount = totalSamples;

                        sampleTransform = WaveSampleTransformerFactory.CreateWaveSampleTransformer(streaminfo.BitsPerSample);

                        try
                        {
                            writer.StartStream(streaminfo);

                            int samplesInBuffer = streaminfo.MaxBlockSize;
                            pcmBuffer = new byte[bytesPerInterChannelSample * samplesInBuffer];
                            long currentSample = 0;
                            int[] samples = new int[streaminfo.ChannelsCount * samplesInBuffer];
                            while (currentSample + samplesInBuffer <= totalSamples)
                            {
                                buffer = new ArraySegment<byte>(pcmBuffer);
                                while (FillBuffer(ref buffer, request))
                                {
                                    yield return request;
                                    if (!request.IsDataPresent)
                                        throw new FlacException("data block expected");
                                }
                                sampleTransform.UnpackData(pcmBuffer, samples);
                                writer.WriteSamples(samples);
                                currentSample += samplesInBuffer;
                            }

                            if (currentSample < totalSamples)
                            {
                                int samplesLeft = (int)(totalSamples - currentSample);
                                buffer = new ArraySegment<byte>(pcmBuffer, 0, bytesPerInterChannelSample * samplesLeft);
                                while (FillBuffer(ref buffer, request))
                                {
                                    yield return request;
                                    if (!request.IsDataPresent)
                                        throw new FlacException("data block expected");
                                }
                                samples = new int[streaminfo.ChannelsCount * samplesLeft];
                                sampleTransform.UnpackData(pcmBuffer, samples);
                                writer.WriteSamples(samples);
                            }
                        }
                        finally
                        {
                            writer.EndStream();
                        }
                        break;
                    }
                    else // otherwise skip
                    {
                        uint dataBlockSize = BitConverter.ToUInt32(blockHeader, 4);
                        byte[] extraData = new byte[(int)dataBlockSize];
                        buffer = new ArraySegment<byte>(extraData);
                        while (FillBuffer(ref buffer, request))
                        {
                            yield return request;
                            if (!request.IsDataPresent)
                                throw new FlacException("extra data is expected");
                        }
                    }
                } while (request.IsDataPresent);
            }
            finally
            {
                writer.Close();
            }
        }
예제 #16
0
 public FlacSpliteReader(FlacStreaminfo info, Stream baseStream, bool leaveOpen)
 {
     this.streaminfo = info;
     this.baseStream = baseStream;
     this.leaveOpen  = leaveOpen;
 }
예제 #17
0
        public void EndStream()
        {
            if (bufferSize > 0) FlushBuffer();
            buffer = null;

            this.streaminfo = null;
        }
예제 #18
0
        public void StartStream(FlacStreaminfo streaminfo, FlacEncodingPolicy policy)
        {
            if (policy == null) throw new ArgumentNullException("policy");
            policy.Validate();
            if (streaminfo == null) throw new ArgumentNullException("baseStream");

            this.streaminfo = streaminfo;

            InitializeEstimation(policy);
            InitializeBuffer();

            WriteFlacHeader();

            metaWriter = new StreaminfoWriter(streaminfo);
        }
예제 #19
0
 public void StartStream(FlacStreaminfo streaminfo, int level)
 {
     StartStream(streaminfo, FlacEncodingPolicy.CreateFromLevel(level));
 }
예제 #20
0
 public void StartStream(FlacStreaminfo streaminfo)
 {
     StartStream(streaminfo, FlacEncodingPolicy.CreateFromLevel(DefaultEncodingPolicyLevel));
 }
예제 #21
0
 private static void EstimateMinAndMaxFrameSize(FlacStreaminfo streaminfo)
 {
     // unknown
     streaminfo.MinFrameSize = 0;
     streaminfo.MaxFrameSize = 0;
 }
예제 #22
0
        private IEnumerator <WriteRequest> WriteFlac(FlacWriter writer, int compressionLevel)
        {
            try
            {
                const int RiffHeaderLength      = 12;
                const int RiffBlockHeaderLength = 8;
                const int MinFormatLength       = 16;
                const int MaxFormatLength       = 128;


                WriteRequest request = new WriteRequest();

                byte[] waveHeader          = new byte[RiffHeaderLength];
                ArraySegment <byte> buffer = new ArraySegment <byte>(waveHeader);
                do
                {
                    yield return(request);

                    if (!request.IsDataPresent)
                    {
                        throw new FlacException("RIFF header is expected");
                    }
                } while (FillBuffer(ref buffer, request));

                if (waveHeader[0] != 'R' || waveHeader[1] != 'I' || waveHeader[2] != 'F' || waveHeader[3] != 'F' ||
                    waveHeader[8] != 'W' || waveHeader[9] != 'A' || waveHeader[10] != 'V' || waveHeader[11] != 'E')
                {
                    throw new FlacException("RIFF and WAVE header are expected");
                }

                long totalStreamLength = BitConverter.ToUInt32(waveHeader, 4);

                do
                {
                    byte[] blockHeader = new byte[RiffBlockHeaderLength];
                    buffer = new ArraySegment <byte>(blockHeader);
                    while (FillBuffer(ref buffer, request))
                    {
                        yield return(request);

                        if (!request.IsDataPresent)
                        {
                            throw new FlacException("RIFF block expected");
                        }
                    }

                    if (blockHeader[0] == 'f' && blockHeader[1] == 'm' && blockHeader[2] == 't' && blockHeader[3] == ' ')
                    {
                        int formatBlockSize = BitConverter.ToInt32(blockHeader, 4);
                        if (formatBlockSize < MinFormatLength || formatBlockSize > MaxFormatLength)
                        {
                            throw new FlacException("Invalid format block size");
                        }

                        byte[] formatBlock = new byte[formatBlockSize];
                        buffer = new ArraySegment <byte>(formatBlock);

                        while (FillBuffer(ref buffer, request))
                        {
                            yield return(request);

                            if (!request.IsDataPresent)
                            {
                                throw new FlacException("format block expected");
                            }
                        }

                        if (BitConverter.ToUInt16(formatBlock, 0) != 1)
                        {
                            throw new FlacException("Unsupported alignment in WAVE");
                        }

                        FlacStreaminfo streaminfo = new FlacStreaminfo();
                        streaminfo.ChannelsCount = BitConverter.ToUInt16(formatBlock, 2);
                        streaminfo.SampleRate    = BitConverter.ToInt32(formatBlock, 4);
                        streaminfo.BitsPerSample = BitConverter.ToUInt16(formatBlock, 14);
                        streaminfo.MinBlockSize  = FlacCommons.DefaultBlockSize;
                        streaminfo.MaxBlockSize  = FlacCommons.DefaultBlockSize;

                        EstimateMinAndMaxFrameSize(streaminfo);

                        this.streaminfo = streaminfo;
                    }
                    else if (blockHeader[0] == 'd' && blockHeader[1] == 'a' && blockHeader[2] == 't' && blockHeader[3] == 'a')
                    {
                        uint dataBlockSize = BitConverter.ToUInt32(blockHeader, 4);
                        if (streaminfo == null)
                        {
                            throw new FlacException("Format block was not found");
                        }

                        int bytesPerInterChannelSample = (streaminfo.ChannelsCount * streaminfo.BitsPerSample) >> 3;

                        long totalSamples = dataBlockSize / bytesPerInterChannelSample;
                        streaminfo.TotalSampleCount = totalSamples;

                        sampleTransform = WaveSampleTransformerFactory.CreateWaveSampleTransformer(streaminfo.BitsPerSample);

                        try
                        {
                            writer.StartStream(streaminfo);

                            int samplesInBuffer = streaminfo.MaxBlockSize;
                            pcmBuffer = new byte[bytesPerInterChannelSample * samplesInBuffer];
                            long  currentSample = 0;
                            int[] samples       = new int[streaminfo.ChannelsCount * samplesInBuffer];
                            while (currentSample + samplesInBuffer <= totalSamples)
                            {
                                buffer = new ArraySegment <byte>(pcmBuffer);
                                while (FillBuffer(ref buffer, request))
                                {
                                    yield return(request);

                                    if (!request.IsDataPresent)
                                    {
                                        throw new FlacException("data block expected");
                                    }
                                }
                                sampleTransform.UnpackData(pcmBuffer, samples);
                                writer.WriteSamples(samples);
                                currentSample += samplesInBuffer;
                            }

                            if (currentSample < totalSamples)
                            {
                                int samplesLeft = (int)(totalSamples - currentSample);
                                buffer = new ArraySegment <byte>(pcmBuffer, 0, bytesPerInterChannelSample * samplesLeft);
                                while (FillBuffer(ref buffer, request))
                                {
                                    yield return(request);

                                    if (!request.IsDataPresent)
                                    {
                                        throw new FlacException("data block expected");
                                    }
                                }
                                samples = new int[streaminfo.ChannelsCount * samplesLeft];
                                sampleTransform.UnpackData(pcmBuffer, samples);
                                writer.WriteSamples(samples);
                            }
                        }
                        finally
                        {
                            writer.EndStream();
                        }
                        break;
                    }
                    else // otherwise skip
                    {
                        uint   dataBlockSize = BitConverter.ToUInt32(blockHeader, 4);
                        byte[] extraData     = new byte[(int)dataBlockSize];
                        buffer = new ArraySegment <byte>(extraData);
                        while (FillBuffer(ref buffer, request))
                        {
                            yield return(request);

                            if (!request.IsDataPresent)
                            {
                                throw new FlacException("extra data is expected");
                            }
                        }
                    }
                } while (request.IsDataPresent);
            }
            finally
            {
                writer.Close();
            }
        }