예제 #1
0
        /* 7th order interpolation.
         * Returns number of samples processed (usually fluid_bufsize but could be
         * smaller if end of sample occurs).
         */
        public static int fluid_dsp_float_interpolate_7th_order(fluid_voice voice)
        {
            ulong dsp_phase = voice.phase;
            ulong dsp_phase_incr;//, end_phase;

            float[] dsp_data     = voice.sample.Data;
            float[] dsp_buf      = voice.dsp_buf;
            float   dsp_amp      = voice.amp;
            float   dsp_amp_incr = voice.amp_incr;
            uint    dsp_i        = 0;
            uint    dsp_phase_index;
            uint    start_index, end_index;
            float   start_points0;
            float   start_points1;
            float   start_points2;
            float   end_points0;
            float   end_points1;
            float   end_points2;

            float[] coeffs;
            bool    looping;
            int     fluid_bufsize = voice.synth.FLUID_BUFSIZE;

            /* Convert playback "speed" floating point value to phase index/fract
             * fluid_phase_set_float(dsp_phase_incr, voice.phase_incr);
             */
            dsp_phase_incr = (((ulong)voice.phase_incr) << 32) |
                             (uint)(((double)(voice.phase_incr) - (int)(voice.phase_incr)) * (double)FLUID_FRACT_MAX);

            /* add 1/2 sample to dsp_phase since 7th order interpolation is centered on
             * the 4th sample point
             * fluid_phase_incr(dsp_phase, (ulong)0x80000000);
             */
            dsp_phase += 0x80000000;

            /* voice is currently looping? */
            looping =
                ((voice.gens[(int)fluid_gen_type.GEN_SAMPLEMODE].Val == (double)fluid_loop.FLUID_LOOP_DURING_RELEASE)
                 ||
                 (voice.gens[(int)fluid_gen_type.GEN_SAMPLEMODE].Val == (double)fluid_loop.FLUID_LOOP_UNTIL_RELEASE &&
                  voice.volenv_section < fluid_voice_envelope_index.FLUID_VOICE_ENVRELEASE));
            //Debug.LogFormat("looping:{0} ", looping);

            /* last index before 7th interpolation point must be specially handled */
            end_index = (uint)(looping ? voice.loopend - 1 : voice.end) - 3;

            if (voice.has_looped)  /* set start_index and start point if looped or not */
            {
                start_index   = (uint)voice.loopstart;
                start_points0 = dsp_data[voice.loopend - 1];
                start_points1 = dsp_data[voice.loopend - 2];
                start_points2 = dsp_data[voice.loopend - 3];
            }
            else
            {
                start_index   = (uint)voice.start;
                start_points0 = dsp_data[voice.start];   /* just duplicate the start point */
                start_points1 = start_points0;
                start_points2 = start_points0;
            }

            /* get the 3 points off the end (loop start if looping, duplicate point if end) */
            if (looping)
            {
                end_points0 = dsp_data[voice.loopstart];
                end_points1 = dsp_data[voice.loopstart + 1];
                end_points2 = dsp_data[voice.loopstart + 2];
            }
            else
            {
                end_points0 = dsp_data[voice.end];
                end_points1 = end_points0;
                end_points2 = end_points0;
            }

            while (true)
            {
                //dsp_phase_index = fluid_phase_index(dsp_phase);
                dsp_phase_index = ((uint)((dsp_phase) >> 32));

                /* interpolate first sample point (start or loop start) if needed */
                for (; dsp_phase_index == start_index && dsp_i < fluid_bufsize; dsp_i++)
                {
                    uint tablerow = ((uint)(((uint)((dsp_phase) & 0xFFFFFFFF)) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT);

                    coeffs = sinc_table7[tablerow];

                    dsp_buf[dsp_i] = dsp_amp
                                     * (coeffs[0] * (float)start_points2
                                        + coeffs[1] * (float)start_points1
                                        + coeffs[2] * (float)start_points0
                                        + coeffs[3] * (float)dsp_data[dsp_phase_index]
                                        + coeffs[4] * (float)dsp_data[dsp_phase_index + 1]
                                        + coeffs[5] * (float)dsp_data[dsp_phase_index + 2]
                                        + coeffs[6] * (float)dsp_data[dsp_phase_index + 3]);

                    /* increment phase and amplitude */
                    //fluid_phase_incr(dsp_phase, dsp_phase_incr);
                    dsp_phase += dsp_phase_incr;

                    //dsp_phase_index = fluid_phase_index(dsp_phase);
                    dsp_phase_index = ((uint)((dsp_phase) >> 32));

                    dsp_amp += dsp_amp_incr;
                }

                start_index++;

                /* interpolate 2nd to first sample point (start or loop start) if needed */
                for (; dsp_phase_index == start_index && dsp_i < fluid_bufsize; dsp_i++)
                {
                    uint tablerow = ((uint)(((uint)((dsp_phase) & 0xFFFFFFFF)) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT);
                    coeffs = sinc_table7[tablerow];

                    dsp_buf[dsp_i] = dsp_amp
                                     * (coeffs[0] * (float)start_points1
                                        + coeffs[1] * (float)start_points0
                                        + coeffs[2] * (float)dsp_data[dsp_phase_index - 1]
                                        + coeffs[3] * (float)dsp_data[dsp_phase_index]
                                        + coeffs[4] * (float)dsp_data[dsp_phase_index + 1]
                                        + coeffs[5] * (float)dsp_data[dsp_phase_index + 2]
                                        + coeffs[6] * (float)dsp_data[dsp_phase_index + 3]);

                    /* increment phase and amplitude */
                    //fluid_phase_incr(dsp_phase, dsp_phase_incr);
                    dsp_phase += dsp_phase_incr;

                    //dsp_phase_index = fluid_phase_index(dsp_phase);
                    dsp_phase_index = ((uint)((dsp_phase) >> 32));

                    dsp_amp += dsp_amp_incr;
                }

                start_index++;

                /* interpolate 3rd to first sample point (start or loop start) if needed */
                for (; dsp_phase_index == start_index && dsp_i < fluid_bufsize; dsp_i++)
                {
                    uint tablerow = ((uint)(((uint)((dsp_phase) & 0xFFFFFFFF)) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT);
                    coeffs = sinc_table7[tablerow];

                    dsp_buf[dsp_i] = dsp_amp
                                     * (coeffs[0] * (float)start_points0
                                        + coeffs[1] * (float)dsp_data[dsp_phase_index - 2]
                                        + coeffs[2] * (float)dsp_data[dsp_phase_index - 1]
                                        + coeffs[3] * (float)dsp_data[dsp_phase_index]
                                        + coeffs[4] * (float)dsp_data[dsp_phase_index + 1]
                                        + coeffs[5] * (float)dsp_data[dsp_phase_index + 2]
                                        + coeffs[6] * (float)dsp_data[dsp_phase_index + 3]);

                    /* increment phase and amplitude */
                    //fluid_phase_incr(dsp_phase, dsp_phase_incr);
                    dsp_phase += dsp_phase_incr;

                    //dsp_phase_index = fluid_phase_index(dsp_phase);
                    dsp_phase_index = ((uint)((dsp_phase) >> 32));

                    dsp_amp += dsp_amp_incr;
                }

                start_index -= 2;   /* set back to original start index */


                /* interpolate the sequence of sample points */
                for (; dsp_i < fluid_bufsize && dsp_phase_index <= end_index; dsp_i++)
                {
                    uint tablerow = ((uint)(((uint)((dsp_phase) & 0xFFFFFFFF)) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT);
                    coeffs = sinc_table7[tablerow];

                    dsp_buf[dsp_i] = dsp_amp
                                     * (coeffs[0] * (float)dsp_data[dsp_phase_index - 3]
                                        + coeffs[1] * (float)dsp_data[dsp_phase_index - 2]
                                        + coeffs[2] * (float)dsp_data[dsp_phase_index - 1]
                                        + coeffs[3] * (float)dsp_data[dsp_phase_index]
                                        + coeffs[4] * (float)dsp_data[dsp_phase_index + 1]
                                        + coeffs[5] * (float)dsp_data[dsp_phase_index + 2]
                                        + coeffs[6] * (float)dsp_data[dsp_phase_index + 3]);

                    /* increment phase and amplitude */
                    //fluid_phase_incr(dsp_phase, dsp_phase_incr);
                    dsp_phase += dsp_phase_incr;

                    //dsp_phase_index = fluid_phase_index(dsp_phase);
                    dsp_phase_index = ((uint)((dsp_phase) >> 32));

                    dsp_amp += dsp_amp_incr;
                }

                /* break out if buffer filled */
                if (dsp_i >= fluid_bufsize)
                {
                    break;
                }

                end_index++;    /* we're now interpolating the 3rd to last point */

                /* interpolate within 3rd to last point */
                for (; dsp_phase_index <= end_index && dsp_i < fluid_bufsize; dsp_i++)
                {
                    uint tablerow = ((uint)(((uint)((dsp_phase) & 0xFFFFFFFF)) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT);
                    coeffs = sinc_table7[tablerow];

                    dsp_buf[dsp_i] = dsp_amp
                                     * (coeffs[0] * (float)dsp_data[dsp_phase_index - 3]
                                        + coeffs[1] * (float)dsp_data[dsp_phase_index - 2]
                                        + coeffs[2] * (float)dsp_data[dsp_phase_index - 1]
                                        + coeffs[3] * (float)dsp_data[dsp_phase_index]
                                        + coeffs[4] * (float)dsp_data[dsp_phase_index + 1]
                                        + coeffs[5] * (float)dsp_data[dsp_phase_index + 2]
                                        + coeffs[6] * (float)end_points0);

                    /* increment phase and amplitude */
                    //fluid_phase_incr(dsp_phase, dsp_phase_incr);
                    dsp_phase += dsp_phase_incr;

                    //dsp_phase_index = fluid_phase_index(dsp_phase);
                    dsp_phase_index = ((uint)((dsp_phase) >> 32));

                    dsp_amp += dsp_amp_incr;
                }

                end_index++;    /* we're now interpolating the 2nd to last point */

                /* interpolate within 2nd to last point */
                for (; dsp_phase_index <= end_index && dsp_i < fluid_bufsize; dsp_i++)
                {
                    uint tablerow = ((uint)(((uint)((dsp_phase) & 0xFFFFFFFF)) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT);
                    coeffs = sinc_table7[tablerow];

                    dsp_buf[dsp_i] = dsp_amp
                                     * (coeffs[0] * (float)dsp_data[dsp_phase_index - 3]
                                        + coeffs[1] * (float)dsp_data[dsp_phase_index - 2]
                                        + coeffs[2] * (float)dsp_data[dsp_phase_index - 1]
                                        + coeffs[3] * (float)dsp_data[dsp_phase_index]
                                        + coeffs[4] * (float)dsp_data[dsp_phase_index + 1]
                                        + coeffs[5] * (float)end_points0
                                        + coeffs[6] * (float)end_points1);

                    /* increment phase and amplitude */
                    //fluid_phase_incr(dsp_phase, dsp_phase_incr);
                    dsp_phase += dsp_phase_incr;

                    //dsp_phase_index = fluid_phase_index(dsp_phase);
                    dsp_phase_index = ((uint)((dsp_phase) >> 32));

                    dsp_amp += dsp_amp_incr;
                }

                end_index++;    /* we're now interpolating the last point */

                /* interpolate within last point */
                for (; dsp_phase_index <= end_index && dsp_i < fluid_bufsize; dsp_i++)
                {
                    uint tablerow = ((uint)(((uint)((dsp_phase) & 0xFFFFFFFF)) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT);
                    coeffs = sinc_table7[tablerow];

                    dsp_buf[dsp_i] = dsp_amp
                                     * (coeffs[0] * (float)dsp_data[dsp_phase_index - 3]
                                        + coeffs[1] * (float)dsp_data[dsp_phase_index - 2]
                                        + coeffs[2] * (float)dsp_data[dsp_phase_index - 1]
                                        + coeffs[3] * (float)dsp_data[dsp_phase_index]
                                        + coeffs[4] * (float)end_points0
                                        + coeffs[5] * (float)end_points1
                                        + coeffs[6] * (float)end_points2);

                    /* increment phase and amplitude */
                    //fluid_phase_incr(dsp_phase, dsp_phase_incr);
                    dsp_phase += dsp_phase_incr;

                    //dsp_phase_index = fluid_phase_index(dsp_phase);
                    dsp_phase_index = ((uint)((dsp_phase) >> 32));

                    dsp_amp += dsp_amp_incr;
                }

                if (!looping)
                {
                    break;              /* break out if not looping (end of sample) */
                }
                /* go back to loop start */
                if (dsp_phase_index > end_index)
                {
                    //fluid_phase_sub_int(dsp_phase, voice.loopend - voice.loopstart);
                    dsp_phase -= ((ulong)(voice.loopend - voice.loopstart)) << 32;

                    if (!voice.has_looped)
                    {
                        //Debug.LogFormat("has_looped end_index:{0} ", end_index);
                        voice.has_looped = true;
                        start_index      = (uint)voice.loopstart;
                        start_points0    = dsp_data[voice.loopend - 1];
                        start_points1    = dsp_data[voice.loopend - 2];
                        start_points2    = dsp_data[voice.loopend - 3];
                    }
                }

                /* break out if filled buffer */
                if (dsp_i >= fluid_bufsize)
                {
                    break;
                }

                end_index -= 3; /* set end back to 4th to last sample point */
            }

            /* sub 1/2 sample from dsp_phase since 7th order interpolation is centered on
             * the 4th sample point (correct back to real value)
             * Subtract b from a (both are fluid_phase_t).
             * #define fluid_phase_decr(a, b)  a -= b
             * fluid_phase_decr(dsp_phase, (ulong)0x80000000);
             */
            dsp_phase  -= 0x80000000;
            voice.phase = dsp_phase;
            voice.amp   = dsp_amp;

            return((int)dsp_i);
        }
예제 #2
0
        /* 4th order (cubic) interpolation.
         * Returns number of samples processed (usually fluid_bufsize but could be
         * smaller if end of sample occurs).
         */
        public static int fluid_dsp_float_interpolate_4th_order(fluid_voice voice)
        {
            ulong dsp_phase = voice.phase;
            ulong dsp_phase_incr;//, end_phase;

            float[] dsp_data     = voice.sample.Data;
            float[] dsp_buf      = voice.dsp_buf;
            float   dsp_amp      = voice.amp;
            float   dsp_amp_incr = voice.amp_incr;
            uint    dsp_i        = 0;
            uint    dsp_phase_index;
            uint    start_index, end_index;
            float   start_point, end_point1, end_point2;

            float[] coeffs;
            bool    looping;
            int     fluid_bufsize = voice.synth.FLUID_BUFSIZE;

            /* Convert playback "speed" floating point value to phase index/fract */
            //fluid_phase_set_float(dsp_phase_incr, voice.phase_incr);
            dsp_phase_incr = (((ulong)voice.phase_incr) << 32) |
                             (uint)(((double)(voice.phase_incr) - (int)(voice.phase_incr)) * (double)FLUID_FRACT_MAX);

            /* voice is currently looping? */
            looping =
                ((voice.gens[(int)fluid_gen_type.GEN_SAMPLEMODE].Val == (double)fluid_loop.FLUID_LOOP_DURING_RELEASE)
                 ||
                 (voice.gens[(int)fluid_gen_type.GEN_SAMPLEMODE].Val == (double)fluid_loop.FLUID_LOOP_UNTIL_RELEASE &&
                  voice.volenv_section < fluid_voice_envelope_index.FLUID_VOICE_ENVRELEASE));
            //Debug.LogFormat("looping:{0} ", looping);

            /* last index before 4th interpolation point must be specially handled */
            end_index = (uint)(looping ? voice.loopend - 1 : voice.end) - 2;

            if (voice.has_looped)  /* set start_index and start point if looped or not */
            {
                start_index = (uint)voice.loopstart;
                start_point = dsp_data[voice.loopend - 1]; /* last point in loop (wrap around) */
            }
            else
            {
                start_index = (uint)voice.start;
                start_point = dsp_data[voice.start];   /* just duplicate the point */
            }

            /* get points off the end (loop start if looping, duplicate point if end) */
            if (looping)
            {
                end_point1 = dsp_data[voice.loopstart];
                end_point2 = dsp_data[voice.loopstart + 1];
            }
            else
            {
                end_point1 = dsp_data[voice.end];
                end_point2 = end_point1;
            }

            while (true)
            {
                //dsp_phase_index = fluid_phase_index(dsp_phase);
                dsp_phase_index = ((uint)((dsp_phase) >> 32));

                /* interpolate first sample point (start or loop start) if needed */
                for (; dsp_phase_index == start_index && dsp_i < fluid_bufsize; dsp_i++)
                {
                    uint tablerow = (((uint)((dsp_phase) & 0xFFFFFFFF)) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT;

                    coeffs         = interp_coeff[tablerow];
                    dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * start_point
                                                + coeffs[1] * dsp_data[dsp_phase_index]
                                                + coeffs[2] * dsp_data[dsp_phase_index + 1]
                                                + coeffs[3] * dsp_data[dsp_phase_index + 2]);

                    /* increment phase and amplitude */
                    //fluid_phase_incr(dsp_phase, dsp_phase_incr);
                    dsp_phase += dsp_phase_incr;

                    //dsp_phase_index = fluid_phase_index(dsp_phase);
                    dsp_phase_index = ((uint)((dsp_phase) >> 32));

                    dsp_amp += dsp_amp_incr;
                }

                /* interpolate the sequence of sample points */
                for (; dsp_i < fluid_bufsize && dsp_phase_index <= end_index; dsp_i++)
                {
                    uint tablerow = ((uint)(((uint)((dsp_phase) & 0xFFFFFFFF)) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT);

                    coeffs         = interp_coeff[tablerow];
                    dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index - 1]
                                                + coeffs[1] * dsp_data[dsp_phase_index]
                                                + coeffs[2] * dsp_data[dsp_phase_index + 1]
                                                + coeffs[3] * dsp_data[dsp_phase_index + 2]);

                    /* increment phase and amplitude */
                    //fluid_phase_incr(dsp_phase, dsp_phase_incr);
                    dsp_phase += dsp_phase_incr;

                    //dsp_phase_index = fluid_phase_index(dsp_phase);
                    dsp_phase_index = ((uint)((dsp_phase) >> 32));

                    dsp_amp += dsp_amp_incr;
                }

                /* break out if buffer filled */
                if (dsp_i >= fluid_bufsize)
                {
                    break;
                }

                end_index++;    /* we're now interpolating the 2nd to last point */

                /* interpolate within 2nd to last point */
                for (; dsp_phase_index <= end_index && dsp_i < fluid_bufsize; dsp_i++)
                {
                    uint tablerow = ((uint)(((uint)((dsp_phase) & 0xFFFFFFFF)) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT);
                    coeffs         = interp_coeff[tablerow];
                    dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index - 1]
                                                + coeffs[1] * dsp_data[dsp_phase_index]
                                                + coeffs[2] * dsp_data[dsp_phase_index + 1]
                                                + coeffs[3] * end_point1);

                    /* increment phase and amplitude */
                    //fluid_phase_incr(dsp_phase, dsp_phase_incr);
                    dsp_phase += dsp_phase_incr;

                    //dsp_phase_index = fluid_phase_index(dsp_phase);
                    dsp_phase_index = ((uint)((dsp_phase) >> 32));

                    dsp_amp += dsp_amp_incr;
                }

                end_index++;    /* we're now interpolating the last point */

                /* interpolate within the last point */
                for (; dsp_phase_index <= end_index && dsp_i < fluid_bufsize; dsp_i++)
                {
                    uint tablerow = ((uint)(((uint)((dsp_phase) & 0xFFFFFFFF)) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT);
                    coeffs         = interp_coeff[tablerow];
                    dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index - 1]
                                                + coeffs[1] * dsp_data[dsp_phase_index]
                                                + coeffs[2] * end_point1
                                                + coeffs[3] * end_point2);

                    /* increment phase and amplitude */
                    //fluid_phase_incr(dsp_phase, dsp_phase_incr);
                    dsp_phase += dsp_phase_incr;

                    //dsp_phase_index = fluid_phase_index(dsp_phase);
                    dsp_phase_index = ((uint)((dsp_phase) >> 32));

                    dsp_amp += dsp_amp_incr;
                }

                if (!looping)
                {
                    break;              /* break out if not looping (end of sample) */
                }
                /* go back to loop start */
                if (dsp_phase_index > end_index)
                {
                    //fluid_phase_sub_int(dsp_phase, voice.loopend - voice.loopstart);
                    dsp_phase -= ((ulong)(voice.loopend - voice.loopstart)) << 32;

                    if (!voice.has_looped)
                    {
                        //Debug.LogFormat("has_looped end_index:{0} ", end_index);
                        voice.has_looped = true;
                        start_index      = (uint)voice.loopstart;
                        start_point      = dsp_data[voice.loopend - 1];
                    }
                }

                /* break out if filled buffer */
                if (dsp_i >= fluid_bufsize)
                {
                    break;
                }

                end_index -= 2; /* set end back to third to last sample point */
            }

            voice.phase = dsp_phase;
            voice.amp   = dsp_amp;

            return((int)dsp_i);
        }
예제 #3
0
        // No interpolation. Just take the sample, which is closest to the playback pointer.
        //  Questionable quality, but very efficient.
        public static int fluid_dsp_float_interpolate_none(fluid_voice voice)
        {
            ulong dsp_phase = voice.phase;
            ulong dsp_phase_incr;

            float[] dsp_data     = voice.sample.Data;
            float[] dsp_buf      = voice.dsp_buf;
            float   dsp_amp      = voice.amp;
            float   dsp_amp_incr = voice.amp_incr;
            uint    dsp_i        = 0;
            uint    dsp_phase_index;
            uint    end_index;
            bool    looping;
            int     fluid_bufsize = voice.synth.FLUID_BUFSIZE;

            //Debug.Log("fluid_dsp_float_interpolate_none");

            /* Convert playback "speed" floating point value to phase index/fract
             * Sets the phase a to a phase increment given in b.
             * For example, assume b is 0.9. After setting a to it, adding a to the playing pointer will advance it by 0.9 samples.
             #define fluid_phase_set_float(a, b)  (a) = (((unsigned long long)(b)) << 32) | (uint32) (((double)(b) - (int)(b)) * (double)FLUID_FRACT_MAX)
             * fluid_phase_set_float (dsp_phase_incr, phase_incr);
             */
            dsp_phase_incr = (((ulong)voice.phase_incr) << 32) |
                             (uint)(((double)(voice.phase_incr) - (int)(voice.phase_incr)) * (double)FLUID_FRACT_MAX);

            /* voice is currently looping?
             * looping = _SAMPLEMODE(voice) == FLUID_LOOP_DURING_RELEASE || (_SAMPLEMODE(voice) == FLUID_LOOP_UNTIL_RELEASE && volenv_section < FLUID_VOICE_ENVRELEASE);
             */
            looping =
                ((voice.gens[(int)fluid_gen_type.GEN_SAMPLEMODE].Val == (double)fluid_loop.FLUID_LOOP_DURING_RELEASE)
                 ||
                 (voice.gens[(int)fluid_gen_type.GEN_SAMPLEMODE].Val == (double)fluid_loop.FLUID_LOOP_UNTIL_RELEASE &&
                  voice.volenv_section < fluid_voice_envelope_index.FLUID_VOICE_ENVRELEASE));

            end_index = looping ? (uint)voice.loopend - 1 : (uint)voice.end;

            //if (looping)Debug.LogFormat("   looping at end_index:{0} ", end_index);

            while (true)
            {
                /*
                 * Get the phase index with fractional rounding
                 #define fluid_phase_index_round(_x)  ((uint)(((_x) + 0x80000000) >> 32))
                 * dsp_phase_index = fluid_phase_index_round(dsp_phase);	/* round to nearest point
                 */

                dsp_phase_index = ((uint)((dsp_phase + 0x80000000) >> 32));

                //Debug.LogFormat("   fluid_dsp_float_interpolate_none dsp_i:{0} dsp_phase_index:{1}  end_index:{2} loopend:{3} end:{4} synth.fluid_bufsize:{5} sample.Data.Length:{6}",
                //    dsp_i, dsp_phase_index, end_index, loopend, end, synth.fluid_bufsize, sample.Data.Length);

                /* interpolate sequence of sample points */
                for (; dsp_i < fluid_bufsize && dsp_phase_index <= end_index; dsp_i++)
                {
                    //Debug.LogFormat("dsp_i:{0} phase_incr:{1,0:F7}  dsp_phase_index:{2} amp:{3,0:F7}  dsp_buf:{4,0:F7} phase:{5}",dsp_i, dsp_phase_incr, dsp_phase_index, dsp_amp, dsp_buf[dsp_i], dsp_phase);

                    dsp_buf[dsp_i] = dsp_amp * dsp_data[dsp_phase_index];

                    // increment phase and amplitude
                    // Advance a by a step of b (both are ulong).
                    // #define fluid_phase_incr(a, b)  a += b
                    // fluid_phase_incr (dsp_phase, dsp_phase_incr); //

                    dsp_phase += dsp_phase_incr;

                    //dsp_phase_index = fluid_phase_index_round(dsp_phase);	/* round to nearest point */
                    dsp_phase_index = ((uint)((dsp_phase + 0x80000000) >> 32));

                    dsp_amp += dsp_amp_incr;
                }

                /* break out if not looping (buffer may not be full) */
                if (!looping)
                {
                    break;
                }

                /* go back to loop start */
                if (dsp_phase_index > end_index)
                {
                    // Purpose:
                    // Subtract b samples from a.
                    // #define fluid_phase_sub_int(a, b)  ((a) -= (unsigned long long)(b) << 32)
                    // fluid_phase_sub_int (dsp_phase, loopend - loopstart);
                    dsp_phase       -= ((ulong)(voice.loopend - voice.loopstart)) << 32;
                    voice.has_looped = true;
                    //Debug.LogFormat("   return to start:{0} end_index:{1} ", ((uint)((dsp_phase + 0x80000000) >> 32)), end_index);
                }

                /* break out if filled buffer */
                if (dsp_i >= fluid_bufsize)
                {
                    break;
                }
            }

            voice.phase = dsp_phase;
            voice.amp   = dsp_amp;

            return((int)dsp_i);
        }
예제 #4
0
        /* Straight line interpolation.
         * Returns number of samples processed (usually fluid_bufsize but could be
         * smaller if end of sample occurs).
         */
        public static int fluid_dsp_float_interpolate_linear(fluid_voice voice)
        {
            ulong dsp_phase = voice.phase;
            ulong dsp_phase_incr;

            float[] dsp_data     = voice.sample.Data;
            float[] dsp_buf      = voice.dsp_buf;
            float   dsp_amp      = voice.amp;
            float   dsp_amp_incr = voice.amp_incr;
            uint    dsp_i        = 0;
            uint    dsp_phase_index;
            uint    end_index;
            float   point;

            float[] coeffs;
            bool    looping;
            int     fluid_bufsize = voice.synth.FLUID_BUFSIZE;

            //Debug.Log("fluid_dsp_float_interpolate_linear");

            /* Convert playback "speed" floating point value to phase index/fract
             * fluid_phase_set_float (dsp_phase_incr, voice->phase_incr);
             */
            dsp_phase_incr = (((ulong)voice.phase_incr) << 32) |
                             (uint)(((double)(voice.phase_incr) - (int)(voice.phase_incr)) * (double)FLUID_FRACT_MAX);


            /* voice is currently looping? */
            looping =
                ((voice.gens[(int)fluid_gen_type.GEN_SAMPLEMODE].Val == (double)fluid_loop.FLUID_LOOP_DURING_RELEASE)
                 ||
                 (voice.gens[(int)fluid_gen_type.GEN_SAMPLEMODE].Val == (double)fluid_loop.FLUID_LOOP_UNTIL_RELEASE &&
                  voice.volenv_section < fluid_voice_envelope_index.FLUID_VOICE_ENVRELEASE));
            //Debug.LogFormat("looping:{0} ", looping);

            /* last index before 2nd interpolation point must be specially handled */
            end_index = (looping ? (uint)voice.loopend - 1 : (uint)voice.end) - 1;

            /* 2nd interpolation point to use at end of loop or sample */
            point = looping ? dsp_data[voice.loopstart] : dsp_data[voice.end];          /* duplicate end for samples no longer looping */

            while (true)
            {
                /* Purpose: Return the index and the fractional part, respectively.
                 #define fluid_phase_index(_x)  ((unsigned int)((_x) >> 32))
                 * dsp_phase_index = fluid_phase_index(dsp_phase);
                 */
                dsp_phase_index = ((uint)((dsp_phase) >> 32));

                /* interpolate the sequence of sample points */
                for (; dsp_i < fluid_bufsize && dsp_phase_index <= end_index; dsp_i++)
                {
                    /*Purpose:
                     * Takes the fractional part of the argument phase and
                     * calculates the corresponding position in the interpolation table.
                     * The fractional position of the playing pointer is calculated with a quite high
                     * resolution(32 bits). It would be unpractical to keep a set of interpolation
                     * coefficients for each possible fractional part...
                     #define fluid_phase_fract(_x)  ((uint32)((_x) & 0xFFFFFFFF))
                     #define fluid_phase_fract_to_tablerow(_x) ((unsigned int) (fluid_phase_fract(_x) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT)
                     * fluid_phase_fract_to_tablerow(dsp_phase)
                     */

                    uint tablerow = ((uint)(((uint)((dsp_phase) & 0xFFFFFFFF)) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT);

                    coeffs = interp_coeff_linear[tablerow];

                    dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index] + coeffs[1] * dsp_data[dsp_phase_index + 1]);

                    /* increment phase and amplitude */
                    //fluid_phase_incr(dsp_phase, dsp_phase_incr);
                    dsp_phase += dsp_phase_incr;

                    //dsp_phase_index = fluid_phase_index(dsp_phase);
                    dsp_phase_index = ((uint)((dsp_phase) >> 32));

                    dsp_amp += dsp_amp_incr;
                }

                /* break out if buffer filled */
                if (dsp_i >= fluid_bufsize)
                {
                    break;
                }

                end_index++;    /* we're now interpolating the last point */

                /* interpolate within last point */
                for (; dsp_phase_index <= end_index && dsp_i < fluid_bufsize; dsp_i++)
                {
                    /*Purpose:
                     * Takes the fractional part of the argument phase and
                     * calculates the corresponding position in the interpolation table.
                     * The fractional position of the playing pointer is calculated with a quite high
                     * resolution(32 bits). It would be unpractical to keep a set of interpolation
                     * coefficients for each possible fractional part...
                     #define fluid_phase_fract(_x)  ((uint32)((_x) & 0xFFFFFFFF))
                     #define fluid_phase_fract_to_tablerow(_x) ((unsigned int) (fluid_phase_fract(_x) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT)
                     */

                    //coeffs = interp_coeff_linear[fluid_phase_fract_to_tablerow(dsp_phase)];
                    uint tablerow = ((uint)(((uint)((dsp_phase) & 0xFFFFFFFF)) & FLUID_INTERP_BITS_MASK) >> FLUID_INTERP_BITS_SHIFT);
                    coeffs = interp_coeff_linear[tablerow];

                    dsp_buf[dsp_i] = dsp_amp * (coeffs[0] * dsp_data[dsp_phase_index] + coeffs[1] * point);

                    /* increment phase and amplitude */
                    //fluid_phase_incr(dsp_phase, dsp_phase_incr);
                    dsp_phase += dsp_phase_incr;

                    //dsp_phase_index = fluid_phase_index(dsp_phase);
                    dsp_phase_index = ((uint)((dsp_phase) >> 32));

                    dsp_amp += dsp_amp_incr;    /* increment amplitude */
                }

                if (!looping)
                {
                    break;              /* break out if not looping (end of sample) */
                }
                /* go back to loop start (if past */
                if (dsp_phase_index > end_index)
                {
                    /* Purpose: Subtract b samples from a.
                     #define fluid_phase_sub_int(a, b)  ((a) -= (unsigned long long)(b) << 32)
                     * fluid_phase_sub_int(dsp_phase, voice.loopend - voice.loopstart);
                     */
                    //Debug.LogFormat("has_looped end_index:{0} ", end_index);
                    dsp_phase       -= ((ulong)(voice.loopend - voice.loopstart)) << 32;
                    voice.has_looped = true;
                }

                /* break out if filled buffer */
                if (dsp_i >= fluid_bufsize)
                {
                    break;
                }

                end_index--;    /* set end back to second to last sample point */
            }

            voice.phase = dsp_phase;
            voice.amp   = dsp_amp;

            return((int)dsp_i);
        }
예제 #5
0
        public ushort SfTrans;      /* transform applied to source */

        public double fluid_mod_get_value(fluid_channel chan, fluid_voice voice)
        {
            double v1 = 0.0, v2 = 1.0;
            double range1 = 127.0, range2 = 127.0;

            if (chan == null)
            {
                return(0.0f);
            }

            /* 'special treatment' for default controller
             *
             *  Reference: SF2.01 section 8.4.2
             *
             * The GM default controller 'vel-to-filter cut off' is not clearly defined: If implemented according to the specs, the filter
             * frequency jumps between vel=63 and vel=64.  To maintain compatibility with existing sound fonts, the implementation is
             * 'hardcoded', it is impossible to implement using only one modulator otherwise.
             *
             * I assume here, that the 'intention' of the paragraph is one octave (1200 cents) filter frequency shift between vel=127 and
             * vel=64.  'amount' is (-2400), at least as long as the controller is set to default.
             *
             * Further, the 'appearance' of the modulator (source enumerator, destination enumerator, flags etc) is different from that
             * described in section 8.4.2, but it matches the definition used in several SF2.1 sound fonts (where it is used only to turn it off).
             * */
            if ((Dest == (byte)fluid_gen_type.GEN_FILTERFC) &&
                (Src2 == (int)fluid_mod_src.FLUID_MOD_VELOCITY) &&
                (Src1 == (int)fluid_mod_src.FLUID_MOD_VELOCITY) &&
                (Flags1 == ((byte)fluid_mod_flags.FLUID_MOD_GC | (byte)fluid_mod_flags.FLUID_MOD_UNIPOLAR | (byte)fluid_mod_flags.FLUID_MOD_NEGATIVE | (byte)fluid_mod_flags.FLUID_MOD_LINEAR)) &&
                (Flags2 == ((byte)fluid_mod_flags.FLUID_MOD_GC | (byte)fluid_mod_flags.FLUID_MOD_UNIPOLAR | (byte)fluid_mod_flags.FLUID_MOD_POSITIVE | (byte)fluid_mod_flags.FLUID_MOD_SWITCH)))

            {
                if (voice.vel < 64)
                {
                    return((double)Amount / 2.0);
                }
                else
                {
                    return((double)Amount * (127 - voice.vel) / 127);
                }
            }

            /* get the initial value of the first source */
            if (Src1 > 0)
            {
                if ((Flags1 & (byte)fluid_mod_flags.FLUID_MOD_CC) > 0)
                {
                    v1 = ((Src1 >= 0) && (Src1 < 128)) ? chan.cc[Src1] : 0;
                    //if (src1 == 10) Debug.Log("retreive pan " + v1);
                }
                else
                {
                    /* source 1 is one of the direct controllers */
                    switch (Src1)
                    {
                    case (int)fluid_mod_src.FLUID_MOD_NONE:             /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
                        v1 = range1;
                        break;

                    case (int)fluid_mod_src.FLUID_MOD_VELOCITY:
                        v1 = voice.vel;
                        break;

                    case (int)fluid_mod_src.FLUID_MOD_KEY:
                        v1 = voice.key;
                        break;

                    case (int)fluid_mod_src.FLUID_MOD_KEYPRESSURE:
                        v1 = chan.key_pressure;
                        break;

                    case (int)fluid_mod_src.FLUID_MOD_CHANNELPRESSURE:
                        v1 = chan.channel_pressure;
                        break;

                    case (int)fluid_mod_src.FLUID_MOD_PITCHWHEEL:
                        v1     = chan.pitch_bend;
                        range1 = 0x4000;
                        break;

                    case (int)fluid_mod_src.FLUID_MOD_PITCHWHEELSENS:
                        v1 = chan.pitch_wheel_sensitivity;
                        break;

                    default:
                        v1 = 0.0;
                        break;
                    }
                }

                /* transform the input value */
                switch (Flags1 & 0x0f)
                {
                case 0:     /* linear, unipolar, positive */
                    v1 /= range1;
                    break;

                case 1:     /* linear, unipolar, negative */
                    v1 = 1.0f - v1 / range1;
                    break;

                case 2:     /* linear, bipolar, positive */
                    v1 = -1.0f + 2.0f * v1 / range1;
                    break;

                case 3:     /* linear, bipolar, negative */
                    v1 = -1.0f + 2.0f * v1 / range1;
                    break;

                case 4:     /* concave, unipolar, positive */
                    v1 = fluid_conv.fluid_concave(v1);
                    break;

                case 5:     /* concave, unipolar, negative */
                    v1 = fluid_conv.fluid_concave(127 - v1);
                    break;

                case 6:     /* concave, bipolar, positive */
                    v1 = (v1 > 64) ? fluid_conv.fluid_concave(2 * (v1 - 64)) : -fluid_conv.fluid_concave(2 * (64 - v1));
                    break;

                case 7:     /* concave, bipolar, negative */
                    v1 = (v1 > 64) ? -fluid_conv.fluid_concave(2 * (v1 - 64)) : fluid_conv.fluid_concave(2 * (64 - v1));
                    break;

                case 8:     /* convex, unipolar, positive */
                    v1 = fluid_conv.fluid_convex(v1);
                    break;

                case 9:     /* convex, unipolar, negative */
                    v1 = fluid_conv.fluid_convex(127 - v1);
                    break;

                case 10:     /* convex, bipolar, positive */
                    v1 = (v1 > 64) ? -fluid_conv.fluid_convex(2 * (v1 - 64)) : fluid_conv.fluid_convex(2 * (64 - v1));
                    break;

                case 11:     /* convex, bipolar, negative */
                    v1 = (v1 > 64) ? -fluid_conv.fluid_convex(2 * (v1 - 64)) : fluid_conv.fluid_convex(2 * (64 - v1));
                    break;

                case 12:     /* switch, unipolar, positive */
                    v1 = (v1 >= 64) ? 1.0f : 0.0f;
                    break;

                case 13:     /* switch, unipolar, negative */
                    v1 = (v1 >= 64) ? 0.0f : 1.0f;
                    break;

                case 14:     /* switch, bipolar, positive */
                    v1 = (v1 >= 64) ? 1.0f : -1.0f;
                    break;

                case 15:     /* switch, bipolar, negative */
                    v1 = (v1 >= 64) ? -1.0f : 1.0f;
                    break;
                }
            }
            else
            {
                return(0.0);
            }

            /* no need to go further */
            if (v1 == 0.0f)
            {
                return(0.0f);
            }

            /* get the second input source */
            if (Src2 > 0)
            {
                if ((Flags2 & (byte)fluid_mod_flags.FLUID_MOD_CC) > 0)
                {
                    v2 = ((Src2 >= 0) && (Src2 < 128)) ? chan.cc[Src2] : 0;
                }
                else
                {
                    switch (Src2)
                    {
                    case (int)fluid_mod_src.FLUID_MOD_NONE:             /* SF 2.01 8.2.1 item 0: src enum=0 => value is 1 */
                        v2 = range2;
                        break;

                    case (int)fluid_mod_src.FLUID_MOD_VELOCITY:
                        v2 = voice.vel;
                        break;

                    case (int)fluid_mod_src.FLUID_MOD_KEY:
                        v2 = voice.key;
                        break;

                    case (int)fluid_mod_src.FLUID_MOD_KEYPRESSURE:
                        v2 = chan.key_pressure;
                        break;

                    case (int)fluid_mod_src.FLUID_MOD_CHANNELPRESSURE:
                        v2 = chan.channel_pressure;
                        break;

                    case (int)fluid_mod_src.FLUID_MOD_PITCHWHEEL:
                        v2 = chan.pitch_bend;
                        break;

                    case (int)fluid_mod_src.FLUID_MOD_PITCHWHEELSENS:
                        v2 = chan.pitch_wheel_sensitivity;
                        break;

                    default:
                        v1 = 0.0f;
                        break;
                    }
                }

                /* transform the second input value */
                switch (Flags2 & 0x0f)
                {
                case 0:     /* linear, unipolar, positive */
                    v2 /= range2;
                    break;

                case 1:     /* linear, unipolar, negative */
                    v2 = 1.0f - v2 / range2;
                    break;

                case 2:     /* linear, bipolar, positive */
                    v2 = -1.0f + 2.0f * v2 / range2;
                    break;

                case 3:     /* linear, bipolar, negative */
                    v2 = -1.0f + 2.0f * v2 / range2;
                    break;

                case 4:     /* concave, unipolar, positive */
                    v2 = fluid_conv.fluid_concave(v2);
                    break;

                case 5:     /* concave, unipolar, negative */
                    v2 = fluid_conv.fluid_concave(127 - v2);
                    break;

                case 6:     /* concave, bipolar, positive */
                    v2 = (v2 > 64) ? fluid_conv.fluid_concave(2 * (v2 - 64)) : -fluid_conv.fluid_concave(2 * (64 - v2));
                    break;

                case 7:     /* concave, bipolar, negative */
                    v2 = (v2 > 64) ? -fluid_conv.fluid_concave(2 * (v2 - 64)) : fluid_conv.fluid_concave(2 * (64 - v2));
                    break;

                case 8:     /* convex, unipolar, positive */
                    v2 = fluid_conv.fluid_convex(v2);
                    break;

                case 9:     /* convex, unipolar, negative */
                    v2 = 1.0f - fluid_conv.fluid_convex(v2);
                    break;

                case 10:     /* convex, bipolar, positive */
                    v2 = (v2 > 64) ? -fluid_conv.fluid_convex(2 * (v2 - 64)) : fluid_conv.fluid_convex(2 * (64 - v2));
                    break;

                case 11:     /* convex, bipolar, negative */
                    v2 = (v2 > 64) ? -fluid_conv.fluid_convex(2 * (v2 - 64)) : fluid_conv.fluid_convex(2 * (64 - v2));
                    break;

                case 12:     /* switch, unipolar, positive */
                    v2 = (v2 >= 64) ? 1.0f : 0.0f;
                    break;

                case 13:     /* switch, unipolar, negative */
                    v2 = (v2 >= 64) ? 0.0f : 1.0f;
                    break;

                case 14:     /* switch, bipolar, positive */
                    v2 = (v2 >= 64) ? 1.0f : -1.0f;
                    break;

                case 15:     /* switch, bipolar, negative */
                    v2 = (v2 >= 64) ? -1.0f : 1.0f;
                    break;
                }
            }
            else
            {
                v2 = 1.0f;
            }

            /* it's as simple as that: */
            return((double)Amount * v1 * v2);
        }