Example #1
0
static boolean ConvertibleRatio(int freq1, int freq2)
{
    int ratio;

    if (freq1 > freq2)
    {
        return ConvertibleRatio(freq2, freq1);
    }
    else if ((freq2 % freq1) != 0)
    {
        // Not in a direct ratio

        return false;
    }
    else
    {
        // Check the ratio is a power of 2

        ratio = freq2 / freq1;

        while ((ratio & 1) == 0)
        {
            ratio = ratio >> 1;
        }

        return ratio == 1;
    }
}
Example #2
0
static void ExpandSoundData(byte *data,
                            int samplerate,
                            int length,
                            Mix_Chunk *destination)
{
    SDL_AudioCVT convertor;
    
    if (samplerate <= mixer_freq
     && ConvertibleRatio(samplerate, mixer_freq)
     && SDL_BuildAudioCVT(&convertor,
                          AUDIO_U8, 1, samplerate,
                          mixer_format, mixer_channels, mixer_freq))
    {
        convertor.buf = destination->abuf;
        convertor.len = length;
        memcpy(convertor.buf, data, length);

        SDL_ConvertAudio(&convertor);
    }
    else
    {
        Sint16 *expanded = (Sint16 *) destination->abuf;
        int expanded_length;
        int expand_ratio;
        int i;

        // Generic expansion if conversion does not work:
        //
        // SDL's audio conversion only works for rate conversions that are
        // powers of 2; if the two formats are not in a direct power of 2
        // ratio, do this naive conversion instead.

        // number of samples in the converted sound

        expanded_length = ((uint64_t) length * mixer_freq) / samplerate;
        expand_ratio = (length << 8) / expanded_length;

        for (i=0; i<expanded_length; ++i)
        {
            Sint16 sample;
            int src;

            src = (i * expand_ratio) >> 8;

            sample = data[src] | (data[src] << 8);
            sample -= 32768;

            // expand 8->16 bits, mono->stereo

            expanded[i * 2] = expanded[i * 2 + 1] = sample;
        }
    }
}
Example #3
0
static dboolean ConvertibleRatio(int freq1, int freq2)
{
    int ratio;

    if (freq1 > freq2)
        return ConvertibleRatio(freq2, freq1);
    else if (freq2 % freq1)
        return false;   // Not in a direct ratio
    else
    {
        // Check the ratio is a power of 2
        ratio = freq2 / freq1;

        while (!(ratio & 1))
            ratio >>= 1;

        return (ratio == 1);
    }
}
Example #4
0
// Generic sound expansion function for any sample rate.
static void ExpandSoundData_SDL(byte *data, int samplerate,
                                uint32_t length, Mix_Chunk *destination)
{
    SDL_AudioCVT        convertor;
    uint32_t            expanded_length;

    // Calculate the length of the expanded version of the sample.
    expanded_length = (uint32_t)(((uint64_t)length * mixer_freq) / samplerate);

    // Double up twice: 8 -> 16 bit and mono -> stereo
    expanded_length *= 4;
    destination->alen = expanded_length;
    destination->abuf = Z_Malloc(expanded_length, PU_STATIC, (void **)&destination->abuf);

    // If we can, use the standard / optimized SDL conversion routines.
    if (samplerate <= mixer_freq
        && ConvertibleRatio(samplerate, mixer_freq)
        && SDL_BuildAudioCVT(&convertor, AUDIO_U8, 1, samplerate, 
                             mixer_format, mixer_channels, mixer_freq))
    {
        convertor.buf = destination->abuf;
        convertor.len = length;
        memcpy(convertor.buf, data, length);

        SDL_ConvertAudio(&convertor);
    }
    else
    {
        Sint16  *expanded = (Sint16 *)destination->abuf;
        int     expanded_length;
        int     expand_ratio;
        int     i;

        // Generic expansion if conversion does not work:
        //
        // SDL's audio conversion only works for rate conversions that are
        // powers of 2; if the two formats are not in a direct power of 2
        // ratio, do this naive conversion instead.

        // number of samples in the converted sound
        expanded_length = ((uint64_t)length * mixer_freq) / samplerate;
        expand_ratio = (length << 8) / expanded_length;

        for (i = 0; i < expanded_length; ++i)
        {
            Sint16      sample;
            int         src;

            src = (i * expand_ratio) >> 8;

            sample = (data[src] | (data[src] << 8)) - 32768;

            // expand 8->16 bits, mono->stereo
            expanded[i * 2] = expanded[i * 2 + 1] = sample;
        }

        {
            float       rc, dt, alpha;

            // Low-pass filter for cutoff frequency f:
            //
            // For sampling rate r, dt = 1 / r
            // rc = 1 / 2*pi*f
            // alpha = dt / (rc + dt)

            // Filter to the half sample rate of the original sound effect
            // (maximum frequency, by nyquist)
            dt = 1.0f / mixer_freq;
            rc = 1.0f / (float)(2 * M_PI * samplerate);
            alpha = dt / (rc + dt);

            // Both channels are processed in parallel, hence [i - 2]:
            for (i = 2; i < expanded_length * 2; ++i)
                expanded[i] = (Sint16)(alpha * expanded[i] + (1 - alpha) * expanded[i - 2]);
        }
    }
}
Example #5
0
static boolean ExpandSoundData_SDL(sfxinfo_t *sfxinfo,
                                   byte *data,
                                   int samplerate,
                                   int length)
{
    SDL_AudioCVT convertor;
    Mix_Chunk *chunk;
    uint32_t expanded_length;
 
    // Calculate the length of the expanded version of the sample.    

    expanded_length = (uint32_t) ((((uint64_t) length) * mixer_freq) / samplerate);

    // Double up twice: 8 -> 16 bit and mono -> stereo

    expanded_length *= 4;

    // Allocate a chunk in which to expand the sound

    chunk = AllocateSound(sfxinfo, expanded_length);

    if (chunk == NULL)
    {
        return false;
    }

    // If we can, use the standard / optimized SDL conversion routines.

    if (samplerate <= mixer_freq
     && ConvertibleRatio(samplerate, mixer_freq)
     && SDL_BuildAudioCVT(&convertor,
                          AUDIO_U8, 1, samplerate,
                          mixer_format, mixer_channels, mixer_freq))
    {
        convertor.buf = chunk->abuf;
        convertor.len = length;
        memcpy(convertor.buf, data, length);

        SDL_ConvertAudio(&convertor);
    }
    else
    {
        Sint16 *expanded = (Sint16 *) chunk->abuf;
        int expanded_length;
        int expand_ratio;
        int i;

        // Generic expansion if conversion does not work:
        //
        // SDL's audio conversion only works for rate conversions that are
        // powers of 2; if the two formats are not in a direct power of 2
        // ratio, do this naive conversion instead.

        // number of samples in the converted sound

        expanded_length = ((uint64_t) length * mixer_freq) / samplerate;
        expand_ratio = (length << 8) / expanded_length;

        for (i=0; i<expanded_length; ++i)
        {
            Sint16 sample;
            int src;

            src = (i * expand_ratio) >> 8;

            sample = data[src] | (data[src] << 8);
            sample -= 32768;

            // expand 8->16 bits, mono->stereo

            expanded[i * 2] = expanded[i * 2 + 1] = sample;
        }

#ifdef LOW_PASS_FILTER
        // Perform a low-pass filter on the upscaled sound to filter
        // out high-frequency noise from the conversion process.

        {
            float rc, dt, alpha;

            // Low-pass filter for cutoff frequency f:
            //
            // For sampling rate r, dt = 1 / r
            // rc = 1 / 2*pi*f
            // alpha = dt / (rc + dt)

            // Filter to the half sample rate of the original sound effect
            // (maximum frequency, by nyquist)

            dt = 1.0f / mixer_freq;
            rc = 1.0f / (3.14f * samplerate);
            alpha = dt / (rc + dt);

            // Both channels are processed in parallel, hence [i-2]:

            for (i=2; i<expanded_length * 2; ++i)
            {
                expanded[i] = (Sint16) (alpha * expanded[i]
                                      + (1 - alpha) * expanded[i-2]);
            }
        }
#endif /* #ifdef LOW_PASS_FILTER */
    }

    return true;
}