Mercurial > libavcodec.hg
comparison resample2.c @ 2306:072fc321fbe6 libavcodec
make most resample filter parameters selectable at runtime
| author | michael |
|---|---|
| date | Thu, 21 Oct 2004 03:11:34 +0000 |
| parents | 9568c8880d96 |
| children | df3e4a8e6aac |
comparison
equal
deleted
inserted
replaced
| 2305:9568c8880d96 | 2306:072fc321fbe6 |
|---|---|
| 25 */ | 25 */ |
| 26 | 26 |
| 27 #include "avcodec.h" | 27 #include "avcodec.h" |
| 28 #include "common.h" | 28 #include "common.h" |
| 29 #include "dsputil.h" | 29 #include "dsputil.h" |
| 30 | |
| 31 #define PHASE_SHIFT 10 | |
| 32 #define PHASE_COUNT (1<<PHASE_SHIFT) | |
| 33 #define PHASE_MASK (PHASE_COUNT-1) | |
| 34 #define FILTER_SIZE 16 | |
| 35 //#define LINEAR 1 | |
| 36 | 30 |
| 37 #if 1 | 31 #if 1 |
| 38 #define FILTER_SHIFT 15 | 32 #define FILTER_SHIFT 15 |
| 39 | 33 |
| 40 #define FELEM int16_t | 34 #define FELEM int16_t |
| 58 int dst_incr; | 52 int dst_incr; |
| 59 int index; | 53 int index; |
| 60 int frac; | 54 int frac; |
| 61 int src_incr; | 55 int src_incr; |
| 62 int compensation_distance; | 56 int compensation_distance; |
| 57 int phase_shift; | |
| 58 int phase_mask; | |
| 59 int linear; | |
| 63 }AVResampleContext; | 60 }AVResampleContext; |
| 64 | 61 |
| 65 /** | 62 /** |
| 66 * 0th order modified bessel function of the first kind. | 63 * 0th order modified bessel function of the first kind. |
| 67 */ | 64 */ |
| 131 | 128 |
| 132 /** | 129 /** |
| 133 * initalizes a audio resampler. | 130 * initalizes a audio resampler. |
| 134 * note, if either rate is not a integer then simply scale both rates up so they are | 131 * note, if either rate is not a integer then simply scale both rates up so they are |
| 135 */ | 132 */ |
| 136 AVResampleContext *av_resample_init(int out_rate, int in_rate){ | 133 AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_size, int phase_shift, int linear){ |
| 137 AVResampleContext *c= av_mallocz(sizeof(AVResampleContext)); | 134 AVResampleContext *c= av_mallocz(sizeof(AVResampleContext)); |
| 138 double factor= FFMIN(out_rate / (double)in_rate, 1.0); | 135 double factor= FFMIN(out_rate / (double)in_rate, 1.0); |
| 139 | 136 int phase_count= 1<<phase_shift; |
| 137 | |
| 140 memset(c, 0, sizeof(AVResampleContext)); | 138 memset(c, 0, sizeof(AVResampleContext)); |
| 141 | 139 |
| 142 c->filter_length= ceil(FILTER_SIZE/factor); | 140 c->phase_shift= phase_shift; |
| 143 c->filter_bank= av_mallocz(c->filter_length*(PHASE_COUNT+1)*sizeof(FELEM)); | 141 c->phase_mask= phase_count-1; |
| 144 av_build_filter(c->filter_bank, factor, c->filter_length, PHASE_COUNT, 1<<FILTER_SHIFT, 1); | 142 c->linear= linear; |
| 145 memcpy(&c->filter_bank[c->filter_length*PHASE_COUNT+1], c->filter_bank, (c->filter_length-1)*sizeof(FELEM)); | 143 |
| 146 c->filter_bank[c->filter_length*PHASE_COUNT]= c->filter_bank[c->filter_length - 1]; | 144 c->filter_length= ceil(filter_size/factor); |
| 145 c->filter_bank= av_mallocz(c->filter_length*(phase_count+1)*sizeof(FELEM)); | |
| 146 av_build_filter(c->filter_bank, factor, c->filter_length, phase_count, 1<<FILTER_SHIFT, 1); | |
| 147 memcpy(&c->filter_bank[c->filter_length*phase_count+1], c->filter_bank, (c->filter_length-1)*sizeof(FELEM)); | |
| 148 c->filter_bank[c->filter_length*phase_count]= c->filter_bank[c->filter_length - 1]; | |
| 147 | 149 |
| 148 c->src_incr= out_rate; | 150 c->src_incr= out_rate; |
| 149 c->ideal_dst_incr= c->dst_incr= in_rate * PHASE_COUNT; | 151 c->ideal_dst_incr= c->dst_incr= in_rate * phase_count; |
| 150 c->index= -PHASE_COUNT*((c->filter_length-1)/2); | 152 c->index= -phase_count*((c->filter_length-1)/2); |
| 151 | 153 |
| 152 return c; | 154 return c; |
| 153 } | 155 } |
| 154 | 156 |
| 155 void av_resample_close(AVResampleContext *c){ | 157 void av_resample_close(AVResampleContext *c){ |
| 179 int dst_incr_frac= c->dst_incr % c->src_incr; | 181 int dst_incr_frac= c->dst_incr % c->src_incr; |
| 180 int dst_incr= c->dst_incr / c->src_incr; | 182 int dst_incr= c->dst_incr / c->src_incr; |
| 181 int compensation_distance= c->compensation_distance; | 183 int compensation_distance= c->compensation_distance; |
| 182 | 184 |
| 183 for(dst_index=0; dst_index < dst_size; dst_index++){ | 185 for(dst_index=0; dst_index < dst_size; dst_index++){ |
| 184 FELEM *filter= c->filter_bank + c->filter_length*(index & PHASE_MASK); | 186 FELEM *filter= c->filter_bank + c->filter_length*(index & c->phase_mask); |
| 185 int sample_index= index >> PHASE_SHIFT; | 187 int sample_index= index >> c->phase_shift; |
| 186 FELEM2 val=0; | 188 FELEM2 val=0; |
| 187 | 189 |
| 188 if(sample_index < 0){ | 190 if(sample_index < 0){ |
| 189 for(i=0; i<c->filter_length; i++) | 191 for(i=0; i<c->filter_length; i++) |
| 190 val += src[ABS(sample_index + i) % src_size] * filter[i]; | 192 val += src[ABS(sample_index + i) % src_size] * filter[i]; |
| 191 }else if(sample_index + c->filter_length > src_size){ | 193 }else if(sample_index + c->filter_length > src_size){ |
| 192 break; | 194 break; |
| 193 }else{ | 195 }else if(c->linear){ |
| 194 #ifdef LINEAR | |
| 195 int64_t v=0; | 196 int64_t v=0; |
| 196 int sub_phase= (frac<<8) / c->src_incr; | 197 int sub_phase= (frac<<8) / c->src_incr; |
| 197 for(i=0; i<c->filter_length; i++){ | 198 for(i=0; i<c->filter_length; i++){ |
| 198 int64_t coeff= filter[i]*(256 - sub_phase) + filter[i + c->filter_length]*sub_phase; | 199 int64_t coeff= filter[i]*(256 - sub_phase) + filter[i + c->filter_length]*sub_phase; |
| 199 v += src[sample_index + i] * coeff; | 200 v += src[sample_index + i] * coeff; |
| 200 } | 201 } |
| 201 val= v>>8; | 202 val= v>>8; |
| 202 #else | 203 }else{ |
| 203 for(i=0; i<c->filter_length; i++){ | 204 for(i=0; i<c->filter_length; i++){ |
| 204 val += src[sample_index + i] * (FELEM2)filter[i]; | 205 val += src[sample_index + i] * (FELEM2)filter[i]; |
| 205 } | 206 } |
| 206 #endif | |
| 207 } | 207 } |
| 208 | 208 |
| 209 val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT; | 209 val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT; |
| 210 dst[dst_index] = (unsigned)(val + 32768) > 65535 ? (val>>31) ^ 32767 : val; | 210 dst[dst_index] = (unsigned)(val + 32768) > 65535 ? (val>>31) ^ 32767 : val; |
| 211 | 211 |
| 220 compensation_distance= 0; | 220 compensation_distance= 0; |
| 221 dst_incr_frac= c->ideal_dst_incr % c->src_incr; | 221 dst_incr_frac= c->ideal_dst_incr % c->src_incr; |
| 222 dst_incr= c->ideal_dst_incr / c->src_incr; | 222 dst_incr= c->ideal_dst_incr / c->src_incr; |
| 223 } | 223 } |
| 224 } | 224 } |
| 225 *consumed= FFMAX(index, 0) >> PHASE_SHIFT; | 225 *consumed= FFMAX(index, 0) >> c->phase_shift; |
| 226 index= FFMIN(index, 0); | 226 index= FFMIN(index, 0); |
| 227 | 227 |
| 228 if(compensation_distance){ | 228 if(compensation_distance){ |
| 229 compensation_distance -= dst_index; | 229 compensation_distance -= dst_index; |
| 230 assert(compensation_distance > 0); | 230 assert(compensation_distance > 0); |
