summaryrefslogtreecommitdiff
path: root/libswresample/resample.c
diff options
context:
space:
mode:
Diffstat (limited to 'libswresample/resample.c')
-rw-r--r--libswresample/resample.c44
1 files changed, 40 insertions, 4 deletions
diff --git a/libswresample/resample.c b/libswresample/resample.c
index 036eff391f..c881ed8f41 100644
--- a/libswresample/resample.c
+++ b/libswresample/resample.c
@@ -74,7 +74,7 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap
int filter_type, int kaiser_beta){
int ph, i;
double x, y, w;
- double *tab = av_malloc_array(tap_count, sizeof(*tab));
+ double *tab = av_malloc_array(tap_count+1, sizeof(*tab));
const int center= (tap_count-1)/2;
if (!tab)
@@ -84,9 +84,10 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap
if (factor > 1.0)
factor = 1.0;
- for(ph=0;ph<phase_count;ph++) {
+ av_assert0(phase_count == 1 || phase_count % 2 == 0);
+ for(ph = 0; ph <= phase_count / 2; ph++) {
double norm = 0;
- for(i=0;i<tap_count;i++) {
+ for(i=0;i<=tap_count;i++) {
x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor;
if (x == 0) y = 1.0;
else y = sin(x) / x;
@@ -110,7 +111,8 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap
}
tab[i] = y;
- norm += y;
+ if (i < tap_count)
+ norm += y;
}
/* normalize so that an uniform color remains the same */
@@ -118,18 +120,52 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap
case AV_SAMPLE_FMT_S16P:
for(i=0;i<tap_count;i++)
((int16_t*)filter)[ph * alloc + i] = av_clip(lrintf(tab[i] * scale / norm), INT16_MIN, INT16_MAX);
+ if (tap_count % 2 == 0) {
+ for (i = 0; i < tap_count; i++)
+ ((int16_t*)filter)[(phase_count-ph) * alloc + tap_count-1-i] = ((int16_t*)filter)[ph * alloc + i];
+ }
+ else {
+ for (i = 1; i <= tap_count; i++)
+ ((int16_t*)filter)[(phase_count-ph) * alloc + tap_count-i] =
+ av_clip(lrintf(tab[i] * scale / (norm - tab[0] + tab[tap_count])), INT16_MIN, INT16_MAX);
+ }
break;
case AV_SAMPLE_FMT_S32P:
for(i=0;i<tap_count;i++)
((int32_t*)filter)[ph * alloc + i] = av_clipl_int32(llrint(tab[i] * scale / norm));
+ if (tap_count % 2 == 0) {
+ for (i = 0; i < tap_count; i++)
+ ((int32_t*)filter)[(phase_count-ph) * alloc + tap_count-1-i] = ((int32_t*)filter)[ph * alloc + i];
+ }
+ else {
+ for (i = 1; i <= tap_count; i++)
+ ((int32_t*)filter)[(phase_count-ph) * alloc + tap_count-i] =
+ av_clipl_int32(llrint(tab[i] * scale / (norm - tab[0] + tab[tap_count])));
+ }
break;
case AV_SAMPLE_FMT_FLTP:
for(i=0;i<tap_count;i++)
((float*)filter)[ph * alloc + i] = tab[i] * scale / norm;
+ if (tap_count % 2 == 0) {
+ for (i = 0; i < tap_count; i++)
+ ((float*)filter)[(phase_count-ph) * alloc + tap_count-1-i] = ((float*)filter)[ph * alloc + i];
+ }
+ else {
+ for (i = 1; i <= tap_count; i++)
+ ((float*)filter)[(phase_count-ph) * alloc + tap_count-i] = tab[i] * scale / (norm - tab[0] + tab[tap_count]);
+ }
break;
case AV_SAMPLE_FMT_DBLP:
for(i=0;i<tap_count;i++)
((double*)filter)[ph * alloc + i] = tab[i] * scale / norm;
+ if (tap_count % 2 == 0) {
+ for (i = 0; i < tap_count; i++)
+ ((double*)filter)[(phase_count-ph) * alloc + tap_count-1-i] = ((double*)filter)[ph * alloc + i];
+ }
+ else {
+ for (i = 1; i <= tap_count; i++)
+ ((double*)filter)[(phase_count-ph) * alloc + tap_count-i] = tab[i] * scale / (norm - tab[0] + tab[tap_count]);
+ }
break;
}
}