[5652a8c] | 1 | #include "aubio-types.h" |
---|
[615ac7d] | 2 | |
---|
[47b465c] | 3 | static char Py_pvoc_doc[] = "" |
---|
| 4 | "pvoc(win_s=512, hop_s=256)\n" |
---|
| 5 | "\n" |
---|
| 6 | "Phase vocoder.\n" |
---|
| 7 | "\n" |
---|
| 8 | "`pvoc` creates callable object implements a phase vocoder [1]_,\n" |
---|
| 9 | "using the tricks detailed in [2]_.\n" |
---|
| 10 | "\n" |
---|
| 11 | "The call function takes one input of type `fvec` and of size\n" |
---|
| 12 | "`hop_s`, and returns a `cvec` of length `win_s//2+1`.\n" |
---|
| 13 | "\n" |
---|
| 14 | "Parameters\n" |
---|
| 15 | "----------\n" |
---|
| 16 | "win_s : int\n" |
---|
| 17 | " number of channels in the phase-vocoder.\n" |
---|
| 18 | "hop_s : int\n" |
---|
| 19 | " number of samples expected between each call\n" |
---|
| 20 | "\n" |
---|
| 21 | "Examples\n" |
---|
| 22 | "--------\n" |
---|
| 23 | ">>> x = aubio.fvec(256)\n" |
---|
| 24 | ">>> pv = aubio.pvoc(512, 256)\n" |
---|
| 25 | ">>> pv(x)\n" |
---|
| 26 | "aubio cvec of 257 elements\n" |
---|
| 27 | "\n" |
---|
| 28 | "Default values for hop_s and win_s are provided:\n" |
---|
| 29 | "\n" |
---|
| 30 | ">>> pv = aubio.pvoc()\n" |
---|
| 31 | ">>> pv.win_s, pv.hop_s\n" |
---|
| 32 | "512, 256\n" |
---|
| 33 | "\n" |
---|
| 34 | "A `cvec` can be resynthesised using `rdo()`:\n" |
---|
| 35 | "\n" |
---|
| 36 | ">>> pv = aubio.pvoc(512, 256)\n" |
---|
| 37 | ">>> y = aubio.cvec(512)\n" |
---|
| 38 | ">>> x_reconstructed = pv.rdo(y)\n" |
---|
| 39 | ">>> x_reconstructed.shape\n" |
---|
| 40 | "(256,)\n" |
---|
| 41 | "\n" |
---|
| 42 | "References\n" |
---|
| 43 | "----------\n" |
---|
| 44 | ".. [1] James A. Moorer. The use of the phase vocoder in computer music\n" |
---|
| 45 | " applications. `Journal of the Audio Engineering Society`,\n" |
---|
| 46 | " 26(1/2):42–45, 1978.\n" |
---|
| 47 | ".. [2] Amalia de Götzen, Nicolas Bernardini, and Daniel Arfib. Traditional\n" |
---|
| 48 | " (?) implementations of a phase vocoder: the tricks of the trade.\n" |
---|
| 49 | " In `Proceedings of the International Conference on Digital Audio\n" |
---|
| 50 | " Effects` (DAFx-00), pages 37–44, University of Verona, Italy, 2000.\n" |
---|
| 51 | " (`online version <" |
---|
| 52 | "https://www.cs.princeton.edu/courses/archive/spr09/cos325/Bernardini.pdf" |
---|
| 53 | ">`_).\n" |
---|
| 54 | ""; |
---|
| 55 | |
---|
[51b9c83] | 56 | |
---|
[202697a] | 57 | typedef struct |
---|
| 58 | { |
---|
| 59 | PyObject_HEAD |
---|
| 60 | aubio_pvoc_t * o; |
---|
| 61 | uint_t win_s; |
---|
| 62 | uint_t hop_s; |
---|
[569b363] | 63 | fvec_t vecin; |
---|
| 64 | cvec_t cvecin; |
---|
[307fdfc] | 65 | PyObject *output; |
---|
| 66 | cvec_t c_output; |
---|
| 67 | PyObject *routput; |
---|
| 68 | fvec_t c_routput; |
---|
[202697a] | 69 | } Py_pvoc; |
---|
| 70 | |
---|
[615ac7d] | 71 | |
---|
| 72 | static PyObject * |
---|
| 73 | Py_pvoc_new (PyTypeObject * type, PyObject * args, PyObject * kwds) |
---|
| 74 | { |
---|
[0f045b2] | 75 | int win_s = 0, hop_s = 0; |
---|
[615ac7d] | 76 | Py_pvoc *self; |
---|
[0f045b2] | 77 | static char *kwlist[] = { "win_s", "hop_s", NULL }; |
---|
[615ac7d] | 78 | |
---|
[0f045b2] | 79 | if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist, |
---|
| 80 | &win_s, &hop_s)) { |
---|
[615ac7d] | 81 | return NULL; |
---|
| 82 | } |
---|
| 83 | |
---|
| 84 | self = (Py_pvoc *) type->tp_alloc (type, 0); |
---|
| 85 | |
---|
| 86 | if (self == NULL) { |
---|
| 87 | return NULL; |
---|
| 88 | } |
---|
| 89 | |
---|
| 90 | self->win_s = Py_default_vector_length; |
---|
| 91 | self->hop_s = Py_default_vector_length/2; |
---|
| 92 | |
---|
| 93 | if (win_s > 0) { |
---|
| 94 | self->win_s = win_s; |
---|
| 95 | } else if (win_s < 0) { |
---|
| 96 | PyErr_SetString (PyExc_ValueError, |
---|
| 97 | "can not use negative window size"); |
---|
| 98 | return NULL; |
---|
| 99 | } |
---|
| 100 | |
---|
| 101 | if (hop_s > 0) { |
---|
| 102 | self->hop_s = hop_s; |
---|
| 103 | } else if (hop_s < 0) { |
---|
| 104 | PyErr_SetString (PyExc_ValueError, |
---|
| 105 | "can not use negative hop size"); |
---|
| 106 | return NULL; |
---|
| 107 | } |
---|
| 108 | |
---|
[5652a8c] | 109 | return (PyObject *) self; |
---|
| 110 | } |
---|
| 111 | |
---|
| 112 | static int |
---|
| 113 | Py_pvoc_init (Py_pvoc * self, PyObject * args, PyObject * kwds) |
---|
| 114 | { |
---|
| 115 | self->o = new_aubio_pvoc ( self->win_s, self->hop_s); |
---|
| 116 | if (self->o == NULL) { |
---|
[3528079] | 117 | // PyErr_Format(PyExc_RuntimeError, ...) was set above by new_ which called |
---|
| 118 | // AUBIO_ERR when failing |
---|
[5652a8c] | 119 | return -1; |
---|
| 120 | } |
---|
| 121 | |
---|
[307fdfc] | 122 | self->output = new_py_cvec(self->win_s); |
---|
| 123 | self->routput = new_py_fvec(self->hop_s); |
---|
[202697a] | 124 | |
---|
[5652a8c] | 125 | return 0; |
---|
[615ac7d] | 126 | } |
---|
| 127 | |
---|
| 128 | |
---|
[202697a] | 129 | static void |
---|
| 130 | Py_pvoc_del (Py_pvoc *self, PyObject *unused) |
---|
| 131 | { |
---|
[307fdfc] | 132 | Py_XDECREF(self->output); |
---|
| 133 | Py_XDECREF(self->routput); |
---|
[8cf51c4] | 134 | if (self->o) { |
---|
| 135 | del_aubio_pvoc(self->o); |
---|
| 136 | } |
---|
[5c1200a] | 137 | Py_TYPE(self)->tp_free((PyObject *) self); |
---|
[202697a] | 138 | } |
---|
| 139 | |
---|
[615ac7d] | 140 | |
---|
[b5bef11] | 141 | static PyObject * |
---|
[c04d250] | 142 | Py_pvoc_do(Py_pvoc * self, PyObject * args) |
---|
[615ac7d] | 143 | { |
---|
| 144 | PyObject *input; |
---|
| 145 | |
---|
| 146 | if (!PyArg_ParseTuple (args, "O", &input)) { |
---|
| 147 | return NULL; |
---|
| 148 | } |
---|
| 149 | |
---|
[569b363] | 150 | if (!PyAubio_ArrayToCFvec (input, &(self->vecin) )) { |
---|
[615ac7d] | 151 | return NULL; |
---|
| 152 | } |
---|
| 153 | |
---|
[99aa353] | 154 | if (self->vecin.length != self->hop_s) { |
---|
| 155 | PyErr_Format(PyExc_ValueError, |
---|
| 156 | "input fvec has length %d, but pvoc expects length %d", |
---|
| 157 | self->vecin.length, self->hop_s); |
---|
| 158 | return NULL; |
---|
| 159 | } |
---|
| 160 | |
---|
[307fdfc] | 161 | Py_INCREF(self->output); |
---|
| 162 | if (!PyAubio_PyCvecToCCvec (self->output, &(self->c_output))) { |
---|
| 163 | return NULL; |
---|
| 164 | } |
---|
[615ac7d] | 165 | // compute the function |
---|
[307fdfc] | 166 | aubio_pvoc_do (self->o, &(self->vecin), &(self->c_output)); |
---|
| 167 | return self->output; |
---|
[615ac7d] | 168 | } |
---|
| 169 | |
---|
[5652a8c] | 170 | static PyMemberDef Py_pvoc_members[] = { |
---|
[615ac7d] | 171 | {"win_s", T_INT, offsetof (Py_pvoc, win_s), READONLY, |
---|
[47b465c] | 172 | "int: Size of phase vocoder analysis windows, in samples.\n" |
---|
| 173 | ""}, |
---|
[615ac7d] | 174 | {"hop_s", T_INT, offsetof (Py_pvoc, hop_s), READONLY, |
---|
[47b465c] | 175 | "int: Interval between two analysis, in samples.\n" |
---|
| 176 | ""}, |
---|
[5652a8c] | 177 | { NULL } // sentinel |
---|
| 178 | }; |
---|
[615ac7d] | 179 | |
---|
[307fdfc] | 180 | static PyObject * |
---|
[c04d250] | 181 | Py_pvoc_rdo(Py_pvoc * self, PyObject * args) |
---|
[615ac7d] | 182 | { |
---|
| 183 | PyObject *input; |
---|
| 184 | if (!PyArg_ParseTuple (args, "O", &input)) { |
---|
| 185 | return NULL; |
---|
| 186 | } |
---|
| 187 | |
---|
[92a8800] | 188 | if (!PyAubio_PyCvecToCCvec (input, &(self->cvecin) )) { |
---|
[615ac7d] | 189 | return NULL; |
---|
| 190 | } |
---|
| 191 | |
---|
[99aa353] | 192 | if (self->cvecin.length != self->win_s / 2 + 1) { |
---|
| 193 | PyErr_Format(PyExc_ValueError, |
---|
| 194 | "input cvec has length %d, but pvoc expects length %d", |
---|
| 195 | self->cvecin.length, self->win_s / 2 + 1); |
---|
| 196 | return NULL; |
---|
| 197 | } |
---|
| 198 | |
---|
[307fdfc] | 199 | Py_INCREF(self->routput); |
---|
| 200 | if (!PyAubio_ArrayToCFvec(self->routput, &(self->c_routput)) ) { |
---|
| 201 | return NULL; |
---|
| 202 | } |
---|
[615ac7d] | 203 | // compute the function |
---|
[307fdfc] | 204 | aubio_pvoc_rdo (self->o, &(self->cvecin), &(self->c_routput)); |
---|
| 205 | return self->routput; |
---|
[615ac7d] | 206 | } |
---|
| 207 | |
---|
[965adee] | 208 | static PyObject * |
---|
| 209 | Pyaubio_pvoc_set_window (Py_pvoc *self, PyObject *args) |
---|
| 210 | { |
---|
| 211 | uint_t err = 0; |
---|
| 212 | char_t *window = NULL; |
---|
| 213 | |
---|
| 214 | if (!PyArg_ParseTuple (args, "s", &window)) { |
---|
| 215 | return NULL; |
---|
| 216 | } |
---|
| 217 | err = aubio_pvoc_set_window (self->o, window); |
---|
| 218 | |
---|
| 219 | if (err > 0) { |
---|
| 220 | PyErr_SetString (PyExc_ValueError, "error running aubio_pvoc_set_window"); |
---|
| 221 | return NULL; |
---|
| 222 | } |
---|
| 223 | Py_RETURN_NONE; |
---|
| 224 | } |
---|
| 225 | |
---|
[615ac7d] | 226 | static PyMethodDef Py_pvoc_methods[] = { |
---|
| 227 | {"rdo", (PyCFunction) Py_pvoc_rdo, METH_VARARGS, |
---|
[47b465c] | 228 | "rdo(fftgrain)\n" |
---|
| 229 | "\n" |
---|
| 230 | "Read a new spectral grain and resynthesise the next `hop_s`\n" |
---|
| 231 | "output samples.\n" |
---|
| 232 | "\n" |
---|
| 233 | "Parameters\n" |
---|
| 234 | "----------\n" |
---|
| 235 | "fftgrain : cvec\n" |
---|
| 236 | " new input `cvec` to synthesize from, should be of size `win_s/2+1`\n" |
---|
| 237 | "\n" |
---|
| 238 | "Returns\n" |
---|
| 239 | "-------\n" |
---|
| 240 | "fvec\n" |
---|
| 241 | " re-synthesised output of shape `(hop_s,)`\n" |
---|
| 242 | "\n" |
---|
| 243 | "Example\n" |
---|
| 244 | "-------\n" |
---|
| 245 | ">>> pv = aubio.pvoc(2048, 512)\n" |
---|
| 246 | ">>> out = pv.rdo(aubio.cvec(2048))\n" |
---|
| 247 | ">>> out.shape\n" |
---|
| 248 | "(512,)\n" |
---|
| 249 | ""}, |
---|
| 250 | {"set_window", (PyCFunction) Pyaubio_pvoc_set_window, METH_VARARGS, |
---|
| 251 | "set_window(window_type)\n" |
---|
| 252 | "\n" |
---|
| 253 | "Set window function\n" |
---|
| 254 | "\n" |
---|
| 255 | "Parameters\n" |
---|
| 256 | "----------\n" |
---|
| 257 | "window_type : str\n" |
---|
| 258 | " the window type to use for this phase vocoder\n" |
---|
| 259 | "\n" |
---|
| 260 | "Raises\n" |
---|
| 261 | "------\n" |
---|
| 262 | "ValueError\n" |
---|
| 263 | " If an unknown window type was given.\n" |
---|
| 264 | "\n" |
---|
| 265 | "See Also\n" |
---|
| 266 | "--------\n" |
---|
| 267 | "window : create a window.\n" |
---|
| 268 | ""}, |
---|
[615ac7d] | 269 | {NULL} |
---|
| 270 | }; |
---|
| 271 | |
---|
[5652a8c] | 272 | PyTypeObject Py_pvocType = { |
---|
| 273 | PyVarObject_HEAD_INIT (NULL, 0) |
---|
| 274 | "aubio.pvoc", |
---|
| 275 | sizeof (Py_pvoc), |
---|
| 276 | 0, |
---|
| 277 | (destructor) Py_pvoc_del, |
---|
| 278 | 0, |
---|
| 279 | 0, |
---|
| 280 | 0, |
---|
| 281 | 0, |
---|
| 282 | 0, |
---|
| 283 | 0, |
---|
| 284 | 0, |
---|
| 285 | 0, |
---|
| 286 | 0, |
---|
| 287 | (ternaryfunc)Py_pvoc_do, |
---|
| 288 | 0, |
---|
| 289 | 0, |
---|
| 290 | 0, |
---|
| 291 | 0, |
---|
| 292 | Py_TPFLAGS_DEFAULT, |
---|
| 293 | Py_pvoc_doc, |
---|
| 294 | 0, |
---|
| 295 | 0, |
---|
| 296 | 0, |
---|
| 297 | 0, |
---|
| 298 | 0, |
---|
| 299 | 0, |
---|
| 300 | Py_pvoc_methods, |
---|
| 301 | Py_pvoc_members, |
---|
| 302 | 0, |
---|
| 303 | 0, |
---|
| 304 | 0, |
---|
| 305 | 0, |
---|
| 306 | 0, |
---|
| 307 | 0, |
---|
| 308 | (initproc) Py_pvoc_init, |
---|
| 309 | 0, |
---|
| 310 | Py_pvoc_new, |
---|
[0e70ef9] | 311 | 0, |
---|
| 312 | 0, |
---|
| 313 | 0, |
---|
| 314 | 0, |
---|
| 315 | 0, |
---|
| 316 | 0, |
---|
| 317 | 0, |
---|
| 318 | 0, |
---|
| 319 | 0, |
---|
[5652a8c] | 320 | }; |
---|