예제 #1
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));
        }
예제 #2
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));
        }
예제 #3
0
 protected FlacMethodFirBased(SubframeType subframeType, int estimatedSize, int order, FlacResidualCoefficeints residual)
     : base(subframeType, estimatedSize)
 {
     this.order    = order;
     this.residual = residual;
 }
예제 #4
0
 public FlacLpcMethod(int bitsPerSample, FlacLpcMethodCoefficeints coefficients, FlacResidualCoefficeints residual)
     : base(SubframeType.SubframeLpc, coefficients.EstimateStorage(bitsPerSample) + residual.EstimatedSize, coefficients.Coefficients.Length, residual)
 {
     this.coefficients = coefficients;
 }
예제 #5
0
 public FlacFixedMethod(int bitsPerSample, int order, FlacResidualCoefficeints residual)
     : base(SubframeType.SubframeFixed, bitsPerSample * order + residual.EstimatedSize, order, residual)
 {
 }
예제 #6
0
 public FlacLpcMethod(int bitsPerSample, FlacLpcMethodCoefficeints coefficients, FlacResidualCoefficeints residual)
     : base(SubframeType.SubframeLpc, coefficients.EstimateStorage(bitsPerSample) + residual.EstimatedSize, coefficients.Coefficients.Length, residual)
 {
     this.coefficients = coefficients;
 }
예제 #7
0
 public FlacFixedMethod(int bitsPerSample, int order, FlacResidualCoefficeints residual)
     : base(SubframeType.SubframeFixed, bitsPerSample * order + residual.EstimatedSize, order, residual)
 {
 }
예제 #8
0
 protected FlacMethodFirBased(SubframeType subframeType, int estimatedSize, int order, FlacResidualCoefficeints residual)
     : base(subframeType, estimatedSize)
 {
     this.order = order;
     this.residual = residual;
 }
예제 #9
0
        private FlacResidualCoefficeints FindBestResidual(int[] channelSamples, int order, IPredictor predictor, FlacEncodingPolicy policy)
        {
            int[] residual;
            if (order > 0)
            {
                residual = new int[channelSamples.Length];
                int lastSample = channelSamples[order - 1];
                for (int i = order; i < residual.Length; i++)
                {
                    int nextSample = channelSamples[i];
                    residual[i] = nextSample - predictor.Next(lastSample);
                    lastSample  = nextSample;
                }
            }
            else
            {
                residual = channelSamples;
            }

            int minRiceOrder = policy.RicePartionOrder.MinValue;
            int maxRiceOrder = policy.RicePartionOrder.MaxValue;
            List <FlacResidualCoefficeints> rices = new List <FlacResidualCoefficeints>();
            int samplesPerPartition = channelSamples.Length >> minRiceOrder;

            if (samplesPerPartition << minRiceOrder != channelSamples.Length)
            {
                minRiceOrder = maxRiceOrder = 0; // reset minRiceOrder to zero;
            }

            for (int riceOrder = minRiceOrder; riceOrder <= maxRiceOrder; riceOrder++)
            {
                if (samplesPerPartition <= order)
                {
                    break;
                }

                int partitionCount = 1 << riceOrder;

                int[] parameters             = new int[partitionCount];
                int   totalPartitionDataSize = 0;
                int   j = order;
                for (int i = 0; i < partitionCount; i++)
                {
                    int skipAmount = i == 0 ? order : 0;
                    int estimatedPartitionSize;
                    int riceParameter;
                    FindBestResidual(residual, samplesPerPartition * i + skipAmount, samplesPerPartition - skipAmount,
                                     out estimatedPartitionSize, out riceParameter);
                    totalPartitionDataSize += estimatedPartitionSize;
                    parameters[i]           = riceParameter;
                }

                const int NormalPrecision               = 4;
                const int ExtendedPrecision             = 5;
                const int MinValueForExtendedParameters = 15;

                bool isExtended = false;
                for (int i = 0; i < parameters.Length && !isExtended; ++i)
                {
                    isExtended = parameters[i] >= MinValueForExtendedParameters;
                }

                int totalSize = 4 + totalPartitionDataSize +
                                partitionCount * (isExtended ? ExtendedPrecision : NormalPrecision);

                FlacResidualCoefficeints rice = new FlacResidualCoefficeints();
                rice.EstimatedSize  = totalSize;
                rice.IsExtended     = isExtended;
                rice.RiceParameters = parameters;
                rice.Order          = riceOrder;

                rices.Add(rice);

                if ((samplesPerPartition & 1) != 0)
                {
                    break;
                }
                samplesPerPartition >>= 1;
            }

            int bestRicePartition = 0;

            for (int i = 1; i < rices.Count; i++)
            {
                if (rices[bestRicePartition].EstimatedSize > rices[i].EstimatedSize)
                {
                    bestRicePartition = i;
                }
            }
            return(rices[bestRicePartition]);
        }
예제 #10
0
        private FlacResidualCoefficeints FindBestResidual(int[] channelSamples, int order, IPredictor predictor, FlacEncodingPolicy policy)
        {
            int[] residual;
            if (order > 0)
            {
                residual = new int[channelSamples.Length];
                int lastSample = channelSamples[order - 1];
                for (int i = order; i < residual.Length; i++)
                {
                    int nextSample = channelSamples[i];
                    residual[i] = nextSample - predictor.Next(lastSample);
                    lastSample = nextSample;
                }
            }
            else
                residual = channelSamples;

            int minRiceOrder = policy.RicePartionOrder.MinValue;
            int maxRiceOrder = policy.RicePartionOrder.MaxValue;
            List<FlacResidualCoefficeints> rices = new List<FlacResidualCoefficeints>();
            int samplesPerPartition = channelSamples.Length >> minRiceOrder;

            if (samplesPerPartition << minRiceOrder != channelSamples.Length)
            {
                minRiceOrder = maxRiceOrder = 0; // reset minRiceOrder to zero;
            }

            for (int riceOrder = minRiceOrder; riceOrder <= maxRiceOrder; riceOrder++)
            {
                if (samplesPerPartition <= order) break;

                int partitionCount = 1 << riceOrder;

                int[] parameters = new int[partitionCount];
                int totalPartitionDataSize = 0;
                int j = order;
                for (int i = 0; i < partitionCount; i++)
                {
                    int skipAmount = i == 0 ? order : 0;
                    int estimatedPartitionSize;
                    int riceParameter;
                    FindBestResidual(residual, samplesPerPartition * i + skipAmount, samplesPerPartition - skipAmount,
                        out estimatedPartitionSize, out riceParameter);
                    totalPartitionDataSize += estimatedPartitionSize;
                    parameters[i] = riceParameter;
                }

                const int NormalPrecision = 4;
                const int ExtendedPrecision = 5;
                const int MinValueForExtendedParameters = 15;

                bool isExtended = Array.Exists(parameters, delegate(int x) {
                    return x >= MinValueForExtendedParameters;
                });

                int totalSize = 4 + totalPartitionDataSize +
                    partitionCount * (isExtended ? ExtendedPrecision : NormalPrecision);

                FlacResidualCoefficeints rice = new FlacResidualCoefficeints();
                rice.EstimatedSize = totalSize;
                rice.IsExtended = isExtended;
                rice.RiceParameters = parameters;
                rice.Order = riceOrder;

                rices.Add(rice);

                if ((samplesPerPartition & 1) != 0) break;
                samplesPerPartition >>= 1;
            }

            int bestRicePartition = 0;
            for (int i = 1; i < rices.Count; i++)
            {
                if (rices[bestRicePartition].EstimatedSize > rices[i].EstimatedSize)
                    bestRicePartition = i;
            }
            return rices[bestRicePartition];
        }