/// <summary>
        /// sets the mode
        /// if sinc set, it overrides interp or filtercnt
        /// </summary>
        public void SetMode(bool interp, int filtercnt, bool sinc, int sinc_size = 64, int sinc_interpsize = 32)
        {
            m_sincsize     = sinc && sinc_size >= 4 ? sinc_size > 8192 ? 8192 : sinc_size : 0;
            m_sincoversize = m_sincsize != 0
                ? (sinc_interpsize <= 1 ? 1 : sinc_interpsize >= 4096 ? 4096 : sinc_interpsize)
                : 1;

            m_filtercnt = m_sincsize != 0
                ? 0
                : (filtercnt <= 0 ? 0 : filtercnt >= WDL_RESAMPLE_MAX_FILTERS ? WDL_RESAMPLE_MAX_FILTERS : filtercnt);
            m_interp = interp && m_sincsize == 0;

            //Debug.WriteLine(String.Format("setting interp={0}, filtercnt={1}, sinc={2},{3}\n", m_interp, m_filtercnt, m_sincsize, m_sincoversize));

            if (m_sincsize == 0)
            {
                m_filter_coeffs      = new float[0]; //.Resize(0);
                m_filter_coeffs_size = 0;
            }
            if (m_filtercnt == 0)
            {
                m_iirfilter = null;
            }
        }
Esempio n. 2
0
        // if numsamples_in < the value return by ResamplePrepare(), then it will be flushed to produce all remaining valid samples
        // do NOT call with nsamples_in greater than the value returned from resamplerprpare()! the extra samples will be ignored.
        // returns number of samples successfully outputted to out
        public int ResampleOut(WDL_ResampleSample[] outBuffer, int outBufferIndex, int nsamples_in, int nsamples_out, int nch)
        {
            if (nch > WDL_RESAMPLE_MAX_NCH || nch < 1)
            {
                return(0);
            }

            if (m_filtercnt > 0)
            {
                if (m_ratio > 1.0 && nsamples_in > 0) // filter input
                {
                    if (m_iirfilter == null)
                    {
                        m_iirfilter = new WDL_Resampler_IIRFilter();
                    }

                    int n = m_filtercnt;
                    m_iirfilter.setParms((1.0 / m_ratio) * m_filterpos, m_filterq);

                    int bufIndex = m_samples_in_rsinbuf * nch;
                    int a, x;
                    int offs = 0;
                    for (x = 0; x < nch; x++)
                    {
                        for (a = 0; a < n; a++)
                        {
                            m_iirfilter.Apply(m_rsinbuf, bufIndex + x, m_rsinbuf, bufIndex + x, nsamples_in, nch, offs++);
                        }
                    }
                }
            }

            m_samples_in_rsinbuf += Math.Min(nsamples_in, m_last_requested); // prevent the user from corrupting the internal state


            int rsinbuf_availtemp = m_samples_in_rsinbuf;

            if (nsamples_in < m_last_requested) // flush out to ensure we can deliver
            {
                int fsize = (m_last_requested - nsamples_in) * 2 + m_sincsize * 2;

                int alloc_size = (m_samples_in_rsinbuf + fsize) * nch;
                Array.Resize(ref m_rsinbuf, alloc_size);
                if (m_rsinbuf.Length == alloc_size)
                {
                    Array.Clear(m_rsinbuf, m_samples_in_rsinbuf * nch, fsize * nch);
                    rsinbuf_availtemp = m_samples_in_rsinbuf + fsize;
                }
            }

            int    ret     = 0;
            double srcpos  = m_fracpos;
            double drspos  = m_ratio;
            int    localin = 0;          // localin is an index into m_rsinbuf

            int outptr = outBufferIndex; // outptr is an index into  outBuffer;

            int ns = nsamples_out;

            int outlatadj = 0;

            if (m_sincsize != 0) // sinc interpolating
            {
                if (m_ratio > 1.0)
                {
                    BuildLowPass(1.0 / (m_ratio * 1.03));
                }
                else
                {
                    BuildLowPass(1.0);
                }

                int filtsz  = m_filter_coeffs_size;
                int filtlen = rsinbuf_availtemp - filtsz;
                outlatadj = filtsz / 2 - 1;
                int filter = 0; // filter is an index into m_filter_coeffs m_filter_coeffs.Get();

                if (nch == 1)
                {
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;

                        if (ipos >= filtlen - 1)
                        {
                            break;                      // quit decoding, not enough input samples
                        }
                        SincSample1(outBuffer, outptr, m_rsinbuf, localin + ipos, srcpos - ipos, m_filter_coeffs, filter, filtsz);
                        outptr++;
                        srcpos += drspos;
                        ret++;
                    }
                }
                else if (nch == 2)
                {
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;

                        if (ipos >= filtlen - 1)
                        {
                            break;                      // quit decoding, not enough input samples
                        }
                        SincSample2(outBuffer, outptr, m_rsinbuf, localin + ipos * 2, srcpos - ipos, m_filter_coeffs, filter, filtsz);
                        outptr += 2;
                        srcpos += drspos;
                        ret++;
                    }
                }
                else
                {
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;

                        if (ipos >= filtlen - 1)
                        {
                            break;                      // quit decoding, not enough input samples
                        }
                        SincSample(outBuffer, outptr, m_rsinbuf, localin + ipos * nch, srcpos - ipos, nch, m_filter_coeffs, filter, filtsz);
                        outptr += nch;
                        srcpos += drspos;
                        ret++;
                    }
                }
            }
            else if (!m_interp) // point sampling
            {
                if (nch == 1)
                {
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;
                        if (ipos >= rsinbuf_availtemp)
                        {
                            break;                            // quit decoding, not enough input samples
                        }
                        outBuffer[outptr++] = m_rsinbuf[localin + ipos];
                        srcpos += drspos;
                        ret++;
                    }
                }
                else if (nch == 2)
                {
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;
                        if (ipos >= rsinbuf_availtemp)
                        {
                            break;                            // quit decoding, not enough input samples
                        }
                        ipos += ipos;

                        outBuffer[outptr + 0] = m_rsinbuf[localin + ipos];
                        outBuffer[outptr + 1] = m_rsinbuf[localin + ipos + 1];
                        outptr += 2;
                        srcpos += drspos;
                        ret++;
                    }
                }
                else
                {
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;
                        if (ipos >= rsinbuf_availtemp)
                        {
                            break;                            // quit decoding, not enough input samples
                        }
                        Array.Copy(m_rsinbuf, localin + ipos * nch, outBuffer, outptr, nch);
                        outptr += nch;
                        srcpos += drspos;
                        ret++;
                    }
                }
            }
            else // linear interpolation
            {
                if (nch == 1)
                {
                    while (ns-- != 0)
                    {
                        int    ipos    = (int)srcpos;
                        double fracpos = srcpos - ipos;

                        if (ipos >= rsinbuf_availtemp - 1)
                        {
                            break; // quit decoding, not enough input samples
                        }

                        double ifracpos = 1.0 - fracpos;
                        int    inptr    = localin + ipos;
                        outBuffer[outptr++] = (WDL_ResampleSample)(m_rsinbuf[inptr] * (ifracpos) + m_rsinbuf[inptr + 1] * (fracpos));
                        srcpos += drspos;
                        ret++;
                    }
                }
                else if (nch == 2)
                {
                    while (ns-- != 0)
                    {
                        int    ipos    = (int)srcpos;
                        double fracpos = srcpos - ipos;

                        if (ipos >= rsinbuf_availtemp - 1)
                        {
                            break; // quit decoding, not enough input samples
                        }

                        double ifracpos = 1.0 - fracpos;
                        int    inptr    = localin + ipos * 2;
                        outBuffer[outptr + 0] = (WDL_ResampleSample)(m_rsinbuf[inptr] * (ifracpos) + m_rsinbuf[inptr + 2] * (fracpos));
                        outBuffer[outptr + 1] = (WDL_ResampleSample)(m_rsinbuf[inptr + 1] * (ifracpos) + m_rsinbuf[inptr + 3] * (fracpos));
                        outptr += 2;
                        srcpos += drspos;
                        ret++;
                    }
                }
                else
                {
                    while (ns-- != 0)
                    {
                        int    ipos    = (int)srcpos;
                        double fracpos = srcpos - ipos;

                        if (ipos >= rsinbuf_availtemp - 1)
                        {
                            break; // quit decoding, not enough input samples
                        }

                        double ifracpos = 1.0 - fracpos;
                        int    ch       = nch;
                        int    inptr    = localin + ipos * nch;
                        while (ch-- != 0)
                        {
                            outBuffer[outptr++] = (WDL_ResampleSample)(m_rsinbuf[inptr] * (ifracpos) + m_rsinbuf[inptr + nch] * (fracpos));
                            inptr++;
                        }
                        srcpos += drspos;
                        ret++;
                    }
                }
            }

            if (m_filtercnt > 0)
            {
                if (m_ratio < 1.0 && ret > 0) // filter output
                {
                    if (m_iirfilter == null)
                    {
                        m_iirfilter = new WDL_Resampler_IIRFilter();
                    }
                    int n = m_filtercnt;
                    m_iirfilter.setParms(m_ratio * m_filterpos, m_filterq);

                    int x, a;
                    int offs = 0;
                    for (x = 0; x < nch; x++)
                    {
                        for (a = 0; a < n; a++)
                        {
                            m_iirfilter.Apply(outBuffer, x, outBuffer, x, ret, nch, offs++);
                        }
                    }
                }
            }

            if (ret > 0 && rsinbuf_availtemp > m_samples_in_rsinbuf) // we had to pad!!
            {
                // check for the case where rsinbuf_availtemp>m_samples_in_rsinbuf, decrease ret down to actual valid samples
                double adj = (srcpos - m_samples_in_rsinbuf + outlatadj) / drspos;
                if (adj > 0)
                {
                    ret -= (int)(adj + 0.5);
                    if (ret < 0)
                    {
                        ret = 0;
                    }
                }
            }

            int isrcpos = (int)srcpos;

            m_fracpos             = srcpos - isrcpos;
            m_samples_in_rsinbuf -= isrcpos;
            if (m_samples_in_rsinbuf <= 0)
            {
                m_samples_in_rsinbuf = 0;
            }
            else
            {
                // TODO: bug here
                Array.Copy(m_rsinbuf, localin + isrcpos * nch, m_rsinbuf, localin, m_samples_in_rsinbuf * nch);
            }



            return(ret);
        }
        // if numsamples_in < the value return by ResamplePrepare(), then it will be flushed to produce all remaining valid samples
        // do NOT call with nsamples_in greater than the value returned from resamplerprpare()! the extra samples will be ignored.
        // returns number of samples successfully outputted to out
        public int ResampleOut(WDL_ResampleSample[] outBuffer, int outBufferIndex, int nsamples_in, int nsamples_out, int nch)
        {
            if (nch > WDL_RESAMPLE_MAX_NCH || nch < 1)
            {
                return 0;
            }

            if (m_filtercnt > 0)
            {
                if (m_ratio > 1.0 && nsamples_in > 0) // filter input
                {
                    if (m_iirfilter == null) m_iirfilter = new WDL_Resampler_IIRFilter();

                    int n = m_filtercnt;
                    m_iirfilter.setParms((1.0 / m_ratio) * m_filterpos, m_filterq);

                    int bufIndex = m_samples_in_rsinbuf * nch;
                    int a, x;
                    int offs = 0;
                    for (x = 0; x < nch; x++)
                        for (a = 0; a < n; a++)
                            m_iirfilter.Apply(m_rsinbuf, bufIndex + x, m_rsinbuf, bufIndex + x, nsamples_in, nch, offs++);
                }
            }

            m_samples_in_rsinbuf += Math.Min(nsamples_in, m_last_requested); // prevent the user from corrupting the internal state


            int rsinbuf_availtemp = m_samples_in_rsinbuf;

            if (nsamples_in < m_last_requested) // flush out to ensure we can deliver
            {
                int fsize = (m_last_requested - nsamples_in) * 2 + m_sincsize * 2;

                int alloc_size = (m_samples_in_rsinbuf + fsize) * nch;
                Array.Resize(ref m_rsinbuf, alloc_size);
                if (m_rsinbuf.Length == alloc_size)
                {
                    Array.Clear(m_rsinbuf, m_samples_in_rsinbuf * nch, fsize * nch);
                    rsinbuf_availtemp = m_samples_in_rsinbuf + fsize;
                }
            }

            int ret = 0;
            double srcpos = m_fracpos;
            double drspos = m_ratio;
            int localin = 0; // localin is an index into m_rsinbuf

            int outptr = outBufferIndex;  // outptr is an index into  outBuffer;

            int ns = nsamples_out;

            int outlatadj = 0;

            if (m_sincsize != 0) // sinc interpolating
            {
                if (m_ratio > 1.0) BuildLowPass(1.0 / (m_ratio * 1.03));
                else BuildLowPass(1.0);

                int filtsz = m_filter_coeffs_size;
                int filtlen = rsinbuf_availtemp - filtsz;
                outlatadj = filtsz / 2 - 1;
                int filter = 0; // filter is an index into m_filter_coeffs m_filter_coeffs.Get();

                if (nch == 1)
                {
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;

                        if (ipos >= filtlen - 1) break; // quit decoding, not enough input samples

                        SincSample1(outBuffer, outptr, m_rsinbuf, localin + ipos, srcpos - ipos, m_filter_coeffs, filter, filtsz);
                        outptr++;
                        srcpos += drspos;
                        ret++;
                    }
                }
                else if (nch == 2)
                {
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;

                        if (ipos >= filtlen - 1) break; // quit decoding, not enough input samples

                        SincSample2(outBuffer, outptr, m_rsinbuf, localin + ipos * 2, srcpos - ipos, m_filter_coeffs, filter, filtsz);
                        outptr += 2;
                        srcpos += drspos;
                        ret++;
                    }
                }
                else
                {
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;

                        if (ipos >= filtlen - 1) break; // quit decoding, not enough input samples

                        SincSample(outBuffer, outptr, m_rsinbuf, localin + ipos * nch, srcpos - ipos, nch, m_filter_coeffs, filter, filtsz);
                        outptr += nch;
                        srcpos += drspos;
                        ret++;
                    }
                }
            }
            else if (!m_interp) // point sampling
            {
                if (nch == 1)
                {
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;
                        if (ipos >= rsinbuf_availtemp) break; // quit decoding, not enough input samples

                        outBuffer[outptr++] = m_rsinbuf[localin + ipos];
                        srcpos += drspos;
                        ret++;
                    }
                }
                else if (nch == 2)
                {
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;
                        if (ipos >= rsinbuf_availtemp) break; // quit decoding, not enough input samples

                        ipos += ipos;

                        outBuffer[outptr + 0] = m_rsinbuf[localin + ipos];
                        outBuffer[outptr + 1] = m_rsinbuf[localin + ipos + 1];
                        outptr += 2;
                        srcpos += drspos;
                        ret++;
                    }
                }
                else
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;
                        if (ipos >= rsinbuf_availtemp) break; // quit decoding, not enough input samples

                        Array.Copy(m_rsinbuf, localin + ipos * nch, outBuffer, outptr, nch);
                        outptr += nch;
                        srcpos += drspos;
                        ret++;
                    }
            }
            else // linear interpolation
            {
                if (nch == 1)
                {
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;
                        double fracpos = srcpos - ipos;

                        if (ipos >= rsinbuf_availtemp - 1)
                        {
                            break; // quit decoding, not enough input samples
                        }

                        double ifracpos = 1.0 - fracpos;
                        int inptr = localin + ipos;
                        outBuffer[outptr++] = (WDL_ResampleSample)(m_rsinbuf[inptr] * (ifracpos) + m_rsinbuf[inptr + 1] * (fracpos));
                        srcpos += drspos;
                        ret++;
                    }
                }
                else if (nch == 2)
                {
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;
                        double fracpos = srcpos - ipos;

                        if (ipos >= rsinbuf_availtemp - 1)
                        {
                            break; // quit decoding, not enough input samples
                        }

                        double ifracpos = 1.0 - fracpos;
                        int inptr = localin + ipos * 2;
                        outBuffer[outptr + 0] = (WDL_ResampleSample)(m_rsinbuf[inptr] * (ifracpos) + m_rsinbuf[inptr + 2] * (fracpos));
                        outBuffer[outptr + 1] = (WDL_ResampleSample)(m_rsinbuf[inptr + 1] * (ifracpos) + m_rsinbuf[inptr + 3] * (fracpos));
                        outptr += 2;
                        srcpos += drspos;
                        ret++;
                    }
                }
                else
                {
                    while (ns-- != 0)
                    {
                        int ipos = (int)srcpos;
                        double fracpos = srcpos - ipos;

                        if (ipos >= rsinbuf_availtemp - 1)
                        {
                            break; // quit decoding, not enough input samples
                        }

                        double ifracpos = 1.0 - fracpos;
                        int ch = nch;
                        int inptr = localin + ipos * nch;
                        while (ch-- != 0)
                        {
                            outBuffer[outptr++] = (WDL_ResampleSample)(m_rsinbuf[inptr] * (ifracpos) + m_rsinbuf[inptr + nch] * (fracpos));
                            inptr++;
                        }
                        srcpos += drspos;
                        ret++;
                    }
                }
            }

            if (m_filtercnt > 0)
            {
                if (m_ratio < 1.0 && ret > 0) // filter output
                {
                    if (m_iirfilter == null) m_iirfilter = new WDL_Resampler_IIRFilter();
                    int n = m_filtercnt;
                    m_iirfilter.setParms(m_ratio * m_filterpos, m_filterq);

                    int x, a;
                    int offs = 0;
                    for (x = 0; x < nch; x++)
                        for (a = 0; a < n; a++)
                            m_iirfilter.Apply(outBuffer, x, outBuffer, x, ret, nch, offs++);
                }
            }

            if (ret > 0 && rsinbuf_availtemp > m_samples_in_rsinbuf) // we had to pad!!
            {
                // check for the case where rsinbuf_availtemp>m_samples_in_rsinbuf, decrease ret down to actual valid samples
                double adj = (srcpos - m_samples_in_rsinbuf + outlatadj) / drspos;
                if (adj > 0)
                {
                    ret -= (int)(adj + 0.5);
                    if (ret < 0) ret = 0;
                }
            }

            int isrcpos = (int)srcpos;
            m_fracpos = srcpos - isrcpos;
            m_samples_in_rsinbuf -= isrcpos;
            if (m_samples_in_rsinbuf <= 0)
            {
                m_samples_in_rsinbuf = 0;
            }
            else
            {
                // TODO: bug here
                Array.Copy(m_rsinbuf, localin + isrcpos * nch, m_rsinbuf, localin, m_samples_in_rsinbuf * nch);
            }



            return ret;
        }
Esempio n. 4
0
        /// <summary>
        /// sets the mode
        /// if sinc set, it overrides interp or filtercnt
        /// </summary>
        public void SetMode(bool interp, int filtercnt, bool sinc, int sinc_size = 64, int sinc_interpsize = 32)
        {
            m_sincsize = sinc && sinc_size >= 4 ? sinc_size > 8192 ? 8192 : sinc_size : 0;
            m_sincoversize = (m_sincsize != 0) ? (sinc_interpsize <= 1 ? 1 : sinc_interpsize >= 4096 ? 4096 : sinc_interpsize) : 1;

            m_filtercnt = (m_sincsize != 0) ? 0 : (filtercnt <= 0 ? 0 : filtercnt >= WDL_RESAMPLE_MAX_FILTERS ? WDL_RESAMPLE_MAX_FILTERS : filtercnt);
            m_interp = interp && (m_sincsize == 0);

            //Debug.WriteLine(String.Format("setting interp={0}, filtercnt={1}, sinc={2},{3}\n", m_interp, m_filtercnt, m_sincsize, m_sincoversize));

            if (m_sincsize == 0)
            {
                m_filter_coeffs = new WDL_SincFilterSample[0]; //.Resize(0);
                m_filter_coeffs_size = 0;
            }
            if (m_filtercnt == 0)
            {
                m_iirfilter = null;
            }
        }