public FlakeReader(string path, Stream IO)
        {
            _path = path;
            _IO = IO != null ? IO : new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000);

            crc8 = new Crc8();
            crc16 = new Crc16();

            _framesBuffer = new byte[0x20000];
            decode_metadata();

            frame = new FlacFrame(PCM.ChannelCount);
            framereader = new BitReader();

            //max_frame_size = 16 + ((Flake.MAX_BLOCKSIZE * PCM.BitsPerSample * PCM.ChannelCount + 1) + 7) >> 3);
            if (((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3) > _framesBuffer.Length)
            {
                byte[] temp = _framesBuffer;
                _framesBuffer = new byte[((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3)];
                if (_framesBufferLength > 0)
                    Array.Copy(temp, _framesBufferOffset, _framesBuffer, 0, _framesBufferLength);
                _framesBufferOffset = 0;
            }
            _samplesInBuffer = 0;

            if ((PCM.BitsPerSample != 16 && PCM.BitsPerSample != 24) || PCM.ChannelCount != 2 || (PCM.SampleRate != 44100 && PCM.SampleRate != 48000))
                throw new Exception("invalid flac file");

            samplesBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount];
            residualBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount];
        }
示例#2
0
        public FlakeReader(Stream IO)
        {
            if (IO == null)
            {
                throw new ArgumentNullException("IO");
            }

            _IO = IO;

            crc8 = new Crc8();

            _framesBuffer = new byte[0x20000];
            decode_metadata();

            frame = new FlacFrame(PCM.ChannelCount);
            framereader = new BitReader();

            //max_frame_size = 16 + ((Flake.MAX_BLOCKSIZE * PCM.BitsPerSample * PCM.ChannelCount + 1) + 7) >> 3);
            if (((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3) > _framesBuffer.Length)
            {
                byte[] temp = _framesBuffer;
                _framesBuffer = new byte[((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3)];
                if (_framesBufferLength > 0)
                    Array.Copy(temp, _framesBufferOffset, _framesBuffer, 0, _framesBufferLength);
                _framesBufferOffset = 0;
            }
            _samplesInBuffer = 0;

            if (PCM.BitsPerSample != 16 && PCM.BitsPerSample != 24)
                throw new Exception("invalid flac file");

            samplesBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount];
            residualBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount];
        }
示例#3
0
        unsafe void restore_samples_fixed(FlacFrame frame, int ch)
        {
            FlacSubframeInfo sub = frame.subframes[ch];

            AudioSamples.MemCpy(sub.samples, sub.best.residual, sub.best.order);
            int *data = sub.samples + sub.best.order;
            int *residual = sub.best.residual + sub.best.order;
            int  data_len = frame.blocksize - sub.best.order;
            int  s0, s1, s2;

            switch (sub.best.order)
            {
            case 0:
                AudioSamples.MemCpy(data, residual, data_len);
                break;

            case 1:
                s1 = data[-1];
                for (int i = data_len; i > 0; i--)
                {
                    s1       += *(residual++);
                    *(data++) = s1;
                }
                //data[i] = residual[i] + data[i - 1];
                break;

            case 2:
                s2 = data[-2];
                s1 = data[-1];
                for (int i = data_len; i > 0; i--)
                {
                    s0        = *(residual++) + (s1 << 1) - s2;
                    *(data++) = s0;
                    s2        = s1;
                    s1        = s0;
                }
                //data[i] = residual[i] + data[i - 1] * 2  - data[i - 2];
                break;

            case 3:
                for (int i = 0; i < data_len; i++)
                {
                    data[i] = residual[i] + (((data[i - 1] - data[i - 2]) << 1) + (data[i - 1] - data[i - 2])) + data[i - 3];
                }
                break;

            case 4:
                for (int i = 0; i < data_len; i++)
                {
                    data[i] = residual[i] + ((data[i - 1] + data[i - 3]) << 2) - ((data[i - 2] << 2) + (data[i - 2] << 1)) - data[i - 4];
                }
                break;
            }
        }
        public FlakeReader(AudioPCMConfig _pcm)
        {
            pcm   = _pcm;
            crc8  = new Crc8();
            crc16 = new Crc16();

            samplesBuffer  = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount];
            residualBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount];
            frame          = new FlacFrame(PCM.ChannelCount);
            framereader    = new BitReader();
        }
示例#5
0
        unsafe void Decode_subframe_fixed(BitReader bitreader, FlacFrame frame, int ch)
        {
            // warm-up samples
            int obits = frame.subframes[ch].obits;

            for (int i = 0; i < frame.subframes[ch].best.order; i++)
            {
                frame.subframes[ch].best.residual[i] = bitreader.Readbits_signed(obits);
            }

            // residual
            Decode_residual(bitreader, frame, ch);
        }
示例#6
0
        unsafe void Decode_residual(BitReader bitreader, FlacFrame frame, int ch)
        {
            // rice-encoded block
            // coding method
            frame.subframes[ch].best.rc.coding_method = (int)bitreader.Readbits(2);             // ????? == 0
            if (frame.subframes[ch].best.rc.coding_method != 0 && frame.subframes[ch].best.rc.coding_method != 1)
            {
                throw new Exception("unsupported residual coding");
            }
            // partition order
            frame.subframes[ch].best.rc.porder = (int)bitreader.Readbits(4);
            if (frame.subframes[ch].best.rc.porder > 8)
            {
                throw new Exception("invalid partition order");
            }
            int psize   = frame.blocksize >> frame.subframes[ch].best.rc.porder;
            int res_cnt = psize - frame.subframes[ch].best.order;

            int rice_len = 4 + frame.subframes[ch].best.rc.coding_method;
            // residual
            int  j = frame.subframes[ch].best.order;
            int *r = frame.subframes[ch].best.residual + j;

            for (int p = 0; p < (1 << frame.subframes[ch].best.rc.porder); p++)
            {
                if (p == 1)
                {
                    res_cnt = psize;
                }
                int n = Math.Min(res_cnt, frame.blocksize - j);

                int k = frame.subframes[ch].best.rc.rparams[p] = (int)bitreader.Readbits(rice_len);
                if (k == (1 << rice_len) - 1)
                {
                    k = frame.subframes[ch].best.rc.esc_bps[p] = (int)bitreader.Readbits(5);
                    for (int i = n; i > 0; i--)
                    {
                        *(r++) = bitreader.Readbits_signed((int)k);
                    }
                }
                else
                {
                    bitreader.Read_rice_block(n, (int)k, r);
                    r += n;
                }
                j += n;
            }
        }
示例#7
0
        unsafe void Restore_samples_lpc(FlacFrame frame, int ch)
        {
            FlacSubframeInfo sub  = frame.subframes[ch];
            ulong            csum = 0;

            fixed(int *coefs = sub.best.coefs)
            {
                for (int i = sub.best.order; i > 0; i--)
                {
                    csum += (ulong)Math.Abs(coefs[i - 1]);
                }
                if ((csum << sub.obits) >= 1UL << 32)
                {
                    Lpc.Decode_residual_long(sub.best.residual, sub.samples, frame.blocksize, sub.best.order, coefs, sub.best.shift);
                }
                else
                {
                    Lpc.Decode_residual(sub.best.residual, sub.samples, frame.blocksize, sub.best.order, coefs, sub.best.shift);
                }
            }
        }
示例#8
0
        public FlakeReader(Stream IO)
        {
            if (IO == null)
            {
                throw new ArgumentNullException("IO");
            }

            _IO = IO;

            crc8 = new Crc8();

            _framesBuffer = new byte[0x20000];
            decode_metadata();

            frame       = new FlacFrame(PCM.ChannelCount);
            framereader = new BitReader();

            //max_frame_size = 16 + ((Flake.MAX_BLOCKSIZE * PCM.BitsPerSample * PCM.ChannelCount + 1) + 7) >> 3);
            if (((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3) > _framesBuffer.Length)
            {
                byte[] temp = _framesBuffer;
                _framesBuffer = new byte[((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3)];
                if (_framesBufferLength > 0)
                {
                    Array.Copy(temp, _framesBufferOffset, _framesBuffer, 0, _framesBufferLength);
                }
                _framesBufferOffset = 0;
            }
            _samplesInBuffer = 0;

            if (PCM.BitsPerSample != 16 && PCM.BitsPerSample != 24)
            {
                throw new Exception("invalid flac file");
            }

            samplesBuffer  = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount];
            residualBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount];
        }
示例#9
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();
            //    }
            //}
        }
 unsafe void restore_samples(FlacFrame frame)
 {
     for (int ch = 0; ch < PCM.ChannelCount; ch++)
     {
         switch (frame.subframes[ch].best.type)
         {
             case SubframeType.Constant:
                 AudioSamples.MemSet(frame.subframes[ch].samples, frame.subframes[ch].best.residual[0], frame.blocksize);
                 break;
             case SubframeType.Verbatim:
                 AudioSamples.MemCpy(frame.subframes[ch].samples, frame.subframes[ch].best.residual, frame.blocksize);
                 break;
             case SubframeType.Fixed:
                 restore_samples_fixed(frame, ch);
                 break;
             case SubframeType.LPC:
                 restore_samples_lpc(frame, ch);
                 break;
         }
         if (frame.subframes[ch].wbits != 0)
         {
             int* s = frame.subframes[ch].samples;
             int x = (int) frame.subframes[ch].wbits;
             for (int i = frame.blocksize; i > 0; i--)
                 *(s++) <<= x;
         }
     }
     if (frame.ch_mode != ChannelMode.NotStereo)
     {
         int* l = frame.subframes[0].samples;
         int* r = frame.subframes[1].samples;
         switch (frame.ch_mode)
         {
             case ChannelMode.LeftRight:
                 break;
             case ChannelMode.MidSide:
                 for (int i = frame.blocksize; i > 0; i--)
                 {
                     int mid = *l;
                     int side = *r;
                     mid <<= 1;
                     mid |= (side & 1); /* i.e. if 'side' is odd... */
                     *(l++) = (mid + side) >> 1;
                     *(r++) = (mid - side) >> 1;
                 }
                 break;
             case ChannelMode.LeftSide:
                 for (int i = frame.blocksize; i > 0; i--)
                 {
                     int _l = *(l++), _r = *r;
                     *(r++) = _l - _r;
                 }
                 break;
             case ChannelMode.RightSide:
                 for (int i = frame.blocksize; i > 0; i--)
                     *(l++) += *(r++);
                 break;
         }
     }
 }
示例#11
0
		public FlakeWriter(string path, Stream IO, AudioPCMConfig pcm)
		{
			_pcm = pcm;

			//if (_pcm.BitsPerSample != 16)
			//    throw new Exception("Bits per sample must be 16.");
			if (_pcm.ChannelCount != 2)
				throw new Exception("ChannelCount must be 2.");

			channels = pcm.ChannelCount;

			// flake_validate_params

			_path = path;
			_IO = IO;

			samplesBuffer = new int[Flake.MAX_BLOCKSIZE * (channels == 2 ? 4 : channels)];
			residualBuffer = new int[Flake.MAX_BLOCKSIZE * (channels == 2 ? 10 : channels + 1)];
			windowBuffer = new float[Flake.MAX_BLOCKSIZE * 2 * lpc.MAX_LPC_WINDOWS];
			windowScale = new double[lpc.MAX_LPC_WINDOWS];

			eparams.flake_set_defaults(_compressionLevel);
			eparams.padding_size = 8192;

			crc8 = new Crc8();
			crc16 = new Crc16();
			frame = new FlacFrame(channels * 2);
		}
示例#12
0
		unsafe void encode_residual_pass2(FlacFrame frame, int ch)
		{
			encode_residual(frame, ch, eparams.prediction_type, eparams.order_method, 2, estimate_best_window(frame, ch));
		}
示例#13
0
		unsafe void output_subframes(FlacFrame frame, BitWriter bitwriter)
		{
			for (int ch = 0; ch < channels; ch++)
			{
				FlacSubframeInfo sub = frame.subframes[ch];
				// subframe header
				int type_code = (int) sub.best.type;
				if (sub.best.type == SubframeType.Fixed)
					type_code |= sub.best.order;
				if (sub.best.type == SubframeType.LPC)
					type_code |= sub.best.order - 1;
				bitwriter.writebits(1, 0);
				bitwriter.writebits(6, type_code);
				bitwriter.writebits(1, sub.wbits != 0 ? 1 : 0);
				if (sub.wbits > 0)
					bitwriter.writebits((int)sub.wbits, 1);

				// subframe
				switch (sub.best.type)
				{
					case SubframeType.Constant:
						output_subframe_constant(frame, bitwriter, sub);
						break;
					case SubframeType.Verbatim:
						output_subframe_verbatim(frame, bitwriter, sub);
						break;
					case SubframeType.Fixed:
						output_subframe_fixed(frame, bitwriter, sub);
						break;
					case SubframeType.LPC:
						output_subframe_lpc(frame, bitwriter, sub);
						break;
				}
			}
		}
示例#14
0
		output_subframe_fixed(FlacFrame frame, BitWriter bitwriter, FlacSubframeInfo sub)
		{
			// warm-up samples
			for (int i = 0; i < sub.best.order; i++)
				bitwriter.writebits_signed(sub.obits, sub.best.residual[i]);

			// residual
			output_residual(frame, bitwriter, sub);
		}
示例#15
0
		output_subframe_constant(FlacFrame frame, BitWriter bitwriter, FlacSubframeInfo sub)
		{
			bitwriter.writebits_signed(sub.obits, sub.best.residual[0]);
		}
        unsafe void decode_subframe_lpc(BitReader bitreader, FlacFrame frame, int ch)
        {
            // warm-up samples
            int obits = frame.subframes[ch].obits;
            for (int i = 0; i < frame.subframes[ch].best.order; i++)
                frame.subframes[ch].best.residual[i] = bitreader.readbits_signed(obits);

            // LPC coefficients
            frame.subframes[ch].best.cbits = (int)bitreader.readbits(4) + 1; // lpc_precision
            frame.subframes[ch].best.shift = bitreader.readbits_signed(5);
            if (frame.subframes[ch].best.shift < 0)
                throw new Exception("negative shift");
            for (int i = 0; i < frame.subframes[ch].best.order; i++)
                frame.subframes[ch].best.coefs[i] = bitreader.readbits_signed(frame.subframes[ch].best.cbits);

            // residual
            decode_residual(bitreader, frame, ch);
        }
示例#17
0
        unsafe void Decode_subframe_constant(BitReader bitreader, FlacFrame frame, int ch)
        {
            int obits = frame.subframes[ch].obits;

            frame.subframes[ch].best.residual[0] = bitreader.Readbits_signed(obits);
        }
示例#18
0
        unsafe void Decode_frame_header(BitReader bitreader, FlacFrame frame)
        {
            int header_start = bitreader.Position;

            if (bitreader.Readbits(15) != 0x7FFC)
            {
                throw new Exception("invalid frame");
            }
            uint vbs = bitreader.Readbit();

            frame.bs_code0 = (int)bitreader.Readbits(4);
            uint sr_code0 = bitreader.Readbits(4);

            frame.ch_mode = (ChannelMode)bitreader.Readbits(4);
            uint bps_code = bitreader.Readbits(3);

            if (Flake.flac_bitdepths[bps_code] != PCM.BitsPerSample)
            {
                throw new Exception("unsupported bps coding");
            }
            uint t1 = bitreader.Readbit();             // == 0?????

            if (t1 != 0)
            {
                throw new Exception("unsupported frame coding");
            }
            frame.frame_number = (int)bitreader.Read_utf8();

            // custom block size
            if (frame.bs_code0 == 6)
            {
                frame.bs_code1  = (int)bitreader.Readbits(8);
                frame.blocksize = frame.bs_code1 + 1;
            }
            else if (frame.bs_code0 == 7)
            {
                frame.bs_code1  = (int)bitreader.Readbits(16);
                frame.blocksize = frame.bs_code1 + 1;
            }
            else
            {
                frame.blocksize = Flake.flac_blocksizes[frame.bs_code0];
            }

            // custom sample rate
            if (sr_code0 < 4 || sr_code0 > 11)
            {
                // sr_code0 == 12 -> sr == bitreader.readbits(8) * 1000;
                // sr_code0 == 13 -> sr == bitreader.readbits(16);
                // sr_code0 == 14 -> sr == bitreader.readbits(16) * 10;
                throw new Exception("invalid sample rate mode");
            }

            int frame_channels = (int)frame.ch_mode + 1;

            if (frame_channels > 11)
            {
                throw new Exception("invalid channel mode");
            }
            if (frame_channels == 2 || frame_channels > 8)             // Mid/Left/Right Side Stereo
            {
                frame_channels = 2;
            }
            else
            {
                frame.ch_mode = ChannelMode.NotStereo;
            }
            if (frame_channels != PCM.ChannelCount)
            {
                throw new Exception("invalid channel mode");
            }

            // CRC-8 of frame header
            byte crc = DoCRC ? crc8.ComputeChecksum(bitreader.Buffer, header_start, bitreader.Position - header_start) : (byte)0;

            frame.crc8 = (byte)bitreader.Readbits(8);
            if (DoCRC && frame.crc8 != crc)
            {
                throw new Exception("header crc mismatch");
            }
        }
        public FlakeReader(AudioPCMConfig _pcm)
        {
            pcm = _pcm;
            crc8 = new Crc8();
            crc16 = new Crc16();

            samplesBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount];
            residualBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount];
            frame = new FlacFrame(PCM.ChannelCount);
            framereader = new BitReader();
        }
 unsafe void restore_samples_lpc(FlacFrame frame, int ch)
 {
     FlacSubframeInfo sub = frame.subframes[ch];
     ulong csum = 0;
     fixed (int* coefs = sub.best.coefs)
     {
         for (int i = sub.best.order; i > 0; i--)
             csum += (ulong)Math.Abs(coefs[i - 1]);
         if ((csum << sub.obits) >= 1UL << 32)
             lpc.decode_residual_long(sub.best.residual, sub.samples, frame.blocksize, sub.best.order, coefs, sub.best.shift);
         else
             lpc.decode_residual(sub.best.residual, sub.samples, frame.blocksize, sub.best.order, coefs, sub.best.shift);
     }
 }
        unsafe void restore_samples_fixed(FlacFrame frame, int ch)
        {
            FlacSubframeInfo sub = frame.subframes[ch];

            AudioSamples.MemCpy(sub.samples, sub.best.residual, sub.best.order);
            int* data = sub.samples + sub.best.order;
            int* residual = sub.best.residual + sub.best.order;
            int data_len = frame.blocksize - sub.best.order;
            int s0, s1, s2;
            switch (sub.best.order)
            {
                case 0:
                    AudioSamples.MemCpy(data, residual, data_len);
                    break;
                case 1:
                    s1 = data[-1];
                    for (int i = data_len; i > 0; i--)
                    {
                        s1 += *(residual++);
                        *(data++) = s1;
                    }
                    //data[i] = residual[i] + data[i - 1];
                    break;
                case 2:
                    s2 = data[-2];
                    s1 = data[-1];
                    for (int i = data_len; i > 0; i--)
                    {
                        s0 = *(residual++) + (s1 << 1) - s2;
                        *(data++) = s0;
                        s2 = s1;
                        s1 = s0;
                    }
                    //data[i] = residual[i] + data[i - 1] * 2  - data[i - 2];
                    break;
                case 3:
                    for (int i = 0; i < data_len; i++)
                        data[i] = residual[i] + (((data[i - 1] - data[i - 2]) << 1) + (data[i - 1] - data[i - 2])) + data[i - 3];
                    break;
                case 4:
                    for (int i = 0; i < data_len; i++)
                        data[i] = residual[i] + ((data[i - 1] + data[i - 3]) << 2) - ((data[i - 2] << 2) + (data[i - 2] << 1)) - data[i - 4];
                    break;
            }
        }
示例#22
0
		unsafe void output_frame_header(FlacFrame frame, BitWriter bitwriter)
		{
			bitwriter.writebits(15, 0x7FFC);
			bitwriter.writebits(1, eparams.variable_block_size > 0 ? 1 : 0);
			bitwriter.writebits(4, frame.bs_code0);
			bitwriter.writebits(4, sr_code0);
			if (frame.ch_mode == ChannelMode.NotStereo)
				bitwriter.writebits(4, ch_code);
			else
				bitwriter.writebits(4, (int) frame.ch_mode);
			bitwriter.writebits(3, bps_code);
			bitwriter.writebits(1, 0);
			bitwriter.write_utf8(frame_count);

			// custom block size
			if (frame.bs_code1 >= 0)
			{
				if (frame.bs_code1 < 256)
					bitwriter.writebits(8, frame.bs_code1);
				else
					bitwriter.writebits(16, frame.bs_code1);
			}

			// custom sample rate
			if (sr_code1 > 0)
			{
				if (sr_code1 < 256)
					bitwriter.writebits(8, sr_code1);
				else
					bitwriter.writebits(16, sr_code1);
			}

			// CRC-8 of frame header
			bitwriter.flush();
			byte crc = crc8.ComputeChecksum(frame_buffer, 0, bitwriter.Length);
			bitwriter.writebits(8, crc);
		}
示例#23
0
		unsafe void output_residual(FlacFrame frame, BitWriter bitwriter, FlacSubframeInfo sub)
		{
			// rice-encoded block
			bitwriter.writebits(2, sub.best.rc.coding_method);

			// partition order
			int porder = sub.best.rc.porder;
			int psize = frame.blocksize >> porder;
			//assert(porder >= 0);
			bitwriter.writebits(4, porder);
			int res_cnt = psize - sub.best.order;

			int rice_len = 4 + sub.best.rc.coding_method;
			// residual
			int j = sub.best.order;
			fixed (byte* fixbuf = &frame_buffer[0])
			for (int p = 0; p < (1 << porder); p++)
			{
				int k = sub.best.rc.rparams[p];
				bitwriter.writebits(rice_len, k);
				if (p == 1) res_cnt = psize;
				int cnt = Math.Min(res_cnt, frame.blocksize - j);
				bitwriter.write_rice_block_signed(fixbuf, k, sub.best.residual + j, cnt);
				j += cnt;
			}
		}
        unsafe void decode_subframe_fixed(BitReader bitreader, FlacFrame frame, int ch)
        {
            // warm-up samples
            int obits = frame.subframes[ch].obits;
            for (int i = 0; i < frame.subframes[ch].best.order; i++)
                frame.subframes[ch].best.residual[i] = bitreader.readbits_signed(obits);

            // residual
            decode_residual(bitreader, frame, ch);
        }
示例#25
0
		output_subframe_verbatim(FlacFrame frame, BitWriter bitwriter, FlacSubframeInfo sub)
		{
			int n = frame.blocksize;
			for (int i = 0; i < n; i++)
				bitwriter.writebits_signed(sub.obits, sub.samples[i]); 
			// Don't use residual here, because we don't copy samples to residual for verbatim frames.
		}
示例#26
0
        unsafe void Decode_subframes(BitReader bitreader, FlacFrame frame)
        {
            fixed(int *r = residualBuffer, s = Samples)
            for (int ch = 0; ch < PCM.ChannelCount; ch++)
            {
                // subframe header
                uint t1 = bitreader.Readbit();                 // ?????? == 0

                if (t1 != 0)
                {
                    throw new Exception("unsupported subframe coding (ch == " + ch.ToString() + ")");
                }
                int type_code = (int)bitreader.Readbits(6);

                frame.subframes[ch].wbits = (int)bitreader.Readbit();
                if (frame.subframes[ch].wbits != 0)
                {
                    frame.subframes[ch].wbits += (int)bitreader.Read_unary();
                }

                frame.subframes[ch].obits = PCM.BitsPerSample - frame.subframes[ch].wbits;
                switch (frame.ch_mode)
                {
                case ChannelMode.MidSide: frame.subframes[ch].obits += ch; break;

                case ChannelMode.LeftSide: frame.subframes[ch].obits += ch; break;

                case ChannelMode.RightSide: frame.subframes[ch].obits += 1 - ch; break;
                }

                frame.subframes[ch].best.type  = (SubframeType)type_code;
                frame.subframes[ch].best.order = 0;

                if ((type_code & (uint)SubframeType.LPC) != 0)
                {
                    frame.subframes[ch].best.order = (type_code - (int)SubframeType.LPC) + 1;
                    frame.subframes[ch].best.type  = SubframeType.LPC;
                }
                else if ((type_code & (uint)SubframeType.Fixed) != 0)
                {
                    frame.subframes[ch].best.order = (type_code - (int)SubframeType.Fixed);
                    frame.subframes[ch].best.type  = SubframeType.Fixed;
                }

                frame.subframes[ch].best.residual = r + ch * Flake.MAX_BLOCKSIZE;
                frame.subframes[ch].samples       = s + ch * Flake.MAX_BLOCKSIZE;

                // subframe
                switch (frame.subframes[ch].best.type)
                {
                case SubframeType.Constant:
                    Decode_subframe_constant(bitreader, frame, ch);
                    break;

                case SubframeType.Verbatim:
                    Decode_subframe_verbatim(bitreader, frame, ch);
                    break;

                case SubframeType.Fixed:
                    Decode_subframe_fixed(bitreader, frame, ch);
                    break;

                case SubframeType.LPC:
                    Decode_subframe_lpc(bitreader, frame, ch);
                    break;

                default:
                    throw new Exception("invalid subframe type");
                }
            }
        }
示例#27
0
		output_subframe_lpc(FlacFrame frame, BitWriter bitwriter, FlacSubframeInfo sub)
		{
			// warm-up samples
			for (int i = 0; i < sub.best.order; i++)
				bitwriter.writebits_signed(sub.obits, sub.best.residual[i]);

			// LPC coefficients
			int cbits = 1;
			for (int i = 0; i < sub.best.order; i++)
				while (cbits < 16 && sub.best.coefs[i] != (sub.best.coefs[i] << (32 - cbits)) >> (32 - cbits))
					cbits++;
			bitwriter.writebits(4, cbits - 1);
			bitwriter.writebits_signed(5, sub.best.shift);
			for (int i = 0; i < sub.best.order; i++)
				bitwriter.writebits_signed(cbits, sub.best.coefs[i]);
			
			// residual
			output_residual(frame, bitwriter, sub);
		}
示例#28
0
		unsafe uint measure_frame_size(FlacFrame frame, bool do_midside)
		{
			// crude estimation of header/footer size
			uint total = (uint)(32 + ((BitReader.log2i(frame_count) + 4) / 5) * 8 + (eparams.variable_block_size != 0 ? 16 : 0) + 16);

			if (do_midside)
			{
				uint bitsBest = AudioSamples.UINT32_MAX;
				ChannelMode modeBest = ChannelMode.LeftRight;

				if (bitsBest > frame.subframes[2].best.size + frame.subframes[3].best.size)
				{
					bitsBest = frame.subframes[2].best.size + frame.subframes[3].best.size;
					modeBest = ChannelMode.MidSide;
				}
				if (bitsBest > frame.subframes[3].best.size + frame.subframes[1].best.size)
				{
					bitsBest = frame.subframes[3].best.size + frame.subframes[1].best.size;
					modeBest = ChannelMode.RightSide;
				}
				if (bitsBest > frame.subframes[3].best.size + frame.subframes[0].best.size)
				{
					bitsBest = frame.subframes[3].best.size + frame.subframes[0].best.size;
					modeBest = ChannelMode.LeftSide;
				}
				if (bitsBest > frame.subframes[0].best.size + frame.subframes[1].best.size)
				{
					bitsBest = frame.subframes[0].best.size + frame.subframes[1].best.size;
					modeBest = ChannelMode.LeftRight;
				}
				frame.ch_mode = modeBest;
				return total + bitsBest;
			}

			for (int ch = 0; ch < channels; ch++)
				total += frame.subframes[ch].best.size;
			return total;
		}
示例#29
0
		unsafe void encode_residual_pass1(FlacFrame frame, int ch, int best_window)
		{
			int max_prediction_order = eparams.max_prediction_order;
			int max_fixed_order = eparams.max_fixed_order;
			int min_fixed_order = eparams.min_fixed_order;
			int lpc_min_precision_search = eparams.lpc_min_precision_search;
			int lpc_max_precision_search = eparams.lpc_max_precision_search;
			int max_partition_order = eparams.max_partition_order;
			int estimation_depth = eparams.estimation_depth;
			eparams.min_fixed_order = 2;
			eparams.max_fixed_order = 2;
			eparams.lpc_min_precision_search = eparams.lpc_max_precision_search;
			eparams.max_prediction_order = 8;
			eparams.estimation_depth = 1;
			encode_residual(frame, ch, eparams.prediction_type, OrderMethod.Akaike, 1, best_window);
			eparams.min_fixed_order = min_fixed_order;
			eparams.max_fixed_order = max_fixed_order;
			eparams.max_prediction_order = max_prediction_order;
			eparams.lpc_min_precision_search = lpc_min_precision_search;
			eparams.lpc_max_precision_search = lpc_max_precision_search;
			eparams.max_partition_order = max_partition_order;
			eparams.estimation_depth = estimation_depth;
		}
示例#30
0
		unsafe int encode_frame(out int size)
		{
			fixed (int* s = samplesBuffer, r = residualBuffer)
			fixed (float* window = windowBuffer)
			{
				frame.InitSize(eparams.block_size, eparams.variable_block_size != 0);

				if (frame.blocksize != _windowsize && frame.blocksize > 4)
				{
					_windowsize = frame.blocksize;
					_windowcount = 0;
					calculate_window(window, lpc.window_welch, WindowFunction.Welch);
					calculate_window(window, lpc.window_tukey, WindowFunction.Tukey);
					calculate_window(window, lpc.window_flattop, WindowFunction.Flattop);
					calculate_window(window, lpc.window_hann, WindowFunction.Hann);
					calculate_window(window, lpc.window_bartlett, WindowFunction.Bartlett);
					if (_windowcount == 0)
						throw new Exception("invalid windowfunction");
				}

				if (channels != 2 || frame.blocksize <= 32 || eparams.stereo_method == StereoMethod.Independent)
				{
					frame.window_buffer = window;
					frame.current.residual = r + channels * Flake.MAX_BLOCKSIZE;
					frame.ch_mode = channels != 2 ? ChannelMode.NotStereo : ChannelMode.LeftRight;
					for (int ch = 0; ch < channels; ch++)
						frame.subframes[ch].Init(s + ch * Flake.MAX_BLOCKSIZE, r + ch * Flake.MAX_BLOCKSIZE,
							_pcm.BitsPerSample, get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize));

					for (int ch = 0; ch < channels; ch++)
						encode_residual_pass2(frame, ch);
				}
				else
				{
					//channel_decorrelation(s, s + Flake.MAX_BLOCKSIZE, s + 2 * Flake.MAX_BLOCKSIZE, s + 3 * Flake.MAX_BLOCKSIZE, frame.blocksize);
					frame.window_buffer = window;
					frame.current.residual = r + 4 * Flake.MAX_BLOCKSIZE;
					for (int ch = 0; ch < 4; ch++)
						frame.subframes[ch].Init(s + ch * Flake.MAX_BLOCKSIZE, r + ch * Flake.MAX_BLOCKSIZE,
							_pcm.BitsPerSample + (ch == 3 ? 1 : 0), get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize));

					//for (int ch = 0; ch < 4; ch++)
					//    for (int iWindow = 0; iWindow < _windowcount; iWindow++)
					//        frame.subframes[ch].lpc_ctx[iWindow].GetReflection(32, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer + iWindow * Flake.MAX_BLOCKSIZE * 2);

					estimate_frame(frame, true);
					uint fs = measure_frame_size(frame, true);

					if (0 != eparams.variable_block_size)
					{
						FlacFrame frame2 = new FlacFrame(channels * 2);
						FlacFrame frame3 = new FlacFrame(channels * 2);
						int tumbler = 1;
						while ((frame.blocksize & 1) == 0 && frame.blocksize >= 1024)
						{
							frame2.InitSize(frame.blocksize / 2, true);
							frame2.window_buffer = frame.window_buffer + frame.blocksize;
							frame2.current.residual = r + tumbler * 5 * Flake.MAX_BLOCKSIZE;
							for (int ch = 0; ch < 4; ch++)
								frame2.subframes[ch].Init(frame.subframes[ch].samples, frame2.current.residual + (ch + 1) * frame2.blocksize,
									frame.subframes[ch].obits + frame.subframes[ch].wbits, frame.subframes[ch].wbits);
							estimate_frame(frame2, true);
							uint fs2 = measure_frame_size(frame2, true);
							uint fs3 = fs2;
							if (eparams.variable_block_size == 2 || eparams.variable_block_size == 4)
							{
								frame3.InitSize(frame2.blocksize, true);
								frame3.window_buffer = frame2.window_buffer;
								frame3.current.residual = frame2.current.residual + 5 * frame2.blocksize;
								for (int ch = 0; ch < 4; ch++)
									frame3.subframes[ch].Init(frame2.subframes[ch].samples + frame2.blocksize, frame3.current.residual + (ch + 1) * frame3.blocksize,
										frame.subframes[ch].obits + frame.subframes[ch].wbits, frame.subframes[ch].wbits);
								estimate_frame(frame3, true);
								fs3 = measure_frame_size(frame3, true);
							}
							if (fs2 + fs3 > fs)
								break;
							FlacFrame tmp = frame;
							frame = frame2;
							frame2 = tmp;
							fs = fs2;
							if (eparams.variable_block_size <= 2)
								break;
							tumbler = 1 - tumbler;
						}
					}

					frame.ChooseSubframes();
					encode_estimated_frame(frame);
				}

				BitWriter bitwriter = new BitWriter(frame_buffer, 0, max_frame_size);

				output_frame_header(frame, bitwriter);
				output_subframes(frame, bitwriter);
				output_frame_footer(bitwriter);

				if (bitwriter.Length >= max_frame_size)
					throw new Exception("buffer overflow");

				if (frame_buffer != null)
				{
					if (eparams.variable_block_size > 0)
						frame_count += frame.blocksize;
					else
						frame_count++;
				}
				size = frame.blocksize;
				return bitwriter.Length;
			}
		}
示例#31
0
		unsafe int estimate_best_window(FlacFrame frame, int ch)
		{
			if (_windowcount == 1) 
				return 0;
			switch (eparams.window_method)
			{
				case WindowMethod.Estimate:
					{
						int best_window = -1;
						double best_error = 0;
						int order = 2;
						for (int i = 0; i < _windowcount; i++)
						{
							frame.subframes[ch].lpc_ctx[i].GetReflection(order, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer + i * Flake.MAX_BLOCKSIZE * 2);
							double err = frame.subframes[ch].lpc_ctx[i].prediction_error[order - 1] / frame.subframes[ch].lpc_ctx[i].autocorr_values[0];
							//double err = frame.subframes[ch].lpc_ctx[i].autocorr_values[0] / frame.subframes[ch].lpc_ctx[i].autocorr_values[2];
							if (best_window == -1 || best_error > err)
							{
								best_window = i;
								best_error = err;
							}
						}
						return best_window;
					}
				case WindowMethod.Evaluate:
					encode_residual_pass1(frame, ch, -1);
					return frame.subframes[ch].best.type == SubframeType.LPC ? frame.subframes[ch].best.window : -1;
				case WindowMethod.Search:
					return -1;
			}
			return -1;
		}
示例#32
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);
		}
示例#33
0
		unsafe void estimate_frame(FlacFrame frame, bool do_midside)
		{
			int subframes = do_midside ? channels * 2 : channels;

			switch (eparams.stereo_method)
			{
				case StereoMethod.Estimate:
					for (int ch = 0; ch < subframes; ch++)
					{
						LpcContext lpc_ctx = frame.subframes[ch].lpc_ctx[0];
						lpc_ctx.GetReflection(4, frame.subframes[ch].samples, frame.blocksize, frame.window_buffer);
						lpc_ctx.SortOrdersAkaike(frame.blocksize, 1, 4, 4.5, 0.0);
						frame.subframes[ch].best.size = (uint)Math.Max(0, lpc_ctx.Akaike(frame.blocksize, lpc_ctx.best_orders[0], 4.5, 0.0) + 7.1 * frame.subframes[ch].obits * eparams.max_prediction_order);
					}
					break;
				case StereoMethod.Evaluate:
					for (int ch = 0; ch < subframes; ch++)
						encode_residual_pass1(frame, ch, 0);
					break;
				case StereoMethod.Search:
					for (int ch = 0; ch < subframes; ch++)
					    encode_residual_pass2(frame, ch);
					break;
			}
		}
 unsafe void decode_subframe_verbatim(BitReader bitreader, FlacFrame frame, int ch)
 {
     int obits = frame.subframes[ch].obits;
     for (int i = 0; i < frame.blocksize; i++)
         frame.subframes[ch].best.residual[i] = bitreader.readbits_signed(obits);
 }
示例#35
0
		unsafe void encode_estimated_frame(FlacFrame frame)
		{
			switch (eparams.stereo_method)
			{
				case StereoMethod.Estimate:
					for (int ch = 0; ch < channels; ch++)
					{
						frame.subframes[ch].best.size = AudioSamples.UINT32_MAX;
						encode_residual_pass2(frame, ch);
					}
					break;
				case StereoMethod.Evaluate:
					for (int ch = 0; ch < channels; ch++)
						encode_residual_pass2(frame, ch);
					break;
				case StereoMethod.Search:
					break;
			}
		}
示例#36
0
        unsafe void Restore_samples(FlacFrame frame)
        {
            for (int ch = 0; ch < PCM.ChannelCount; ch++)
            {
                switch (frame.subframes[ch].best.type)
                {
                case SubframeType.Constant:
                    AudioSamples.MemSet(frame.subframes[ch].samples, frame.subframes[ch].best.residual[0], frame.blocksize);
                    break;

                case SubframeType.Verbatim:
                    AudioSamples.MemCpy(frame.subframes[ch].samples, frame.subframes[ch].best.residual, frame.blocksize);
                    break;

                case SubframeType.Fixed:
                    Restore_samples_fixed(frame, ch);
                    break;

                case SubframeType.LPC:
                    Restore_samples_lpc(frame, ch);
                    break;
                }
                if (frame.subframes[ch].wbits != 0)
                {
                    int *s = frame.subframes[ch].samples;
                    int  x = (int)frame.subframes[ch].wbits;
                    for (int i = frame.blocksize; i > 0; i--)
                    {
                        *(s++) <<= x;
                    }
                }
            }
            if (frame.ch_mode != ChannelMode.NotStereo)
            {
                int *l = frame.subframes[0].samples;
                int *r = frame.subframes[1].samples;
                switch (frame.ch_mode)
                {
                case ChannelMode.LeftRight:
                    break;

                case ChannelMode.MidSide:
                    for (int i = frame.blocksize; i > 0; i--)
                    {
                        int mid  = *l;
                        int side = *r;
                        mid  <<= 1;
                        mid   |= (side & 1);                               /* i.e. if 'side' is odd... */
                        *(l++) = (mid + side) >> 1;
                        *(r++) = (mid - side) >> 1;
                    }
                    break;

                case ChannelMode.LeftSide:
                    for (int i = frame.blocksize; i > 0; i--)
                    {
                        int _l = *(l++), _r = *r;
                        *(r++) = _l - _r;
                    }
                    break;

                case ChannelMode.RightSide:
                    for (int i = frame.blocksize; i > 0; i--)
                    {
                        *(l++) += *(r++);
                    }
                    break;
                }
            }
        }
示例#37
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);
				}
		}
示例#38
0
        public FlakeWriter(Stream IO, FlakeWriterSettings settings)
        {
            m_settings = settings;

            //if (Settings.PCM.BitsPerSample != 16)
            //    throw new Exception("Bits per sample must be 16.");
            //if (Settings.PCM.ChannelCount != 2)
            //    throw new Exception("ChannelCount must be 2.");

            channels = Settings.PCM.ChannelCount;

            // flake_validate_params

            //_path = path;

            if (IO == null)
            {
                throw new ArgumentNullException("IO");

            }

            _IO = IO;

            samplesBuffer = new int[Flake.MAX_BLOCKSIZE * (channels == 2 ? 4 : channels)];
            residualBuffer = new int[Flake.MAX_BLOCKSIZE * (channels == 2 ? 10 : channels + 1)];
            windowBuffer = new float[Flake.MAX_BLOCKSIZE * 2 * lpc.MAX_LPC_WINDOWS];
            windowScale = new double[lpc.MAX_LPC_WINDOWS];

            var _compressionLevel = Settings.EncoderModeIndex;
            eparams.flake_set_defaults(_compressionLevel);

            crc8 = new Crc8();
            frame = new FlacFrame(channels * 2);
        }
示例#39
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);
				}
			}
		}
示例#40
0
 unsafe void encode_residual_pass1(FlacFrame frame, int ch, int best_window)
 {
     int max_prediction_order = eparams.max_prediction_order;
     int max_fixed_order = eparams.max_fixed_order;
     int min_fixed_order = eparams.min_fixed_order;
     int lpc_min_precision_search = eparams.lpc_min_precision_search;
     int lpc_max_precision_search = eparams.lpc_max_precision_search;
     int max_partition_order = eparams.max_partition_order;
     int estimation_depth = eparams.estimation_depth;
     var development_mode = eparams.development_mode;
     eparams.min_fixed_order = 2;
     eparams.max_fixed_order = 2;
     eparams.lpc_min_precision_search = eparams.lpc_max_precision_search;
     eparams.max_prediction_order = Math.Min(eparams.max_prediction_order, Math.Max(eparams.min_prediction_order, 8));
     eparams.estimation_depth = 1;
     eparams.development_mode = Math.Min(eparams.development_mode, -1);
     encode_residual(frame, ch, eparams.prediction_type, OrderMethod.Akaike, 1, best_window);
     eparams.min_fixed_order = min_fixed_order;
     eparams.max_fixed_order = max_fixed_order;
     eparams.max_prediction_order = max_prediction_order;
     eparams.lpc_min_precision_search = lpc_min_precision_search;
     eparams.lpc_max_precision_search = lpc_max_precision_search;
     eparams.max_partition_order = max_partition_order;
     eparams.estimation_depth = estimation_depth;
     eparams.development_mode = development_mode;
 }