Ejemplo n.º 1
0
		unsafe void encode_residual(FlacFrame frame, int ch, PredictionType predict, OrderMethod omethod, int pass, int best_window)
		{
			int* smp = frame.subframes[ch].samples;
			int i, n = frame.blocksize;
			// save best.window, because we can overwrite it later with fixed frame

			// CONSTANT
			for (i = 1; i < n; i++)
			{
				if (smp[i] != smp[0]) break;
			}
			if (i == n)
			{
				frame.subframes[ch].best.type = SubframeType.Constant;
				frame.subframes[ch].best.residual[0] = smp[0];
				frame.subframes[ch].best.size = (uint)frame.subframes[ch].obits;
				return;
			}

			// VERBATIM
			frame.current.type = SubframeType.Verbatim;
			frame.current.size = (uint)(frame.subframes[ch].obits * frame.blocksize);
			frame.ChooseBestSubframe(ch);

			if (n < 5 || predict == PredictionType.None)
				return;

			// FIXED
			if (predict == PredictionType.Fixed ||
				(predict == PredictionType.Search && pass != 1) ||
				//predict == PredictionType.Search ||
				//(pass == 2 && frame.subframes[ch].best.type == SubframeType.Fixed) ||
				n <= eparams.max_prediction_order)
			{
				int max_fixed_order = Math.Min(eparams.max_fixed_order, 4);
				int min_fixed_order = Math.Min(eparams.min_fixed_order, max_fixed_order);

				for (i = min_fixed_order; i <= max_fixed_order; i++)
					encode_residual_fixed_sub(frame, i, ch);
			}

			// LPC
			if (n > eparams.max_prediction_order &&
			   (predict == PredictionType.Levinson ||
				predict == PredictionType.Search)
				//predict == PredictionType.Search ||
				//(pass == 2 && frame.subframes[ch].best.type == SubframeType.LPC))
				)
			{
				float* lpcs = stackalloc float[lpc.MAX_LPC_ORDER * lpc.MAX_LPC_ORDER];
				int min_order = eparams.min_prediction_order;
				int max_order = eparams.max_prediction_order;

				for (int iWindow = 0; iWindow < _windowcount; iWindow++)
				{
					if (best_window != -1 && iWindow != best_window)
						continue;

					LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[iWindow];

					lpc_ctx.GetReflection(max_order, smp, n, frame.window_buffer + iWindow * Flake.MAX_BLOCKSIZE * 2);
					lpc_ctx.ComputeLPC(lpcs);

					//int frameSize = n;
					//float* F = stackalloc float[frameSize];
					//float* B = stackalloc float[frameSize];
					//float* PE = stackalloc float[max_order + 1];
					//float* arp = stackalloc float[max_order];
					//float* rc = stackalloc float[max_order];

					//for (int j = 0; j < frameSize; j++)
					//    F[j] = B[j] = smp[j];

					//for (int K = 1; K <= max_order; K++)
					//{
					//    // BURG:
					//    float denominator = 0.0f;
					//    //float denominator = F[K - 1] * F[K - 1] + B[frameSize - K] * B[frameSize - K];
					//    for (int j = 0; j < frameSize - K; j++)
					//        denominator += F[j + K] * F[j + K] + B[j] * B[j];
					//    denominator /= 2;

					//    // Estimate error
					//    PE[K - 1] = denominator / (frameSize - K);

					//    float reflectionCoeff = 0.0f;
					//    for (int j = 0; j < frameSize - K; j++)
					//        reflectionCoeff += F[j + K] * B[j];
					//    reflectionCoeff /= denominator;
					//    rc[K - 1] = arp[K - 1] = reflectionCoeff;

					//    // Levinson-Durbin
					//    for (int j = 0; j < (K - 1) >> 1; j++)
					//    {
					//        float arptmp = arp[j];
					//        arp[j] -= reflectionCoeff * arp[K - 2 - j];
					//        arp[K - 2 - j] -= reflectionCoeff * arptmp;
					//    }
					//    if (((K - 1) & 1) != 0)
					//        arp[(K - 1) >> 1] -= reflectionCoeff * arp[(K - 1) >> 1];

					//    for (int j = 0; j < frameSize - K; j++)
					//    {
					//        float f = F[j + K];
					//        float b = B[j];
					//        F[j + K] = f - reflectionCoeff * b;
					//        B[j] = b - reflectionCoeff * f;
					//    }

					//    for (int j = 0; j < K; j++)
					//        lpcs[(K - 1) * lpc.MAX_LPC_ORDER + j] = (float)arp[j];
					//}

					switch (omethod)
					{
						case OrderMethod.Akaike:
							//lpc_ctx.SortOrdersAkaike(frame.blocksize, eparams.estimation_depth, max_order, 7.1, 0.0);
							lpc_ctx.SortOrdersAkaike(frame.blocksize, eparams.estimation_depth, max_order, 4.5, 0.0);
							break;
						default:
							throw new Exception("unknown order method");
					}

					for (i = 0; i < eparams.estimation_depth && i < max_order; i++)
						encode_residual_lpc_sub(frame, lpcs, iWindow, lpc_ctx.best_orders[i], ch);
				}
			}
		}
Ejemplo n.º 2
0
		unsafe void encode_residual_lpc_sub(FlacFrame frame, float* lpcs, int iWindow, int order, int ch)
		{
			// select LPC precision based on block size
			uint lpc_precision;
			if (frame.blocksize <= 192) lpc_precision = 7U;
			else if (frame.blocksize <= 384) lpc_precision = 8U;
			else if (frame.blocksize <= 576) lpc_precision = 9U;
			else if (frame.blocksize <= 1152) lpc_precision = 10U;
			else if (frame.blocksize <= 2304) lpc_precision = 11U;
			else if (frame.blocksize <= 4608) lpc_precision = 12U;
			else if (frame.blocksize <= 8192) lpc_precision = 13U;
			else if (frame.blocksize <= 16384) lpc_precision = 14U;
			else lpc_precision = 15;

			for (int i_precision = eparams.lpc_min_precision_search; i_precision <= eparams.lpc_max_precision_search && lpc_precision + i_precision < 16; i_precision++)
				// check if we already calculated with this order, window and precision
				if ((frame.subframes[ch].lpc_ctx[iWindow].done_lpcs[i_precision] & (1U << (order - 1))) == 0)
				{
					frame.subframes[ch].lpc_ctx[iWindow].done_lpcs[i_precision] |= (1U << (order - 1));

					uint cbits = lpc_precision + (uint)i_precision;

					frame.current.type = SubframeType.LPC;
					frame.current.order = order;
					frame.current.window = iWindow;

					fixed (int* coefs = frame.current.coefs)
					{
						lpc.quantize_lpc_coefs(lpcs + (frame.current.order - 1) * lpc.MAX_LPC_ORDER,
							frame.current.order, cbits, coefs, out frame.current.shift, 15, 0);

						if (frame.current.shift < 0 || frame.current.shift > 15)
							throw new Exception("negative shift");

						ulong csum = 0;
						for (int i = frame.current.order; i > 0; i--)
							csum += (ulong)Math.Abs(coefs[i - 1]);

						if ((csum << frame.subframes[ch].obits) >= 1UL << 32)
							lpc.encode_residual_long(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order, coefs, frame.current.shift);
						else
							lpc.encode_residual(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order, coefs, frame.current.shift);

					}
					int pmax = get_max_p_order(eparams.max_partition_order, frame.blocksize, frame.current.order);
					int pmin = Math.Min(eparams.min_partition_order, pmax);
					uint best_size = calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, PCM.BitsPerSample);
					// not working
					//for (int o = 1; o <= frame.current.order; o++)
					//{
					//    if (frame.current.coefs[o - 1] > -(1 << frame.current.shift))
					//    {
					//        for (int i = o; i < frame.blocksize; i++)
					//            frame.current.residual[i] += frame.subframes[ch].samples[i - o] >> frame.current.shift;
					//        frame.current.coefs[o - 1]--;
					//        uint new_size = calc_rice_params(ref frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order);
					//        if (new_size > best_size)
					//        {
					//            for (int i = o; i < frame.blocksize; i++)
					//                frame.current.residual[i] -= frame.subframes[ch].samples[i - o] >> frame.current.shift;
					//            frame.current.coefs[o - 1]++;
					//        }
					//    }
					//}
					frame.current.size = (uint)(frame.current.order * frame.subframes[ch].obits + 4 + 5 + frame.current.order * (int)cbits + 6 + (int)best_size);
					frame.ChooseBestSubframe(ch);
				}
		}
Ejemplo n.º 3
0
		unsafe void encode_residual_fixed_sub(FlacFrame frame, int order, int ch)
		{
			if ((frame.subframes[ch].done_fixed & (1U << order)) != 0)
				return; // already calculated;

			frame.current.order = order;
			frame.current.type = SubframeType.Fixed;

			encode_residual_fixed(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order);

			int pmax = get_max_p_order(eparams.max_partition_order, frame.blocksize, frame.current.order);
			int pmin = Math.Min(eparams.min_partition_order, pmax);
			frame.current.size = (uint)(frame.current.order * frame.subframes[ch].obits) + 6
				+ calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, PCM.BitsPerSample);

			frame.subframes[ch].done_fixed |= (1U << order);

			frame.ChooseBestSubframe(ch);
		}
Ejemplo n.º 4
0
        unsafe void postprocess_coefs(FlacFrame frame, FlacSubframe sf, int ch)
        {
            if (eparams.development_mode < 0)
                return;
            if (sf.type != SubframeType.LPC || sf.order > 30)
                return;
            int orig_window = sf.window;
            int orig_order = sf.order;
            int orig_shift = sf.shift;
            int orig_cbits = sf.cbits;
            uint orig_size = sf.size;
            var orig_coefs = stackalloc int[orig_order];
            for (int i = 0; i < orig_order; i++) orig_coefs[i] = sf.coefs[i];
            int orig_xx = -1;
            int orig_seq = 0;
            int maxxx = Math.Min(good_x[orig_order].Length, eparams.development_mode);
            var pmax = get_max_p_order(eparams.max_partition_order, frame.blocksize, orig_order);
            var pmin = Math.Min(eparams.min_partition_order, pmax);
            ulong* sums = stackalloc ulong[(pmax + 1) * Flake.MAX_PARTITIONS];

            while (true)
            {
                var best_coefs = stackalloc int[orig_order];
                int best_shift = orig_shift;
                int best_cbits = orig_cbits;
                uint best_size = orig_size;
                int best_xx = -1;
                for (int xx = -1; xx < maxxx; xx++)
                {
                    int x = xx;
                    if (xx < 0)
                    {
                        if (orig_xx < 0 || maxxx < 1/*3*/)// || (orig_xx >> orig_order) != 0)
                            continue;
                        x = orig_xx;
                        orig_seq++;
                    }
                    else
                    {
                        orig_seq = 0;
                        if (orig_order < good_x.Length && good_x[orig_order] != null)
                            x = good_x[orig_order][xx];
                    }

                    frame.current.type = SubframeType.LPC;
                    frame.current.order = orig_order;
                    frame.current.window = orig_window;
                    frame.current.shift = orig_shift;
                    frame.current.cbits = orig_cbits;

                    if (((x >> orig_order) & 1) != 0)
                    {
                        frame.current.shift--;
                        frame.current.cbits--;
                        if (frame.current.shift < 0 || frame.current.cbits < 2)
                            continue;
                    }

                    ulong csum = 0;
                    int qmax = (1 << (frame.current.cbits - 1)) - 1;
                    for (int i = 0; i < frame.current.order; i++)
                    {
                        int shift = (x >> orig_order) & 1;
                        int increment = (x == 1 << orig_order) ? 0 : (((x >> i) & 1) << 1) - 1;
                        frame.current.coefs[i] = (orig_coefs[i] + (increment << orig_seq)) >> shift;
                        if (frame.current.coefs[i] < -(qmax + 1)) frame.current.coefs[i] = -(qmax + 1);
                        if (frame.current.coefs[i] > qmax) frame.current.coefs[i] = qmax;
                        csum += (ulong)Math.Abs(frame.current.coefs[i]);
                    }

                    fixed (int* coefs = frame.current.coefs)
                    {
                        if ((csum << frame.subframes[ch].obits) >= 1UL << 32)
                            lpc.encode_residual_long(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order, coefs, frame.current.shift);
                        else
                            lpc.encode_residual(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order, coefs, frame.current.shift);
                    }

                    var cur_size = calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, Settings.PCM.BitsPerSample);
                    frame.current.size = (uint)(frame.current.order * frame.subframes[ch].obits + 4 + 5 + frame.current.order * frame.current.cbits + 6 + (int)cur_size);

                    if (frame.current.size < best_size)
                    {
                        //var dif = best_size - frame.current.size;
                        for (int i = 0; i < frame.current.order; i++) best_coefs[i] = frame.current.coefs[i];
                        best_shift = frame.current.shift;
                        best_cbits = frame.current.cbits;
                        best_size = frame.current.size;
                        best_xx = x;
                        frame.ChooseBestSubframe(ch);
                        //if (dif > orig_order * 5)
                        //    break;
                    }

                    if (xx < 0 && best_size < orig_size)
                        break;
                }

                if (best_size < orig_size)
                {
                    //if (best_xx >= 0) best_x[order, best_xx]++;
                    //if (orig_size != 0x7FFFFFFF)
                    //    System.Console.Write(string.Format(" {0}[{1:x}]", orig_size - best_size, best_xx));
                    for (int i = 0; i < orig_order; i++) orig_coefs[i] = best_coefs[i];
                    orig_shift = best_shift;
                    orig_cbits = best_cbits;
                    orig_size = best_size;
                    orig_xx = best_xx;
                }
                else
                {
                    break;
                }
            }

            //if (orig_size != 0x7FFFFFFF)
            //    System.Console.WriteLine();

            //if (frame_count % 0x400 == 0)
            //{
            //    for (int o = 0; o < best_x.GetLength(0); o++)
            //    {
            //        //for (int x = 0; x <= (1 << o); x++)
            //        //    if (best_x[o, x] != 0)
            //        //        System.Console.WriteLine(string.Format("{0:x2}\t{1:x4}\t{2}", o, x, best_x[o, x]));
            //        var s = new List<KeyValuePair<int, int>>();
            //        for (int x = 0; x < (1 << o); x++)
            //            if (best_x[o, x] != 0)
            //                s.Add(new KeyValuePair<int, int>(x, best_x[o, x]));
            //        s.Sort((x, y) => y.Value.CompareTo(x.Value));
            //        foreach (var x in s)
            //            System.Console.WriteLine(string.Format("{0:x2}\t{1:x4}\t{2}", o, x.Key, x.Value));
            //        int i = 0;
            //        foreach (var x in s)
            //        {
            //            System.Console.Write(string.Format(o <= 8 ? "0x{0:x2}," : "0x{0:x3},", x.Key));
            //            if ((++i) % 16 == 0)
            //                System.Console.WriteLine();
            //        }
            //        System.Console.WriteLine();
            //    }
            //}
        }