mirror of
				https://github.com/libsdl-org/SDL.git
				synced 2025-10-26 12:27:44 +00:00 
			
		
		
		
	audio: Resampler now special-cases stereo and mono processing.
Turns out that iterating from 0 to channels-1 was a serious performance hit! These cases now tend to match or beat the original audio resampler's speed!
This commit is contained in:
		| @@ -249,16 +249,52 @@ SDL_ResampleAudioSimple(const int chans, const double rate_incr, | |||||||
|     SDL_assert((dest_samples * framelen) <= outbuflen); |     SDL_assert((dest_samples * framelen) <= outbuflen); | ||||||
|     SDL_assert((inbuflen % framelen) == 0); |     SDL_assert((inbuflen % framelen) == 0); | ||||||
|  |  | ||||||
|     if (rate_incr > 1.0) { |     if (rate_incr > 1.0) {  /* upsample */ | ||||||
|         float *target = (outbuf + chans); |         float *target = (outbuf + chans); | ||||||
|         const float *earlier_sample = &inbuf[finalpos]; |  | ||||||
|         float final_sample[8]; |  | ||||||
|         dst = outbuf + (dest_samples * chans); |         dst = outbuf + (dest_samples * chans); | ||||||
|         idx = (double) total; |         idx = (double) total; | ||||||
|  |  | ||||||
|         /* save this off so we can correctly maintain state between runs. */ |         if (chans == 1) { | ||||||
|  |             const float final_sample = inbuf[finalpos]; | ||||||
|  |             float earlier_sample = inbuf[finalpos]; | ||||||
|  |             while (dst > target) { | ||||||
|  |                 const int pos = ((int) idx) * chans; | ||||||
|  |                 const float *src = &inbuf[pos]; | ||||||
|  |                 const float val = *(--src); | ||||||
|  |                 SDL_assert(pos >= 0.0); | ||||||
|  |                 *(--dst) = (val + earlier_sample) * 0.5f; | ||||||
|  |                 earlier_sample = val; | ||||||
|  |                 idx -= src_incr; | ||||||
|  |             } | ||||||
|  |             /* do last sample, interpolated against previous run's state. */ | ||||||
|  |             *(--dst) = (inbuf[0] + last_sample[0]) * 0.5f; | ||||||
|  |             *last_sample = final_sample; | ||||||
|  |         } else if (chans == 2) { | ||||||
|  |             const float final_sample2 = inbuf[finalpos+1]; | ||||||
|  |             const float final_sample1 = inbuf[finalpos]; | ||||||
|  |             float earlier_sample2 = inbuf[finalpos]; | ||||||
|  |             float earlier_sample1 = inbuf[finalpos-1]; | ||||||
|  |             while (dst > target) { | ||||||
|  |                 const int pos = ((int) idx) * chans; | ||||||
|  |                 const float *src = &inbuf[pos]; | ||||||
|  |                 const float val2 = *(--src); | ||||||
|  |                 const float val1 = *(--src); | ||||||
|  |                 SDL_assert(pos >= 0.0); | ||||||
|  |                 *(--dst) = (val2 + earlier_sample2) * 0.5f; | ||||||
|  |                 *(--dst) = (val1 + earlier_sample1) * 0.5f; | ||||||
|  |                 earlier_sample2 = val2; | ||||||
|  |                 earlier_sample1 = val1; | ||||||
|  |                 idx -= src_incr; | ||||||
|  |             } | ||||||
|  |             /* do last sample, interpolated against previous run's state. */ | ||||||
|  |             *(--dst) = (inbuf[1] + last_sample[1]) * 0.5f; | ||||||
|  |             *(--dst) = (inbuf[0] + last_sample[0]) * 0.5f; | ||||||
|  |             last_sample[1] = final_sample2; | ||||||
|  |             last_sample[0] = final_sample1; | ||||||
|  |         } else { | ||||||
|  |             const float *earlier_sample = &inbuf[finalpos]; | ||||||
|  |             float final_sample[8]; | ||||||
|             SDL_memcpy(final_sample, &inbuf[finalpos], framelen); |             SDL_memcpy(final_sample, &inbuf[finalpos], framelen); | ||||||
|  |  | ||||||
|             while (dst > target) { |             while (dst > target) { | ||||||
|                 const int pos = ((int) idx) * chans; |                 const int pos = ((int) idx) * chans; | ||||||
|                 const float *src = &inbuf[pos]; |                 const float *src = &inbuf[pos]; | ||||||
| @@ -270,18 +306,47 @@ SDL_ResampleAudioSimple(const int chans, const double rate_incr, | |||||||
|                 earlier_sample = src; |                 earlier_sample = src; | ||||||
|                 idx -= src_incr; |                 idx -= src_incr; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             /* do last sample, interpolated against previous run's state. */ |             /* do last sample, interpolated against previous run's state. */ | ||||||
|             for (i = chans - 1; i >= 0; i--) { |             for (i = chans - 1; i >= 0; i--) { | ||||||
|                 const float val = inbuf[i]; |                 const float val = inbuf[i]; | ||||||
|                 *(--dst) = (val + last_sample[i]) * 0.5f; |                 *(--dst) = (val + last_sample[i]) * 0.5f; | ||||||
|             } |             } | ||||||
|             SDL_memcpy(last_sample, final_sample, framelen); |             SDL_memcpy(last_sample, final_sample, framelen); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         dst = (outbuf + (dest_samples * chans)) - 1; |         dst = (outbuf + (dest_samples * chans)) - 1; | ||||||
|     } else { |     } else {  /* downsample */ | ||||||
|         float *target = (outbuf + (dest_samples * chans)); |         float *target = (outbuf + (dest_samples * chans)); | ||||||
|         dst = outbuf; |         dst = outbuf; | ||||||
|         idx = 0.0; |         idx = 0.0; | ||||||
|  |         if (chans == 1) { | ||||||
|  |             float last = *last_sample; | ||||||
|  |             while (dst < target) { | ||||||
|  |                 const int pos = ((int) idx) * chans; | ||||||
|  |                 const float val = inbuf[pos]; | ||||||
|  |                 SDL_assert(pos <= finalpos); | ||||||
|  |                 *(dst++) = (val + last) * 0.5f; | ||||||
|  |                 last = val; | ||||||
|  |                 idx += src_incr; | ||||||
|  |             } | ||||||
|  |             *last_sample = last; | ||||||
|  |         } else if (chans == 2) { | ||||||
|  |             float last1 = last_sample[0]; | ||||||
|  |             float last2 = last_sample[1]; | ||||||
|  |             while (dst < target) { | ||||||
|  |                 const int pos = ((int) idx) * chans; | ||||||
|  |                 const float val1 = inbuf[pos]; | ||||||
|  |                 const float val2 = inbuf[pos+1]; | ||||||
|  |                 SDL_assert(pos <= finalpos); | ||||||
|  |                 *(dst++) = (val1 + last1) * 0.5f; | ||||||
|  |                 *(dst++) = (val2 + last2) * 0.5f; | ||||||
|  |                 last1 = val1; | ||||||
|  |                 last2 = val2; | ||||||
|  |                 idx += src_incr; | ||||||
|  |             } | ||||||
|  |             last_sample[0] = last1; | ||||||
|  |             last_sample[1] = last2; | ||||||
|  |         } else { | ||||||
|             while (dst < target) { |             while (dst < target) { | ||||||
|                 const int pos = ((int) idx) * chans; |                 const int pos = ((int) idx) * chans; | ||||||
|                 const float *src = &inbuf[pos]; |                 const float *src = &inbuf[pos]; | ||||||
| @@ -294,6 +359,7 @@ SDL_ResampleAudioSimple(const int chans, const double rate_incr, | |||||||
|                 idx += src_incr; |                 idx += src_incr; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return (int) ((dst - outbuf) * ((int) sizeof (float))); |     return (int) ((dst - outbuf) * ((int) sizeof (float))); | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Ryan C. Gordon
					Ryan C. Gordon