private FlacMethod FindBestLpcMethod(int[] channelSamples, int bitsPerSample, FlacEncodingPolicy policy)
        {
            if (!policy.LpcOrder.HasValue)
            {
                return(null);
            }

            int minLpcOrder = policy.LpcOrder.Value.MinValue;
            int maxLpcOrder = Math.Min(policy.LpcOrder.Value.MaxValue,
                                       channelSamples.Length - 1);

            double[] r = new double[maxLpcOrder + 1];
            parallel.For(0, r.Length, i =>
            {
                double sum = 0;
                for (int j = 0, q = channelSamples.Length - i; j < i; j++, q++)
                {
                    sum += (double)channelSamples[j] * channelSamples[q];
                }
                for (int j = i, q = 0; j < channelSamples.Length; j++, q++)
                {
                    sum += (double)channelSamples[j] * channelSamples[q];
                }
                r[i] = sum;
            });

            FlacMethod[] methods = new FlacMethod[maxLpcOrder];
            parallel.For(minLpcOrder, maxLpcOrder + 1, order =>
            {
                double[] coef = SolveLpc(r, order);

                int[] integerCoefficients;
                int shift;
                int precision;
                ConvertLpcCoeficientsToIntegers(coef, out integerCoefficients, out precision, out shift);

                IPredictor predictor = PredictorFactory.CreateLpcPredictor(integerCoefficients, shift, ArrayUtils.CutArray(channelSamples, 0, order - 1));
                FlacResidualCoefficeints residual         = FindBestResidual(channelSamples, order, predictor, policy);
                FlacLpcMethodCoefficeints lpcCoefficients = new FlacLpcMethodCoefficeints(
                    precision, integerCoefficients, shift);

                FlacMethod method  = new FlacLpcMethod(bitsPerSample, lpcCoefficients, residual);
                methods[order - 1] = method;
            });

            return(FindBestMethod(methods));
        }
        internal override FlacMethod FindBestMethod(int[] channelSamples, int bitsPerSample)
        {
            int i           = 1;
            int firstSample = channelSamples[0];

            while (i < channelSamples.Length && channelSamples[i] == firstSample)
            {
                i++;
            }

            if (i == channelSamples.Length)
            {
                // constant method will be better than other methods
                return(new FlacConstantMethod(bitsPerSample));
            }

            FlacMethod verbatimMethod;

            verbatimMethod = new FlacVerbatimMethod(
                channelSamples.Length, bitsPerSample);

            FlacMethod fixedMethod = null, lpcMethod = null;

            parallel.Invoke(
                delegate
            {
                fixedMethod = FindBestFixedMethod(channelSamples, bitsPerSample, policy);
            },
                delegate
            {
                lpcMethod = FindBestLpcMethod(channelSamples, bitsPerSample, policy);
            }
                );

            return(FindBestMethod(new FlacMethod[] {
                verbatimMethod, fixedMethod, lpcMethod
            }));
        }
        private FlacMethod FindBestFixedMethod(int[] channelSamples, int bitsPerSample, FlacEncodingPolicy policy)
        {
            if (!policy.FixedOrder.HasValue)
            {
                return(null);
            }

            int minFixedOrder = policy.FixedOrder.Value.MinValue;
            int maxFixedOrder = Math.Min(channelSamples.Length - 1,
                                         policy.FixedOrder.Value.MaxValue);

            FlacMethod[] methods = new FlacMethod[maxFixedOrder + 1];
            parallel.For(minFixedOrder, maxFixedOrder + 1, order =>
            {
                IPredictor predictor = PredictorFactory.CreateFixedPredictor(order, ArrayUtils.CutArray(channelSamples, 0, order - 1));
                FlacResidualCoefficeints residual = FindBestResidual(channelSamples, order, predictor, policy);

                FlacMethod method = new FlacFixedMethod(bitsPerSample, order, residual);
                methods[order]    = method;
            });

            return(FindBestMethod(methods));
        }
 public FlacMethodAndDataPair(FlacMethod method, int bitsPerSample, int[] data)
 {
     this.Method = method;
     this.Data = data;
     this.BitsPerSample = bitsPerSample;
 }
示例#5
0
        public void WriteFrame(int[][] samples, SoundChannelAssignmentType channelAssigment)
        {
            if (samples == null)
            {
                throw new ArgumentNullException("samples");
            }
            int channelsCount = Streaminfo.ChannelsCount;

            if (samples.Length != channelsCount)
            {
                throw new ArgumentException("Expected same amount of channels as in Streaminfo");
            }
            int samplesPerChannel = samples[0].Length;

            if ( // samplesPerChannel < Streaminfo.MinBlockSize ||
                Streaminfo.MaxBlockSize < samplesPerChannel)
            {
                throw new ArgumentException("Amount of samples more or less than specified in Streaminfo");
            }

            for (int i = 1; i < channelsCount; i++)
            {
                if (samplesPerChannel != samples[i].Length)
                {
                    throw new ArgumentException("Expected same amount of samples on all the channels");
                }
            }

            FlacMethod[] methods;

            if (channelsCount == 2 && channelAssigment == SoundChannelAssignmentType.Auto)
            {
                FlacMethodAndDataPair[] methodsForLeftAndRight;

                SoundChannelAssignmentType assigmentType =
                    FindBestMethod(samples[0], samples[1], out methodsForLeftAndRight);

                WriteFrame(methodsForLeftAndRight, assigmentType);
            }
            else
            {
                methods = new FlacMethod[channelsCount];

                SoundChannelAssignment[]   assignments;
                SoundChannelAssignmentType definedChannelAssigmentType;
                if (channelAssigment == SoundChannelAssignmentType.Auto)
                {
                    assignments = FlacCommons.StaticChannelAssignments[channelsCount - 1];
                    definedChannelAssigmentType = (SoundChannelAssignmentType)(channelsCount - 1);
                }
                else
                {
                    assignments = FlacCommons.StaticChannelAssignments[(int)channelAssigment];
                    definedChannelAssigmentType = channelAssigment;
                }

                FlacMethodAndDataPair[] samplesAndMethods = estimator.FindBestMethods(
                    samples, Streaminfo.BitsPerSample);

                WriteFrame(samplesAndMethods, definedChannelAssigmentType);
            }
        }
示例#6
0
        public void WriteFrame(int[][] samples, SoundChannelAssignmentType channelAssigment)
        {
            if(samples == null) throw new ArgumentNullException("samples");
            int channelsCount = Streaminfo.ChannelsCount;
            if (samples.Length != channelsCount)
                throw new ArgumentException("Expected same amount of channels as in Streaminfo");
            int samplesPerChannel = samples[0].Length;
            if( // samplesPerChannel < Streaminfo.MinBlockSize ||
                Streaminfo.MaxBlockSize < samplesPerChannel)
                throw new ArgumentException("Amount of samples more or less than specified in Streaminfo");

            for (int i = 1; i < channelsCount; i++)
            {
                if(samplesPerChannel != samples[i].Length)
                throw new ArgumentException("Expected same amount of samples on all the channels");
            }

            FlacMethod[] methods;

            if(channelsCount == 2 && channelAssigment == SoundChannelAssignmentType.Auto)
            {
                FlacMethodAndDataPair[] methodsForLeftAndRight;

                SoundChannelAssignmentType assigmentType =
                    FindBestMethod(samples[0], samples[1], out methodsForLeftAndRight);

                WriteFrame(methodsForLeftAndRight, assigmentType);
            }
            else
            {
                methods = new FlacMethod[channelsCount];

                SoundChannelAssignment[] assignments;
                SoundChannelAssignmentType definedChannelAssigmentType;
                if (channelAssigment == SoundChannelAssignmentType.Auto)
                {
                    assignments = FlacCommons.StaticChannelAssignments[channelsCount - 1];
                    definedChannelAssigmentType = (SoundChannelAssignmentType)(channelsCount - 1);
                }
                else
                {
                    assignments = FlacCommons.StaticChannelAssignments[(int)channelAssigment];
                    definedChannelAssigmentType = channelAssigment;
                }

                FlacMethodAndDataPair[] samplesAndMethods = estimator.FindBestMethods(
                    samples, Streaminfo.BitsPerSample);

                WriteFrame(samplesAndMethods, definedChannelAssigmentType);
            }
        }
示例#7
0
 public FlacMethodAndDataPair(FlacMethod method, int bitsPerSample, int[] data)
 {
     this.Method        = method;
     this.Data          = data;
     this.BitsPerSample = bitsPerSample;
 }
        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);
        }
示例#9
0
        private FlacMethod FindBestLpcMethod(int[] channelSamples, int bitsPerSample, FlacEncodingPolicy policy)
        {
            if (!policy.LpcOrder.HasValue) return null;

            int minLpcOrder = policy.LpcOrder.Value.MinValue;
            int maxLpcOrder = Math.Min(policy.LpcOrder.Value.MaxValue,
                channelSamples.Length - 1);

            double[] r = new double[maxLpcOrder + 1];
            parallel.For(0, r.Length, i =>
            {
                double sum = 0;
                for (int j = 0, q = channelSamples.Length - i; j < i; j++, q++)
                    sum += (double)channelSamples[j] * channelSamples[q];
                for (int j = i, q = 0; j < channelSamples.Length; j++, q++)
                    sum += (double)channelSamples[j] * channelSamples[q];
                r[i] = sum;
            });

            FlacMethod[] methods = new FlacMethod[maxLpcOrder];
            parallel.For(minLpcOrder, maxLpcOrder + 1, order =>
            {
                double[] coef = SolveLpc(r, order);

                int[] integerCoefficients;
                int shift;
                int precision;
                ConvertLpcCoeficientsToIntegers(coef, out integerCoefficients, out precision, out shift);

                IPredictor predictor = PredictorFactory.CreateLpcPredictor(integerCoefficients, shift, ArrayUtils.CutArray(channelSamples, 0, order - 1));
                FlacResidualCoefficeints residual = FindBestResidual(channelSamples, order, predictor, policy);
                FlacLpcMethodCoefficeints lpcCoefficients = new FlacLpcMethodCoefficeints(
                    precision, integerCoefficients, shift);

                FlacMethod method = new FlacLpcMethod(bitsPerSample, lpcCoefficients, residual);
                methods[order - 1] = method;
            });

            return FindBestMethod(methods);
        }
示例#10
0
        private FlacMethod FindBestFixedMethod(int[] channelSamples, int bitsPerSample, FlacEncodingPolicy policy)
        {
            if (!policy.FixedOrder.HasValue) return null;

            int minFixedOrder = policy.FixedOrder.Value.MinValue;
            int maxFixedOrder = Math.Min(channelSamples.Length - 1,
                policy.FixedOrder.Value.MaxValue);

            FlacMethod[] methods = new FlacMethod[maxFixedOrder + 1];
            parallel.For(minFixedOrder, maxFixedOrder + 1, order =>
            {
                IPredictor predictor = PredictorFactory.CreateFixedPredictor(order, ArrayUtils.CutArray(channelSamples, 0, order - 1));
                FlacResidualCoefficeints residual = FindBestResidual(channelSamples, order, predictor, policy);

                FlacMethod method = new FlacFixedMethod(bitsPerSample, order, residual);
                methods[order] = method;
            });

            return FindBestMethod(methods);
        }