internal override FlacMethodAndDataPair[] FindBestMethods(int[][] samples, int bitsPerSamples)
 {
     FlacMethodAndDataPair[] samplesAndMethods = new FlacMethodAndDataPair[samples.Length];
     parallel.For(0, samples.Length, i =>
     {
         samplesAndMethods[i] = new FlacMethodAndDataPair(
             FindBestMethod(samples[i], bitsPerSamples),
             bitsPerSamples,
             samples[i]);
     });
     return(samplesAndMethods);
 }
Example #2
0
        private void WriteSubframe(FlacBitStreamWriter bitWriter, FlacMethodAndDataPair flacMethodAndDataPair)
        {
            bitWriter.WriteUnsigned(0, 1);

            int subframeType = flacMethodAndDataPair.Method.SubframeTypeCode;

            bitWriter.WriteUnsigned((uint)subframeType, 6);

            bitWriter.WriteUnsigned(0, 1);

            flacMethodAndDataPair.WriteData(bitWriter);
        }
Example #3
0
 internal override FlacMethodAndDataPair[] FindBestMethods(int[][] samples, int bitsPerSamples)
 {
     FlacMethodAndDataPair[] samplesAndMethods = new FlacMethodAndDataPair[samples.Length];
     parallel.For(0, samples.Length, i =>
     {
         samplesAndMethods[i] = new FlacMethodAndDataPair(
             FindBestMethod(samples[i], bitsPerSamples),
             bitsPerSamples,
             samples[i]);
     });
     return samplesAndMethods;
 }
Example #4
0
        private void WriteSubframe(FlacBitStreamWriter bitWriter, FlacMethodAndDataPair flacMethodAndDataPair)
        {
            bitWriter.WriteUnsigned(0, 1);

            int subframeType = flacMethodAndDataPair.Method.SubframeTypeCode;
            bitWriter.WriteUnsigned((uint)subframeType, 6);

            bitWriter.WriteUnsigned(0, 1);

            flacMethodAndDataPair.WriteData(bitWriter);
        }
Example #5
0
        public void WriteFrame(FlacMethodAndDataPair[] methods, SoundChannelAssignmentType channelAssignment)
        {
            EnsureFramesMode();

            sink.StartFrame(streamPosition, currentSample);

            if (methods == null) throw new ArgumentNullException("methods");
            if(methods.Length != Streaminfo.ChannelsCount)
                throw new ArgumentNullException("Methods items does not correspond to amount of channels");

            int samplesCount = methods[0].Data.Length;

            const byte Blocking = 0x00; // fixed

            MemoryStream frameHeader = new MemoryStream();
            // sync code + reserved = 0 + blocking
            frameHeader.WriteByte(0xFF); frameHeader.WriteByte(0xF8 | Blocking);

            int interChannelSamplesTypeIndex = Array.IndexOf(FlacCommons.StaticBlockSizeSamples, samplesCount);
            int interChannelSamplesType;
            if (interChannelSamplesTypeIndex > 0)
                interChannelSamplesType = interChannelSamplesTypeIndex;
            else if (samplesCount > 256)
                interChannelSamplesType = FlacCommons.Bit16BlockSizeSamplesType;
            else
                interChannelSamplesType = FlacCommons.Bit8BlockSizeSamplesType;

            int sampleRateTypeIndex = Array.IndexOf(FlacCommons.StaticSampleRates, Streaminfo.SampleRate);
            int sampleRateType = sampleRateTypeIndex > 0
                ? sampleRateTypeIndex : FlacCommons.StreaminfoSampleRateType;
            frameHeader.WriteByte((byte)(interChannelSamplesType << 4 | sampleRateType));

            int channelAssignmetType = (int)channelAssignment;

            int sampleSizeInBitsTypeIndex = Array.IndexOf(FlacCommons.StaticSampleSizeInBits, Streaminfo.BitsPerSample);
            int sampleSizeInBitsType = sampleSizeInBitsTypeIndex > 0
                ? sampleSizeInBitsTypeIndex : FlacCommons.StreaminfoSizeInBitsType;
            frameHeader.WriteByte((byte)(channelAssignmetType << 4 | sampleSizeInBitsType << 1));

            WriteUtf8Number(frameHeader, frameNumber);
            switch (interChannelSamplesType)
            {
                case FlacCommons.Bit8BlockSizeSamplesType:
                    frameHeader.WriteByte((byte)(samplesCount - 1)); break;
                case FlacCommons.Bit16BlockSizeSamplesType:
                    frameHeader.WriteByte((byte)((samplesCount - 1) >> 8));
                    frameHeader.WriteByte((byte)(samplesCount - 1));
                    break;
            }
            frameHeader.Close();

            byte[] frameHeaderData = frameHeader.ToArray();

            byte crc8 = CrcUtils.Crc8(0, frameHeaderData);

            BaseStream.Write(frameHeaderData, 0, frameHeaderData.Length);
            BaseStream.WriteByte(crc8);

            ++frameNumber;

            ushort crc16Seed = CrcUtils.Crc16(CrcUtils.Crc16(0, frameHeaderData), crc8);

            // write channels
            FlacBitStreamWriter bitWriter = new FlacBitStreamWriter(BaseStream, crc16Seed);

            for (int i = 0; i < methods.Length; i++)
            {
                WriteSubframe(bitWriter, methods[i]);
            }

            int subframesLength;
            ushort crc16;
            bitWriter.Complete(out crc16, out subframesLength);

            // write footer
            BaseStream.WriteByte((byte)(crc16 >> 8)); BaseStream.WriteByte((byte)crc16);

            int frameSize = frameHeaderData.Length + 1 + subframesLength + 2;
            streamPosition += frameSize;
            currentSample += samplesCount;

            sink.EndFrame(streamPosition, currentSample);
        }
Example #6
0
        public SoundChannelAssignmentType FindBestMethod(int[] leftSamples, int[] rightSamples, out FlacMethodAndDataPair[] methods)
        {
            if (leftSamples == null) throw new ArgumentNullException("leftSamples");
            if (rightSamples == null) throw new ArgumentNullException("rightSamples");
            if (leftSamples.Length != rightSamples.Length)
                throw new ArgumentException("leftSamples and rightSamples has to have same amount of samples");
            if(leftSamples.Length == 0)
                throw new ArgumentException("channels has to have at least one item");

            return estimator.FindBestMethods(leftSamples, rightSamples, Streaminfo.BitsPerSample,
                out methods);
        }
        internal override SoundChannelAssignmentType FindBestMethods(int[] leftSamples, int[] rightSamples, int bitsPerSample, out FlacMethodAndDataPair[] methods)
        {
            if (policy.StereoEncoding == StereoEncodingPolicy.AsIs)
            {
                methods = FindBestMethods(new int[2][] { leftSamples, rightSamples }, bitsPerSample);
                return(SoundChannelAssignmentType.LeftRight);
            }

            int samplesPerChannel = leftSamples.Length;

            int[] differenceLeftMinusRight = null, average = null;

            FlacMethod methodForLeft = null, methodForRight = null, methodForSide = null, methodForAverage = null;

            parallel.Invoke(
                delegate
            {
                methodForLeft = FindBestMethod(leftSamples, bitsPerSample);
            },
                delegate
            {
                methodForRight = FindBestMethod(rightSamples, bitsPerSample);
            },
                delegate
            {
                differenceLeftMinusRight = new int[samplesPerChannel];
                for (int i = 0; i < samplesPerChannel; i++)
                {
                    differenceLeftMinusRight[i] = leftSamples[i] - rightSamples[i];
                }
                methodForSide = FindBestMethod(differenceLeftMinusRight, bitsPerSample + 1);
            },
                delegate
            {
                if (policy.StereoEncoding == StereoEncodingPolicy.TrySidesAndAverage)
                {
                    average = new int[samplesPerChannel];
                    for (int i = 0; i < samplesPerChannel; i++)
                    {
                        average[i] = (leftSamples[i] + rightSamples[i]) >> 1;
                    }
                    methodForAverage = FindBestMethod(average, bitsPerSample);
                }
            }
                );

            int independentEstimation = methodForLeft.EstimatedSize + methodForRight.EstimatedSize;
            int leftSideEstimation    = methodForLeft.EstimatedSize + methodForSide.EstimatedSize;
            int rightSideEstimation   = methodForSide.EstimatedSize + methodForRight.EstimatedSize;
            int averageEstimation     = average == null ? int.MaxValue :
                                        methodForAverage.EstimatedSize + methodForSide.EstimatedSize;

            SoundChannelAssignmentType type;

            if (Math.Min(independentEstimation, leftSideEstimation) < Math.Min(rightSideEstimation, averageEstimation))
            {
                if (independentEstimation <= leftSideEstimation)
                {
                    type    = SoundChannelAssignmentType.LeftRight;
                    methods = new FlacMethodAndDataPair[] {
                        new FlacMethodAndDataPair(methodForLeft, bitsPerSample, leftSamples),
                        new FlacMethodAndDataPair(methodForRight, bitsPerSample, rightSamples)
                    };
                }
                else
                {
                    type    = SoundChannelAssignmentType.LeftSide;
                    methods = new FlacMethodAndDataPair[] {
                        new FlacMethodAndDataPair(methodForLeft, bitsPerSample, leftSamples),
                        new FlacMethodAndDataPair(methodForSide, bitsPerSample + 1, differenceLeftMinusRight)
                    };
                }
            }
            else
            {
                if (rightSideEstimation <= averageEstimation)
                {
                    type    = SoundChannelAssignmentType.RightSide;
                    methods = new FlacMethodAndDataPair[] {
                        new FlacMethodAndDataPair(methodForSide, bitsPerSample + 1, differenceLeftMinusRight),
                        new FlacMethodAndDataPair(methodForRight, bitsPerSample, rightSamples)
                    };
                }
                else
                {
                    type    = SoundChannelAssignmentType.MidSide;
                    methods = new FlacMethodAndDataPair[] {
                        new FlacMethodAndDataPair(methodForAverage, bitsPerSample, average),
                        new FlacMethodAndDataPair(methodForSide, bitsPerSample + 1, differenceLeftMinusRight)
                    };
                }
            }
            return(type);
        }
Example #8
0
        internal override SoundChannelAssignmentType FindBestMethods(int[] leftSamples, int[] rightSamples, int bitsPerSample, out FlacMethodAndDataPair[] methods)
        {
            if (policy.StereoEncoding == StereoEncodingPolicy.AsIs)
            {
                methods = FindBestMethods(new int[2][] { leftSamples, rightSamples }, bitsPerSample);
                return SoundChannelAssignmentType.LeftRight;
            }

            int samplesPerChannel = leftSamples.Length;
            int[] differenceLeftMinusRight = null, average = null;

            FlacMethod methodForLeft = null, methodForRight = null, methodForSide = null, methodForAverage = null;

            parallel.Invoke(
                delegate
                {
                    methodForLeft = FindBestMethod(leftSamples, bitsPerSample);
                },
                delegate
                {
                    methodForRight = FindBestMethod(rightSamples, bitsPerSample);
                },
                delegate
                {
                    differenceLeftMinusRight = new int[samplesPerChannel];
                    for (int i = 0; i < samplesPerChannel; i++)
                    {
                        differenceLeftMinusRight[i] = leftSamples[i] - rightSamples[i];
                    }
                    methodForSide = FindBestMethod(differenceLeftMinusRight, bitsPerSample + 1);
                },
                delegate
                {
                    if (policy.StereoEncoding == StereoEncodingPolicy.TrySidesAndAverage)
                    {
                        average = new int[samplesPerChannel];
                        for (int i = 0; i < samplesPerChannel; i++)
                        {
                            average[i] = (leftSamples[i] + rightSamples[i]) >> 1;
                        }
                        methodForAverage = FindBestMethod(average, bitsPerSample);
                    }
                }
            );

            int independentEstimation = methodForLeft.EstimatedSize + methodForRight.EstimatedSize;
            int leftSideEstimation = methodForLeft.EstimatedSize + methodForSide.EstimatedSize;
            int rightSideEstimation = methodForSide.EstimatedSize + methodForRight.EstimatedSize;
            int averageEstimation = average == null ? int.MaxValue :
                methodForAverage.EstimatedSize + methodForSide.EstimatedSize;

            SoundChannelAssignmentType type;
            if (Math.Min(independentEstimation, leftSideEstimation) < Math.Min(rightSideEstimation, averageEstimation))
            {
                if (independentEstimation <= leftSideEstimation)
                {
                    type = SoundChannelAssignmentType.LeftRight;
                    methods = new FlacMethodAndDataPair[] {
                        new FlacMethodAndDataPair(methodForLeft, bitsPerSample, leftSamples),
                        new FlacMethodAndDataPair(methodForRight, bitsPerSample, rightSamples)
                    };
                }
                else
                {
                    type = SoundChannelAssignmentType.LeftSide;
                    methods = new FlacMethodAndDataPair[] {
                        new FlacMethodAndDataPair(methodForLeft, bitsPerSample, leftSamples),
                        new FlacMethodAndDataPair(methodForSide, bitsPerSample + 1, differenceLeftMinusRight)
                    };
                }
            }
            else
            {
                if (rightSideEstimation <= averageEstimation)
                {
                    type = SoundChannelAssignmentType.RightSide;
                    methods = new FlacMethodAndDataPair[] {
                        new FlacMethodAndDataPair(methodForSide, bitsPerSample + 1, differenceLeftMinusRight),
                        new FlacMethodAndDataPair(methodForRight, bitsPerSample, rightSamples)
                    };
                }
                else
                {
                    type = SoundChannelAssignmentType.MidSide;
                    methods = new FlacMethodAndDataPair[] {
                        new FlacMethodAndDataPair(methodForAverage, bitsPerSample, average),
                        new FlacMethodAndDataPair(methodForSide, bitsPerSample + 1, differenceLeftMinusRight)
                    };
                }
            }
            return type;
        }
Example #9
0
 internal abstract SoundChannelAssignmentType FindBestMethods(int[] leftSamples, int[] rightSamples, int bitsPerSample, out FlacMethodAndDataPair[] methods);