2 * audio resampling with soxr
3 * Copyright (c) 2012 Rob Sykes <robs@users.sourceforge.net>
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * audio resampling with soxr
27 #include "libavutil/log.h"
28 #include "swresample_internal.h"
32 static struct ResampleContext
*create(struct ResampleContext
*c
, int out_rate
, int in_rate
, int filter_size
, int phase_shift
, int linear
,
33 double cutoff
, enum AVSampleFormat format
, enum SwrFilterType filter_type
, double kaiser_beta
, double precision
, int cheby
, int exact_rational
){
36 soxr_datatype_t type
=
37 format
== AV_SAMPLE_FMT_S16P
? SOXR_INT16_S
:
38 format
== AV_SAMPLE_FMT_S16
? SOXR_INT16_I
:
39 format
== AV_SAMPLE_FMT_S32P
? SOXR_INT32_S
:
40 format
== AV_SAMPLE_FMT_S32
? SOXR_INT32_I
:
41 format
== AV_SAMPLE_FMT_FLTP
? SOXR_FLOAT32_S
:
42 format
== AV_SAMPLE_FMT_FLT
? SOXR_FLOAT32_I
:
43 format
== AV_SAMPLE_FMT_DBLP
? SOXR_FLOAT64_S
:
44 format
== AV_SAMPLE_FMT_DBL
? SOXR_FLOAT64_I
: (soxr_datatype_t
)-1;
46 soxr_io_spec_t io_spec
= soxr_io_spec(type
, type
);
48 soxr_quality_spec_t q_spec
= soxr_quality_spec((int)((precision
-2)/4), (SOXR_HI_PREC_CLOCK
|SOXR_ROLLOFF_NONE
)*!!cheby
);
49 q_spec
.precision
= precision
;
50 #if !defined SOXR_VERSION /* Deprecated @ March 2013: */
51 q_spec
.bw_pc
= cutoff
? FFMAX(FFMIN(cutoff
,.995),.8)*100 : q_spec
.bw_pc
;
53 q_spec
.passband_end
= cutoff
? FFMAX(FFMIN(cutoff
,.995),.8) : q_spec
.passband_end
;
56 soxr_delete((soxr_t
)c
);
57 c
= (struct ResampleContext
*)
58 soxr_create(in_rate
, out_rate
, 0, &error
, &io_spec
, &q_spec
, 0);
60 av_log(NULL
, AV_LOG_ERROR
, "soxr_create: %s\n", error
);
64 static void destroy(struct ResampleContext
* *c
){
65 soxr_delete((soxr_t
)*c
);
69 static int flush(struct SwrContext
*s
){
70 s
->delayed_samples_fixup
= soxr_delay((soxr_t
)s
->resample
);
72 soxr_process((soxr_t
)s
->resample
, NULL
, 0, NULL
, NULL
, 0, NULL
);
77 soxr_process((soxr_t
)s
->resample
, &f
, 0, &idone
, &f
, 0, &odone
);
78 s
->delayed_samples_fixup
-= soxr_delay((soxr_t
)s
->resample
);
85 struct ResampleContext
* c
, AudioData
*dst
, int dst_size
,
86 AudioData
*src
, int src_size
, int *consumed
){
88 soxr_error_t error
= soxr_set_error((soxr_t
)c
, soxr_set_num_channels((soxr_t
)c
, src
->ch_count
));
90 error
= soxr_process((soxr_t
)c
, src
->ch
, (size_t)src_size
,
91 &idone
, dst
->ch
, (size_t)dst_size
, &odone
);
95 *consumed
= (int)idone
;
96 return error
? -1 : odone
;
99 static int64_t get_delay(struct SwrContext
*s
, int64_t base
){
100 double delayed_samples
= soxr_delay((soxr_t
)s
->resample
);
104 delayed_samples
+= s
->delayed_samples_fixup
;
106 delay_s
= delayed_samples
/ s
->out_sample_rate
;
108 return (int64_t)(delay_s
* base
+ .5);
111 static int invert_initial_buffer(struct ResampleContext
*c
, AudioData
*dst
, const AudioData
*src
,
112 int in_count
, int *out_idx
, int *out_sz
){
116 static int64_t get_out_samples(struct SwrContext
*s
, int in_samples
){
117 double out_samples
= (double)s
->out_sample_rate
/ s
->in_sample_rate
* in_samples
;
118 double delayed_samples
= soxr_delay((soxr_t
)s
->resample
);
121 delayed_samples
+= s
->delayed_samples_fixup
;
123 return (int64_t)(out_samples
+ delayed_samples
+ 1 + .5);
126 struct Resampler
const swri_soxr_resampler
={
127 create
, destroy
, process
, flush
, NULL
/* set_compensation */, get_delay
,
128 invert_initial_buffer
, get_out_samples