/** phasevocoder internal object */
struct _aubio_pvoc_t {
- /** grain length */
- uint_t win_s;
- /** overlap step */
- uint_t hop_s;
- /** number of channels */
- uint_t channels;
- /** spectral data */
- aubio_mfft_t * fft;
- /**cur output grain [win_s] */
- fvec_t * synth;
- /**last input frame [win_s-hop_s] */
- fvec_t * synthold;
- /**current input grain [win_s] */
- fvec_t * data;
- /**last input frame [win_s-hop_s] */
- fvec_t * dataold;
- /** grain window [win_s] */
- float * w;
+ uint_t win_s; /** grain length */
+ uint_t hop_s; /** overlap step */
+ uint_t channels; /** number of channels */
+ aubio_mfft_t * fft; /** spectral data */
+ fvec_t * synth; /**cur output grain [win_s] */
+ fvec_t * synthold; /**last input frame [win_s-hop_s] */
+ fvec_t * data; /**current input grain [win_s] */
+ fvec_t * dataold; /**last input frame [win_s-hop_s] */
- float * w; /** grain window [win_s] */
++ smpl_t * w; /** grain window [win_s] */
};
/** returns data and dataold slided by hop_s */
- static void aubio_pvoc_swapbuffers(
- smpl_t * data,
- smpl_t * dataold,
- const smpl_t * datanew,
- uint_t win_s, uint_t hop_s);
- /** do additive synthesis from 'old' and 'cur' */
- static void aubio_pvoc_addsynth(
- const smpl_t * synth,
- smpl_t * synthold,
- smpl_t * synthnew,
- uint_t win_s, uint_t hop_s);
+ static void aubio_pvoc_swapbuffers(smpl_t * data, smpl_t * dataold, const
+ smpl_t * datanew, uint_t win_s, uint_t hop_s);
+ /** do additive synthesis from 'old' and 'cur' */
+ static void aubio_pvoc_addsynth(const smpl_t * synth, smpl_t * synthold,
+ smpl_t * synthnew, uint_t win_s, uint_t hop_s);
void aubio_pvoc_do(aubio_pvoc_t *pv, fvec_t * datanew, cvec_t *fftgrain) {
- uint_t i,j;
- for (i=0; i<pv->channels; i++) {
- /* slide */
- aubio_pvoc_swapbuffers(pv->data->data[i],pv->dataold->data[i],
- datanew->data[i],pv->win_s,pv->hop_s);
- /* windowing */
- for (j=0; j<pv->win_s; j++) pv->data->data[i][j] *= pv->w[j];
- }
- /* shift */
- vec_shift(pv->data);
- /* calculate fft */
- aubio_mfft_do (pv->fft,pv->data,fftgrain);
+ uint_t i,j;
+ for (i=0; i<pv->channels; i++) {
+ /* slide */
+ aubio_pvoc_swapbuffers(pv->data->data[i],pv->dataold->data[i],
+ datanew->data[i],pv->win_s,pv->hop_s);
+ /* windowing */
+ for (j=0; j<pv->win_s; j++) pv->data->data[i][j] *= pv->w[j];
+ }
+ /* shift */
+ vec_shift(pv->data);
+ /* calculate fft */
+ aubio_mfft_do (pv->fft,pv->data,fftgrain);
}
void aubio_pvoc_rdo(aubio_pvoc_t *pv,cvec_t * fftgrain, fvec_t * synthnew) {
- uint_t i,j;
- /* calculate rfft */
- aubio_mfft_rdo(pv->fft,fftgrain,pv->synth);
- /* unshift */
- vec_shift(pv->synth);
- for (i=0; i<pv->channels; i++) {
- for (j=0; j<pv->win_s; j++) pv->synth->data[i][j] *= pv->w[j];
- aubio_pvoc_addsynth(pv->synth->data[i],pv->synthold->data[i],
- synthnew->data[i],pv->win_s,pv->hop_s);
- }
+ uint_t i;
+ /* calculate rfft */
+ aubio_mfft_rdo(pv->fft,fftgrain,pv->synth);
+ /* unshift */
+ vec_shift(pv->synth);
+ for (i=0; i<pv->channels; i++) {
+ aubio_pvoc_addsynth(pv->synth->data[i],pv->synthold->data[i],
+ synthnew->data[i],pv->win_s,pv->hop_s);
+ }
}
aubio_pvoc_t * new_aubio_pvoc (uint_t win_s, uint_t hop_s, uint_t channels) {
- aubio_pvoc_t * pv = AUBIO_NEW(aubio_pvoc_t);
-
- if (win_s < 2*hop_s) {
- AUBIO_ERR("Hop size bigger than half the window size!\n");
- AUBIO_ERR("Resetting hop size to half the window size.\n");
- hop_s = win_s / 2;
- }
-
- if (hop_s < 1) {
- AUBIO_ERR("Hop size is smaller than 1!\n");
- AUBIO_ERR("Resetting hop size to half the window size.\n");
- hop_s = win_s / 2;
- }
-
- pv->fft = new_aubio_mfft(win_s,channels);
-
- /* remember old */
- pv->data = new_fvec (win_s, channels);
- pv->synth = new_fvec (win_s, channels);
-
- /* new input output */
- pv->dataold = new_fvec (win_s-hop_s, channels);
- pv->synthold = new_fvec (win_s-hop_s, channels);
- pv->w = AUBIO_ARRAY(smpl_t,win_s);
- aubio_window(pv->w,win_s,aubio_win_hanningz);
-
- pv->channels = channels;
- pv->hop_s = hop_s;
- pv->win_s = win_s;
-
- return pv;
+ aubio_pvoc_t * pv = AUBIO_NEW(aubio_pvoc_t);
+
+ if (win_s < 2*hop_s) {
+ AUBIO_ERR("Hop size bigger than half the window size!\n");
+ AUBIO_ERR("Resetting hop size to half the window size.\n");
+ hop_s = win_s / 2;
+ }
+
+ if (hop_s < 1) {
+ AUBIO_ERR("Hop size is smaller than 1!\n");
+ AUBIO_ERR("Resetting hop size to half the window size.\n");
+ hop_s = win_s / 2;
+ }
+
+ pv->fft = new_aubio_mfft(win_s,channels);
+
+ /* remember old */
+ pv->data = new_fvec (win_s, channels);
+ pv->synth = new_fvec (win_s, channels);
+
+ /* new input output */
+ pv->dataold = new_fvec (win_s-hop_s, channels);
+ pv->synthold = new_fvec (win_s-hop_s, channels);
+ pv->w = AUBIO_ARRAY(smpl_t,win_s);
+ aubio_window(pv->w,win_s,aubio_win_hanningz);
+
+ pv->channels = channels;
+ pv->hop_s = hop_s;
+ pv->win_s = win_s;
+
+ return pv;
}
void del_aubio_pvoc(aubio_pvoc_t *pv) {
- del_fvec(pv->data);
- del_fvec(pv->synth);
- del_fvec(pv->dataold);
- del_fvec(pv->synthold);
- del_aubio_mfft(pv->fft);
- AUBIO_FREE(pv->w);
- AUBIO_FREE(pv);
+ del_fvec(pv->data);
+ del_fvec(pv->synth);
+ del_fvec(pv->dataold);
+ del_fvec(pv->synthold);
+ del_aubio_mfft(pv->fft);
+ AUBIO_FREE(pv->w);
+ AUBIO_FREE(pv);
}
static void aubio_pvoc_swapbuffers(smpl_t * data, smpl_t * dataold,
- const smpl_t * datanew, uint_t win_s, uint_t hop_s)
+ const smpl_t * datanew, uint_t win_s, uint_t hop_s)
{
- uint_t i;
- for (i=0;i<win_s-hop_s;i++)
- data[i] = dataold[i];
- for (i=0;i<hop_s;i++)
- data[win_s-hop_s+i] = datanew[i];
- for (i=0;i<win_s-hop_s;i++)
- dataold[i] = data[i+hop_s];
+ uint_t i;
+ for (i=0;i<win_s-hop_s;i++)
+ data[i] = dataold[i];
+ for (i=0;i<hop_s;i++)
+ data[win_s-hop_s+i] = datanew[i];
+ for (i=0;i<win_s-hop_s;i++)
+ dataold[i] = data[i+hop_s];
}
static void aubio_pvoc_addsynth(const smpl_t * synth, smpl_t * synthold,
smpl_t * synthnew, uint_t win_s, uint_t hop_s)
{
- uint_t i;
- smpl_t scale = 2*hop_s/(win_s+.0);
- /* add new synth to old one and put result in synthnew */
- for (i=0;i<hop_s;i++)
- synthnew[i] = synthold[i]+synth[i]*scale;
- /* shift synthold */
- for (i=0;i<win_s-2*hop_s;i++)
- synthold[i] = synthold[i+hop_s];
- /* erase last frame in synthold */
- for (i=win_s-hop_s;i<win_s;i++)
- synthold[i-hop_s]=0.;
- /* additive synth */
- for (i=0;i<win_s-hop_s;i++)
- synthold[i] += synth[i+hop_s]*scale;
+ uint_t i;
+ smpl_t scale = 2*hop_s/(win_s+.0);
+ /* add new synth to old one and put result in synthnew */
+ for (i=0;i<hop_s;i++)
+ synthnew[i] = synthold[i]+synth[i]*scale;
+ /* shift synthold */
+ for (i=0;i<win_s-2*hop_s;i++)
+ synthold[i] = synthold[i+hop_s];
+ /* erase last frame in synthold */
+ for (i=win_s-hop_s;i<win_s;i++)
+ synthold[i-hop_s]=0.;
+ /* additive synth */
+ for (i=0;i<win_s-hop_s;i++)
+ synthold[i] += synth[i+hop_s]*scale;
}
--- /dev/null
-buf_size = 2048
-channels = 1
+ import unittest
+ import math
+
+ from aubio.aubiowrapper import *
+
- """ test aubio_mfft_do on impulse one channel """
++buf_size = 8092
++channels = 4
++
++precision = 6
+
+ class aubio_mfft_test_case(unittest.TestCase):
+
+ def setUp(self):
+ self.o = new_aubio_mfft(buf_size, channels)
+
+ def tearDown(self):
+ del_aubio_mfft(self.o)
+
+ def test_create(self):
+ """ test creation and deletion of fft object """
+ pass
+
+ def test_aubio_mfft_do_zeroes(self):
+ """ test aubio_mfft_do on zeroes """
+ input = new_fvec(buf_size, channels)
+ fftgrain = new_cvec(buf_size, channels)
+ for index in range(buf_size):
+ for channel in range(channels):
+ self.assertEqual(0., fvec_read_sample(input, channel, index))
+ aubio_mfft_do(self.o, input, fftgrain)
+ for index in range(buf_size/2+1):
+ for channel in range(channels):
+ self.assertEqual(0., cvec_read_norm(fftgrain, channel, index))
+ for index in range(buf_size/2+1):
+ for channel in range(channels):
+ self.assertEqual(0., cvec_read_phas(fftgrain, channel, index))
+ del fftgrain
+ del input
+
+ def test_aubio_mfft_rdo_zeroes(self):
+ """ test aubio_mfft_rdo on zeroes """
+ fftgrain = new_cvec(buf_size, channels)
+ output = new_fvec(buf_size, channels)
+ aubio_mfft_rdo(self.o, fftgrain, output)
+ # check output
+ for index in range(buf_size):
+ for channel in range(channels):
+ self.assertEqual(0., fvec_read_sample(output, channel, index))
+ del fftgrain
+ del output
+
+ def test_aubio_mfft_do_impulse(self):
- fvec_write_sample(input, 1., 0, 0)
++ """ test aubio_mfft_do with an impulse on one channel """
+ input = new_fvec(buf_size, channels)
+ fftgrain = new_cvec(buf_size, channels)
+ # write impulse in channel 0, sample 0.
- self.assertEqual(1., cvec_read_norm(fftgrain, 0, index), index)
++ some_constant = 0.3412432456
++ fvec_write_sample(input, some_constant, 0, 0)
+ aubio_mfft_do(self.o, input, fftgrain)
+ # check norm
+ for index in range(buf_size/2+1):
- cvec_write_norm(fftgrain, 1., 0, 0)
++ self.assertAlmostEqual(some_constant, cvec_read_norm(fftgrain, 0, index), precision)
+ for index in range(buf_size/2+1):
+ for channel in range(1, channels):
+ self.assertEqual(0., cvec_read_norm(fftgrain, channel, index))
+ # check phas
+ for index in range(buf_size/2+1):
+ for channel in range(channels):
+ self.assertEqual(0., cvec_read_phas(fftgrain, channel, index))
+ del fftgrain
+ del input
+
++ def test_aubio_mfft_do_constant(self):
++ """ test aubio_mfft_do with a constant on one channel """
++ input = new_fvec(buf_size, channels)
++ fftgrain = new_cvec(buf_size, channels)
++ # write impulse in channel 0, sample 0.
++ some_constant = 0.003412432456
++ for index in range(1,buf_size):
++ fvec_write_sample(input, some_constant, 0, index)
++ aubio_mfft_do(self.o, input, fftgrain)
++ # check norm and phase == 0 in all other channels
++ for index in range(buf_size/2+1):
++ for channel in range(1, channels):
++ self.assertEqual(0., cvec_read_norm(fftgrain, channel, index))
++ # check norm and phase == 0 in first first and last bin of first channel
++ self.assertAlmostEqual((buf_size-1)*some_constant, cvec_read_norm(fftgrain, 0, 0), precision)
++ self.assertEqual(0., cvec_read_phas(fftgrain, 0, 0))
++ self.assertEqual(0., cvec_read_norm(fftgrain, 0, buf_size/2+1))
++ self.assertEqual(0., cvec_read_phas(fftgrain, 0, buf_size/2+1))
++ # check unwrap2pi(phas) ~= pi everywhere but in first bin
++ for index in range(1,buf_size/2+1):
++ self.assertAlmostEqual ( math.pi, aubio_unwrap2pi(cvec_read_phas(fftgrain, 0, index)), precision)
++ self.assertAlmostEqual(some_constant, cvec_read_norm(fftgrain, 0, index), precision)
++ del fftgrain
++ del input
++
+ def test_aubio_mfft_do_impulse_multichannel(self):
+ " test aubio_mfft_do on impulse two channels "
+ input = new_fvec(buf_size, channels)
+ fftgrain = new_cvec(buf_size, channels)
+ # put an impulse in first an last channel, at first and last index
+ fvec_write_sample(input, 1., 0, 0)
+ fvec_write_sample(input, 1., channels-1, 0)
+ aubio_mfft_do(self.o, input, fftgrain)
+ # check the norm
+ for index in range(buf_size/2+1):
+ self.assertEqual(1., cvec_read_norm(fftgrain, 0, index))
+ for index in range(buf_size/2+1):
+ for channel in range(1, channels-1):
+ self.assertEqual(0., cvec_read_norm(fftgrain, channel, index))
+ for index in range(buf_size/2+1):
+ self.assertEqual(1., cvec_read_norm(fftgrain, channels-1, index))
+ # check the phase
+ for index in range(buf_size/2+1):
+ for channel in range(channels):
+ self.assertEqual(0., cvec_read_phas(fftgrain, channel, index))
+ del fftgrain
+ del input
+
+ def test_aubio_mfft_rdo_impulse(self):
+ """ test aubio_mfft_rdo on impulse """
+ fftgrain = new_cvec(buf_size, channels)
- self.assertEqual(fvec_read_sample(output, channel, index),1./buf_size)
++ for channel in range(channels):
++ cvec_write_norm(fftgrain, 1., channel, 0)
+ output = new_fvec(buf_size, channels)
+ aubio_mfft_rdo(self.o, fftgrain, output)
+ for index in range(buf_size/2+1):
+ for channel in range(channels):
- self.assertAlmostEqual(fvec_read_sample(output, channel, index), 0.67, 7)
++ self.assertAlmostEqual(fvec_read_sample(output, channel, index), 1./buf_size, precision)
+ del fftgrain
+ del output
+
+ def test_aubio_mfft_do_back_and_forth(self):
+ """ test aubio_mfft_rdo on a constant """
+ input = new_fvec(buf_size, channels)
+ output = new_fvec(buf_size, channels)
+ fftgrain = new_cvec(buf_size, channels)
+ for index in range(buf_size/2+1):
+ for channel in range(channels):
+ fvec_write_sample(input, 0.67, channel, index)
+ aubio_mfft_do(self.o, input, fftgrain)
+ aubio_mfft_rdo(self.o, fftgrain, output)
+ for index in range(buf_size/2+1):
+ for channel in range(channels):
++ self.assertAlmostEqual(fvec_read_sample(output, channel, index), 0.67, precision)
+ del fftgrain
+ del output
+
+ if __name__ == '__main__': unittest.main()