diff --git a/audio/cc_resampler.c b/audio/cc_resampler.c index 591a9354a0..82702c8a9e 100644 --- a/audio/cc_resampler.c +++ b/audio/cc_resampler.c @@ -13,35 +13,37 @@ #include #include +#ifndef RESAMPLER_TEST #include "../general.h" +#else +#define RARCH_LOG(...) fprintf(stderr, __VA_ARGS__) +#endif + +#ifdef _MIPS_ARCH_ALLEGREX1 typedef struct rarch_CC_resampler { int dummy; }rarch_CC_resampler_t; -typedef struct audio_frame_float -{ - float l; - float r; -}audio_frame_float_t; - -typedef struct audio_frame_int16 -{ - int16_t l; - int16_t r; -}audio_frame_int16_t; - - -#ifdef _MIPS_ARCH_ALLEGREX static void resampler_CC_process(void *re_, struct resampler_data *data) { (void)re_; // rarch_CC_resampler_t *re = (rarch_CC_resampler_t*)re_; - - float ratio,fraction; + typedef struct audio_frame_float + { + float l; + float r; + }audio_frame_float_t; + + typedef struct audio_frame_int16 + { + int16_t l; + int16_t r; + }audio_frame_int16_t; + audio_frame_float_t *inp = (audio_frame_float_t*)data->data_in; audio_frame_float_t *inp_max = inp + data->input_frames; @@ -123,9 +125,7 @@ static void resampler_CC_process(void *re_, struct resampler_data *data) done: data->output_frames = (outp - (audio_frame_float_t*)data->data_out); } -#else -#error "platform not supported" -#endif + static void resampler_CC_free(void *re_) { @@ -153,8 +153,202 @@ static void *resampler_CC_init(double bandwidth_mod) ".set pop\n" ); + RARCH_LOG("\nConvoluted Cosine resampler (VFPU): \n"); return re; } +#else + + +//#define HAVE_SSE_MATHFUN_H +#if defined(__SSE2__) && defined(HAVE_SSE_MATHFUN_H) +#define USE_SSE2 +#include "sse_mathfun.h" + +static inline float _mm_sin(float x) +{ + static float temp; + __m128 vector = _mm_set1_ps(x); + vector = sin_ps(vector); + _mm_store1_ps(&temp,vector); + return temp; +} +static inline float _mm_cos(float x) +{ + static float temp; + __m128 vector = _mm_set1_ps(x); + vector = cos_ps(vector); + _mm_store1_ps(&temp,vector); + return temp; +} + +#define sin(x) _mm_sin(x) +#define cos(x) _mm_cos(x) +#endif + + +typedef struct audio_frame_float +{ + float l; + float r; +}audio_frame_float_t; + +typedef struct rarch_CC_resampler +{ + audio_frame_float_t buffer[4]; + float distance; + void (*process)(void *re, struct resampler_data *data); + +}rarch_CC_resampler_t; + + + +static inline float cc_int(float x, float b){ + float val = x * b * M_PI + sin(x * b * M_PI); + return (val > M_PI)? M_PI : (val < -M_PI)? -M_PI : val; +} + +static inline float cc_kernel(float x, float b){ + return (cc_int(x + 0.5, b) - cc_int(x - 0.5, b)) / (2.0 * M_PI); +} + +static inline void add_to(const audio_frame_float_t* source,audio_frame_float_t* target, float ratio){ + target->l += source->l * ratio; + target->r += source->r * ratio; +} + +static void resampler_CC_downsample(void *re_, struct resampler_data *data) +{ + + rarch_CC_resampler_t *re = (rarch_CC_resampler_t*)re_; + + audio_frame_float_t *inp = (audio_frame_float_t*)data->data_in; + audio_frame_float_t *inp_max = inp + data->input_frames; + audio_frame_float_t *outp = (audio_frame_float_t*)data->data_out; + + float ratio = 1.0 / data->ratio; + + float b = data->ratio; // cutoff frequency + + while(inp != inp_max) + { + add_to(inp, re->buffer + 0, cc_kernel(re->distance, b)); + add_to(inp, re->buffer + 1, cc_kernel(re->distance - ratio, b)); + add_to(inp, re->buffer + 2, cc_kernel(re->distance - ratio - ratio, b)); + + re->distance++; + inp++; + + if (re->distance > (ratio + 0.5)) + { + *outp=re->buffer[0]; + + re->buffer[0] = re->buffer[1]; + re->buffer[1] = re->buffer[2]; + + re->buffer[2].l = 0.0; + re->buffer[2].r = 0.0; + + re->distance-=ratio; + outp++; + } + } + + data->output_frames = (outp - (audio_frame_float_t*)data->data_out); +} + +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + +static void resampler_CC_upsample(void *re_, struct resampler_data *data) +{ + + rarch_CC_resampler_t *re = (rarch_CC_resampler_t*)re_; + + audio_frame_float_t *inp = (audio_frame_float_t*)data->data_in; + audio_frame_float_t *inp_max = inp + data->input_frames; + audio_frame_float_t *outp = (audio_frame_float_t*)data->data_out; + + float b = min(data->ratio, 1.00); // cutoff frequency + float ratio = 1.0 / data->ratio; + + while(inp != inp_max) + { + re->buffer[0] = re->buffer[1]; + re->buffer[1] = re->buffer[2]; + re->buffer[2] = re->buffer[3]; + re->buffer[3] = *inp; + + while (re->distance < 1.0) + { + int i; + float temp; + outp->l = 0.0; + outp->r = 0.0; + + for (i=0; i!=4; i++) + { + temp = cc_kernel(re->distance + 1.0 - i, b); + outp->l += re->buffer[i].l * temp; + outp->r += re->buffer[i].r * temp; + } + + re->distance += ratio; + outp++; + } + + re->distance-= 1.0; + inp++; + } + + data->output_frames = (outp - (audio_frame_float_t*)data->data_out); + +} + +static void resampler_CC_process(void *re_, struct resampler_data *data) +{ + rarch_CC_resampler_t *re = (rarch_CC_resampler_t*)re_; + re->process(re_, data); +} + +static void resampler_CC_free(void *re_) +{ + rarch_CC_resampler_t *re = (rarch_CC_resampler_t*)re_; + if (re) + free(re); +} + +static void *resampler_CC_init(double bandwidth_mod) +{ + int i; + rarch_CC_resampler_t *re = (rarch_CC_resampler_t*)calloc(1, sizeof(rarch_CC_resampler_t)); + if (!re) + return NULL; + + for (i=0; i!=4 ; i++) + { + re->buffer[i].l=0.0; + re->buffer[i].r=0.0; + } + + RARCH_LOG("Convoluted Cosine resampler (C) : "); + + if (bandwidth_mod < 0.75) // variations of data->ratio around 0.75 are safer than around 1.0 for both up/downsampler. + { + RARCH_LOG("CC_downsample @%f \n", bandwidth_mod); + re->process = resampler_CC_downsample; + re->distance = 0.0; + } + else + { + RARCH_LOG("CC_upsample @%f \n", bandwidth_mod); + re->process = resampler_CC_upsample; + re->distance = 2.0; + } + + return re; +} +#endif const rarch_resampler_t CC_resampler = { resampler_CC_init, @@ -162,6 +356,3 @@ const rarch_resampler_t CC_resampler = { resampler_CC_free, "CC", }; - - -