src/audio/SDL_audiocvt.c
changeset 10842 30b37eaf3b3c
parent 10841 b9d6a3d65394
child 10843 31c9dede7b9c
equal deleted inserted replaced
10841:b9d6a3d65394 10842:30b37eaf3b3c
   856 
   856 
   857     cvt->needed = (cvt->filter_index != 0);
   857     cvt->needed = (cvt->filter_index != 0);
   858     return (cvt->needed);
   858     return (cvt->needed);
   859 }
   859 }
   860 
   860 
   861 typedef int (*SDL_ResampleAudioStreamFunc)(SDL_AudioStream *stream, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen);
   861 typedef int (*SDL_ResampleAudioStreamFunc)(SDL_AudioStream *stream, const void *inbuf, const int inbuflen, void *outbuf, const int outbuflen);
   862 typedef void (*SDL_ResetAudioStreamResamplerFunc)(SDL_AudioStream *stream);
   862 typedef void (*SDL_ResetAudioStreamResamplerFunc)(SDL_AudioStream *stream);
   863 typedef void (*SDL_CleanupAudioStreamResamplerFunc)(SDL_AudioStream *stream);
   863 typedef void (*SDL_CleanupAudioStreamResamplerFunc)(SDL_AudioStream *stream);
   864 
   864 
   865 struct SDL_AudioStream
   865 struct SDL_AudioStream
   866 {
   866 {
   888     SDL_CleanupAudioStreamResamplerFunc cleanup_resampler_func;
   888     SDL_CleanupAudioStreamResamplerFunc cleanup_resampler_func;
   889 };
   889 };
   890 
   890 
   891 #ifdef HAVE_LIBSAMPLERATE_H
   891 #ifdef HAVE_LIBSAMPLERATE_H
   892 static int
   892 static int
   893 SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
   893 SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
   894 {
   894 {
       
   895     const float *inbuf = (const float *) _inbuf;
       
   896     float *outbuf = (float *) _outbuf;
   895     const int framelen = sizeof(float) * stream->pre_resample_channels;
   897     const int framelen = sizeof(float) * stream->pre_resample_channels;
   896     SRC_STATE *state = (SRC_STATE *)stream->resampler_state;
   898     SRC_STATE *state = (SRC_STATE *)stream->resampler_state;
   897     SRC_DATA data;
   899     SRC_DATA data;
   898     int result;
   900     int result;
   899 
   901 
   968 
   970 
   969 
   971 
   970 typedef struct
   972 typedef struct
   971 {
   973 {
   972     SDL_bool resampler_seeded;
   974     SDL_bool resampler_seeded;
   973     float resampler_state[8];
   975     union
       
   976     {
       
   977         float f[8];
       
   978         Sint16 si16[2];
       
   979     } resampler_state;
   974 } SDL_AudioStreamResamplerState;
   980 } SDL_AudioStreamResamplerState;
   975 
   981 
   976 static int
   982 static int
   977 SDL_ResampleAudioStream(SDL_AudioStream *stream, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
   983 SDL_ResampleAudioStream(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
   978 {
   984 {
       
   985     const float *inbuf = (const float *) _inbuf;
       
   986     float *outbuf = (float *) _outbuf;
   979     SDL_AudioStreamResamplerState *state = (SDL_AudioStreamResamplerState*)stream->resampler_state;
   987     SDL_AudioStreamResamplerState *state = (SDL_AudioStreamResamplerState*)stream->resampler_state;
   980     const int chans = (int)stream->pre_resample_channels;
   988     const int chans = (int)stream->pre_resample_channels;
   981 
   989 
   982     SDL_assert(chans <= SDL_arraysize(state->resampler_state));
   990     SDL_assert(chans <= SDL_arraysize(state->resampler_state.f));
   983 
   991 
   984     if (!state->resampler_seeded) {
   992     if (!state->resampler_seeded) {
   985         int i;
   993         SDL_memcpy(state->resampler_state.f, inbuf, chans * sizeof (float));
   986         for (i = 0; i < chans; i++) {
       
   987             state->resampler_state[i] = inbuf[i];
       
   988         }
       
   989         state->resampler_seeded = SDL_TRUE;
   994         state->resampler_seeded = SDL_TRUE;
   990     }
   995     }
   991 
   996 
   992     return SDL_ResampleAudioSimple(chans, stream->rate_incr, state->resampler_state, inbuf, inbuflen, outbuf, outbuflen);
   997     return SDL_ResampleAudioSimple(chans, stream->rate_incr, state->resampler_state.f, inbuf, inbuflen, outbuf, outbuflen);
       
   998 }
       
   999 
       
  1000 static int
       
  1001 SDL_ResampleAudioStream_si16_c2(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
       
  1002 {
       
  1003     const Sint16 *inbuf = (const Sint16 *) _inbuf;
       
  1004     Sint16 *outbuf = (Sint16 *) _outbuf;
       
  1005     SDL_AudioStreamResamplerState *state = (SDL_AudioStreamResamplerState*)stream->resampler_state;
       
  1006     const int chans = (int)stream->pre_resample_channels;
       
  1007 
       
  1008     SDL_assert(chans <= SDL_arraysize(state->resampler_state.si16));
       
  1009 
       
  1010     if (!state->resampler_seeded) {
       
  1011         state->resampler_state.si16[0] = inbuf[0];
       
  1012         state->resampler_state.si16[1] = inbuf[1];
       
  1013         state->resampler_seeded = SDL_TRUE;
       
  1014     }
       
  1015 
       
  1016     return SDL_ResampleAudioSimple_si16_c2(stream->rate_incr, state->resampler_state.si16, inbuf, inbuflen, outbuf, outbuflen);
   993 }
  1017 }
   994 
  1018 
   995 static void
  1019 static void
   996 SDL_ResetAudioStreamResampler(SDL_AudioStream *stream)
  1020 SDL_ResetAudioStreamResampler(SDL_AudioStream *stream)
   997 {
  1021 {
  1014                    const int dst_rate)
  1038                    const int dst_rate)
  1015 {
  1039 {
  1016     const int packetlen = 4096;  /* !!! FIXME: good enough for now. */
  1040     const int packetlen = 4096;  /* !!! FIXME: good enough for now. */
  1017     Uint8 pre_resample_channels;
  1041     Uint8 pre_resample_channels;
  1018     SDL_AudioStream *retval;
  1042     SDL_AudioStream *retval;
       
  1043 #ifndef HAVE_LIBSAMPLERATE_H
       
  1044     const SDL_bool SRC_available = SDL_FALSE;
       
  1045 #endif
  1019 
  1046 
  1020     retval = (SDL_AudioStream *) SDL_calloc(1, sizeof (SDL_AudioStream));
  1047     retval = (SDL_AudioStream *) SDL_calloc(1, sizeof (SDL_AudioStream));
  1021     if (!retval) {
  1048     if (!retval) {
  1022         return NULL;
  1049         return NULL;
  1023     }
  1050     }
  1041     retval->rate_incr = ((double) dst_rate) / ((double) src_rate);
  1068     retval->rate_incr = ((double) dst_rate) / ((double) src_rate);
  1042 
  1069 
  1043     /* Not resampling? It's an easy conversion (and maybe not even that!). */
  1070     /* Not resampling? It's an easy conversion (and maybe not even that!). */
  1044     if (src_rate == dst_rate) {
  1071     if (src_rate == dst_rate) {
  1045         retval->cvt_before_resampling.needed = SDL_FALSE;
  1072         retval->cvt_before_resampling.needed = SDL_FALSE;
  1046         retval->cvt_before_resampling.len_mult = 1;
       
  1047         if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, src_format, src_channels, dst_rate, dst_format, dst_channels, dst_rate) < 0) {
  1073         if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, src_format, src_channels, dst_rate, dst_format, dst_channels, dst_rate) < 0) {
  1048             SDL_FreeAudioStream(retval);
  1074             SDL_FreeAudioStream(retval);
  1049             return NULL;  /* SDL_BuildAudioCVT should have called SDL_SetError. */
  1075             return NULL;  /* SDL_BuildAudioCVT should have called SDL_SetError. */
  1050         }
  1076         }
       
  1077     /* fast path special case for stereo Sint16 data that just needs resampling. */
       
  1078     } else if ((!SRC_available) && (src_channels == 2) && (dst_channels == 2) && (src_format == AUDIO_S16SYS) && (dst_format == AUDIO_S16SYS)) {
       
  1079         SDL_assert(src_rate != dst_rate);
       
  1080         retval->resampler_state = SDL_calloc(1, sizeof(SDL_AudioStreamResamplerState));
       
  1081         if (!retval->resampler_state) {
       
  1082             SDL_FreeAudioStream(retval);
       
  1083             SDL_OutOfMemory();
       
  1084             return NULL;
       
  1085         }
       
  1086         retval->resampler_func = SDL_ResampleAudioStream_si16_c2;
       
  1087         retval->reset_resampler_func = SDL_ResetAudioStreamResampler;
       
  1088         retval->cleanup_resampler_func = SDL_CleanupAudioStreamResampler;
  1051     } else {
  1089     } else {
  1052         /* Don't resample at first. Just get us to Float32 format. */
  1090         /* Don't resample at first. Just get us to Float32 format. */
  1053         /* !!! FIXME: convert to int32 on devices without hardware float. */
  1091         /* !!! FIXME: convert to int32 on devices without hardware float. */
  1054         if (SDL_BuildAudioCVT(&retval->cvt_before_resampling, src_format, src_channels, src_rate, AUDIO_F32SYS, pre_resample_channels, src_rate) < 0) {
  1092         if (SDL_BuildAudioCVT(&retval->cvt_before_resampling, src_format, src_channels, src_rate, AUDIO_F32SYS, pre_resample_channels, src_rate) < 0) {
  1055             SDL_FreeAudioStream(retval);
  1093             SDL_FreeAudioStream(retval);
  1134         buflen = stream->cvt_before_resampling.len_cvt;
  1172         buflen = stream->cvt_before_resampling.len_cvt;
  1135     }
  1173     }
  1136 
  1174 
  1137     if (stream->dst_rate != stream->src_rate) {
  1175     if (stream->dst_rate != stream->src_rate) {
  1138         const int workbuflen = buflen * ((int) SDL_ceil(stream->rate_incr));
  1176         const int workbuflen = buflen * ((int) SDL_ceil(stream->rate_incr));
  1139         float *workbuf = (float *) EnsureBufferSize(&stream->resample_buffer, &stream->resample_buffer_len, workbuflen);
  1177         void *workbuf = EnsureBufferSize(&stream->resample_buffer, &stream->resample_buffer_len, workbuflen);
  1140         if (workbuf == NULL) {
  1178         if (workbuf == NULL) {
  1141             return -1;  /* probably out of memory. */
  1179             return -1;  /* probably out of memory. */
  1142         }
  1180         }
  1143         buflen = stream->resampler_func(stream, (float *) buf, buflen, workbuf, workbuflen);
  1181         buflen = stream->resampler_func(stream, buf, buflen, workbuf, workbuflen);
  1144         buf = workbuf;
  1182         buf = workbuf;
  1145     }
  1183     }
  1146 
  1184 
  1147     if (stream->cvt_after_resampling.needed) {
  1185     if (stream->cvt_after_resampling.needed) {
  1148         const int workbuflen = buflen * stream->cvt_before_resampling.len_mult;  /* will be "* 1" if not needed */
  1186         const int workbuflen = buflen * stream->cvt_after_resampling.len_mult;  /* will be "* 1" if not needed */
  1149         Uint8 *workbuf;
  1187         Uint8 *workbuf;
  1150 
  1188 
  1151         if (buf == stream->resample_buffer) {
  1189         if (buf == stream->resample_buffer) {
  1152             workbuf = EnsureBufferSize(&stream->resample_buffer, &stream->resample_buffer_len, workbuflen);
  1190             workbuf = EnsureBufferSize(&stream->resample_buffer, &stream->resample_buffer_len, workbuflen);
  1153         } else {
  1191         } else {