288 lines · 16.8 KB · Text
RawDownload
/*  _______         ____    __         ___    ___ * \    _  \       \    /  \  /       \   \  /   /       '   '  ' *  |  | \  \       |  |    ||         |   \/   |         .      . *  |  |  |  |      |  |    ||         ||\  /|  | *  |  |  |  |      |  |    ||         || \/ |  |         '  '  ' *  |  |  |  |      |  |    ||         ||    |  |         .      . *  |  |_/  /        \  \__//          ||    |  | * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque *                                                      /  \ *                                                     / .  \ * resample.inc - Resampling helper template.         / / \  \ *                                                   | <  /   \_ * By Bob and entheh.                                |  \/ /\   / *                                                    \_  /  > / * In order to find a good trade-off between            | \ / / * speed and accuracy in this code, some tests          |  ' / * were carried out regarding the behaviour of           \__/ * long long ints with gcc. The following code * was tested: * * int a, b, c; * c = ((long long)a * b) >> 16; * * DJGPP GCC Version 3.0.3 generated the following assembly language code for * the multiplication and scaling, leaving the 32-bit result in EAX. * * movl  -8(%ebp), %eax    ; read one int into EAX * imull -4(%ebp)          ; multiply by the other; result goes in EDX:EAX * shrdl $16, %edx, %eax   ; shift EAX right 16, shifting bits in from EDX * * Note that a 32*32->64 multiplication is performed, allowing for high * accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally), * so it is a minor concern when four multiplications are being performed * (the cubic resampler). On the Pentium MMX and earlier, it takes four or * more cycles, so this method is unsuitable for use in the low-quality * resamplers. * * Since "long long" is a gcc-specific extension, we use LONG_LONG instead, * defined in dumb.h. We may investigate later what code MSVC generates, but * if it seems too slow then we suggest you use a good compiler. * * FIXME: these comments are somewhat out of date now. */ void dumb_reset_resampler(DUMB_RESAMPLER *resampler, SRCTYPE *src,                          int src_channels, long pos, long start, long end,                          int quality) {    int i;    resampler->src = src;    resampler->pos = pos;    resampler->subpos = 0;    resampler->start = start;    resampler->end = end;    resampler->dir = 1;    resampler->pickup = NULL;    resampler->pickup_data = NULL;    if (quality < 0) {        resampler->quality = 0;    } else if (quality > DUMB_RQ_N_LEVELS - 1) {        resampler->quality = DUMB_RQ_N_LEVELS - 1;    } else {        resampler->quality = quality;    }    for (i = 0; i < src_channels * 3; i++)        resampler->X[i] = 0;    resampler->overshot = -1;    resampler->fir_resampler_ratio = 0;    resampler_clear(resampler->fir_resampler[0]);    resampler_clear(resampler->fir_resampler[1]);    resampler_set_quality(resampler->fir_resampler[0], resampler->quality);    resampler_set_quality(resampler->fir_resampler[1], resampler->quality);} DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos,                                     long start, long end, int quality) {    DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler));    if (!resampler)        return NULL;    dumb_reset_resampler(resampler, src, src_channels, pos, start, end,                         quality);    return resampler;} #define UPDATE_VOLUME(pvol, vol)                                               \    {                                                                          \        if (pvol) {                                                            \            vol##r += vol##d;                                                  \            if ((vol##d < 0 && vol##r <= vol##t) ||                            \                (vol##d > 0 && vol##r >= vol##t)) {                            \                pvol->volume = pvol->target;                                   \                if (pvol->declick_stage == 0 || pvol->declick_stage >= 3)      \                    pvol->declick_stage++;                                     \                pvol = NULL;                                                   \                vol = vol##t * vol##m;                                         \            } else {                                                           \                vol = vol##r * vol##m;                                         \            }                                                                  \        }                                                                      \    } /* Create mono source resampler. */#define SUFFIX2 _1#define SRC_CHANNELS 1#define DIVIDE_BY_SRC_CHANNELS(x) (x)#define COPYSRC(dstarray, dstindex, srcarray, srcindex)                        \    (dstarray)[dstindex] = (srcarray)[srcindex]#define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex)            \    (dstarray)[dstindex] = condition ? (srcarray)[srcindex] : 0#define MONO_DEST_VOLUME_PARAMETERS DUMB_VOLUME_RAMP_INFO *volume#define MONO_DEST_VOLUME_VARIABLES vol, volr, vold, volt, volm#define MONO_DEST_VOLUME_ZEROS 0#define SET_MONO_DEST_VOLUME_VARIABLES                                         \    {                                                                          \        if (volume) {                                                          \            volr = volume->volume;                                             \            vold = volume->delta;                                              \            volt = volume->target;                                             \            volm = volume->mix;                                                \            vol = volr * volm;                                                 \            if (volr == volt)                                                  \                volume = NULL;                                                 \        } else {                                                               \            vol = 0;                                                           \            volr = 0;                                                          \            vold = 0;                                                          \            volt = 0;                                                          \            volm = 0;                                                          \        }                                                                      \    }#define RETURN_MONO_DEST_VOLUME_VARIABLES                                      \    if (volume)                                                                \    volume->volume = volr#define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0 && volt == 0)#define POKE_FIR(offset)                                                       \    {                                                                          \        resampler_write_sample_float(resampler->fir_resampler[0],              \                                     FIR(x[offset]));                          \    }#define MONO_DEST_PEEK_FIR                                                     \    *dst = resampler_get_sample_float(resampler->fir_resampler[0]) * vol *     \           16777216.0f#define MONO_DEST_MIX_FIR                                                      \    {                                                                          \        *dst++ += resampler_get_sample_float(resampler->fir_resampler[0]) *    \                  vol * 16777216.0f;                                           \        UPDATE_VOLUME(volume, vol);                                            \    }#define ADVANCE_FIR resampler_remove_sample(resampler->fir_resampler[0], 1)#define STEREO_DEST_PEEK_FIR                                                   \    {                                                                          \        float sample =                                                         \            resampler_get_sample_float(resampler->fir_resampler[0]);           \        *dst++ = sample * lvol * 16777216.0f;                                  \        *dst++ = sample * rvol * 16777216.0f;                                  \    }#define STEREO_DEST_MIX_FIR                                                    \    {                                                                          \        float sample =                                                         \            resampler_get_sample_float(resampler->fir_resampler[0]);           \        *dst++ += sample * lvol * 16777216.0f;                                 \        *dst++ += sample * rvol * 16777216.0f;                                 \        UPDATE_VOLUME(volume_left, lvol);                                      \        UPDATE_VOLUME(volume_right, rvol);                                     \    }#include "resamp2.inc" /* Create stereo source resampler. */#define SUFFIX2 _2#define SRC_CHANNELS 2#define DIVIDE_BY_SRC_CHANNELS(x) ((x) >> 1)#define COPYSRC(dstarray, dstindex, srcarray, srcindex)                        \    {                                                                          \        (dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2];                   \        (dstarray)[(dstindex)*2 + 1] = (srcarray)[(srcindex)*2 + 1];           \    }#define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex)            \    {                                                                          \        if (condition) {                                                       \            (dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2];               \            (dstarray)[(dstindex)*2 + 1] = (srcarray)[(srcindex)*2 + 1];       \        } else {                                                               \            (dstarray)[(dstindex)*2] = 0;                                      \            (dstarray)[(dstindex)*2 + 1] = 0;                                  \        }                                                                      \    } #define MONO_DEST_VOLUME_PARAMETERS                                            \    DUMB_VOLUME_RAMP_INFO *volume_left, DUMB_VOLUME_RAMP_INFO *volume_right#define MONO_DEST_VOLUME_VARIABLES                                             \    lvol, lvolr, lvold, lvolt, lvolm, rvol, rvolr, rvold, rvolt, rvolm#define MONO_DEST_VOLUME_ZEROS 0, 0#define SET_MONO_DEST_VOLUME_VARIABLES                                         \    {                                                                          \        if (volume_left) {                                                     \            lvolr = volume_left->volume;                                       \            lvold = volume_left->delta;                                        \            lvolt = volume_left->target;                                       \            lvolm = volume_left->mix;                                          \            lvol = lvolr * lvolm;                                              \            if (lvolr == lvolt)                                                \                volume_left = NULL;                                            \        } else {                                                               \            lvol = 0;                                                          \            lvolr = 0;                                                         \            lvold = 0;                                                         \            lvolt = 0;                                                         \            lvolm = 0;                                                         \        }                                                                      \        if (volume_right) {                                                    \            rvolr = volume_right->volume;                                      \            rvold = volume_right->delta;                                       \            rvolt = volume_right->target;                                      \            rvolm = volume_right->mix;                                         \            rvol = rvolr * rvolm;                                              \            if (rvolr == rvolt)                                                \                volume_right = NULL;                                           \        } else {                                                               \            rvol = 0;                                                          \            rvolr = 0;                                                         \            rvold = 0;                                                         \            rvolt = 0;                                                         \            rvolm = 0;                                                         \        }                                                                      \    }#define RETURN_MONO_DEST_VOLUME_VARIABLES                                      \    {                                                                          \        if (volume_left)                                                       \            volume_left->volume = lvolr;                                       \        if (volume_right)                                                      \            volume_right->volume = rvolr;                                      \    }#define MONO_DEST_VOLUMES_ARE_ZERO                                             \    (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)#define POKE_FIR(offset)                                                       \    {                                                                          \        resampler_write_sample_float(resampler->fir_resampler[0],              \                                     FIR(x[(offset)*2 + 0]));                  \        resampler_write_sample_float(resampler->fir_resampler[1],              \                                     FIR(x[(offset)*2 + 1]));                  \    }#define MONO_DEST_PEEK_FIR                                                     \    {                                                                          \        *dst =                                                                 \            (resampler_get_sample_float(resampler->fir_resampler[0]) * lvol +  \             resampler_get_sample_float(resampler->fir_resampler[1]) * rvol) * \            16777216.0f;                                                       \    }#define MONO_DEST_MIX_FIR                                                      \    {                                                                          \        *dst++ +=                                                              \            (resampler_get_sample_float(resampler->fir_resampler[0]) * lvol +  \             resampler_get_sample_float(resampler->fir_resampler[1]) * rvol) * \            16777216.0f;                                                       \        UPDATE_VOLUME(volume_left, lvol);                                      \        UPDATE_VOLUME(volume_right, rvol);                                     \    }#define ADVANCE_FIR                                                            \    {                                                                          \        resampler_remove_sample(resampler->fir_resampler[0], 1);               \        resampler_remove_sample(resampler->fir_resampler[1], 1);               \    }#define STEREO_DEST_PEEK_FIR                                                   \    {                                                                          \        *dst++ = resampler_get_sample_float(resampler->fir_resampler[0]) *     \                 lvol * 16777216.0f;                                           \        *dst++ = resampler_get_sample_float(resampler->fir_resampler[1]) *     \                 rvol * 16777216.0f;                                           \    }#define STEREO_DEST_MIX_FIR                                                    \    {                                                                          \        *dst++ += resampler_get_sample_float(resampler->fir_resampler[0]) *    \                  lvol * 16777216.0f;                                          \        *dst++ += resampler_get_sample_float(resampler->fir_resampler[1]) *    \                  rvol * 16777216.0f;                                          \        UPDATE_VOLUME(volume_left, lvol);                                      \        UPDATE_VOLUME(volume_right, rvol);                                     \    }#include "resamp2.inc" void dumb_end_resampler(DUMB_RESAMPLER *resampler) {    if (resampler)        free(resampler);} #undef FIR#undef SRCBITS#undef SRCTYPE#undef SUFFIX

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t