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; }
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); } }
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); } }
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); }
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); }
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); }