X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fresample2.c;h=31d2be7ded984a9f47d7cae21e627c7e1d55329b;hb=f95bfab05cb0edbed2830dca7bc79d46b42bbf95;hp=6f487bfd95af23cde39184b93108d067ae747746;hpb=ca6940f871c2b8fdd056407f7928659d42c6d1b0;p=ffmpeg diff --git a/libavcodec/resample2.c b/libavcodec/resample2.c index 6f487bfd95a..31d2be7ded9 100644 --- a/libavcodec/resample2.c +++ b/libavcodec/resample2.c @@ -17,37 +17,47 @@ * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * */ /** - * @file resample2.c + * @file libavcodec/resample2.c * audio resampling * @author Michael Niedermayer */ #include "avcodec.h" -#include "common.h" #include "dsputil.h" -#if 1 +#ifndef CONFIG_RESAMPLE_HP #define FILTER_SHIFT 15 #define FELEM int16_t #define FELEM2 int32_t +#define FELEML int64_t #define FELEM_MAX INT16_MAX #define FELEM_MIN INT16_MIN -#else +#define WINDOW_TYPE 9 +#elif !defined(CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE) #define FILTER_SHIFT 30 #define FELEM int32_t #define FELEM2 int64_t +#define FELEML int64_t #define FELEM_MAX INT32_MAX #define FELEM_MIN INT32_MIN +#define WINDOW_TYPE 12 +#else +#define FILTER_SHIFT 0 + +#define FELEM double +#define FELEM2 double +#define FELEML double +#define WINDOW_TYPE 24 #endif typedef struct AVResampleContext{ + const AVClass *av_class; FELEM *filter_bank; int filter_length; int ideal_dst_incr; @@ -69,9 +79,10 @@ static double bessel(double x){ double t=1; int i; + x= x*x/4; for(i=1; i<50; i++){ - t *= i; - v += pow(x*x/4, i)/(t*t); + t *= x/(i*i); + v += t; } return v; } @@ -80,10 +91,10 @@ static double bessel(double x){ * builds a polyphase filterbank. * @param factor resampling factor * @param scale wanted sum of coefficients for each filter - * @param type 0->cubic, 1->blackman nuttall windowed sinc, 2->kaiser windowed sinc beta=16 + * @param type 0->cubic, 1->blackman nuttall windowed sinc, 2..16->kaiser windowed sinc beta=2..16 */ void av_build_filter(FELEM *filter, double factor, int tap_count, int phase_count, int scale, int type){ - int ph, i, v; + int ph, i; double x, y, w, tab[tap_count]; const int center= (tap_count-1)/2; @@ -108,9 +119,9 @@ void av_build_filter(FELEM *filter, double factor, int tap_count, int phase_coun w = 2.0*x / (factor*tap_count) + M_PI; y *= 0.3635819 - 0.4891775 * cos(w) + 0.1365995 * cos(2*w) - 0.0106411 * cos(3*w); break; - case 2: + default: w = 2.0*x / (factor*tap_count*M_PI); - y *= bessel(16*sqrt(FFMAX(1-w*w, 0))); + y *= bessel(type*sqrt(FFMAX(1-w*w, 0))); break; } @@ -120,8 +131,11 @@ void av_build_filter(FELEM *filter, double factor, int tap_count, int phase_coun /* normalize so that an uniform color remains the same */ for(i=0;ifilter_length= FFMAX((int)ceil(filter_size/factor), 1); c->filter_bank= av_mallocz(c->filter_length*(phase_count+1)*sizeof(FELEM)); - av_build_filter(c->filter_bank, factor, c->filter_length, phase_count, 1<filter_bank, factor, c->filter_length, phase_count, 1<filter_bank[c->filter_length*phase_count+1], c->filter_bank, (c->filter_length-1)*sizeof(FELEM)); c->filter_bank[c->filter_length*phase_count]= c->filter_bank[c->filter_length - 1]; @@ -193,33 +203,12 @@ void av_resample_close(AVResampleContext *c){ av_freep(&c); } -/** - * Compensates samplerate/timestamp drift. The compensation is done by changing - * the resampler parameters, so no audible clicks or similar distortions ocur - * @param compensation_distance distance in output samples over which the compensation should be performed - * @param sample_delta number of output samples which should be output less - * - * example: av_resample_compensate(c, 10, 500) - * here instead of 510 samples only 500 samples would be output - * - * note, due to rounding the actual compensation might be slightly different, - * especially if the compensation_distance is large and the in_rate used during init is small - */ void av_resample_compensate(AVResampleContext *c, int sample_delta, int compensation_distance){ // sample_delta += (c->ideal_dst_incr - c->dst_incr)*(int64_t)c->compensation_distance / c->ideal_dst_incr; c->compensation_distance= compensation_distance; c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / compensation_distance; } -/** - * resamples. - * @param src an array of unconsumed samples - * @param consumed the number of samples of src which have been consumed are returned here - * @param src_size the number of unconsumed samples available - * @param dst_size the amount of space in samples available in dst - * @param update_ctx if this is 0 then the context wont be modified, that way several channels can be resampled with the same context - * @return the number of samples written in dst or -1 if an error occured - */ int av_resample(AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx){ int dst_index, i; int index= c->index; @@ -253,21 +242,24 @@ int av_resample(AVResampleContext *c, short *dst, short *src, int *consumed, int }else if(sample_index + c->filter_length > src_size){ break; }else if(c->linear){ - int64_t v=0; - int sub_phase= (frac<<8) / c->src_incr; + FELEM2 v2=0; for(i=0; ifilter_length; i++){ - int64_t coeff= filter[i]*(256 - sub_phase) + filter[i + c->filter_length]*sub_phase; - v += src[sample_index + i] * coeff; + val += src[sample_index + i] * (FELEM2)filter[i]; + v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_length]; } - val= v>>8; + val+=(v2-val)*(FELEML)frac / c->src_incr; }else{ for(i=0; ifilter_length; i++){ val += src[sample_index + i] * (FELEM2)filter[i]; } } +#ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE + dst[dst_index] = av_clip_int16(lrintf(val)); +#else val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT; dst[dst_index] = (unsigned)(val + 32768) > 65535 ? (val>>31) ^ 32767 : val; +#endif frac += dst_incr_frac; index += dst_incr;