annotate libaf/af_scaletempo.c @ 24897:d4a8f31df9ba

af_scaletempo: Fix audio copy position Because of a missing *num_channels factor the filter copied audio from an incorrect position. This mixed up the channel order and hurt audio quality even if the channels had identical content.
author uau
date Thu, 01 Nov 2007 06:52:41 +0000
parents 8133163bd1dd
children 0701957d2bf7
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
24896
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
1 /*
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
2 * scaletempo audio filter
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
3 * Copyright (c) 2007 Robert Juliano
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
4 *
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
5 * This file is part of MPlayer.
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
6 *
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
7 * MPlayer is free software; you can redistribute it and/or modify
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
8 * it under the terms of the GNU General Public License as published by
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
9 * the Free Software Foundation; either version 2 of the License, or
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
10 * (at your option) any later version.
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
11 *
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
12 * MPlayer is distributed in the hope that it will be useful,
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
15 * GNU General Public License for more details.
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
16 *
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
17 * You should have received a copy of the GNU General Public License
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
18 * along with MPlayer; if not, write to the Free Software
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
20 *
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
21 * scale tempo while maintaining pitch
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
22 * (WSOLA technique with cross correlation)
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
23 * inspired by SoundTouch library by Olli Parviainen
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
24 *
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
25 * basic algorithm
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
26 * - produce 'stride' output samples per loop
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
27 * - consume stride*scale input samples per loop
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
28 *
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
29 * to produce smoother transitions between strides, blend next overlap
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
30 * samples from last stride with correlated samples of current input
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
31 *
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
32 */
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
33
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
34 #include <stdlib.h>
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
35 #include <string.h>
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
36 #include <limits.h>
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
37
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
38 #include "af.h"
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
39 #include "libavutil/common.h"
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
40 #include "subopt-helper.h"
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
41 #include "help_mp.h"
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
42
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
43 // Data for specific instances of this filter
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
44 typedef struct af_scaletempo_s
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
45 {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
46 // stride
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
47 float scale;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
48 float speed;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
49 float frames_stride_scaled;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
50 float frames_stride_error;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
51 int bytes_per_frame;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
52 int bytes_stride;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
53 float bytes_stride_scaled;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
54 int bytes_queue;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
55 int bytes_queued;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
56 int bytes_to_slide;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
57 int8_t* buf_queue;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
58 // overlap
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
59 int samples_overlap;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
60 int samples_standing;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
61 int bytes_overlap;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
62 int bytes_standing;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
63 int8_t* buf_overlap;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
64 int8_t* table_blend;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
65 void (*output_overlap)(struct af_scaletempo_s* s, int8_t* out_buf, int bytes_off);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
66 // best overlap
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
67 int frames_search;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
68 int num_channels;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
69 int8_t* buf_pre_corr;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
70 int8_t* table_window;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
71 int (*best_overlap_offset)(struct af_scaletempo_s* s);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
72 short shift_corr;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
73 // command line
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
74 float scale_nominal;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
75 float ms_stride;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
76 float percent_overlap;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
77 float ms_search;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
78 short speed_tempo;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
79 short speed_pitch;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
80 } af_scaletempo_t;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
81
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
82 int fill_queue(struct af_instance_s* af, af_data_t* data, int offset) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
83 af_scaletempo_t* s = af->setup;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
84 int bytes_in = data->len - offset;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
85 int offset_unchanged = offset;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
86
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
87 if (s->bytes_to_slide > 0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
88 if (s->bytes_to_slide < s->bytes_queued) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
89 int bytes_move = s->bytes_queued - s->bytes_to_slide;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
90 memmove(s->buf_queue,
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
91 s->buf_queue + s->bytes_to_slide,
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
92 bytes_move);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
93 s->bytes_to_slide = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
94 s->bytes_queued = bytes_move;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
95 } else {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
96 int bytes_skip;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
97 s->bytes_to_slide -= s->bytes_queued;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
98 bytes_skip = FFMIN(s->bytes_to_slide, bytes_in);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
99 s->bytes_queued = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
100 s->bytes_to_slide -= bytes_skip;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
101 offset += bytes_skip;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
102 bytes_in -= bytes_skip;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
103 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
104 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
105
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
106 if (bytes_in > 0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
107 int bytes_copy = FFMIN(s->bytes_queue - s->bytes_queued, bytes_in);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
108 memcpy(s->buf_queue + s->bytes_queued,
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
109 (int8_t*)data->audio + offset,
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
110 bytes_copy);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
111 s->bytes_queued += bytes_copy;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
112 offset += bytes_copy;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
113 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
114
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
115 return offset - offset_unchanged;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
116 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
117
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
118 int _best_overlap_offset_float(af_scaletempo_t* s) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
119 float *pw, *po, *ppc, *search_start;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
120 float best_corr = INT_MIN;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
121 int best_off = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
122 int i, off;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
123
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
124 pw = (float*)s->table_window;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
125 po = (float*)s->buf_overlap + s->num_channels;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
126 ppc = (float*)s->buf_pre_corr;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
127 for (i=s->num_channels; i<s->samples_overlap; i++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
128 *ppc++ = *pw++ * *po++;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
129 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
130
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
131 search_start = (float*)s->buf_queue + s->num_channels;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
132 for (off=0; off<s->frames_search; off++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
133 float corr = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
134 float* ps = search_start;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
135 ppc = (float*)s->buf_pre_corr;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
136 for (i=s->num_channels; i<s->samples_overlap; i++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
137 corr += *ppc++ * *ps++;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
138 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
139 if (corr > best_corr) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
140 best_corr = corr;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
141 best_off = off;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
142 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
143 search_start += s->num_channels;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
144 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
145
24897
d4a8f31df9ba af_scaletempo: Fix audio copy position
uau
parents: 24896
diff changeset
146 return best_off * 4 * s->num_channels;
24896
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
147 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
148
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
149 int _best_overlap_offset_s16(af_scaletempo_t* s) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
150 int32_t *pw, *ppc;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
151 int16_t *po, *search_start;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
152 int32_t best_corr = INT_MIN;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
153 int best_off = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
154 int i, off;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
155
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
156 pw = (int32_t*)s->table_window;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
157 po = (int16_t*)s->buf_overlap + s->num_channels;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
158 ppc = (int32_t*)s->buf_pre_corr;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
159 for (i=s->num_channels; i<s->samples_overlap; i++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
160 *ppc++ = ( *pw++ * *po++ ) >> 15;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
161 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
162
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
163 search_start = (int16_t*)s->buf_queue + s->num_channels;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
164 for (off=0; off<s->frames_search; off++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
165 int32_t corr = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
166 int16_t* ps = search_start;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
167 ppc = (int32_t*)s->buf_pre_corr;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
168 for (i=s->num_channels; i<s->samples_overlap; i++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
169 corr += ( *ppc++ * *ps++ ) >> s->shift_corr;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
170 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
171 if (corr > best_corr) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
172 best_corr = corr;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
173 best_off = off;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
174 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
175 search_start += s->num_channels;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
176 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
177
24897
d4a8f31df9ba af_scaletempo: Fix audio copy position
uau
parents: 24896
diff changeset
178 return best_off * 2 * s->num_channels;
24896
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
179 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
180
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
181 void _output_overlap_float(af_scaletempo_t* s, int8_t* buf_out, int bytes_off) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
182 float* pout = (float*)buf_out;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
183 float* pb = (float*)s->table_blend;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
184 float* po = (float*)s->buf_overlap;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
185 float* pin = (float*)(s->buf_queue + bytes_off);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
186 int i;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
187 for (i=0; i<s->samples_overlap; i++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
188 *pout++ = *po - *pb++ * ( *po - *pin++ ); po++;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
189 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
190 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
191 void _output_overlap_s16(af_scaletempo_t* s, int8_t* buf_out, int bytes_off) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
192 int16_t* pout = (int16_t*)buf_out;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
193 int32_t* pb = (int32_t*)s->table_blend;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
194 int16_t* po = (int16_t*)s->buf_overlap;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
195 int16_t* pin = (int16_t*)(s->buf_queue + bytes_off);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
196 int i;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
197 for (i=0; i<s->samples_overlap; i++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
198 *pout++ = *po - ( ( *pb++ * ( *po - *pin++ ) ) >> 16 ); po++;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
199 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
200 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
201
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
202 // Filter data through filter
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
203 static af_data_t* play(struct af_instance_s* af, af_data_t* data)
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
204 {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
205 af_scaletempo_t* s = af->setup;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
206 int offset_in;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
207 int max_bytes_out;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
208 int8_t* pout;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
209
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
210 if (s->scale == 1.0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
211 return data;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
212 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
213
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
214 // RESIZE_LOCAL_BUFFER - can't use macro
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
215 max_bytes_out = ((int)(data->len / s->bytes_stride_scaled) + 1) * s->bytes_stride;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
216 if (max_bytes_out > af->data->len) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
217 af_msg(AF_MSG_VERBOSE, "[libaf] Reallocating memory in module %s, "
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
218 "old len = %i, new len = %i\n",af->info->name,af->data->len,max_bytes_out);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
219 af->data->audio = realloc(af->data->audio, max_bytes_out);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
220 if (!af->data->audio) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
221 af_msg(AF_MSG_FATAL, "[libaf] Could not allocate memory\n");
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
222 return NULL;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
223 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
224 af->data->len = max_bytes_out;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
225 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
226
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
227 offset_in = fill_queue(af, data, 0);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
228 pout = af->data->audio;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
229 while (s->bytes_queued >= s->bytes_queue) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
230 int ti;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
231 float tf;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
232 int bytes_off = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
233
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
234 // output stride
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
235 if (s->output_overlap) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
236 if (s->best_overlap_offset)
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
237 bytes_off = s->best_overlap_offset(s);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
238 s->output_overlap(s, pout, bytes_off);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
239 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
240 memcpy(pout + s->bytes_overlap,
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
241 s->buf_queue + bytes_off + s->bytes_overlap,
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
242 s->bytes_standing);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
243 pout += s->bytes_stride;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
244
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
245 // input stride
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
246 memcpy(s->buf_overlap,
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
247 s->buf_queue + bytes_off + s->bytes_stride,
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
248 s->bytes_overlap);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
249 tf = s->frames_stride_scaled + s->frames_stride_error;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
250 ti = (int)tf;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
251 s->frames_stride_error = tf - ti;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
252 s->bytes_to_slide = ti * s->bytes_per_frame;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
253
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
254 offset_in += fill_queue(af, data, offset_in);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
255 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
256
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
257 data->audio = af->data->audio;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
258 data->len = (int)pout - (int)af->data->audio;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
259 return data;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
260 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
261
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
262 // Initialization and runtime control
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
263 static int control(struct af_instance_s* af, int cmd, void* arg)
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
264 {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
265 af_scaletempo_t* s = af->setup;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
266 switch(cmd){
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
267 case AF_CONTROL_REINIT:{
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
268 af_data_t* data = (af_data_t*)arg;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
269 float srate = data->rate / 1000;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
270 int nch = data->nch;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
271 int bps;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
272 int use_int = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
273 int frames_stride, frames_overlap;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
274 int i, j;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
275
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
276 af_msg(AF_MSG_VERBOSE,
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
277 "[scaletempo] %.3f speed * %.3f scale_nominal = %.3f\n",
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
278 s->speed, s->scale_nominal, s->scale);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
279
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
280 if (s->scale == 1.0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
281 if (s->speed_tempo && s->speed_pitch)
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
282 return AF_DETACH;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
283 memcpy(af->data, data, sizeof(af_data_t));
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
284 return af_test_output(af, data);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
285 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
286
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
287 af->data->rate = data->rate;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
288 af->data->nch = data->nch;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
289 if ( data->format == AF_FORMAT_S16_LE
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
290 || data->format == AF_FORMAT_S16_BE ) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
291 use_int = 1;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
292 af->data->format = AF_FORMAT_S16_NE;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
293 af->data->bps = bps = 2;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
294 } else {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
295 af->data->format = AF_FORMAT_FLOAT_NE;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
296 af->data->bps = bps = 4;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
297 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
298
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
299 frames_stride = srate * s->ms_stride;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
300 s->bytes_stride = frames_stride * bps * nch;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
301 s->bytes_stride_scaled = s->scale * s->bytes_stride;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
302 s->frames_stride_scaled = s->scale * frames_stride;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
303 s->frames_stride_error = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
304 af->mul = (double)s->bytes_stride / s->bytes_stride_scaled;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
305
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
306 frames_overlap = frames_stride * s->percent_overlap;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
307 if (frames_overlap <= 0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
308 s->bytes_standing = s->bytes_stride;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
309 s->samples_standing = s->bytes_standing / bps;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
310 s->output_overlap = NULL;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
311 } else {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
312 s->samples_overlap = frames_overlap * nch;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
313 s->bytes_overlap = frames_overlap * nch * bps;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
314 s->bytes_standing = s->bytes_stride - s->bytes_overlap;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
315 s->samples_standing = s->bytes_standing / bps;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
316 s->buf_overlap = realloc(s->buf_overlap, s->bytes_overlap);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
317 s->table_blend = realloc(s->table_blend, s->bytes_overlap * 4);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
318 if(!s->buf_overlap || !s->table_blend) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
319 af_msg(AF_MSG_FATAL, "[scaletempo] Out of memory\n");
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
320 return AF_ERROR;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
321 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
322 bzero(s->buf_overlap, s->bytes_overlap);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
323 if (use_int) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
324 int32_t* pb = (int32_t*)s->table_blend;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
325 int64_t blend = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
326 for (i=0; i<frames_overlap; i++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
327 int32_t v = blend / frames_overlap;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
328 for (j=0; j<nch; j++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
329 *pb++ = v;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
330 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
331 blend += 65536; // 2^16
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
332 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
333 s->output_overlap = _output_overlap_s16;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
334 } else {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
335 float* pb = (float*)s->table_blend;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
336 for (i=0; i<frames_overlap; i++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
337 float v = i / (float)frames_overlap;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
338 for (j=0; j<nch; j++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
339 *pb++ = v;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
340 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
341 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
342 s->output_overlap = _output_overlap_float;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
343 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
344 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
345
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
346 s->frames_search = (frames_overlap > 1) ? srate * s->ms_search : 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
347 if (s->frames_search <= 0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
348 s->best_overlap_offset = NULL;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
349 } else {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
350 if (use_int) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
351 int64_t t = frames_overlap;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
352 int32_t n = 8589934588LL / (t * t); // 4 * (2^31 - 1) / t^2
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
353 int32_t* pw;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
354 s->buf_pre_corr = realloc(s->buf_pre_corr, s->bytes_overlap * 2);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
355 s->table_window = realloc(s->table_window, s->bytes_overlap * 2 - nch * bps * 2);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
356 if(!s->buf_pre_corr && !s->table_window) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
357 af_msg(AF_MSG_FATAL, "[scaletempo] Out of memory\n");
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
358 return AF_ERROR;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
359 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
360 pw = (int32_t*)s->table_window;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
361 for (i=1; i<frames_overlap; i++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
362 int32_t v = ( i * (t - i) * n ) >> 15;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
363 for (j=0; j<nch; j++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
364 *pw++ = v;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
365 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
366 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
367 s->shift_corr = av_log2( 2*(s->samples_overlap - nch) - 1 );
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
368 s->best_overlap_offset = _best_overlap_offset_s16;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
369 } else {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
370 float* pw;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
371 s->buf_pre_corr = realloc(s->buf_pre_corr, s->bytes_overlap);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
372 s->table_window = realloc(s->table_window, s->bytes_overlap - nch * bps);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
373 if(!s->buf_pre_corr || !s->table_window) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
374 af_msg(AF_MSG_FATAL, "[scaletempo] Out of memory\n");
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
375 return AF_ERROR;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
376 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
377 pw = (float*)s->table_window;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
378 for (i=1; i<frames_overlap; i++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
379 float v = i * (frames_overlap - i);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
380 for (j=0; j<nch; j++) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
381 *pw++ = v;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
382 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
383 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
384 s->best_overlap_offset = _best_overlap_offset_float;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
385 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
386 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
387
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
388 s->bytes_per_frame = bps * nch;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
389 s->num_channels = nch;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
390
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
391 s->bytes_queue
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
392 = (s->frames_search + frames_stride + frames_overlap) * bps * nch;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
393 s->buf_queue = realloc(s->buf_queue, s->bytes_queue);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
394 if(!s->buf_queue) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
395 af_msg(AF_MSG_FATAL, "[scaletempo] Out of memory\n");
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
396 return AF_ERROR;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
397 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
398
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
399 af_msg (AF_MSG_DEBUG0, "[scaletempo] "
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
400 "%.2f stride_in, %i stride_out, %i standing, "
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
401 "%i overlap, %i search, %i queue, %s mode\n",
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
402 s->frames_stride_scaled,
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
403 (int)(s->bytes_stride / nch / bps),
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
404 (int)(s->bytes_standing / nch / bps),
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
405 (int)(s->bytes_overlap / nch / bps),
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
406 s->frames_search,
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
407 (int)(s->bytes_queue / nch / bps),
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
408 (use_int?"s16":"float"));
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
409
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
410 return af_test_output(af, (af_data_t*)arg);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
411 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
412 case AF_CONTROL_PLAYBACK_SPEED | AF_CONTROL_SET:{
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
413 if (s->speed_tempo) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
414 if (s->speed_pitch) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
415 break;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
416 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
417 s->speed = *(float*)arg;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
418 s->scale = s->speed * s->scale_nominal;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
419 } else {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
420 if (s->speed_pitch) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
421 s->speed = 1 / *(float*)arg;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
422 s->scale = s->speed * s->scale_nominal;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
423 break;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
424 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
425 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
426 return AF_OK;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
427 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
428 case AF_CONTROL_SCALETEMPO_AMOUNT | AF_CONTROL_SET:{
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
429 s->scale = *(float*)arg;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
430 s->scale = s->speed * s->scale_nominal;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
431 return AF_OK;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
432 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
433 case AF_CONTROL_SCALETEMPO_AMOUNT | AF_CONTROL_GET:
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
434 *(float*)arg = s->scale;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
435 return AF_OK;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
436 case AF_CONTROL_COMMAND_LINE:{
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
437 strarg_t speed;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
438 opt_t subopts[] = {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
439 {"scale", OPT_ARG_FLOAT, &s->scale_nominal, NULL},
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
440 {"stride", OPT_ARG_FLOAT, &s->ms_stride, NULL},
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
441 {"overlap", OPT_ARG_FLOAT, &s->percent_overlap, NULL},
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
442 {"search", OPT_ARG_FLOAT, &s->ms_search, NULL},
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
443 {"speed", OPT_ARG_STR, &speed, NULL},
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
444 {NULL},
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
445 };
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
446 if (subopt_parse(arg, subopts) != 0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
447 return AF_ERROR;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
448 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
449 if (s->scale_nominal <= 0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
450 af_msg(AF_MSG_ERROR, "[scaletempo] "
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
451 MSGTR_ErrorParsingCommandLine ": " MSGTR_AF_ValueOutOfRange
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
452 ": scale > 0\n");
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
453 return AF_ERROR;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
454 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
455 if (s->ms_stride <= 0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
456 af_msg(AF_MSG_ERROR, "[scaletempo] "
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
457 MSGTR_ErrorParsingCommandLine ": " MSGTR_AF_ValueOutOfRange
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
458 ": stride > 0\n");
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
459 return AF_ERROR;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
460 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
461 if (s->percent_overlap < 0 || s->percent_overlap > 1) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
462 af_msg(AF_MSG_ERROR, "[scaletempo] "
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
463 MSGTR_ErrorParsingCommandLine ": " MSGTR_AF_ValueOutOfRange
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
464 ": 0 <= overlap <= 1\n");
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
465 return AF_ERROR;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
466 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
467 if (s->ms_search < 0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
468 af_msg(AF_MSG_ERROR, "[scaletempo] "
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
469 MSGTR_ErrorParsingCommandLine ": " MSGTR_AF_ValueOutOfRange
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
470 ": search >= 0\n");
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
471 return AF_ERROR;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
472 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
473 if (speed.len > 0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
474 if (strcmp(speed.str, "pitch") == 0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
475 s->speed_tempo = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
476 s->speed_pitch = 1;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
477 } else if (strcmp(speed.str, "tempo") == 0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
478 s->speed_tempo = 1;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
479 s->speed_pitch = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
480 } else if (strcmp(speed.str, "none") == 0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
481 s->speed_tempo = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
482 s->speed_pitch = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
483 } else if (strcmp(speed.str, "both") == 0) {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
484 s->speed_tempo = 1;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
485 s->speed_pitch = 1;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
486 } else {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
487 af_msg(AF_MSG_ERROR, "[scaletempo] "
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
488 MSGTR_ErrorParsingCommandLine ": " MSGTR_AF_ValueOutOfRange
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
489 ": speed=[pitch|tempo|none|both]\n");
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
490 return AF_ERROR;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
491 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
492 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
493 s->scale = s->speed * s->scale_nominal;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
494 af_msg(AF_MSG_DEBUG0, "[scaletempo] %6.3f scale, %6.2f stride, %6.2f overlap, %6.2f search, speed = %s\n", s->scale_nominal, s->ms_stride, s->percent_overlap, s->ms_search, (s->speed_tempo?(s->speed_pitch?"tempo and speed":"tempo"):(s->speed_pitch?"pitch":"none")));
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
495 return AF_OK;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
496 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
497 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
498 return AF_UNKNOWN;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
499 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
500
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
501 // Deallocate memory
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
502 static void uninit(struct af_instance_s* af)
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
503 {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
504 af_scaletempo_t* s = af->setup;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
505 free(af->data->audio);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
506 free(af->data);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
507 free(s->buf_queue);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
508 free(s->buf_overlap);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
509 free(s->buf_pre_corr);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
510 free(s->table_blend);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
511 free(s->table_window);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
512 free(af->setup);
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
513 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
514
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
515 // Allocate memory and set function pointers
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
516 static int af_open(af_instance_t* af){
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
517 af_scaletempo_t* s;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
518
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
519 af->control = control;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
520 af->uninit = uninit;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
521 af->play = play;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
522 af->mul = 1;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
523 af->data = calloc(1,sizeof(af_data_t));
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
524 af->setup = calloc(1,sizeof(af_scaletempo_t));
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
525 if(af->data == NULL || af->setup == NULL)
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
526 return AF_ERROR;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
527
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
528 s = af->setup;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
529 s->scale = s->speed = s->scale_nominal = 1.0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
530 s->speed_tempo = 1;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
531 s->speed_pitch = 0;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
532 s->ms_stride = 60;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
533 s->percent_overlap = .20;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
534 s->ms_search = 14;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
535
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
536 return AF_OK;
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
537 }
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
538
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
539 // Description of this filter
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
540 af_info_t af_info_scaletempo = {
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
541 "Scale audio tempo while maintaining pitch",
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
542 "scaletempo",
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
543 "Robert Juliano",
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
544 "",
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
545 AF_FLAGS_REENTRANT,
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
546 af_open
8133163bd1dd Add audio filter scaletempo
uau
parents:
diff changeset
547 };