src/audio/SDL_audiocvt.c
changeset 10851 9209506bac56
parent 10849 bc671e6906ae
child 10883 c6b2a9e91f91
     1.1 --- a/src/audio/SDL_audiocvt.c	Tue Jan 24 16:18:25 2017 -0500
     1.2 +++ b/src/audio/SDL_audiocvt.c	Tue Jan 24 20:30:48 2017 -0500
     1.3 @@ -867,7 +867,6 @@
     1.4      SDL_AudioCVT cvt_before_resampling;
     1.5      SDL_AudioCVT cvt_after_resampling;
     1.6      SDL_DataQueue *queue;
     1.7 -    Uint8 *work_buffer;  /* always aligned to 16 bytes. */
     1.8      Uint8 *work_buffer_base;  /* maybe unaligned pointer from SDL_realloc(). */
     1.9      int work_buffer_len;
    1.10      int src_sample_frame_size;
    1.11 @@ -887,6 +886,29 @@
    1.12      SDL_CleanupAudioStreamResamplerFunc cleanup_resampler_func;
    1.13  };
    1.14  
    1.15 +static Uint8 *
    1.16 +EnsureStreamBufferSize(SDL_AudioStream *stream, const int newlen)
    1.17 +{
    1.18 +    Uint8 *ptr;
    1.19 +    size_t offset;
    1.20 +
    1.21 +    if (stream->work_buffer_len >= newlen) {
    1.22 +        ptr = stream->work_buffer_base;
    1.23 +    } else {
    1.24 +        ptr = (Uint8 *) SDL_realloc(stream->work_buffer_base, newlen + 32);
    1.25 +        if (!ptr) {
    1.26 +            SDL_OutOfMemory();
    1.27 +            return NULL;
    1.28 +        }
    1.29 +        /* Make sure we're aligned to 16 bytes for SIMD code. */
    1.30 +        stream->work_buffer_base = ptr;
    1.31 +        stream->work_buffer_len = newlen;
    1.32 +    }
    1.33 +
    1.34 +    offset = ((size_t) ptr) & 15;
    1.35 +    return offset ? ptr + (16 - offset) : ptr;
    1.36 +}
    1.37 +
    1.38  #ifdef HAVE_LIBSAMPLERATE_H
    1.39  static int
    1.40  SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
    1.41 @@ -898,6 +920,17 @@
    1.42      SRC_DATA data;
    1.43      int result;
    1.44  
    1.45 +    if (inbuf == ((const float *) outbuf)) {  /* libsamplerate can't work in-place. */
    1.46 +        Uint8 *ptr = EnsureStreamBufferSize(stream, inbuflen + outbuflen);
    1.47 +        if (ptr == NULL) {
    1.48 +            SDL_OutOfMemory();
    1.49 +            return 0;
    1.50 +        }
    1.51 +        SDL_memcpy(ptr + outbuflen, ptr, inbuflen);
    1.52 +        inbuf = (const float *) (ptr + outbuflen);
    1.53 +        outbuf = (float *) ptr;
    1.54 +    }
    1.55 +
    1.56      data.data_in = (float *)inbuf; /* Older versions of libsamplerate had a non-const pointer, but didn't write to it */
    1.57      data.input_frames = inbuflen / framelen;
    1.58      data.input_frames_used = 0;
    1.59 @@ -1125,24 +1158,6 @@
    1.60      return retval;
    1.61  }
    1.62  
    1.63 -static Uint8 *
    1.64 -EnsureStreamBufferSize(SDL_AudioStream *stream, const int newlen)
    1.65 -{
    1.66 -    if (stream->work_buffer_len < newlen) {
    1.67 -        Uint8 *ptr = (Uint8 *) SDL_realloc(stream->work_buffer_base, newlen + 32);
    1.68 -        const size_t offset = ((size_t) ptr) & 15;
    1.69 -        if (!ptr) {
    1.70 -            SDL_OutOfMemory();
    1.71 -            return NULL;
    1.72 -        }
    1.73 -        /* Make sure we're aligned to 16 bytes for SIMD code. */
    1.74 -        stream->work_buffer = offset ? ptr + (16 - offset) : ptr;
    1.75 -        stream->work_buffer_base = ptr;
    1.76 -        stream->work_buffer_len = newlen;
    1.77 -    }
    1.78 -    return stream->work_buffer;
    1.79 -}
    1.80 -
    1.81  int
    1.82  SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, const Uint32 _buflen)
    1.83  {
    1.84 @@ -1190,11 +1205,14 @@
    1.85          if (workbuf == NULL) {
    1.86              return -1;  /* probably out of memory. */
    1.87          }
    1.88 -        if (buf == origbuf) {  /* copy if we haven't before. */
    1.89 -            SDL_memcpy(workbuf, buf, buflen);
    1.90 +        /* don't SDL_memcpy(workbuf, buf, buflen) here; our resampler can work inplace or not,
    1.91 +           libsamplerate needs buffers to be separate; either way, avoid a copy here if possible. */
    1.92 +        if (buf != origbuf) {
    1.93 +            buf = workbuf;  /* in case we realloc()'d the pointer. */
    1.94          }
    1.95 -        buflen = stream->resampler_func(stream, workbuf, buflen, workbuf, workbuflen);
    1.96 -        buf = workbuf;
    1.97 +        buflen = stream->resampler_func(stream, buf, buflen, workbuf, workbuflen);
    1.98 +        buf = EnsureStreamBufferSize(stream, workbuflen);
    1.99 +        SDL_assert(buf != NULL);  /* shouldn't be growing, just aligning. */
   1.100      }
   1.101  
   1.102      if (stream->cvt_after_resampling.needed) {