From ff9c62afb5f3149cb084e41f9bc780b4fdc27211 Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Sat, 17 Nov 2018 01:53:28 +0100 Subject: [PATCH] [api] add meltohz and hztomel, Slaney and Htk versions --- src/musicutils.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ src/musicutils.h | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 src/musicutils.c diff --git a/src/musicutils.c b/src/musicutils.c new file mode 100644 index 00000000..14ef849e --- /dev/null +++ b/src/musicutils.c @@ -0,0 +1,85 @@ +/* + 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 . + +*/ + +#include "aubio_priv.h" +#include "musicutils.h" + +smpl_t +aubio_hztomel (smpl_t freq) +{ + const smpl_t lin_space = 3./200.; + const smpl_t split_hz = 1000.; + const smpl_t split_mel = split_hz * lin_space; + const smpl_t log_space = 27./LOG(6400/1000.); + if (freq < 0) { + AUBIO_WRN("hztomel: input frequency should be >= 0\n"); + return 0; + } + if (freq < split_hz) + { + return freq * lin_space; + } else { + return split_mel + log_space * LOG (freq / split_hz); + } + +} + +smpl_t +aubio_meltohz (smpl_t mel) +{ + const smpl_t lin_space = 200./3.; + const smpl_t split_hz = 1000.; + const smpl_t split_mel = split_hz / lin_space; + const smpl_t logSpacing = POW(6400/1000., 1/27.); + if (mel < 0) { + AUBIO_WRN("meltohz: input mel should be >= 0\n"); + return 0; + } + if (mel < split_mel) { + return lin_space * mel; + } else { + return split_hz * POW(logSpacing, mel - split_mel); + } +} + +smpl_t +aubio_hztomel_htk (smpl_t freq) +{ + const smpl_t split_hz = 700.; + const smpl_t log_space = 1127.; + if (freq < 0) { + AUBIO_WRN("hztomel_htk: input frequency should be >= 0\n"); + return 0; + } + return log_space * LOG (1 + freq / split_hz); +} + +smpl_t +aubio_meltohz_htk (smpl_t mel) +{ + const smpl_t split_hz = 700.; + const smpl_t log_space = 1./1127.; + if (mel < 0) { + AUBIO_WRN("meltohz_htk: input frequency should be >= 0\n"); + return 0; + } + return split_hz * ( EXP ( mel * log_space) - 1.); +} + diff --git a/src/musicutils.h b/src/musicutils.h index d9638ac1..a6594951 100644 --- a/src/musicutils.h +++ b/src/musicutils.h @@ -86,6 +86,105 @@ smpl_t aubio_bintofreq (smpl_t bin, smpl_t samplerate, smpl_t fftsize); /** convert frequency (Hz) to frequency bin */ smpl_t aubio_freqtobin (smpl_t freq, smpl_t samplerate, smpl_t fftsize); +/** convert frequency (Hz) to mel + + \param freq input frequency, in Hz + + \return output mel + + Converts a scalar from the frequency domain to the mel scale using Slaney + Auditory Toolbox's implementation: + + If \f$ f < 1000 \f$, \f$ m = 3 f / 200 \f$. + + If \f$ f >= 1000 \f$, \f$ m = 1000 + 27 \frac{{ln}(f) - ln(1000))} + {{ln}(6400) - ln(1000)} + \f$ + + See also + -------- + + aubio_meltohz(), aubio_hztomel_htk(). + +*/ +smpl_t aubio_hztomel (smpl_t freq); + +/** convert mel to frequency (Hz) + + \param mel input mel + + \return output frequency, in Hz + + Converts a scalar from the mel scale to the frequency domain using Slaney + Auditory Toolbox's implementation: + + If \f$ f < 1000 \f$, \f$ f = 200 m/3 \f$. + + If \f$ f \geq 1000 \f$, \f$ f = 1000 + \left(\frac{6400}{1000}\right) + ^{\frac{m - 1000}{27}} \f$ + + See also + -------- + + aubio_hztomel(), aubio_meltohz_htk(). + + References + ---------- + + Malcolm Slaney, *Auditory Toolbox Version 2, Technical Report #1998-010* + https://engineering.purdue.edu/~malcolm/interval/1998-010/ + +*/ +smpl_t aubio_meltohz (smpl_t mel); + +/** convert frequency (Hz) to mel + + \param freq input frequency, in Hz + + \return output mel + + Converts a scalar from the frequency domain to the mel scale, using the + equation defined by O'Shaughnessy, as implemented in the HTK speech + recognition toolkit: + + \f$ m = 1127 + ln(1 + \frac{f}{700}) \f$ + + See also + -------- + + aubio_meltohz_htk(), aubio_hztomel(). + + References + ---------- + + Douglas O'Shaughnessy (1987). *Speech communication: human and machine*. + Addison-Wesley. p. 150. ISBN 978-0-201-16520-3. + + HTK Speech Recognition Toolkit: http://htk.eng.cam.ac.uk/ + + */ +smpl_t aubio_hztomel_htk (smpl_t freq); + +/** convert mel to frequency (Hz) + + \param mel input mel + + \return output frequency, in Hz + + Converts a scalar from the mel scale to the frequency domain, using the + equation defined by O'Shaughnessy, as implemented in the HTK speech + recognition toolkit: + + \f$ f = 700 * {e}^\left(\frac{f}{1127} - 1\right) \f$ + + See also + -------- + + aubio_hztomel_htk(), aubio_meltohz(). + +*/ +smpl_t aubio_meltohz_htk (smpl_t mel); + /** convert frequency (Hz) to midi value (0-128) */ smpl_t aubio_freqtomidi (smpl_t freq); -- 2.11.0