Пример #1
0
        // deserializing
        protected void LoadFromReader(BinaryReader reader)
        {
            int count;

            voice0 = new Voice(reader);
            voice1 = new Voice(reader);
            voice2 = new Voice(reader);

            voice0.wave.UpdateAfterLoad(voice0, voice1, voice2);
            voice1.wave.UpdateAfterLoad(voice0, voice1, voice2);
            voice2.wave.UpdateAfterLoad(voice0, voice1, voice2);

            filter = new Filter(reader);

            extfilt = new ExternalFilter(reader);

            bus_value         = reader.ReadInt32();
            bus_value_ttl     = reader.ReadInt32();
            clock_frequency   = reader.ReadDouble();
            ext_in            = reader.ReadInt32();
            sampling          = (SIDDefs.sampling_method)reader.ReadInt16();
            cycles_per_sample = reader.ReadInt32();
            sample_offset     = reader.ReadInt32();
            sample_index      = reader.ReadInt32();
            sample_prev       = reader.ReadInt16();
            fir_N             = reader.ReadInt32();
            fir_RES           = reader.ReadInt32();

            count = reader.ReadInt32();
            if (count == -1)
            {
                sample = null;
            }
            else
            {
                sample = new short[count];
                for (int i = 0; i < count; i++)
                {
                    sample[i] = reader.ReadInt16();
                }
            }

            count = reader.ReadInt32();
            if (count == -1)
            {
                fir = null;
            }
            else
            {
                fir = new short[count];
                for (int i = 0; i < count; i++)
                {
                    fir[i] = reader.ReadInt16();
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Setting of SID sampling parameters.
        /// Use a clock freqency of 985248Hz for PAL C64, 1022730Hz for NTSC C64. The
        /// default end of passband frequency is pass_freq = 0.9*sample_freq/2 for
        /// sample frequencies up to ~ 44.1kHz, and 20kHz for higher sample
        /// frequencies.
        ///
        /// For resampling, the ratio between the clock frequency and the sample
        /// frequency is limited as follows: 125*clock_freq/sample_freq < 16384 E.g.
        /// provided a clock frequency of ~ 1MHz, the sample frequency can not be set
        /// lower than ~ 8kHz. A lower sample frequency would make the resampling
        /// code overfill its 16k sample ring buffer.
        ///
        /// The end of passband frequency is also limited: pass_freq <=
        /// 0.9*sample_freq/2
        ///
        /// E.g. for a 44.1kHz sampling rate the end of passband frequency is limited
        /// to slightly below 20kHz. This constraint ensures that the FIR table is
        /// not overfilled.
        /// </summary>
        /// <param name="clock_freq"></param>
        /// <param name="method"></param>
        /// <param name="sample_freq"></param>
        /// <param name="pass_freq"></param>
        /// <param name="filter_scale"></param>
        /// <returns></returns>
        public bool set_sampling_parameters(double clock_freq, SIDDefs.sampling_method method, double sample_freq, double pass_freq, double filter_scale)
        {
            // Check resampling constraints
            if (method == SIDDefs.sampling_method.SAMPLE_RESAMPLE_INTERPOLATE || method == SIDDefs.sampling_method.SAMPLE_RESAMPLE_FAST)
            {
                // Check whether the sample ring buffer would overfill.
                if (FIR_N * clock_freq / sample_freq >= RINGSIZE)
                {
                    return(false);
                }
            }
            // The default passband limit is 0.9*sample_freq/2 for sample
            // frequencies below ~ 44.1kHz, and 20kHz for higher sample
            // frequencies
            if (pass_freq < 0)
            {
                pass_freq = 20000;
                if (2 * pass_freq / sample_freq >= 0.9)
                {
                    pass_freq = 0.9 * sample_freq / 2;
                }
            }
            // Check whether the FIR table would overfill
            else if (pass_freq > 0.9 * sample_freq / 2)
            {
                return(false);
            }

            // The filter scaling is only included to avoid clipping, so keep it sane.
            if (filter_scale < 0.9 || filter_scale > 1.0)
            {
                return(false);
            }

            // Set the external filter to the pass freq
            extfilt.set_sampling_parameter(pass_freq);
            clock_frequency = clock_freq;
            sampling        = method;

            cycles_per_sample = (int)(clock_freq / sample_freq * (1 << FIXP_SHIFT) + 0.5);

            sample_offset = 0;
            sample_prev   = 0;

            // FIR initialization is only necessary for resampling
            if (method != SIDDefs.sampling_method.SAMPLE_RESAMPLE_INTERPOLATE && method != SIDDefs.sampling_method.SAMPLE_RESAMPLE_FAST)
            {
                sample = null;
                fir    = null;
                return(true);
            }

            double pi = 3.1415926535897932385;

            // 16 bits -> -96dB stopband attenuation
            double A = -20 * Math.Log10(1.0 / (1 << 16));
            // A fraction of the bandwidth is allocated to the transition band,
            double dw = (1 - 2 * pass_freq / sample_freq) * pi;
            // The cutoff frequency is midway through the transition band.
            double wc = (2 * pass_freq / sample_freq + 1) * pi / 2;

            // For calculation of beta and N see the reference for the kaiserord
            // function in the MATLAB Signal Processing Toolbox:
            // http://www.mathworks.com/access/helpdesk/help/toolbox/signal/kaiserord.html
            double beta   = 0.1102 * (A - 8.7);
            double I0beta = I0(beta);

            // The filter order will maximally be 124 with the current constraints.
            // N >= (96.33 - 7.95)/(2.285*0.1*pi) -> N >= 123
            // The filter order is equal to the number of zero crossings, i.e.
            // it should be an even number (sinc is symmetric about x = 0).
            int N = (int)((A - 7.95) / (2.285 * dw) + 0.5);

            N += N & 1;

            double f_samples_per_cycle = sample_freq / clock_freq;
            double f_cycles_per_sample = clock_freq / sample_freq;

            // The filter length is equal to the filter order + 1.
            // The filter length must be an odd number (sinc is symmetric about x =
            // 0).
            fir_N  = (int)(N * f_cycles_per_sample) + 1;
            fir_N |= 1;

            // We clamp the filter table resolution to 2^n, making the fixpoint
            // sample_offset a whole multiple of the filter table resolution.
            int res = method == SIDDefs.sampling_method.SAMPLE_RESAMPLE_INTERPOLATE ? FIR_RES_INTERPOLATE : FIR_RES_FAST;
            int n   = (int)Math.Ceiling(Math.Log(res / f_cycles_per_sample) / Math.Log((double)2));

            fir_RES = 1 << n;

            // Allocate memory for FIR tables.
            fir = null;
            fir = new short[fir_N * fir_RES];

            // Calculate fir_RES FIR tables for linear interpolation.
            for (int i = 0; i < fir_RES; i++)
            {
                int    fir_offset = i * fir_N + fir_N / 2;
                double j_offset   = (double)(i) / fir_RES;
                // Calculate FIR table. This is the sinc function, weighted by the
                // Kaiser window.
                for (int j = -fir_N / 2; j <= fir_N / 2; j++)
                {
                    double jx = j - j_offset;
                    double wt = wc * jx / f_cycles_per_sample;
                    double temp = jx / ((double)fir_N / 2d);
                    double Kaiser = Math.Abs(temp) <= 1 ? I0(beta * Math.Sqrt(1 - temp * temp)) / I0beta : 0;
                    double sincwt = Math.Abs(wt) >= 1e-6 ? Math.Sin(wt) / wt : 1; double val = (1 << FIR_SHIFT) * filter_scale * f_samples_per_cycle * wc / pi * sincwt * Kaiser;
                    fir[fir_offset + j] = (short)(val + 0.5);
                }
            }

            // Allocate sample buffer.
            if ((sample == null))
            {
                sample = new short[RINGSIZE * 2];
            }
            // Clear sample buffer.
            for (int j = 0; j < RINGSIZE * 2; j++)
            {
                sample[j] = 0;
            }
            sample_index = 0;

            return(true);
        }