From: Paul Brossier Date: Fri, 14 Sep 2018 16:10:54 +0000 (+0200) Subject: src/spectral/constantq.c: first constant-q draft, plain implementation X-Git-Url: https://git.aubio.org/?a=commitdiff_plain;h=b6d0dd0ef6f223821a0a5804933178c9704bd9e8;p=aubio.git src/spectral/constantq.c: first constant-q draft, plain implementation --- diff --git a/src/aubio.h b/src/aubio.h index 0d021361..86883000 100644 --- a/src/aubio.h +++ b/src/aubio.h @@ -183,6 +183,7 @@ extern "C" #include "temporal/c_weighting.h" #include "spectral/fft.h" #include "spectral/phasevoc.h" +#include "spectral/constantq.h" #include "spectral/filterbank.h" #include "spectral/filterbank_mel.h" #include "spectral/mfcc.h" diff --git a/src/spectral/constantq.c b/src/spectral/constantq.c new file mode 100644 index 00000000..4293f3fe --- /dev/null +++ b/src/spectral/constantq.c @@ -0,0 +1,123 @@ +/* + Copyright (C) 2018 Paul Brossier + + This file is part of aubio. + + aubio is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + aubio is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with aubio. If not, see . + +*/ + +/** \file + + Constant-Q Transform + + TODO add long description + + \example spectral/test-constantq.c + +*/ + +#include "aubio_priv.h" +#include "fvec.h" +#include "cvec.h" +#include "fmat.h" +#include "spectral/constantq.h" + +struct _aubio_constantq_t { + uint_t size; + uint_t samplerate; + uint_t bins_per_octave; + fmat_t *coeffs; + smpl_t high_freq; + smpl_t low_freq; +}; + +uint_t aubio_constantq_reset_filters (aubio_constantq_t *s); + +aubio_constantq_t * new_aubio_constantq(uint_t size, uint_t samplerate, + uint_t bins_per_octave) { + aubio_constantq_t * s = AUBIO_NEW (aubio_constantq_t); + if ((sint_t) size <= 0) { + AUBIO_ERROR("constantq: failed creating with size %d, should be > 0\n", + size); + goto beach; + } + if ((sint_t) bins_per_octave <= 0) { + AUBIO_ERROR("constantq: failed creating with bins_per_octave %d" + ", should be > 0\n", bins_per_octave); + goto beach; + } + + s->size = size / 2 + 1; + s->samplerate = samplerate; + s->bins_per_octave = bins_per_octave; + s->low_freq = aubio_miditofreq(19.0); + s->high_freq = aubio_miditofreq(MIN(140.0, 139.0 + 12.0/s->bins_per_octave)); + if (aubio_constantq_reset_filters (s) != AUBIO_OK) goto beach; + //AUBIO_WRN ("constantq: %d size, %d Hz, %d bins\n", s->size, s->samplerate, + // s->bins_per_octave); + return s; +beach: + AUBIO_FREE(s); + return NULL; +} + +uint_t aubio_constantq_reset_filters (aubio_constantq_t *s) +{ + // compute transform coefficients + uint_t i, j; + smpl_t ratio = POW(2.0, 1.0 / s->bins_per_octave); + uint_t nbins = (uint_t) FLOOR (LOG (s->high_freq / s->low_freq) / LOG (ratio)); + if (nbins <= 0) { + AUBIO_ERROR ("constantq: can not be created with 0 bins, low_freq %.2f, " + "high_freq %.2f, bins_per_octave %d\n", s->low_freq, s->high_freq, + s->bins_per_octave); + return AUBIO_FAIL; + } + if (s->coeffs) del_fmat(s->coeffs); + s->coeffs = new_fmat (nbins, s->size); + + smpl_t freq_step = s->samplerate * 0.5 / (s->size - 1.); + smpl_t min_bw = (smpl_t) s->samplerate / (smpl_t) s->size; + + for (i = 0; i < nbins; i++) { + smpl_t band_freq = s->low_freq * POW (ratio, i); + smpl_t band_bw = MAX (band_freq * (ratio - 1.), min_bw); + for (j = 0; j < s->size; j++) { + smpl_t fftfreq = j * freq_step; + smpl_t val = (band_freq - fftfreq) / band_bw; + s->coeffs->data[i][j] = EXP (- 0.5 * SQR(val)); + } + } + + return AUBIO_OK; +} + +void del_aubio_constantq(aubio_constantq_t *s) { + del_fmat(s->coeffs); + AUBIO_FREE(s); +} + +void aubio_constantq_do(aubio_constantq_t *s, const cvec_t *input, + fvec_t *cqt_output) { + fvec_t input_norm; + input_norm.length = input->length; + input_norm.data = input->norm; + fmat_vecmul (s->coeffs, &input_norm, cqt_output); +} + +uint_t aubio_constantq_get_numbins (aubio_constantq_t *s) { + if (!s || !s->coeffs) return 0; + return s->coeffs->height; +} diff --git a/src/spectral/constantq.h b/src/spectral/constantq.h new file mode 100644 index 00000000..b57130b3 --- /dev/null +++ b/src/spectral/constantq.h @@ -0,0 +1,84 @@ +/* + Copyright (C) 2017 Paul Brossier + + This file is part of aubio. + + aubio is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + aubio is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with aubio. If not, see . + +*/ + +/** \file + + Constant-Q Transform + + TODO add long description + + \example spectral/test-constantq.c + +*/ + +#ifndef AUBIO_CONSTANTQ_H +#define AUBIO_CONSTANTQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** Constant-Q transofmr object + + This object computes the forward Constant-Q transform. + +*/ +typedef struct _aubio_constantq_t aubio_constantq_t; + +/** create new constant-Q computation object + + \param size length of the Constant-Q + \param samplerate sampling rate of the input signal + \param bins_per_octave number of bins per octave + +*/ +aubio_constantq_t * new_aubio_constantq(uint_t size, uint_t samplerate, + uint_t bins_per_octave); + +/** compute constant-Q + + \param s constant-Q object as returned by new_aubio_constantq + \param input input fft grain + \param cqt_output transformed input array + +*/ +void aubio_constantq_do (aubio_constantq_t *s, const cvec_t * input, + fvec_t * cqt_output); + +/** delete constant-q object + + \param s constant-q object as returned by new_aubio_constantq + +*/ +void del_aubio_constantq (aubio_constantq_t *s); + +/** get number of output bins of a constant-q object + + \param s constant-q object as returned by new_aubio_constantq + \return number of output bins + +*/ +uint_t aubio_constantq_get_numbins (aubio_constantq_t *s); + +#ifdef __cplusplus +} +#endif + +#endif /* AUBIO_CONSTANTQ_H */