src/audio/SDL_audiocvt.c
changeset 10842 30b37eaf3b3c
parent 10841 b9d6a3d65394
child 10843 31c9dede7b9c
     1.1 --- a/src/audio/SDL_audiocvt.c	Tue Jan 24 00:03:36 2017 -0500
     1.2 +++ b/src/audio/SDL_audiocvt.c	Tue Jan 24 00:08:24 2017 -0500
     1.3 @@ -858,7 +858,7 @@
     1.4      return (cvt->needed);
     1.5  }
     1.6  
     1.7 -typedef int (*SDL_ResampleAudioStreamFunc)(SDL_AudioStream *stream, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen);
     1.8 +typedef int (*SDL_ResampleAudioStreamFunc)(SDL_AudioStream *stream, const void *inbuf, const int inbuflen, void *outbuf, const int outbuflen);
     1.9  typedef void (*SDL_ResetAudioStreamResamplerFunc)(SDL_AudioStream *stream);
    1.10  typedef void (*SDL_CleanupAudioStreamResamplerFunc)(SDL_AudioStream *stream);
    1.11  
    1.12 @@ -890,8 +890,10 @@
    1.13  
    1.14  #ifdef HAVE_LIBSAMPLERATE_H
    1.15  static int
    1.16 -SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
    1.17 +SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
    1.18  {
    1.19 +    const float *inbuf = (const float *) _inbuf;
    1.20 +    float *outbuf = (float *) _outbuf;
    1.21      const int framelen = sizeof(float) * stream->pre_resample_channels;
    1.22      SRC_STATE *state = (SRC_STATE *)stream->resampler_state;
    1.23      SRC_DATA data;
    1.24 @@ -970,26 +972,48 @@
    1.25  typedef struct
    1.26  {
    1.27      SDL_bool resampler_seeded;
    1.28 -    float resampler_state[8];
    1.29 +    union
    1.30 +    {
    1.31 +        float f[8];
    1.32 +        Sint16 si16[2];
    1.33 +    } resampler_state;
    1.34  } SDL_AudioStreamResamplerState;
    1.35  
    1.36  static int
    1.37 -SDL_ResampleAudioStream(SDL_AudioStream *stream, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
    1.38 +SDL_ResampleAudioStream(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
    1.39  {
    1.40 +    const float *inbuf = (const float *) _inbuf;
    1.41 +    float *outbuf = (float *) _outbuf;
    1.42      SDL_AudioStreamResamplerState *state = (SDL_AudioStreamResamplerState*)stream->resampler_state;
    1.43      const int chans = (int)stream->pre_resample_channels;
    1.44  
    1.45 -    SDL_assert(chans <= SDL_arraysize(state->resampler_state));
    1.46 +    SDL_assert(chans <= SDL_arraysize(state->resampler_state.f));
    1.47  
    1.48      if (!state->resampler_seeded) {
    1.49 -        int i;
    1.50 -        for (i = 0; i < chans; i++) {
    1.51 -            state->resampler_state[i] = inbuf[i];
    1.52 -        }
    1.53 +        SDL_memcpy(state->resampler_state.f, inbuf, chans * sizeof (float));
    1.54          state->resampler_seeded = SDL_TRUE;
    1.55      }
    1.56  
    1.57 -    return SDL_ResampleAudioSimple(chans, stream->rate_incr, state->resampler_state, inbuf, inbuflen, outbuf, outbuflen);
    1.58 +    return SDL_ResampleAudioSimple(chans, stream->rate_incr, state->resampler_state.f, inbuf, inbuflen, outbuf, outbuflen);
    1.59 +}
    1.60 +
    1.61 +static int
    1.62 +SDL_ResampleAudioStream_si16_c2(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
    1.63 +{
    1.64 +    const Sint16 *inbuf = (const Sint16 *) _inbuf;
    1.65 +    Sint16 *outbuf = (Sint16 *) _outbuf;
    1.66 +    SDL_AudioStreamResamplerState *state = (SDL_AudioStreamResamplerState*)stream->resampler_state;
    1.67 +    const int chans = (int)stream->pre_resample_channels;
    1.68 +
    1.69 +    SDL_assert(chans <= SDL_arraysize(state->resampler_state.si16));
    1.70 +
    1.71 +    if (!state->resampler_seeded) {
    1.72 +        state->resampler_state.si16[0] = inbuf[0];
    1.73 +        state->resampler_state.si16[1] = inbuf[1];
    1.74 +        state->resampler_seeded = SDL_TRUE;
    1.75 +    }
    1.76 +
    1.77 +    return SDL_ResampleAudioSimple_si16_c2(stream->rate_incr, state->resampler_state.si16, inbuf, inbuflen, outbuf, outbuflen);
    1.78  }
    1.79  
    1.80  static void
    1.81 @@ -1016,6 +1040,9 @@
    1.82      const int packetlen = 4096;  /* !!! FIXME: good enough for now. */
    1.83      Uint8 pre_resample_channels;
    1.84      SDL_AudioStream *retval;
    1.85 +#ifndef HAVE_LIBSAMPLERATE_H
    1.86 +    const SDL_bool SRC_available = SDL_FALSE;
    1.87 +#endif
    1.88  
    1.89      retval = (SDL_AudioStream *) SDL_calloc(1, sizeof (SDL_AudioStream));
    1.90      if (!retval) {
    1.91 @@ -1043,11 +1070,22 @@
    1.92      /* Not resampling? It's an easy conversion (and maybe not even that!). */
    1.93      if (src_rate == dst_rate) {
    1.94          retval->cvt_before_resampling.needed = SDL_FALSE;
    1.95 -        retval->cvt_before_resampling.len_mult = 1;
    1.96          if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, src_format, src_channels, dst_rate, dst_format, dst_channels, dst_rate) < 0) {
    1.97              SDL_FreeAudioStream(retval);
    1.98              return NULL;  /* SDL_BuildAudioCVT should have called SDL_SetError. */
    1.99          }
   1.100 +    /* fast path special case for stereo Sint16 data that just needs resampling. */
   1.101 +    } else if ((!SRC_available) && (src_channels == 2) && (dst_channels == 2) && (src_format == AUDIO_S16SYS) && (dst_format == AUDIO_S16SYS)) {
   1.102 +        SDL_assert(src_rate != dst_rate);
   1.103 +        retval->resampler_state = SDL_calloc(1, sizeof(SDL_AudioStreamResamplerState));
   1.104 +        if (!retval->resampler_state) {
   1.105 +            SDL_FreeAudioStream(retval);
   1.106 +            SDL_OutOfMemory();
   1.107 +            return NULL;
   1.108 +        }
   1.109 +        retval->resampler_func = SDL_ResampleAudioStream_si16_c2;
   1.110 +        retval->reset_resampler_func = SDL_ResetAudioStreamResampler;
   1.111 +        retval->cleanup_resampler_func = SDL_CleanupAudioStreamResampler;
   1.112      } else {
   1.113          /* Don't resample at first. Just get us to Float32 format. */
   1.114          /* !!! FIXME: convert to int32 on devices without hardware float. */
   1.115 @@ -1136,16 +1174,16 @@
   1.116  
   1.117      if (stream->dst_rate != stream->src_rate) {
   1.118          const int workbuflen = buflen * ((int) SDL_ceil(stream->rate_incr));
   1.119 -        float *workbuf = (float *) EnsureBufferSize(&stream->resample_buffer, &stream->resample_buffer_len, workbuflen);
   1.120 +        void *workbuf = EnsureBufferSize(&stream->resample_buffer, &stream->resample_buffer_len, workbuflen);
   1.121          if (workbuf == NULL) {
   1.122              return -1;  /* probably out of memory. */
   1.123          }
   1.124 -        buflen = stream->resampler_func(stream, (float *) buf, buflen, workbuf, workbuflen);
   1.125 +        buflen = stream->resampler_func(stream, buf, buflen, workbuf, workbuflen);
   1.126          buf = workbuf;
   1.127      }
   1.128  
   1.129      if (stream->cvt_after_resampling.needed) {
   1.130 -        const int workbuflen = buflen * stream->cvt_before_resampling.len_mult;  /* will be "* 1" if not needed */
   1.131 +        const int workbuflen = buflen * stream->cvt_after_resampling.len_mult;  /* will be "* 1" if not needed */
   1.132          Uint8 *workbuf;
   1.133  
   1.134          if (buf == stream->resample_buffer) {