Bug Summary

File:build-analysis/../src/plugins/vocoder/pvocoder.c
Warning:line 185, column 25
Array access (via field 'stftplans') results in a null pointer dereference

Annotated Source Code

1/* Phase vocoder routine for time-stretching of audio signal
2 * Copyright (C) 2006 Juho Vähä-Herttua
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301, USA.
18 *
19 *
20 * References
21 * ----------
22 *
23 * Phase vocoder routine based on matlab example code of Dan Ellis:
24 * http://labrosa.ee.columbia.edu/matlab/pvoc/
25 *
26 * Attack detection methods based on paper:
27 * Axel Röbel - Transient detection and preservation in the phase vocoder
28 * (Released in ICMC2003)
29 *
30 */
31
32#include <stdlib.h>
33#include <string.h>
34#include <math.h>
35#include <assert.h>
36
37#include "pvocoder.h"
38
39#define CLAMP(x, low, high)(((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)
))
(((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
40#define ABS(x)(x < 0.0 ? -x : x) (x < 0.0 ? -x : x)
41
42struct pvocoder_s {
43 /* Basic information about the stream */
44 int channels;
45 int chunksize;
46 int overlaps;
47
48 /* Configurable processing variables */
49 double scale;
50 int attack_detection;
51
52 /* Index variables and input/output buffers */
53 long index;
54 double scaleidx;
55 pvocoder_sample_t *win;
56 pvocoder_sample_t *inbuf;
57 pvocoder_sample_t *outbuf;
58
59 /* Fourier transformation buffers */
60 FFTWT (complex)fftwf_complex **stft;
61 FFTWT (complex)fftwf_complex *stftbuf;
62 FFTWT (plan)fftwf_plan *stftplans;
63 long stftidx;
64
65 /* Center of gravity buffer and plan and data */
66 FFTWT (complex)fftwf_complex *cogbuf;
67 FFTWT (plan)fftwf_plan cogplan;
68 int transient;
69
70 /* Inverse transformation buffers */
71 FFTWT (complex)fftwf_complex *invbuf;
72 FFTWT (plan)fftwf_plan invplan;
73
74 /* Current phase information */
75 FFTWT (complex)fftwf_complex *phase;
76};
77
78static void pvocoder_reset (pvocoder_t *pvoc);
79static void pvocoder_get_window (pvocoder_sample_t *buffer,
80 int chunksize,
81 int winsize);
82static void pvocoder_calculate_chunk (pvocoder_t *pvoc, double index);
83
84pvocoder_t *
85pvocoder_init (int chunksize, int channels)
86{
87 pvocoder_t *ret;
88 int i, nsamples;
89
90 assert (chunksize > 0)((chunksize > 0) ? (void) (0) : __assert_fail ("chunksize > 0"
, "../src/plugins/vocoder/pvocoder.c", 90, __PRETTY_FUNCTION__
))
;
91 assert (channels > 0)((channels > 0) ? (void) (0) : __assert_fail ("channels > 0"
, "../src/plugins/vocoder/pvocoder.c", 91, __PRETTY_FUNCTION__
))
;
92
93 ret = calloc (1, sizeof (pvocoder_t));
94 if (!ret)
1
Assuming 'ret' is non-null
2
Taking false branch
95 goto error_init;
96
97 nsamples = chunksize * channels;
98 ret->channels = channels;
99 ret->chunksize = chunksize;
100 ret->scale = 1.0;
101 ret->attack_detection = 0;
102 pvocoder_reset (ret);
3
Calling 'pvocoder_reset'
4
Returning from 'pvocoder_reset'
103
104 /* Create the (Hann) window for sample chunks */
105 ret->win = FFTWT (malloc)fftwf_malloc(chunksize * sizeof (FFTWT (complex)fftwf_complex));
106 if (!ret->win)
5
Assuming the condition is false
6
Taking false branch
107 goto error_init;
108 pvocoder_get_window (ret->win, chunksize, chunksize);
109
110 /* Reserve inbuf and outbuf for 2 chunks so we can filter all overlaps */
111 ret->inbuf = calloc (2 * nsamples, sizeof (pvocoder_sample_t));
112 ret->outbuf = calloc (2 * nsamples, sizeof (pvocoder_sample_t));
113 if (!ret->inbuf || !ret->outbuf)
7
Assuming the condition is false
8
Assuming the condition is false
9
Taking false branch
114 goto error_init;
115
116 /* One buffer for each overlap plus the one of next chunk */
117 ret->stft = calloc (ret->overlaps + 1, sizeof (FFTWT (complex *)fftwf_complex *));
118 ret->stftbuf = FFTWT (malloc)fftwf_malloc((ret->overlaps + 1) * nsamples *
119 sizeof (FFTWT (complex)fftwf_complex));
120 ret->stftplans = calloc (ret->overlaps + 1, sizeof (FFTWT (plan)fftwf_plan));
10
Value assigned to field 'stftplans'
121 if (!ret->stft || !ret->stftbuf || !ret->stftplans)
11
Assuming the condition is false
12
Assuming the condition is false
13
Assuming pointer value is null
14
Taking true branch
122 goto error_init;
15
Control jumps to line 166
123
124 /* Update pointers into stftbuf array */
125 for (i=0; i<=ret->overlaps; i++)
126 ret->stft[i] = ret->stftbuf + i * nsamples;
127 /* Calculate best plans for each stft buffer */
128 for (i=1; i<=ret->overlaps; i++) {
129 ret->stftplans[i] =
130 FFTWT (plan_many_dft)fftwf_plan_many_dft(1, &chunksize, channels,
131 ret->stft[i], NULL((void*)0), channels, 1,
132 ret->stft[i], NULL((void*)0), channels, 1,
133 FFTW_FORWARD(-1), FFTW_MEASURE(0U));
134 }
135
136 /* Allocate center of gravity buffer and create plan */
137 ret->cogbuf = FFTWT (malloc)fftwf_malloc(nsamples * sizeof (FFTWT (complex)fftwf_complex));
138 if (!ret->cogbuf)
139 goto error_init;
140 ret->cogplan = FFTWT (plan_many_dft)fftwf_plan_many_dft(1, &chunksize, channels,
141 ret->cogbuf, NULL((void*)0), channels, 1,
142 ret->cogbuf, NULL((void*)0), channels, 1,
143 FFTW_BACKWARD(+1), FFTW_MEASURE(0U));
144 ret->transient = 0;
145
146 /* Allocate buffer for doing the calculations and inverse fft */
147 ret->invbuf = FFTWT (malloc)fftwf_malloc(nsamples * sizeof (FFTWT (complex)fftwf_complex));
148 if (!ret->invbuf)
149 goto error_init;
150 for (i=0; i<nsamples; i++) {
151 ret->invbuf[i][0] = ret->invbuf[i][1] = 0.0;
152 }
153 ret->invplan = FFTWT (plan_many_dft)fftwf_plan_many_dft(1, &chunksize, channels,
154 ret->invbuf, NULL((void*)0), channels, 1,
155 ret->invbuf, NULL((void*)0), channels, 1,
156 FFTW_BACKWARD(+1), FFTW_MEASURE(0U));
157
158 /* Allocate buffer for phase information of current stream */
159 ret->phase = FFTWT (malloc)fftwf_malloc(nsamples/2 * sizeof (FFTWT (complex)fftwf_complex));
160 if (!ret->phase)
161 goto error_init;
162
163 return ret;
164
165error_init:
166 pvocoder_close (ret);
16
Calling 'pvocoder_close'
167 return NULL((void*)0);
168}
169
170void
171pvocoder_close (pvocoder_t *pvoc)
172{
173 int i;
174
175 if (pvoc) {
17
Taking true branch
176 FFTWT (free)fftwf_free(pvoc->phase);
177
178 FFTWT (destroy_plan)fftwf_destroy_plan(pvoc->invplan);
179 FFTWT (free)fftwf_free(pvoc->invbuf);
180
181 FFTWT (destroy_plan)fftwf_destroy_plan(pvoc->cogplan);
182 FFTWT (free)fftwf_free(pvoc->cogbuf);
183
184 for (i=1; i<=pvoc->overlaps; i++)
18
Loop condition is true. Entering loop body
185 FFTWT (destroy_plan)fftwf_destroy_plan(pvoc->stftplans[i]);
19
Array access (via field 'stftplans') results in a null pointer dereference
186 free (pvoc->stftplans);
187 FFTWT (free)fftwf_free(pvoc->stftbuf);
188 free (pvoc->stft);
189
190 free (pvoc->inbuf);
191 free (pvoc->outbuf);
192 free (pvoc->win);
193 }
194 free (pvoc);
195}
196
197void
198pvocoder_set_scale (pvocoder_t *pvoc, double scale)
199{
200 assert (pvoc)((pvoc) ? (void) (0) : __assert_fail ("pvoc", "../src/plugins/vocoder/pvocoder.c"
, 200, __PRETTY_FUNCTION__))
;
201
202 if (!pvoc)
203 return;
204 pvoc->scale = scale;
205}
206
207void
208pvocoder_set_attack_detection (pvocoder_t *pvoc, int enabled)
209{
210 assert (pvoc)((pvoc) ? (void) (0) : __assert_fail ("pvoc", "../src/plugins/vocoder/pvocoder.c"
, 210, __PRETTY_FUNCTION__))
;
211
212 if (!pvoc)
213 return;
214 pvoc->attack_detection = enabled;
215}
216
217/**
218 * Add new chunk to stft table, mainly window the data, perform some
219 * stft transforms and update the stft table accordingly.
220 */
221void
222pvocoder_add_chunk (pvocoder_t *pvoc, pvocoder_sample_t *chunk)
223{
224 pvocoder_sample_t *inbuf;
225 int nsamples, i, j;
226
227 assert (pvoc)((pvoc) ? (void) (0) : __assert_fail ("pvoc", "../src/plugins/vocoder/pvocoder.c"
, 227, __PRETTY_FUNCTION__))
;
228 assert (chunk)((chunk) ? (void) (0) : __assert_fail ("chunk", "../src/plugins/vocoder/pvocoder.c"
, 228, __PRETTY_FUNCTION__))
;
229
230 /* Copy the added data to inbuf for windowing */
231 nsamples = pvoc->chunksize * pvoc->channels;
232 memmove (pvoc->inbuf, pvoc->inbuf + nsamples,
233 nsamples * sizeof (pvocoder_sample_t));
234 memcpy (pvoc->inbuf + nsamples, chunk,
235 nsamples * sizeof (pvocoder_sample_t));
236
237 /* Exchange two vectors in stft table (old last is new first) */
238 memcpy (pvoc->stft[0], pvoc->stft[pvoc->overlaps],
239 nsamples * sizeof (FFTWT (complex)fftwf_complex));
240
241 /**
242 * Run windowing for overlapping chunk, the first one is skipped
243 * because it was already handled on last add.
244 */
245 inbuf = pvoc->inbuf;
246 for (i=1; i<=pvoc->overlaps; i++) {
247 double cog = 0.0;
248
249 /* Window the current chunk */
250 inbuf += nsamples / pvoc->overlaps;
251 for (j=0; j<nsamples; j++) {
252 pvoc->stft[i][j][0] = inbuf[j] * pvoc->win[j / pvoc->channels];
253 pvoc->cogbuf[j][0] = j * pvoc->stft[i][j][0];
254 pvoc->stft[i][j][1] = pvoc->cogbuf[j][1] = 0.0;
255 }
256
257 /* Perform fourier transformation for every channel */
258 FFTWT (execute)fftwf_execute(pvoc->stftplans[i]);
259
260 /* Calculate center of gravity for chunk if requested */
261 if (pvoc->attack_detection) {
262 double numer = 0.0, denom = 0.0;
263
264 FFTWT (execute)fftwf_execute(pvoc->cogplan);
265 for (j=0; j<nsamples; j++) {
266 double abs;
267
268 numer += pvoc->stft[i][j][0] * pvoc->cogbuf[j][0] -
269 pvoc->stft[i][j][1] * pvoc->cogbuf[j][1];
270 abs = sqrt (pvoc->stft[i][j][0] * pvoc->stft[i][j][0] +
271 pvoc->stft[i][j][1] * pvoc->stft[i][j][1]);
272 denom += abs * abs;
273 }
274 cog = numer / denom / nsamples;
275 }
276
277 /* Scale with 2/3 because Hann window changes amplitude */
278 for (j=0; j<nsamples/2; j++) {
279 pvoc->stft[i][j][0] *= 2.0/3.0;
280 pvoc->stft[i][j][1] *= 2.0/3.0;
281 }
282
283 /* Set center of gravity information of this chunk */
284 pvoc->stft[i][nsamples/2][0] = cog;
285 }
286
287 /* Update the input idx of stft table with added chunks */
288 pvoc->stftidx += pvoc->overlaps;
289 if (pvoc->stftidx == 0) {
290 /* Save first phase for correct reconstruction when scale is 1.0 */
291 for (i=0; i<nsamples/2; i++)
292 pvoc->phase[i][0] = atan2 (pvoc->stft[0][i][1],
293 pvoc->stft[0][i][0]);
294 }
295}
296
297/**
298 * Get one chunk of chunksize * channels (interleaved) if available and return
299 * how many chunks need to be added before this request can be completed.
300 *
301 * Generally if it returns > 0, run add_chunk and try again, if it returns 0
302 * just handle the chunk buffer values and if it returns < 0 we have a problem.
303 */
304int
305pvocoder_get_chunk (pvocoder_t *pvoc, pvocoder_sample_t *chunk)
306{
307 int nsamples, pos, i, j;
308
309 assert (pvoc)((pvoc) ? (void) (0) : __assert_fail ("pvoc", "../src/plugins/vocoder/pvocoder.c"
, 309, __PRETTY_FUNCTION__))
;
310 assert (chunk)((chunk) ? (void) (0) : __assert_fail ("chunk", "../src/plugins/vocoder/pvocoder.c"
, 310, __PRETTY_FUNCTION__))
;
311
312 nsamples = pvoc->chunksize * pvoc->channels;
313
314 /**
315 * Run the calculation routine for as many times as there are overlaps
316 * to get a full chunk in outbuf that can be copied into use
317 */
318 for (i=pvoc->index%pvoc->overlaps; i<pvoc->overlaps; i++) {
319 double tmpidx;
320
321 /**
322 * Calculate current position of outbuf and check that we have
323 * enough data in stft table for completion of this run, if not
324 * return information how many chunks would need to be added
325 */
326 pos = i * nsamples / pvoc->overlaps;
327 tmpidx = pvoc->scaleidx - pvoc->stftidx;
328 if (tmpidx < 0 || tmpidx >= pvoc->overlaps) {
329 if (tmpidx < 0)
330 tmpidx -= pvoc->overlaps;
331 return (tmpidx / pvoc->overlaps);
332 }
333
334 /**
335 * Call the data modification routine that also performs the
336 * inverse stft and windowing and copy the result to outbuf
337 */
338 pvocoder_calculate_chunk (pvoc, tmpidx);
339 for (j=0; j<nsamples; j++)
340 pvoc->outbuf[pos+j] += pvoc->invbuf[j][0];
341
342 /* Increment both output index and scaled input index */
343 pvoc->index++;
344 pvoc->scaleidx += pvoc->scale;
345 }
346
347 /* Copy the result from outbuf and make room for some new output data */
348 if (i == pvoc->overlaps) {
349 memcpy (chunk, pvoc->outbuf,
350 nsamples * sizeof (pvocoder_sample_t));
351 memmove (pvoc->outbuf, pvoc->outbuf + nsamples,
352 nsamples * sizeof (pvocoder_sample_t));
353 memset (pvoc->outbuf + nsamples, 0,
354 nsamples * sizeof (pvocoder_sample_t));
355 }
356
357 /* Rounding can cause too high or low values so we need to clip */
358 for (i=0; i<nsamples; i++)
359 chunk[i] = CLAMP (chunk[i], -1.0, 1.0)(((chunk[i]) > (1.0)) ? (1.0) : (((chunk[i]) < (-1.0)) ?
(-1.0) : (chunk[i])))
;
360
361 /* Operation was successfull so return 0 delta for needed chunks */
362 return 0;
363}
364
365void
366pvocoder_get_final (pvocoder_t *pvoc, pvocoder_sample_t *chunk)
367{
368 int nsamples;
369
370 assert (pvoc)((pvoc) ? (void) (0) : __assert_fail ("pvoc", "../src/plugins/vocoder/pvocoder.c"
, 370, __PRETTY_FUNCTION__))
;
371 assert (chunk)((chunk) ? (void) (0) : __assert_fail ("chunk", "../src/plugins/vocoder/pvocoder.c"
, 371, __PRETTY_FUNCTION__))
;
372
373 nsamples = pvoc->chunksize * pvoc->channels;
374 memcpy (chunk, pvoc->outbuf, nsamples * sizeof (pvocoder_sample_t));
375 memset (pvoc->outbuf, 0, nsamples * sizeof (pvocoder_sample_t));
376 pvocoder_reset (pvoc);
377}
378
379static void
380pvocoder_reset (pvocoder_t *pvoc)
381{
382 /* 4 overlaps for (1-1/pvoc->overlaps) 75% should be a good value */
383 pvoc->overlaps = 4;
384
385 /* Reset index values */
386 pvoc->index = 0;
387 pvoc->scaleidx = 0.0;
388 pvoc->stftidx = -2 * pvoc->overlaps;
389}
390
391/* Fill given chunk with a Hann window of specified size */
392static void
393pvocoder_get_window (pvocoder_sample_t *buffer, int chunksize, int winsize)
394{
395 int halfsize, halfwinsize, i;
396
397 halfsize = chunksize / 2;
398 halfwinsize = winsize / 2;
399
400 for (i=0; i<halfwinsize; i++)
401 buffer[halfsize-i] = 0.5 * (1.0 + cos (M_PI3.14159265358979323846 * i / halfwinsize));
402 for (i=halfsize; i<chunksize; i++)
403 buffer[i] = buffer[chunksize-i];
404}
405
406/**
407 * First make linear interpolation of the absolute values of the two chunks
408 * in stft table we are currently handling. Then add the current phase to our
409 * buffer, calculate delta phase and add it to phase buffer for next run.
410 *
411 * Finally run inverse fourier transformation and normalize and window the
412 * result. Resulting data can be found from pvoc->invbuf later on.
413 */
414static void
415pvocoder_calculate_chunk (pvocoder_t *pvoc, double index)
416{
417 FFTWT (complex)fftwf_complex *buffer;
418 int nsamples, idx, i, j, attack = 0;
419 double diff;
420
421 /* Calculate help variables we use in the routine */
422 nsamples = pvoc->chunksize * pvoc->channels;
423 idx = floor (index);
424 diff = index - floor (index);
425 buffer = pvoc->invbuf;
426
427 if (pvoc->attack_detection) {
428 double treshold = 0.57;
429
430 if (pvoc->stft[idx+1][nsamples/2][0] > treshold) {
431 pvoc->transient = 1;
432 return;
433 } else if (pvoc->stft[idx][nsamples/2][0] < treshold &&
434 pvoc->transient) {
435 /* Release attack */
436 attack = 1;
437 }
438 pvoc->transient = 0;
439 }
440
441 /* Run modification loop for first half frequency data */
442 for (i=0; i<nsamples/2; i++) {
443 double dp;
444
445 /**
446 * Interpolate absolute values of the stft buffers.
447 * buffer = (1-diff)*abs(stft[idx]) + diff*abs(stft[idx+1]);
448 */
449 buffer[i][0] = (1.0-diff)*sqrt (pow (pvoc->stft[idx][i][0], 2) +
450 pow (pvoc->stft[idx][i][1], 2));
451 buffer[i][0] += diff*sqrt (pow (pvoc->stft[idx+1][i][0], 2) +
452 pow (pvoc->stft[idx+1][i][1], 2));
453
454 /**
455 * Add current phase into the buffer, notice that the fact that
456 * neither buffer nor phase includes config values which makes
457 * this operation much more simple.
458 * buffer = buffer*e^(j*phase);
459 */
460 buffer[i][1] = buffer[i][0] * sin (pvoc->phase[i][0]);
461 buffer[i][0] *= cos (pvoc->phase[i][0]);
462
463 /**
464 * Calculate the phase delta for the frequency we are handling.
465 * dp = angle(stft[idx+1]) - angle(stft[idx]);
466 */
467 dp = atan2 (pvoc->stft[idx+1][i][1], pvoc->stft[idx+1][i][0]) -
468 atan2 (pvoc->stft[idx][i][1], pvoc->stft[idx][i][0]);
469 /* Phase delta is in [-2pi, 2pi] so we scale it to [-pi, pi] */
470 dp -= 2 * M_PI3.14159265358979323846 * floor (dp / (2 * M_PI3.14159265358979323846) + 0.5);
471
472 /* Save current phase delta for next iteration */
473 pvoc->phase[i][0] += dp;
474 }
475
476 /* Mirror the modifications to the second half as well */
477 for (i=pvoc->channels; i<nsamples/2; i+=pvoc->channels) {
478 for (j=0; j<pvoc->channels; j++) {
479 buffer[nsamples-i+j][0] = buffer[i+j][0];
480 buffer[nsamples-i+j][1] = -buffer[i+j][1];
481 }
482 }
483 buffer[nsamples/2][0] = buffer[nsamples/2][1] = 0.0;
484
485 /* Perform inverse fourier transform for each channel */
486 FFTWT (execute)fftwf_execute(pvoc->invplan);
487
488 /* Window and normalize the resulting sample buffer */
489 if (attack) {
490 double max = 0.0, mult = 1.5;
491
492 /* Clear first half of the output buffer */
493 for (i=0; i<nsamples/2; i++) {
494 buffer[i][0] = buffer[i][1] = 0.0;
495 }
496
497 /* Make sure we don't clip when amplifying attack */
498 for (i=nsamples/2; i<nsamples; i++) {
499 if (ABS (buffer[i][0])(buffer[i][0] < 0.0 ? -buffer[i][0] : buffer[i][0]) > max) {
500 max = ABS (buffer[i][0])(buffer[i][0] < 0.0 ? -buffer[i][0] : buffer[i][0]);
501 }
502 }
503 mult = CLAMP (mult, 0, 1.0/max)(((mult) > (1.0/max)) ? (1.0/max) : (((mult) < (0)) ? (
0) : (mult)))
;
504
505 /* Window and scale the second half of output buffer */
506 for (i=nsamples/2; i<nsamples; i++) {
507 buffer[i][0] *= mult * pvoc->win[i / pvoc->channels] /
508 pvoc->chunksize;
509 buffer[i][1] = 0.0;
510 }
511 } else {
512 for (i=0; i<nsamples; i++) {
513 buffer[i][0] *= pvoc->win[i / pvoc->channels] /
514 pvoc->chunksize;
515 buffer[i][1] = 0.0;
516 }
517 }
518}