示例#1
0
        public WaveOverFlacStream(FlacWriter writer, int compressionLevel)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }
            ValidateCompressionLevel(compressionLevel);

            this.dataConsumer = WriteFlac(writer, compressionLevel);
            this.dataConsumer.MoveNext();
            this.mode = WaveOverFlacStreamMode.Encode;
        }
示例#2
0
 public WaveOverFlacStream(FlacWriter writer)
     : this(writer, FlacWriter.DefaultEncodingPolicyLevel)
 {
 }
示例#3
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();
            }
        }
示例#4
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();
            }
        }
示例#5
0
        public WaveOverFlacStream(FlacWriter writer, int compressionLevel)
        {
            if (writer == null) throw new ArgumentNullException("writer");
            ValidateCompressionLevel(compressionLevel);

            this.dataConsumer = WriteFlac(writer, compressionLevel);
            this.dataConsumer.MoveNext();
            this.mode = WaveOverFlacStreamMode.Encode;
        }
示例#6
0
 public WaveOverFlacStream(FlacWriter writer)
     : this(writer, FlacWriter.DefaultEncodingPolicyLevel)
 {
 }