mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-26 21:37:50 +00:00
avfilter/asrc_sine: increase frequency accuracy
Previously the delta phase was fixed point fractional with 2^32 fractions, which caused inaccuracies in the output frequency, unless the input frequency*2^32 was divisable by the sample rate. This patch improves frequency accuracy by tracking subfractions of the delta phase fractions. For this we are using a denominator which is a multiple of the sample rate, making sure that integer frequencies are always accurately represented. Signed-off-by: Marton Balint <cus@passwd.hu>
This commit is contained in:
parent
06247ae746
commit
8d6f3bcb96
@ -33,6 +33,9 @@
|
||||
typedef struct SamplingContext {
|
||||
uint32_t phi; ///< current phase of the sine (2pi = 1<<32)
|
||||
uint32_t dphi; ///< phase increment between two samples
|
||||
int phi_rem; ///< current fractional phase in 1/dphi_den subfractions
|
||||
int dphi_rem;
|
||||
int dphi_den;
|
||||
} SamplingContext;
|
||||
|
||||
typedef struct SineContext {
|
||||
@ -148,12 +151,31 @@ enum {
|
||||
|
||||
static void sampling_init(SamplingContext *c, double frequency, int sample_rate)
|
||||
{
|
||||
c->dphi = ldexp(frequency, 32) / sample_rate + 0.5;
|
||||
AVRational r;
|
||||
int r_den, max_r_den;
|
||||
|
||||
max_r_den = INT_MAX / sample_rate;
|
||||
frequency = fmod(frequency, sample_rate);
|
||||
r = av_d2q(fmod(frequency, 1.0), max_r_den);
|
||||
r_den = FFMIN(r.den, max_r_den);
|
||||
c->dphi = ldexp(frequency, 32) / sample_rate;
|
||||
c->dphi_den = r_den * sample_rate;
|
||||
c->dphi_rem = round((ldexp(frequency, 32) / sample_rate - c->dphi) * c->dphi_den);
|
||||
if (c->dphi_rem >= c->dphi_den) {
|
||||
c->dphi++;
|
||||
c->dphi_rem = 0;
|
||||
}
|
||||
c->phi_rem = (-c->dphi_den - 1) / 2;
|
||||
}
|
||||
|
||||
static av_always_inline void sampling_advance(SamplingContext *c)
|
||||
{
|
||||
c->phi += c->dphi;
|
||||
c->phi_rem += c->dphi_rem;
|
||||
if (c->phi_rem >= 0) {
|
||||
c->phi_rem -= c->dphi_den;
|
||||
c->phi++;
|
||||
}
|
||||
}
|
||||
|
||||
static av_cold int init(AVFilterContext *ctx)
|
||||
|
Loading…
Reference in New Issue
Block a user