ref: ef1c3b74e92fb9e513e77a2a261ff07b6768dbe1
parent: 7212394ef4949689232625ced2a2600c275aa75a
parent: 7a46bf6cec4e3b9ce9f40ff1db3a98933e016c56
author: Amaury Hazan <[email protected]>
date: Mon Sep 10 20:14:01 EDT 2007
merged from aubio_mfcc, added slaney filterbank (70% done)
--- a/INSTALL
+++ /dev/null
@@ -1,229 +1,0 @@
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
-Foundation, Inc.
-
- This file is free documentation; the Free Software Foundation gives
-unlimited permission to copy, distribute and modify it.
-
-Basic Installation
-==================
-
- These are generic installation instructions.
-
- The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation. It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions. Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
- It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring. (Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.)
-
- If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release. If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
- The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'. You only need
-`configure.ac' if you want to change it or regenerate `configure' using
-a newer version of `autoconf'.
-
-The simplest way to compile this package is:
-
- 1. `cd' to the directory containing the package's source code and type
- `./configure' to configure the package for your system. If you're
- using `csh' on an old version of System V, you might need to type
- `sh ./configure' instead to prevent `csh' from trying to execute
- `configure' itself.
-
- Running `configure' takes awhile. While running, it prints some
- messages telling which features it is checking for.
-
- 2. Type `make' to compile the package.
-
- 3. Optionally, type `make check' to run any self-tests that come with
- the package.
-
- 4. Type `make install' to install the programs and any data files and
- documentation.
-
- 5. You can remove the program binaries and object files from the
- source code directory by typing `make clean'. To also remove the
- files that `configure' created (so you can compile the package for
- a different kind of computer), type `make distclean'. There is
- also a `make maintainer-clean' target, but that is intended mainly
- for the package's developers. If you use it, you may have to get
- all sorts of other programs in order to regenerate files that came
- with the distribution.
-
-Compilers and Options
-=====================
-
- Some systems require unusual options for compilation or linking that
-the `configure' script does not know about. Run `./configure --help'
-for details on some of the pertinent environment variables.
-
- You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment. Here
-is an example:
-
- ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
-
- *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
- You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory. To do this, you must use a version of `make' that
-supports the `VPATH' variable, such as GNU `make'. `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script. `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
-
- If you have to use a `make' that does not support the `VPATH'
-variable, you have to compile the package for one architecture at a
-time in the source code directory. After you have installed the
-package for one architecture, use `make distclean' before reconfiguring
-for another architecture.
-
-Installation Names
-==================
-
- By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc. You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PATH'.
-
- You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files. If you
-give `configure' the option `--exec-prefix=PATH', the package will use
-PATH as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
-
- In addition, if you use an unusual directory layout you can give
-options like `--bindir=PATH' to specify different values for particular
-kinds of files. Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.
-
- If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
-Optional Features
-=================
-
- Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System). The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
- For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
-Specifying the System Type
-==========================
-
- There may be some features `configure' cannot figure out
-automatically, but needs to determine by the type of machine the package
-will run on. Usually, assuming the package is built to be run on the
-_same_ architectures, `configure' can figure that out, but if it prints
-a message saying it cannot guess the machine type, give it the
-`--build=TYPE' option. TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
- CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
- OS KERNEL-OS
-
- See the file `config.sub' for the possible values of each field. If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
- If you are _building_ compiler tools for cross-compiling, you should
-use the `--target=TYPE' option to select the type of system they will
-produce code for.
-
- If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
- If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists. Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
- Variables not defined in a site shell script can be set in the
-environment passed to `configure'. However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost. In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'. For example:
-
- ./configure CC=/usr/local2/bin/gcc
-
-will cause the specified gcc to be used as the C compiler (unless it is
-overridden in the site shell script).
-
-`configure' Invocation
-======================
-
- `configure' recognizes the following options to control how it
-operates.
-
-`--help'
-`-h'
- Print a summary of the options to `configure', and exit.
-
-`--version'
-`-V'
- Print the version of Autoconf used to generate the `configure'
- script, and exit.
-
-`--cache-file=FILE'
- Enable the cache: use and save the results of the tests in FILE,
- traditionally `config.cache'. FILE defaults to `/dev/null' to
- disable caching.
-
-`--config-cache'
-`-C'
- Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
- Do not print messages saying which checks are being made. To
- suppress all normal output, redirect it to `/dev/null' (any error
- messages will still be shown).
-
-`--srcdir=DIR'
- Look for the package's source code in directory DIR. Usually
- `configure' can determine that directory automatically.
-
-`configure' also accepts some other, not widely useful, options. Run
-`configure --help' for more details.
-
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -10,7 +10,8 @@
bin_PROGRAMS = \
aubioonset \
aubiotrack \
- aubionotes
+ aubionotes \
+ aubiomfcc
noinst_PROGRAMS = \
aubioquiet
@@ -22,8 +23,10 @@
aubionotes_SOURCES = aubionotes.c utils.c
aubiotrack_SOURCES = aubiotrack.c utils.c
aubioquiet_SOURCES = aubioquiet.c utils.c
+aubiomfcc_SOURCES = aubiomfcc.c utils.c
aubioonset_LDADD = @JACK_LIBS@
aubionotes_LDADD = @JACK_LIBS@
aubiotrack_LDADD = @JACK_LIBS@
aubioquiet_LDADD = @JACK_LIBS@
+aubiomfcc_LDADD = @JACK_LIBS@
--- /dev/null
+++ b/examples/aubiomfcc.c
@@ -1,0 +1,112 @@
+/*
+ Copyright (C) 2007 Amaury Hazan <[email protected]>
+ and Paul Brossier <[email protected]>
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "utils.h"
+
+/* mfcc objects */
+fvec_t * mfcc_out;
+aubio_mfcc_t * mfcc;
+
+uint_t n_filters = 20;
+uint_t n_coefs = 11;
+
+unsigned int pos = 0; /*frames%dspblocksize*/
+uint_t usepitch = 0;
+
+int aubio_process(float **input, float **output, int nframes);
+int aubio_process(float **input, float **output, int nframes) {
+ unsigned int i; /*channels*/
+ unsigned int j; /*frames*/
+
+ for (j=0;j<(unsigned)nframes;j++) {
+ if(usejack) {
+ for (i=0;i<channels;i++) {
+ /* write input to datanew */
+ fvec_write_sample(ibuf, input[i][j], i, pos);
+ /* put synthnew in output */
+ output[i][j] = fvec_read_sample(obuf, i, pos);
+ }
+ }
+ /*time for fft*/
+ if (pos == overlap_size-1) {
+ /* block loop */
+
+ //compute mag spectrum
+ aubio_pvoc_do (pv,ibuf, fftgrain);
+
+ //compute mfccs
+ aubio_mfcc_do(mfcc, fftgrain, mfcc_out);
+
+ /* end of block loop */
+ pos = -1; /* so it will be zero next j loop */
+ }
+ pos++;
+ }
+ return 1;
+}
+
+void process_print (void);
+void process_print (void) {
+ /* output times in seconds
+ write extracted mfccs
+ */
+
+ uint_t coef_cnt;
+ if (output_filename == NULL) {
+// if(frames >= 4) {
+// outmsg("%f\t",(frames-4)*overlap_size/(float)samplerate);
+// }
+// else if (frames < 4) {
+// outmsg("%f\t",0.);
+// }
+ //outmsg("%f ",mfcc_out->data[0][0]);
+
+ /*for (coef_cnt = 0; coef_cnt < n_coefs; coef_cnt++) {
+ outmsg("%f ",mfcc_out->data[0][coef_cnt]);
+ }
+ outmsg("\n");/*/
+ }
+}
+
+int main(int argc, char **argv) {
+ // params
+
+ examples_common_init(argc,argv);
+ smpl_t lowfreq = 133.333f;
+ smpl_t highfreq = 44100.f;
+ mfcc_out = new_fvec(n_coefs,channels);
+
+ //populating the filter
+ mfcc = new_aubio_mfcc(buffer_size, samplerate, n_filters, n_coefs , lowfreq, highfreq, channels);
+ dump_filterbank(mfcc);
+
+ //process
+ examples_common_process(aubio_process,process_print);
+
+ //destroying mfcc
+ del_aubio_mfcc(mfcc);
+ del_fvec(mfcc_out);
+
+ examples_common_del();
+ debug("End of program.\n");
+ fflush(stderr);
+
+ return 0;
+}
+
--- /dev/null
+++ b/examples/plotfb.py
@@ -1,0 +1,21 @@
+#!/usr/bin/env python
+
+import pylab
+import numpy
+import sys
+
+filename=sys.argv[1]
+
+mat = pylab.load(filename)
+nmat= numpy.array(mat)
+print numpy.shape(nmat)
+
+pylab.hold(True)
+
+n_filters=numpy.shape(nmat)[0]
+for i in range(n_filters):
+ pylab.plot(nmat[i,:])
+
+
+pylab.hold(False)
+pylab.show()
\ No newline at end of file
--- /dev/null
+++ b/examples/plotmat.py
@@ -1,0 +1,18 @@
+#!/usr/bin/env python
+
+import pylab
+import numpy
+import sys
+
+filename=sys.argv[1]
+
+mat=pylab.load(filename)
+nmat=numpy.array(mat).T
+print numpy.shape(nmat)
+
+
+pylab.matshow(nmat, cmap=pylab.cm.gray, aspect='auto')
+#pylab.imshow(nmat, cmap=pylab.cm.gray, aspect='auto', interpolation=False)
+#pylab.contour(nmat, cmap=pylab.cm.gray, aspect='auto')
+
+pylab.show()
\ No newline at end of file
--- a/examples/tests/test-beattracking.c
+++ b/examples/tests/test-beattracking.c
@@ -12,8 +12,15 @@
uint_t i = 0;
+ smpl_t curtempo;
+
while (i < 10) {
aubio_beattracking_do(tempo,in,out);
+ curtempo = aubio_beattracking_get_bpm(tempo);
+ if (curtempo != 0.) {
+ fprintf(stdout,"%f\n",curtempo);
+ return 1;
+ }
i++;
};
--- a/examples/tests/test-tempo.c
+++ b/examples/tests/test-tempo.c
@@ -9,8 +9,14 @@
aubio_tempo_t * o = new_aubio_tempo(aubio_onset_complex, win_s, win_s/4, channels);
uint_t i = 0;
+ smpl_t curtempo;
+
while (i < 1000) {
aubio_tempo(o,in,out);
+ curtempo = aubio_tempo_get_bpm(o);
+ if (curtempo != 0.) {
+ fprintf(stdout,"%f\n",curtempo);
+ }
i++;
};
--- a/examples/utils.c
+++ b/examples/utils.c
@@ -60,7 +60,6 @@
int isonset = 0;
aubio_pickpeak_t * parms;
-
/* pitch objects */
smpl_t pitch = 0.;
aubio_pitchdetection_t * pitchdet;
@@ -300,6 +299,7 @@
obuf = new_fvec(overlap_size, channels);
fftgrain = new_cvec(buffer_size, channels);
+
if (usepitch) {
pitchdet = new_aubio_pitchdetection(buffer_size*4,
overlap_size, channels, samplerate, type_pitch, mode_pitch);
@@ -312,6 +312,7 @@
}
/* phase vocoder */
pv = new_aubio_pvoc(buffer_size, overlap_size, channels);
+
/* onsets */
parms = new_aubio_peakpicker(threshold);
o = new_aubio_onsetdetection(type_onset,buffer_size,channels);
@@ -345,6 +346,7 @@
del_cvec(fftgrain);
del_fvec(onset);
del_fvec(woodblock);
+
aubio_cleanup();
}
--- a/examples/utils.h
+++ b/examples/utils.h
@@ -97,7 +97,6 @@
extern int isonset;
extern aubio_pickpeak_t * parms;
-
/* pitch objects */
extern smpl_t pitch;
extern aubio_pitchdetection_t * pitchdet;
--- a/python/aubio/aubioclass.py
+++ b/python/aubio/aubioclass.py
@@ -126,7 +126,7 @@
channels=1,samplerate=44100.,omode=aubio_pitchm_freq,yinthresh=0.1):
self.pitchp = new_aubio_pitchdetection(bufsize,hopsize,channels,
samplerate,mode,omode)
- aubio_pitchdetection_set_yinthresh(self.pitchp,yinthresh)
+ aubio_pitchdetection_set_yinthresh(self.pitchp,yinthresh)
#self.filt = filter(srate,"adsgn")
def __del__(self):
del_aubio_pitchdetection(self.pitchp)
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,7 +21,10 @@
beattracking.h \
onset.h \
tempo.h \
- filter.h
+ filter.h \
+ filterbank.h \
+ mfcc.h
+
nodist_pkginclude_HEADERS = config.h
lib_LTLIBRARIES = libaubio.la
@@ -68,7 +71,11 @@
tempo.c \
tempo.h \
filter.c \
- filter.h
+ filter.h \
+ filterbank.c \
+ filterbank.h \
+ mfcc.h \
+ mfcc.c
AM_CFLAGS = @AUBIO_CFLAGS@ @FFTWLIB_CFLAGS@ @SAMPLERATE_CFLAGS@
libaubio_la_LIBADD = @FFTWLIB_LIBS@ @SAMPLERATE_LIBS@ @LTLIBOBJS@
--- a/src/aubio.h
+++ b/src/aubio.h
@@ -79,6 +79,8 @@
#include "beattracking.h"
#include "onset.h"
#include "tempo.h"
+#include "filterbank.h"
+#include "mfcc.h"
#ifdef __cplusplus
} /* extern "C" */
--- /dev/null
+++ b/src/bark.c
@@ -1,0 +1,54 @@
+/*
+ Copyright (C) 2006 Amaury Hazan
+ Ported to aubio from LibXtract
+ http://libxtract.sourceforge.net/
+
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#define XTRACT_BARK_BANDS 26
+#include "bark.c"
+
+int xtract_init_bark(int N, float sr, int *band_limits){
+
+ float edges[] = {0, 100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270, 1480, 1720, 2000, 2320, 2700, 3150, 3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500, 20500, 27000}; /* Takes us up to sr = 54kHz (CCRMA: JOS)*/
+
+ int bands = XTRACT_BARK_BANDS;
+
+ while(bands--)
+ band_limits[bands] = edges[bands] / sr * N;
+ /*FIX shohuld use rounding, but couldn't get it to work */
+
+ return XTRACT_SUCCESS;
+}
+
+
+
+
+int xtract_bark_coefficients(const float *data, const int N, const void *argv, float *result){
+
+ int *limits, band, n;
+
+ limits = (int *)argv;
+
+ for(band = 0; band < XTRACT_BARK_BANDS - 1; band++){
+ for(n = limits[band]; n < limits[band + 1]; n++)
+ result[band] += data[n];
+ }
+
+ return XTRACT_SUCCESS;
+}
\ No newline at end of file
--- /dev/null
+++ b/src/bark.h
@@ -1,0 +1,53 @@
+/*
+ Copyright (C) 2006 Amaury Hazan
+ Ported to aubio from LibXtract
+ http://libxtract.sourceforge.net/
+
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef BARK_H
+#define BARK_H
+
+
+// Initalization
+
+/** \brief A function to initialise bark filter bounds
+ *
+ * A pointer to an array of BARK_BANDS ints most be passed in, and is populated with BARK_BANDS fft bin numbers representing the limits of each band
+ *
+ * \param N: the audio block size
+ * \param sr: The sample audio sample rate
+ * \param *band_limits: a pointer to an array of BARK_BANDS ints
+ */
+int xtract_init_bark(int N, float sr, int *band_limits);
+
+// Computation
+
+/** \brief Extract Bark band coefficients based on a method
+ * \param *data: a pointer to the first element in an array of floats representing the magnitude coefficients from the magnitude spectrum of an audio vector, (e.g. the first half of the array pointed to by *result from xtract_spectrum().
+ * \param N: the number of array elements to be considered
+ * \param *argv: a pointer to an array of ints representing the limits of each bark band. This can be obtained by calling xtract_init_bark.
+ * \param *result: a pointer to an array containing resultant bark coefficients
+ *
+ * The limits array pointed to by *argv must be obtained by first calling xtract_init_bark
+ *
+ */
+int xtract_bark_coefficients(const float *data, const int N, const void *argv, float *result);
+
+
+#endif
\ No newline at end of file
--- a/src/beattracking.c
+++ b/src/beattracking.c
@@ -452,3 +452,11 @@
bt->rp2 = rp2;
}
+
+smpl_t aubio_beattracking_get_bpm(aubio_beattracking_t * bt) {
+ if (bt->timesig != 0 && bt->counter == 0 && bt->flagstep == 0) {
+ return 5168. / (smpl_t)bt->gp;
+ } else {
+ return 0.;
+ }
+}
--- a/src/beattracking.h
+++ b/src/beattracking.h
@@ -59,6 +59,15 @@
*/
void aubio_beattracking_do(aubio_beattracking_t * bt, fvec_t * dfframes, fvec_t * out);
+/** get current tempo in bpm
+
+ \param bt beat tracking object
+
+ Returns the currently observed tempo, in beats per minutes, or 0 if no
+ consistent value is found.
+
+*/
+smpl_t aubio_beattracking_get_bpm(aubio_beattracking_t * bt);
/** delete beat tracking object
\param p beat tracking object
--- /dev/null
+++ b/src/filterbank.c
@@ -1,0 +1,363 @@
+/*
+ Copyright (C) 2007 Amaury Hazan <[email protected]>
+ and Paul Brossier <[email protected]>
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/* part of this mfcc implementation were inspired from LibXtract
+ http://libxtract.sourceforge.net/
+*/
+
+#include "aubio_priv.h"
+#include "sample.h"
+#include "filterbank.h"
+
+#include "stdio.h"
+
+#define USE_EQUAL_GAIN 1
+#define VERY_SMALL_NUMBER 2e-42
+
+/** \brief A structure to store a set of n_filters filters of lenghts win_s */
+struct aubio_filterbank_t_ {
+ uint_t win_s;
+ uint_t n_filters;
+ fvec_t **filters;
+};
+
+aubio_filterbank_t * new_aubio_filterbank(uint_t n_filters, uint_t win_s){
+ /** allocating space for filterbank object */
+ aubio_filterbank_t * fb = AUBIO_NEW(aubio_filterbank_t);
+ uint_t filter_cnt;
+ fb->win_s=win_s;
+ fb->n_filters=n_filters;
+
+ /** allocating filter tables */
+ fb->filters=AUBIO_ARRAY(fvec_t*,n_filters);
+ for (filter_cnt=0; filter_cnt<n_filters; filter_cnt++)
+ /* considering one-channel filters */
+ fb->filters[filter_cnt]=new_fvec(win_s, 1);
+
+ return fb;
+}
+
+aubio_filterbank_t * new_aubio_filterbank_mfcc(uint_t n_filters, uint_t win_s, smpl_t samplerate, smpl_t freq_min, smpl_t freq_max){
+
+ smpl_t nyquist = samplerate/2.;
+ uint_t style = 1;
+ aubio_filterbank_t * fb = new_aubio_filterbank(n_filters, win_s);
+
+ uint_t n, i, k, *fft_peak, M, next_peak;
+ smpl_t norm, mel_freq_max, mel_freq_min, norm_fact, height, inc, val,
+ freq_bw_mel, *mel_peak, *height_norm, *lin_peak;
+
+ mel_peak = height_norm = lin_peak = NULL;
+ fft_peak = NULL;
+ norm = 1;
+
+ mel_freq_max = 1127 * log(1 + freq_max / 700);
+ mel_freq_min = 1127 * log(1 + freq_min / 700);
+ freq_bw_mel = (mel_freq_max - mel_freq_min) / fb->n_filters;
+
+ mel_peak = (smpl_t *)malloc((fb->n_filters + 2) * sizeof(smpl_t));
+ /* +2 for zeros at start and end */
+ lin_peak = (smpl_t *)malloc((fb->n_filters + 2) * sizeof(smpl_t));
+ fft_peak = (uint_t *)malloc((fb->n_filters + 2) * sizeof(uint_t));
+ height_norm = (smpl_t *)malloc(fb->n_filters * sizeof(smpl_t));
+
+ if(mel_peak == NULL || height_norm == NULL ||
+ lin_peak == NULL || fft_peak == NULL)
+ return NULL;
+
+ M = fb->win_s >> 1;
+
+ mel_peak[0] = mel_freq_min;
+ lin_peak[0] = 700 * (exp(mel_peak[0] / 1127) - 1);
+ fft_peak[0] = lin_peak[0] / nyquist * M;
+
+ for (n = 1; n <= fb->n_filters; n++){
+ /*roll out peak locations - mel, linear and linear on fft window scale */
+ mel_peak[n] = mel_peak[n - 1] + freq_bw_mel;
+ lin_peak[n] = 700 * (exp(mel_peak[n] / 1127) -1);
+ fft_peak[n] = lin_peak[n] / nyquist * M;
+ }
+
+ for (n = 0; n < fb->n_filters; n++){
+ /*roll out normalised gain of each peak*/
+ if (style == USE_EQUAL_GAIN){
+ height = 1;
+ norm_fact = norm;
+ }
+ else{
+ height = 2 / (lin_peak[n + 2] - lin_peak[n]);
+ norm_fact = norm / (2 / (lin_peak[2] - lin_peak[0]));
+ }
+ height_norm[n] = height * norm_fact;
+ }
+
+ i = 0;
+
+ for(n = 0; n < fb->n_filters; n++){
+
+ /*calculate the rise increment*/
+ if(n > 0)
+ inc = height_norm[n] / (fft_peak[n] - fft_peak[n - 1]);
+ else
+ inc = height_norm[n] / fft_peak[n];
+ val = 0;
+
+ /*zero the start of the array*/
+ for(k = 0; k < i; k++)
+ fb->filters[n]->data[0][k]=0.f;
+
+ /*fill in the rise */
+ for(; i <= fft_peak[n]; i++){
+ fb->filters[n]->data[0][k]=val;
+ val += inc;
+ }
+
+ /*calculate the fall increment */
+ inc = height_norm[n] / (fft_peak[n + 1] - fft_peak[n]);
+
+ val = 0;
+ next_peak = fft_peak[n + 1];
+
+ /*reverse fill the 'fall' */
+ for(i = next_peak; i > fft_peak[n]; i--){
+ fb->filters[n]->data[0][k]=val;
+ val += inc;
+ }
+
+ /*zero the rest of the array*/
+ for(k = next_peak + 1; k < fb->win_s; k++)
+ fb->filters[n]->data[0][k]=0.f;
+
+
+ }
+
+ free(mel_peak);
+ free(lin_peak);
+ free(height_norm);
+ free(fft_peak);
+
+
+ return fb;
+
+}
+
+
+aubio_filterbank_t * new_aubio_filterbank_mfcc2(uint_t n_filters, uint_t win_s, smpl_t samplerate, smpl_t freq_min, smpl_t freq_max){
+
+ //slaney params
+ smpl_t lowestFrequency = 133.3333;
+ smpl_t linearSpacing = 66.66666666;
+ smpl_t logSpacing = 1.0711703;
+
+ uint_t linearFilters = 13;
+ uint_t logFilters = 27;
+ uint_t allFilters = linearFilters + logFilters;
+
+ //buffers for computing filter frequencies
+ fvec_t * freqs=new_fvec( allFilters +2 , 1);
+ fvec_t * lower_freqs=new_fvec( allFilters, 1);
+ fvec_t * upper_freqs=new_fvec( allFilters, 1);
+ fvec_t * center_freqs=new_fvec( allFilters, 1);
+ fvec_t * triangle_heights=new_fvec( allFilters, 1);
+ //lookup table of each bin frequency in hz
+ fvec_t * fft_freqs=(win_s, 1);
+
+ uint_t filter_cnt, bin_cnt;
+
+ //first: filling all the linear filter frequencies
+ for(filter_cnt=0; filter_cnt<linearFilters; filter_cnt++){
+ freqs[0][filter_cnt]=lowestFrequency+ filter_cnt*linearSpacing;
+ }
+ smpl_t lastlinearCF=freqs[0][filter_cnt-1];
+
+ //second: filling all the log filter frequencies
+ for(filter_cnt=0; filter_cnt<logFilters+2; filter_cnt++){
+ freqs[filter_cnt+linearFilters]=lastlinearCF*(pow(logSpacing,filter_cnt+1));
+ }
+ //TODO: check if the referencing above works!
+ lower_freqs->data=freqs->data;
+ center_freqs->data=&(freqs->data[1]);
+ upper_freqs->data=&(freqs->data[2]);
+
+ //computing triangle heights so that each triangle has unit area
+ for(filter_cnt=0; filter_cnt<allFilters; filter_cnt++){
+ triangle_heights[filter_cnt]=2./(upper_freqs[filter_cnt]-lower_freqs[filter_cnt]);
+ }
+
+ //filling the lookup table, which assign the frequency in hz to each bin
+ for(bin_cnt=0; bin_cnt<win_s; bin_cnt++){
+ //TODO: check the formula!
+ fft_freqs[bin_cnt]=((smpl_t) bin_cnt/(smpl_t) win_s)* (smpl_t) samplerate;
+ }
+
+ //building each filter
+ for(filter_cnt=0; filter_cnt<allFilters; filter_cnt++){
+ //finding bins corresponding to lower, center, and upper frequencies
+
+ for(bin_cnt=0; bin_cnt<; bin_cnt++)
+ fb->filters[filter_cnt]->data[0][bin_cnt]=0.f;
+ }
+
+ // xtract
+ smpl_t nyquist = samplerate/2.;
+ uint_t style = 1;
+ aubio_filterbank_t * fb = new_aubio_filterbank(n_filters, win_s);
+
+ uint_t n, i, k, *fft_peak, M, next_peak;
+ smpl_t norm, mel_freq_max, mel_freq_min, norm_fact, height, inc, val,
+ freq_bw_mel, *mel_peak, *height_norm, *lin_peak;
+
+ mel_peak = height_norm = lin_peak = NULL;
+ fft_peak = NULL;
+ norm = 1;
+
+ mel_freq_max = 1127 * log(1 + freq_max / 700);
+ mel_freq_min = 1127 * log(1 + freq_min / 700);
+ freq_bw_mel = (mel_freq_max - mel_freq_min) / fb->n_filters;
+
+ mel_peak = (smpl_t *)malloc((fb->n_filters + 2) * sizeof(smpl_t));
+ /* +2 for zeros at start and end */
+ lin_peak = (smpl_t *)malloc((fb->n_filters + 2) * sizeof(smpl_t));
+ fft_peak = (uint_t *)malloc((fb->n_filters + 2) * sizeof(uint_t));
+ height_norm = (smpl_t *)malloc(fb->n_filters * sizeof(smpl_t));
+
+ if(mel_peak == NULL || height_norm == NULL ||
+ lin_peak == NULL || fft_peak == NULL)
+ return NULL;
+
+ M = fb->win_s >> 1;
+
+ mel_peak[0] = mel_freq_min;
+ lin_peak[0] = 700 * (exp(mel_peak[0] / 1127) - 1);
+ fft_peak[0] = lin_peak[0] / nyquist * M;
+
+ for (n = 1; n <= fb->n_filters; n++){
+ /*roll out peak locations - mel, linear and linear on fft window scale */
+ mel_peak[n] = mel_peak[n - 1] + freq_bw_mel;
+ lin_peak[n] = 700 * (exp(mel_peak[n] / 1127) -1);
+ fft_peak[n] = lin_peak[n] / nyquist * M;
+ }
+
+ for (n = 0; n < fb->n_filters; n++){
+ /*roll out normalised gain of each peak*/
+ if (style == USE_EQUAL_GAIN){
+ height = 1;
+ norm_fact = norm;
+ }
+ else{
+ height = 2 / (lin_peak[n + 2] - lin_peak[n]);
+ norm_fact = norm / (2 / (lin_peak[2] - lin_peak[0]));
+ }
+ height_norm[n] = height * norm_fact;
+ }
+
+ i = 0;
+
+ for(n = 0; n < fb->n_filters; n++){
+
+ /*calculate the rise increment*/
+ if(n > 0)
+ inc = height_norm[n] / (fft_peak[n] - fft_peak[n - 1]);
+ else
+ inc = height_norm[n] / fft_peak[n];
+ val = 0;
+
+ /*zero the start of the array*/
+ for(k = 0; k < i; k++)
+ fb->filters[n]->data[0][k]=0.f;
+
+ /*fill in the rise */
+ for(; i <= fft_peak[n]; i++){
+ fb->filters[n]->data[0][k]=val;
+ val += inc;
+ }
+
+ /*calculate the fall increment */
+ inc = height_norm[n] / (fft_peak[n + 1] - fft_peak[n]);
+
+ val = 0;
+ next_peak = fft_peak[n + 1];
+
+ /*reverse fill the 'fall' */
+ for(i = next_peak; i > fft_peak[n]; i--){
+ fb->filters[n]->data[0][k]=val;
+ val += inc;
+ }
+
+ /*zero the rest of the array*/
+ for(k = next_peak + 1; k < fb->win_s; k++)
+ fb->filters[n]->data[0][k]=0.f;
+
+
+ }
+
+ free(mel_peak);
+ free(lin_peak);
+ free(height_norm);
+ free(fft_peak);
+
+
+ return fb;
+
+}
+
+void aubio_dump_filterbank(aubio_filterbank_t * fb){
+
+ FILE * mlog;
+ mlog=fopen("filterbank.txt","w");
+
+ int k,n;
+ //dumping filter values
+ //smpl_t area_tmp=0.f;
+ for(n = 0; n < fb->n_filters; n++){
+ for(k = 0; k < fb->win_s; k++){
+ fprintf(mlog,"%f ",fb->filters[n]->data[0][k]);
+ }
+ fprintf(mlog,"\n");
+ }
+
+ if(mlog) fclose(mlog);
+}
+
+void del_aubio_filterbank(aubio_filterbank_t * fb){
+ uint_t filter_cnt;
+ /** deleting filter tables first */
+ for (filter_cnt=0; filter_cnt<fb->n_filters; filter_cnt++)
+ del_fvec(fb->filters[filter_cnt]);
+ AUBIO_FREE(fb->filters);
+ AUBIO_FREE(fb);
+}
+
+void aubio_filterbank_do(aubio_filterbank_t * f, cvec_t * in, fvec_t *out) {
+ uint_t n, filter_cnt;
+ for(filter_cnt = 0; (filter_cnt < f->n_filters)
+ && (filter_cnt < out->length); filter_cnt++){
+ out->data[0][filter_cnt] = 0.f;
+ for(n = 0; n < in->length; n++){
+ out->data[0][filter_cnt] += in->norm[0][n]
+ * f->filters[filter_cnt]->data[0][n];
+ }
+ out->data[0][filter_cnt] =
+ LOG(out->data[0][filter_cnt] < VERY_SMALL_NUMBER ?
+ VERY_SMALL_NUMBER : out->data[0][filter_cnt]);
+ }
+
+ return;
+}
--- /dev/null
+++ b/src/filterbank.h
@@ -1,0 +1,91 @@
+/*
+ Copyright (C) 2007 Amaury Hazan <[email protected]>
+ and Paul Brossier <[email protected]>
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/** \file
+
+ Filterbank object
+
+ General-purpose spectral filterbank object. Comes with mel-filter initialization function.
+
+*/
+
+#ifndef FILTERBANK_H
+#define FILTERBANK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct aubio_filterbank_t_ aubio_filterbank_t;
+
+/** create filterbank object
+
+ \param win_s size of analysis buffer (and length the FFT transform)
+ \param n_filters number of filters to create
+
+*/
+
+aubio_filterbank_t * new_aubio_filterbank(uint_t n_filters, uint_t win_s);
+
+/** filterbank initialization for mel filters
+
+
+ \param n_filters number of filters
+ \param win_s window size
+ \param samplerate
+ \param freq_min lowest filter frequency
+ \param freq_max highest filter frequency
+
+*/
+aubio_filterbank_t * new_aubio_filterbank_mfcc(uint_t n_filters, uint_t win_s, smpl_t samplerate, smpl_t freq_min, smpl_t freq_max);
+
+/** filterbank initialization for mel filters
+
+ \param n_filters number of filters
+ \param win_s window size
+ \param samplerate
+ \param freq_min lowest filter frequency
+ \param freq_max highest filter frequency
+
+*/
+aubio_filterbank_t * new_aubio_filterbank_mfcc_2(uint_t n_filters, uint_t win_s, smpl_t samplerate, smpl_t freq_min, smpl_t freq_max);
+
+
+/** destroy filterbank object
+
+ \param fb filterbank, as returned by new_aubio_filterbank method
+
+*/
+void del_aubio_filterbank(aubio_filterbank_t * fb);
+
+/** compute filterbank
+
+*/
+void aubio_filterbank_do(aubio_filterbank_t * fb, cvec_t * in, fvec_t *out);
+
+/** dump filterbank filter tables in a txt file
+
+*/
+void aubio_dump_filterbank(aubio_filterbank_t * fb);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // FILTERBANK_H
--- a/src/mathutils.c
+++ b/src/mathutils.c
@@ -29,7 +29,7 @@
switch(wintype) {
case aubio_win_rectangle:
for (i=0;i<size;i++)
- w[i] = 0.5;
+ w[i] = 0.5;
break;
case aubio_win_hamming:
for (i=0;i<size;i++)
@@ -47,11 +47,11 @@
for (i=0;i<size;i++)
w[i] = 0.42
- 0.50 * COS( TWO_PI*i/(size-1.0))
- + 0.08 * COS(2.0*TWO_PI*i/(size-1.0));
+ + 0.08 * COS(2.0*TWO_PI*i/(size-1.0));
break;
case aubio_win_blackman_harris:
for (i=0;i<size;i++)
- w[i] = 0.35875
+ w[i] = 0.35875
- 0.48829 * COS( TWO_PI*i/(size-1.0))
+ 0.14128 * COS(2.0*TWO_PI*i/(size-1.0))
- 0.01168 * COS(3.0*TWO_PI*i/(size-1.0));
@@ -73,15 +73,12 @@
}
}
-
smpl_t aubio_unwrap2pi(smpl_t phase) {
/* mod(phase+pi,-2pi)+pi */
return phase + TWO_PI * (1. + FLOOR(-(phase+PI)/TWO_PI));
}
-
-smpl_t vec_mean(fvec_t *s)
-{
+smpl_t vec_mean(fvec_t *s) {
uint_t i,j;
smpl_t tmp = 0.0f;
for (i=0; i < s->channels; i++)
@@ -90,9 +87,7 @@
return tmp/(smpl_t)(s->length);
}
-
-smpl_t vec_sum(fvec_t *s)
-{
+smpl_t vec_sum(fvec_t *s) {
uint_t i,j;
smpl_t tmp = 0.0f;
for (i=0; i < s->channels; i++)
@@ -101,9 +96,7 @@
return tmp;
}
-
-smpl_t vec_max(fvec_t *s)
-{
+smpl_t vec_max(fvec_t *s) {
uint_t i,j;
smpl_t tmp = 0.0f;
for (i=0; i < s->channels; i++)
@@ -112,8 +105,7 @@
return tmp;
}
-smpl_t vec_min(fvec_t *s)
-{
+smpl_t vec_min(fvec_t *s) {
uint_t i,j;
smpl_t tmp = s->data[0][0];
for (i=0; i < s->channels; i++)
@@ -122,9 +114,7 @@
return tmp;
}
-
-uint_t vec_min_elem(fvec_t *s)
-{
+uint_t vec_min_elem(fvec_t *s) {
uint_t i,j=0, pos=0.;
smpl_t tmp = s->data[0][0];
for (i=0; i < s->channels; i++)
@@ -135,8 +125,7 @@
return pos;
}
-uint_t vec_max_elem(fvec_t *s)
-{
+uint_t vec_max_elem(fvec_t *s) {
uint_t i,j=0, pos=0.;
smpl_t tmp = 0.0f;
for (i=0; i < s->channels; i++)
@@ -147,8 +136,7 @@
return pos;
}
-void vec_shift(fvec_t *s)
-{
+void vec_shift(fvec_t *s) {
uint_t i,j;
//smpl_t tmp = 0.0f;
for (i=0; i < s->channels; i++)
@@ -160,8 +148,7 @@
}
}
-smpl_t vec_local_energy(fvec_t * f)
-{
+smpl_t vec_local_energy(fvec_t * f) {
smpl_t locE = 0.;
uint_t i,j;
for (i=0;i<f->channels;i++)
@@ -170,8 +157,7 @@
return locE;
}
-smpl_t vec_local_hfc(fvec_t * f)
-{
+smpl_t vec_local_hfc(fvec_t * f) {
smpl_t locE = 0.;
uint_t i,j;
for (i=0;i<f->channels;i++)
@@ -180,8 +166,7 @@
return locE;
}
-smpl_t vec_alpha_norm(fvec_t * DF, smpl_t alpha)
-{
+smpl_t vec_alpha_norm(fvec_t * DF, smpl_t alpha) {
smpl_t tmp = 0.;
uint_t i,j;
for (i=0;i<DF->channels;i++)
@@ -190,9 +175,7 @@
return POW(tmp/DF->length,1./alpha);
}
-
-void vec_dc_removal(fvec_t * mag)
-{
+void vec_dc_removal(fvec_t * mag) {
smpl_t mini = 0.;
uint_t length = mag->length, i=0, j;
mini = vec_min(mag);
@@ -201,9 +184,7 @@
}
}
-
-void vec_alpha_normalise(fvec_t * mag, uint_t alpha)
-{
+void vec_alpha_normalise(fvec_t * mag, uint_t alpha) {
smpl_t alphan = 1.;
uint_t length = mag->length, i=0, j;
alphan = vec_alpha_norm(mag,alpha);
@@ -212,7 +193,6 @@
}
}
-
void vec_add(fvec_t * mag, smpl_t threshold) {
uint_t length = mag->length, i=0, j;
for (j=0;j<length;j++) {
@@ -220,10 +200,8 @@
}
}
-
-void vec_adapt_thres(fvec_t * vec, fvec_t * tmp,
- uint_t post, uint_t pre)
-{
+void vec_adapt_thres(fvec_t * vec, fvec_t * tmp,
+ uint_t post, uint_t pre) {
uint_t length = vec->length, i=0, j;
for (j=0;j<length;j++) {
vec->data[i][j] -= vec_moving_thres(vec, tmp, post, pre, j);
@@ -231,8 +209,7 @@
}
smpl_t vec_moving_thres(fvec_t * vec, fvec_t * tmpvec,
- uint_t post, uint_t pre, uint_t pos)
-{
+ uint_t post, uint_t pre, uint_t pos) {
smpl_t * medar = (smpl_t *)tmpvec->data[0];
uint_t k;
uint_t win_length = post+pre+1;
@@ -239,7 +216,7 @@
uint_t length = vec->length;
/* post part of the buffer does not exist */
if (pos<post+1) {
- for (k=0;k<post+1-pos;k++)
+ for (k=0;k<post+1-pos;k++)
medar[k] = 0.; /* 0-padding at the beginning */
for (k=post+1-pos;k<win_length;k++)
medar[k] = vec->data[0][k+pos-post];
@@ -251,9 +228,9 @@
} else {
for (k=0;k<length-pos+post+1;k++)
medar[k] = vec->data[0][k+pos-post];
- for (k=length-pos+post+1;k<win_length;k++)
+ for (k=length-pos+post+1;k<win_length;k++)
medar[k] = 0.; /* 0-padding at the end */
- }
+ }
return vec_median(tmpvec);
}
@@ -320,9 +297,9 @@
/* increase frac */
for (frac = 0.; frac < 2.; frac = frac + step) {
res = aubio_quadfrac(s0, s1, s2, frac);
- if (res > resold)
+ if (res > resold)
resold = res;
- else {
+ else {
exactpos += (frac-step)*2. - 1.;
break;
}
@@ -344,7 +321,7 @@
res = aubio_quadfrac(s0, s1, s2, frac);
if (res < resold) {
resold = res;
- } else {
+ } else {
exactpos += (frac-step)*span - span/2.;
break;
}
@@ -359,28 +336,28 @@
}
uint_t vec_peakpick(fvec_t * onset, uint_t pos) {
- uint_t i=0, tmp=0;
- /*for (i=0;i<onset->channels;i++)*/
- tmp = (onset->data[i][pos] > onset->data[i][pos-1]
- && onset->data[i][pos] > onset->data[i][pos+1]
- && onset->data[i][pos] > 0.);
- return tmp;
+ uint_t i=0, tmp=0;
+ /*for (i=0;i<onset->channels;i++)*/
+ tmp = (onset->data[i][pos] > onset->data[i][pos-1]
+ && onset->data[i][pos] > onset->data[i][pos+1]
+ && onset->data[i][pos] > 0.);
+ return tmp;
}
smpl_t aubio_freqtomidi(smpl_t freq) {
- /* log(freq/A-2)/log(2) */
- smpl_t midi = freq/6.875;
- midi = LOG(midi)/0.69314718055995;
- midi *= 12;
- midi -= 3;
- return midi;
+ /* log(freq/A-2)/log(2) */
+ smpl_t midi = freq/6.875;
+ midi = LOG(midi)/0.69314718055995;
+ midi *= 12;
+ midi -= 3;
+ return midi;
}
smpl_t aubio_miditofreq(smpl_t midi) {
- smpl_t freq = (midi+3.)/12.;
- freq = EXP(freq*0.69314718055995);
- freq *= 6.875;
- return freq;
+ smpl_t freq = (midi+3.)/12.;
+ freq = EXP(freq*0.69314718055995);
+ freq *= 6.875;
+ return freq;
}
smpl_t aubio_bintofreq(smpl_t bin, smpl_t samplerate, smpl_t fftsize) {
@@ -403,9 +380,7 @@
return aubio_freqtobin(freq,samplerate,fftsize);
}
-
-
-/** returns 1 if wassilence is 0 and RMS(ibuf)<threshold
+/** returns 1 if wassilence is 0 and RMS(ibuf)<threshold
* \bug mono
*/
uint_t aubio_silence_detection(fvec_t * ibuf, smpl_t threshold) {
@@ -435,9 +410,9 @@
loudness = LIN2DB(loudness);
if (loudness < threshold)
- return 1.;
+ return 1.;
else
- return loudness;
+ return loudness;
}
smpl_t aubio_zero_crossing_rate(fvec_t * input) {
@@ -450,7 +425,7 @@
zcr += 1;
}
//previous was positive
- } else if ( input->data[i][j] <= 0. ){
+ } else if ( input->data[i][j] <= 0. ) {
zcr += 1;
}
}
@@ -470,27 +445,26 @@
return sc / sum * samplerate / (smpl_t)(spectrum->length);
}
-void aubio_autocorr(fvec_t * input, fvec_t * output){
- uint_t i = 0, j = 0, length = input->length;
- smpl_t * data = input->data[0];
- smpl_t * acf = output->data[0];
- smpl_t tmp =0.;
- for(i=0;i<length;i++){
- for(j=i;j<length;j++){
- tmp += data[j-i]*data[j];
- }
- acf[i] = tmp /(smpl_t)(length-i);
- tmp = 0.0;
- }
-}
+void aubio_autocorr(fvec_t * input, fvec_t * output) {
+ uint_t i = 0, j = 0, length = input->length;
+ smpl_t * data = input->data[0];
+ smpl_t * acf = output->data[0];
+ smpl_t tmp =0.;
+ for(i=0;i<length;i++){
+ for(j=i;j<length;j++){
+ tmp += data[j-i]*data[j];
+ }
+ acf[i] = tmp /(smpl_t)(length-i);
+ tmp = 0.0;
+ }
+}
-void aubio_cleanup(void)
-{
+void aubio_cleanup(void) {
#if FFTW3_SUPPORT
- fftw_cleanup();
+ fftw_cleanup();
#else
#if FFTW3F_SUPPORT
- fftwf_cleanup();
+ fftwf_cleanup();
#endif
#endif
}
--- /dev/null
+++ b/src/mfcc.c
@@ -1,0 +1,119 @@
+/*
+ Copyright (C) 2006 Amaury Hazan
+ Ported to aubio from LibXtract
+ http://libxtract.sourceforge.net/
+
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "aubio_priv.h"
+#include "sample.h"
+#include "fft.h"
+#include "filterbank.h"
+#include "mfcc.h"
+#include "math.h"
+
+/** Internal structure for mfcc object **/
+
+struct aubio_mfcc_t_{
+ uint_t win_s; /** grain length */
+ uint_t samplerate; /** sample rate (needed?) */
+ uint_t channels; /** number of channels */
+ uint_t n_filters; /** number of *filters */
+ uint_t n_coefs; /** number of coefficients (<= n_filters/2 +1) */
+ smpl_t lowfreq; /** lowest frequency for filters */
+ smpl_t highfreq; /** highest frequency for filters */
+ aubio_filterbank_t * fb; /** filter bank */
+ fvec_t * in_dct; /** input buffer for dct * [fb->n_filters] */
+ aubio_mfft_t * fft_dct; /** fft object for dct */
+ cvec_t * fftgrain_dct; /** output buffer for dct */
+};
+
+
+aubio_mfcc_t * new_aubio_mfcc (uint_t win_s, uint_t samplerate, uint_t n_filters, uint_t n_coefs, smpl_t lowfreq, smpl_t highfreq, uint_t channels){
+ /** allocating space for mfcc object */
+ aubio_mfcc_t * mfcc = AUBIO_NEW(aubio_mfcc_t);
+
+ //we need (n_coefs-1)*2 filters to obtain n_coefs coefficients after dct
+ //uint_t n_filters = (n_coefs-1)*2;
+
+ mfcc->win_s=win_s;
+ mfcc->samplerate=samplerate;
+ mfcc->channels=channels;
+ mfcc->n_filters=n_filters;
+ mfcc->n_coefs=n_coefs;
+ mfcc->lowfreq=lowfreq;
+ mfcc->highfreq=highfreq;
+
+ /** filterbank allocation */
+ mfcc->fb = new_aubio_filterbank_mfcc(n_filters, mfcc->win_s, samplerate, lowfreq, highfreq);
+
+ /** allocating space for fft object (used for dct) */
+ mfcc->fft_dct=new_aubio_mfft(n_filters, 1);
+
+ /** allocating buffers */
+ mfcc->in_dct=new_fvec(mfcc->win_s, 1);
+
+ mfcc->fftgrain_dct=new_cvec(n_filters, 1);
+
+ return mfcc;
+};
+
+void del_aubio_mfcc(aubio_mfcc_t *mf){
+ /** deleting filterbank */
+ del_aubio_filterbank(mf->fb);
+ /** deleting mfft object */
+ del_aubio_mfft(mf->fft_dct);
+ /** deleting buffers */
+ del_fvec(mf->in_dct);
+ del_cvec(mf->fftgrain_dct);
+
+ /** deleting mfcc object */
+ AUBIO_FREE(mf);
+}
+
+void aubio_mfcc_do(aubio_mfcc_t * mf, cvec_t *in, fvec_t *out){
+ // compute filterbank
+ aubio_filterbank_do(mf->fb, in, mf->in_dct);
+ //TODO: check that zero padding
+ // the following line seems useless since the in_dct buffer has the correct size
+ //for(n = filter + 1; n < N; n++) result[n] = 0;
+
+ aubio_dct_do(mf, mf->in_dct, out);
+
+ return;
+}
+
+void aubio_dct_do(aubio_mfcc_t * mf, fvec_t *in, fvec_t *out){
+ uint_t i;
+ //compute mag spectrum
+ aubio_mfft_do (mf->fft_dct, in, mf->fftgrain_dct);
+ //extract real part of fft grain
+ for(i=0; i<mf->n_coefs ;i++){
+ //for(i=0; i<out->length;i++){
+ out->data[0][i]= mf->fftgrain_dct->norm[0][i]
+ *COS(mf->fftgrain_dct->phas[0][i]);
+ }
+ return;
+}
+
+//a bit a kludge
+void dump_filterbank(aubio_mfcc_t * mf){
+ aubio_dump_filterbank(mf->fb);
+
+}
+
--- /dev/null
+++ b/src/mfcc.h
@@ -1,0 +1,83 @@
+/*
+ Copyright (C) 2007 Amaury Hazan <[email protected]>
+ and Paul Brossier <[email protected]>
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/* part of this mfcc implementation were inspired from LibXtract
+ http://libxtract.sourceforge.net/
+*/
+
+#ifndef MFCC_H
+#define MFCC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "sample.h"
+#include "filterbank.h"
+
+typedef struct aubio_mfcc_t_ aubio_mfcc_t;
+
+/** create mfcc object
+
+ \param win_s size of analysis buffer (and length the FFT transform)
+ \param samplerate
+ \param n_coefs: number of desired coefs
+ \param lowfreq: lowest frequency to use in filterbank
+ \param highfreq highest frequency to use in filterbank
+ \param channels number of channels
+
+*/
+aubio_mfcc_t * new_aubio_mfcc (uint_t win_s, uint_t samplerate, uint_t n_filters, uint_t n_coefs, smpl_t lowfreq, smpl_t highfreq, uint_t channels);
+/** delete mfcc object
+
+ \param mf mfcc object as returned by new_aubio_mfcc
+
+*/
+void del_aubio_mfcc(aubio_mfcc_t *mf);
+/** mfcc object processing
+
+ \param mf mfcc object as returned by new_aubio_mfcc
+ \param in input spectrum (win_s long)
+ \param out output mel coefficients buffer (n_filters/2 +1 long)
+
+*/
+void aubio_mfcc_do(aubio_mfcc_t * mf, cvec_t *in, fvec_t *out);
+
+/** intermediate dct involved in aubio_mfcc_do
+
+ \param mf mfcc object as returned by new_aubio_mfcc
+ \param in input spectrum (n_filters long)
+ \param out output mel coefficients buffer (n_filters/2 +1 long)
+
+*/
+void aubio_dct_do(aubio_mfcc_t * mf, fvec_t *in, fvec_t *out);
+
+/** dump filterbank to log file
+
+ \param mf mfcc object as returned by new_aubio_mfcc
+
+*/
+void dump_filterbank(aubio_mfcc_t * mf);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MFCC_H
--- a/src/tempo.c
+++ b/src/tempo.c
@@ -123,6 +123,10 @@
return o;
}
+smpl_t aubio_tempo_get_bpm(aubio_tempo_t *o) {
+ return aubio_beattracking_get_bpm(o->bt);
+}
+
void del_aubio_tempo (aubio_tempo_t *o)
{
del_aubio_onsetdetection(o->od);
--- a/src/tempo.h
+++ b/src/tempo.h
@@ -49,6 +49,15 @@
/** set tempo detection peak picking threshold */
void aubio_tempo_set_threshold(aubio_tempo_t * o, smpl_t threshold);
+/** get current tempo
+
+ \param bt beat tracking object
+
+ Returns the currently observed tempo, or 0 if no consistent value is found
+
+*/
+smpl_t aubio_tempo_get_bpm(aubio_tempo_t * bt);
+
/** delete tempo detection object */
void del_aubio_tempo(aubio_tempo_t * o);