src/spectral/phasevoc.c: window only once, remove unused variable
[aubio.git] / src / spectral / phasevoc.c
1 /*
2    Copyright (C) 2003 Paul Brossier
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (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., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include "aubio_priv.h"
21 #include "fvec.h"
22 #include "cvec.h"
23 #include "mathutils.h"
24 #include "spectral/fft.h"
25 #include "spectral/phasevoc.h"
26
27 /** phasevocoder internal object */
28 struct _aubio_pvoc_t {
29   uint_t win_s;       /** grain length */
30   uint_t hop_s;       /** overlap step */
31   uint_t channels;    /** number of channels */
32   aubio_fft_t * fft;  /** fft object */
33   fvec_t * synth;     /** cur output grain [win_s] */
34   fvec_t * synthold;  /** last input frame [win_s-hop_s] */
35   fvec_t * data;      /** current input grain [win_s] */
36   fvec_t * dataold;   /** last input frame [win_s-hop_s] */
37   fvec_t * w;         /** grain window [win_s] */
38 };
39
40
41 /** returns data and dataold slided by hop_s */
42 static void aubio_pvoc_swapbuffers(smpl_t * data, smpl_t * dataold, const
43     smpl_t * datanew, uint_t win_s, uint_t hop_s);
44
45 /** do additive synthesis from 'old' and 'cur' */
46 static void aubio_pvoc_addsynth(const smpl_t * synth, smpl_t * synthold,
47     smpl_t * synthnew, uint_t win_s, uint_t hop_s);
48
49 void aubio_pvoc_do(aubio_pvoc_t *pv, fvec_t * datanew, cvec_t *fftgrain) {
50   uint_t i;
51   for (i=0; i<pv->channels; i++) {
52     /* slide  */
53     aubio_pvoc_swapbuffers(pv->data->data[i],pv->dataold->data[i],
54         datanew->data[i],pv->win_s,pv->hop_s);
55   }
56   /* windowing */
57   fvec_weight(pv->data, pv->w);
58   /* shift */
59   vec_shift(pv->data);
60   /* calculate fft */
61   aubio_fft_do (pv->fft,pv->data,fftgrain);
62 }
63
64 void aubio_pvoc_rdo(aubio_pvoc_t *pv,cvec_t * fftgrain, fvec_t * synthnew) {
65   uint_t i;
66   /* calculate rfft */
67   aubio_fft_rdo(pv->fft,fftgrain,pv->synth);
68   /* unshift */
69   vec_shift(pv->synth);
70   for (i=0; i<pv->channels; i++) {
71     aubio_pvoc_addsynth(pv->synth->data[i],pv->synthold->data[i],
72         synthnew->data[i],pv->win_s,pv->hop_s);
73   }
74 }
75
76 aubio_pvoc_t * new_aubio_pvoc (uint_t win_s, uint_t hop_s, uint_t channels) {
77   aubio_pvoc_t * pv = AUBIO_NEW(aubio_pvoc_t);
78
79   /* if (win_s < 2*hop_s) {
80     AUBIO_WRN("Hop size bigger than half the window size!\n");
81   } */
82
83   if (hop_s < 1) {
84     AUBIO_ERR("Hop size is smaller than 1!\n");
85     AUBIO_ERR("Resetting hop size to half the window size.\n");
86     hop_s = win_s / 2;
87   }
88
89   pv->fft      = new_aubio_fft(win_s,channels);
90
91   /* remember old */
92   pv->data     = new_fvec (win_s, channels);
93   pv->synth    = new_fvec (win_s, channels);
94
95   /* new input output */
96   pv->dataold  = new_fvec  (win_s-hop_s, channels);
97   pv->synthold = new_fvec (win_s-hop_s, channels);
98   pv->w        = new_aubio_window (win_s, aubio_win_hanningz);
99
100   pv->channels = channels;
101   pv->hop_s    = hop_s;
102   pv->win_s    = win_s;
103
104   return pv;
105 }
106
107 void del_aubio_pvoc(aubio_pvoc_t *pv) {
108   del_fvec(pv->data);
109   del_fvec(pv->synth);
110   del_fvec(pv->dataold);
111   del_fvec(pv->synthold);
112   del_fvec(pv->w);
113   del_aubio_fft(pv->fft);
114   AUBIO_FREE(pv);
115 }
116
117 static void aubio_pvoc_swapbuffers(smpl_t * data, smpl_t * dataold, 
118     const smpl_t * datanew, uint_t win_s, uint_t hop_s)
119 {
120   uint_t i;
121   for (i=0;i<win_s-hop_s;i++)
122     data[i] = dataold[i];
123   for (i=0;i<hop_s;i++)
124     data[win_s-hop_s+i] = datanew[i];
125   for (i=0;i<win_s-hop_s;i++)
126     dataold[i] = data[i+hop_s];
127 }
128
129 static void aubio_pvoc_addsynth(const smpl_t * synth, smpl_t * synthold, 
130                 smpl_t * synthnew, uint_t win_s, uint_t hop_s)
131 {
132   uint_t i;
133   smpl_t scale = 2*hop_s/(win_s+.0);
134   /* add new synth to old one and put result in synthnew */
135   for (i=0;i<hop_s;i++)
136     synthnew[i] = synthold[i]+synth[i]*scale;
137   /* shift synthold */
138   for (i=0;i<win_s-2*hop_s;i++)
139     synthold[i] = synthold[i+hop_s];
140   /* erase last frame in synthold */
141   for (i=win_s-hop_s;i<win_s;i++)
142     synthold[i-hop_s]=0.;
143   /* additive synth */
144   for (i=0;i<win_s-hop_s;i++)
145     synthold[i] += synth[i+hop_s]*scale;
146 }
147