diff --git a/libswresample/dither.c b/libswresample/dither.c index f43d8911df..c79d37213a 100644 --- a/libswresample/dither.c +++ b/libswresample/dither.c @@ -41,35 +41,35 @@ void swri_get_dither(SwrContext *s, void *dst, int len, unsigned seed, enum AVSa if(in_fmt == AV_SAMPLE_FMT_S32 && out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1L<<24; if(in_fmt == AV_SAMPLE_FMT_S16 && out_fmt == AV_SAMPLE_FMT_U8 ) scale = 1L<<8; - scale *= s->dither_scale; + scale *= s->dither.scale; - s->ns_pos = 0; - s->ns_scale = scale; - s->ns_scale_1 = 1/scale; - memset(s->ns_errors, 0, sizeof(s->ns_errors)); + s->dither.ns_pos = 0; + s->dither.ns_scale = scale; + s->dither.ns_scale_1 = 1/scale; + memset(s->dither.ns_errors, 0, sizeof(s->dither.ns_errors)); for (i=0; filters[i].coefs; i++) { const filter_t *f = &filters[i]; - if (fabs(s->out_sample_rate - f->rate) / f->rate <= .05 && f->name == s->dither_method) { + if (fabs(s->out_sample_rate - f->rate) / f->rate <= .05 && f->name == s->dither.method) { int j; - s->ns_taps = f->len; + s->dither.ns_taps = f->len; for (j=0; jlen; j++) - s->ns_coeffs[j] = f->coefs[j]; + s->dither.ns_coeffs[j] = f->coefs[j]; break; } } - if (!filters[i].coefs && s->dither_method > SWR_DITHER_NS) { + if (!filters[i].coefs && s->dither.method > SWR_DITHER_NS) { av_log(s, AV_LOG_WARNING, "Requested noise shaping dither not available at this sampling rate, using triangular hp dither\n"); - s->dither_method = SWR_DITHER_TRIANGULAR_HIGHPASS; + s->dither.method = SWR_DITHER_TRIANGULAR_HIGHPASS; } for(i=0; idither_method){ + switch(s->dither.method){ case SWR_DITHER_RECTANGULAR: v= ((double)seed) / UINT_MAX - 0.5; break; default: - av_assert0(s->dither_method < SWR_DITHER_NB); + av_assert0(s->dither.method < SWR_DITHER_NB); v = ((double)seed) / UINT_MAX; seed = seed*1664525 + 1013904223; v-= ((double)seed) / UINT_MAX; @@ -81,9 +81,9 @@ void swri_get_dither(SwrContext *s, void *dst, int len, unsigned seed, enum AVSa for(i=0; idither_method){ + switch(s->dither.method){ default: - av_assert0(s->dither_method < SWR_DITHER_NB); + av_assert0(s->dither.method < SWR_DITHER_NB); v = tmp[i]; break; case SWR_DITHER_TRIANGULAR_HIGHPASS : diff --git a/libswresample/dither_template.c b/libswresample/dither_template.c index 7e99c50700..ffa5bdd664 100644 --- a/libswresample/dither_template.c +++ b/libswresample/dither_template.c @@ -25,27 +25,27 @@ ERROR void RENAME(swri_noise_shaping)(SwrContext *s, AudioData *srcs, AudioData *noises, int count){ int i, j, pos, ch; - int taps = s->ns_taps; - float S = s->ns_scale; - float S_1 = s->ns_scale_1; + int taps = s->dither.ns_taps; + float S = s->dither.ns_scale; + float S_1 = s->dither.ns_scale_1; for (ch=0; chch_count; ch++) { - const float *noise = ((const float *)noises->ch[ch]) + s->dither_pos; + const float *noise = ((const float *)noises->ch[ch]) + s->dither.dither_pos; DELEM *data = (DELEM*)srcs->ch[ch]; - pos = s->ns_pos; + pos = s->dither.ns_pos; for (i=0; ins_coeffs[j] * s->ns_errors[ch][pos + j]; + d -= s->dither.ns_coeffs[j] * s->dither.ns_errors[ch][pos + j]; pos = pos ? pos - 1 : pos - 1 + taps; d1 = rint((d + noise[i]) * S_1)*S; - s->ns_errors[ch][pos + taps] = s->ns_errors[ch][pos] = d1 - d; + s->dither.ns_errors[ch][pos + taps] = s->dither.ns_errors[ch][pos] = d1 - d; CLIP(d1); data[i] = d1; } } - s->ns_pos = pos; + s->dither.ns_pos = pos; } #undef RENAME diff --git a/libswresample/swresample.c b/libswresample/swresample.c index f11bbd715c..218d346816 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -73,9 +73,9 @@ static const AVOption options[]={ {"swr_flags" , "set flags" , OFFSET(flags ), AV_OPT_TYPE_FLAGS, {.i64=0 }, 0 , UINT_MAX , PARAM, "flags"}, {"res" , "force resampling" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_FLAG_RESAMPLE }, INT_MIN, INT_MAX , PARAM, "flags"}, -{"dither_scale" , "set dither scale" , OFFSET(dither_scale ), AV_OPT_TYPE_FLOAT, {.dbl=1 }, 0 , INT_MAX , PARAM}, +{"dither_scale" , "set dither scale" , OFFSET(dither.scale ), AV_OPT_TYPE_FLOAT, {.dbl=1 }, 0 , INT_MAX , PARAM}, -{"dither_method" , "set dither method" , OFFSET(dither_method ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_DITHER_NB-1, PARAM, "dither_method"}, +{"dither_method" , "set dither method" , OFFSET(dither.method ), AV_OPT_TYPE_INT , {.i64=0 }, 0 , SWR_DITHER_NB-1, PARAM, "dither_method"}, {"rectangular" , "select rectangular dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_RECTANGULAR}, INT_MIN, INT_MAX , PARAM, "dither_method"}, {"triangular" , "select triangular dither" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_TRIANGULAR }, INT_MIN, INT_MAX , PARAM, "dither_method"}, {"triangular_hp" , "select triangular dither with high pass" , 0 , AV_OPT_TYPE_CONST, {.i64=SWR_DITHER_TRIANGULAR_HIGHPASS }, INT_MIN, INT_MAX, PARAM, "dither_method"}, @@ -217,7 +217,7 @@ av_cold void swr_free(SwrContext **ss){ free_temp(&s->midbuf); free_temp(&s->preout); free_temp(&s->in_buffer); - free_temp(&s->dither); + free_temp(&s->dither.noise); swri_audio_convert_free(&s-> in_convert); swri_audio_convert_free(&s->out_convert); swri_audio_convert_free(&s->full_convert); @@ -237,7 +237,7 @@ av_cold int swr_init(struct SwrContext *s){ free_temp(&s->midbuf); free_temp(&s->preout); free_temp(&s->in_buffer); - free_temp(&s->dither); + free_temp(&s->dither.noise); memset(s->in.ch, 0, sizeof(s->in.ch)); memset(s->out.ch, 0, sizeof(s->out.ch)); swri_audio_convert_free(&s-> in_convert); @@ -355,7 +355,7 @@ av_assert0(s->out.ch_count); s->in_buffer= s->in; - if(!s->resample && !s->rematrix && !s->channel_map && !s->dither_method){ + if(!s->resample && !s->rematrix && !s->channel_map && !s->dither.method){ s->full_convert = swri_audio_convert_alloc(s->out_sample_fmt, s-> in_sample_fmt, s-> in.ch_count, NULL, 0); return 0; @@ -391,9 +391,9 @@ av_assert0(s->out.ch_count); set_audiodata_fmt(&s->in_buffer, s->int_sample_fmt); } - s->dither = s->preout; + s->dither.noise = s->preout; - if(s->rematrix || s->dither_method) + if(s->rematrix || s->dither.method) return swri_rematrix_init(s); return 0; @@ -609,7 +609,7 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co if(s->resample_first ? !s->rematrix : !s->resample) preout= midbuf; - if (preout == in && s->dither_method) { + if (preout == in && s->dither.method) { av_assert1(postin == midbuf && midbuf == preout); postin = midbuf = preout = &preout_tmp; } @@ -643,45 +643,45 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co } if(preout != out && out_count){ - if(s->dither_method){ + if(s->dither.method){ int ch, len1; int dither_count= FFMAX(out_count, 1<<16); av_assert0(preout != in); - if((ret=swri_realloc_audio(&s->dither, dither_count))<0) + if((ret=swri_realloc_audio(&s->dither.noise, dither_count))<0) return ret; if(ret) - for(ch=0; chdither.ch_count; ch++) - swri_get_dither(s, s->dither.ch[ch], s->dither.count, 12345678913579<out_sample_fmt, s->int_sample_fmt); - av_assert0(s->dither.ch_count == preout->ch_count); + for(ch=0; chdither.noise.ch_count; ch++) + swri_get_dither(s, s->dither.noise.ch[ch], s->dither.noise.count, 12345678913579<out_sample_fmt, s->int_sample_fmt); + av_assert0(s->dither.noise.ch_count == preout->ch_count); - if(s->dither_pos + out_count > s->dither.count) - s->dither_pos = 0; + if(s->dither.dither_pos + out_count > s->dither.noise.count) + s->dither.dither_pos = 0; - if (s->dither_method < SWR_DITHER_NS){ + if (s->dither.method < SWR_DITHER_NS){ if (s->mix_2_1_simd) { int len1= out_count&~15; int off = len1 * preout->bps; if(len1) for(ch=0; chch_count; ch++) - s->mix_2_1_simd(preout->ch[ch], preout->ch[ch], s->dither.ch[ch] + s->dither.bps * s->dither_pos, s->native_one, 0, 0, len1); + s->mix_2_1_simd(preout->ch[ch], preout->ch[ch], s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.dither_pos, s->native_one, 0, 0, len1); if(out_count != len1) for(ch=0; chch_count; ch++) - s->mix_2_1_f(preout->ch[ch] + off, preout->ch[ch] + off, s->dither.ch[ch] + s->dither.bps * s->dither_pos + off + len1, s->native_one, 0, 0, out_count - len1); + s->mix_2_1_f(preout->ch[ch] + off, preout->ch[ch] + off, s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.dither_pos + off + len1, s->native_one, 0, 0, out_count - len1); } else { for(ch=0; chch_count; ch++) - s->mix_2_1_f(preout->ch[ch], preout->ch[ch], s->dither.ch[ch] + s->dither.bps * s->dither_pos, s->native_one, 0, 0, out_count); + s->mix_2_1_f(preout->ch[ch], preout->ch[ch], s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.dither_pos, s->native_one, 0, 0, out_count); } } else { switch(s->int_sample_fmt) { - case AV_SAMPLE_FMT_S16P :swri_noise_shaping_int16(s, preout, &s->dither, out_count); break; - case AV_SAMPLE_FMT_S32P :swri_noise_shaping_int32(s, preout, &s->dither, out_count); break; - case AV_SAMPLE_FMT_FLTP :swri_noise_shaping_float(s, preout, &s->dither, out_count); break; - case AV_SAMPLE_FMT_DBLP :swri_noise_shaping_double(s,preout, &s->dither, out_count); break; + case AV_SAMPLE_FMT_S16P :swri_noise_shaping_int16(s, preout, &s->dither.noise, out_count); break; + case AV_SAMPLE_FMT_S32P :swri_noise_shaping_int32(s, preout, &s->dither.noise, out_count); break; + case AV_SAMPLE_FMT_FLTP :swri_noise_shaping_float(s, preout, &s->dither.noise, out_count); break; + case AV_SAMPLE_FMT_DBLP :swri_noise_shaping_double(s,preout, &s->dither.noise, out_count); break; } } - s->dither_pos += out_count; + s->dither.dither_pos += out_count; } //FIXME packed doesnt need more than 1 chan here! swri_audio_convert(s->out_convert, out, preout, out_count); diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h index 986eecc7f9..9276b5c8cb 100644 --- a/libswresample/swresample_internal.h +++ b/libswresample/swresample_internal.h @@ -50,6 +50,19 @@ typedef struct AudioData{ enum AVSampleFormat fmt; ///< sample format } AudioData; +struct DitherContext { + enum SwrDitherType method; + int dither_pos; + float scale; + int ns_taps; ///< Noise shaping dither taps + float ns_scale; ///< Noise shaping dither scale + float ns_scale_1; ///< Noise shaping dither scale^-1 + int ns_pos; ///< Noise shaping dither position + float ns_coeffs[NS_TAPS]; ///< Noise shaping filter coefficients + float ns_errors[SWR_CH_MAX][2*NS_TAPS]; + AudioData noise; ///< noise used for dithering +}; + struct SwrContext { const AVClass *av_class; ///< AVClass used for AVOption and av_log() int log_level_offset; ///< logging level offset @@ -70,15 +83,8 @@ struct SwrContext { const int *channel_map; ///< channel index (or -1 if muted channel) map int used_ch_count; ///< number of used input channels (mapped channel count if channel_map, otherwise in.ch_count) enum SwrEngine engine; - enum SwrDitherType dither_method; - int dither_pos; - float dither_scale; - int ns_taps; ///< Noise shaping dither taps - float ns_scale; ///< Noise shaping dither scale - float ns_scale_1; ///< Noise shaping dither scale^-1 - int ns_pos; ///< Noise shaping dither position - float ns_coeffs[NS_TAPS]; ///< Noise shaping filter coefficients - float ns_errors[SWR_CH_MAX][2*NS_TAPS]; + + struct DitherContext dither; int filter_size; /**< length of each FIR filter in the resampling filterbank relative to the cutoff frequency */ int phase_shift; /**< log2 of the number of entries in the resampling polyphase filterbank */ @@ -105,7 +111,6 @@ struct SwrContext { AudioData preout; ///< pre-output audio data: used for rematrix/resample AudioData out; ///< converted output audio data AudioData in_buffer; ///< cached audio data (convert and resample purpose) - AudioData dither; ///< noise used for dithering int in_buffer_index; ///< cached buffer position int in_buffer_count; ///< cached buffer length int resample_in_constraint; ///< 1 if the input end was reach before the output end, 0 otherwise