2 Copyright (C) 2003 Paul Brossier
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.
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.
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.
20 #include "aubio_priv.h"
23 #include "mathutils.h"
25 #include "onsetdetection.h"
28 struct _aubio_onsetdetection_t {
29 aubio_onsetdetection_type type;
30 /** Pointer to aubio_onsetdetection_<type> function */
31 void (*funcpointer)(aubio_onsetdetection_t *o,
32 cvec_t * fftgrain, fvec_t * onset);
39 aubio_hist_t * histog;
43 static aubio_onsetdetection_t * aubio_onsetdetection_alloc(aubio_onsetdetection_type type, uint_t size, uint_t channels);
45 /* Energy based onset detection function */
46 void aubio_onsetdetection_energy (aubio_onsetdetection_t *o,
47 cvec_t * fftgrain, fvec_t * onset) {
49 for (i=0;i<fftgrain->channels;i++) {
50 onset->data[i][0] = 0.;
51 for (j=0;j<fftgrain->length;j++) {
52 onset->data[i][0] += SQR(fftgrain->norm[i][j]);
57 /* High Frequency Content onset detection function */
58 void aubio_onsetdetection_hfc(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){
60 for (i=0;i<fftgrain->channels;i++) {
61 onset->data[i][0] = 0.;
62 for (j=0;j<fftgrain->length;j++) {
63 onset->data[i][0] += (j+1)*fftgrain->norm[i][j];
69 /* Complex Domain Method onset detection function */
70 /* moved to /2 032402 */
71 void aubio_onsetdetection_complex (aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset) {
73 uint_t nbins = fftgrain->length;
74 for (i=0;i<fftgrain->channels; i++) {
75 onset->data[i][0] = 0.;
76 for (j=0;j<nbins; j++) {
77 o->dev1->data[i][j] = unwrap2pi(
79 -2.0*o->theta1->data[i][j]+
80 o->theta2->data[i][j]);
81 o->meas[j] = fftgrain->norm[i][j]*CEXPC(I*o->dev1->data[i][j]);
83 onset->data[i][0] += //(fftgrain->norm[i][j]);
84 SQRT(SQR( REAL(o->oldmag->data[i][j]-o->meas[j]) )
85 + SQR( IMAG(o->oldmag->data[i][j]-o->meas[j]) )
87 /* swap old phase data (need to remember 2 frames behind)*/
88 o->theta2->data[i][j] = o->theta1->data[i][j];
89 o->theta1->data[i][j] = fftgrain->phas[i][j];
90 /* swap old magnitude data (1 frame is enough) */
91 o->oldmag->data[i][j] = fftgrain->norm[i][j];
97 /* Phase Based Method onset detection function */
98 void aubio_onsetdetection_phase(aubio_onsetdetection_t *o,
99 cvec_t * fftgrain, fvec_t * onset){
101 uint_t nbins = fftgrain->length;
102 for (i=0;i<fftgrain->channels; i++) {
103 onset->data[i][0] = 0.0f;
104 o->dev1->data[i][0]=0.;
105 for ( j=0;j<nbins; j++ ) {
106 o->dev1->data[i][j] =
109 -2.0*o->theta1->data[i][j]
110 +o->theta2->data[i][j]);
111 if ( o->threshold < fftgrain->norm[i][j] )
112 o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
114 o->dev1->data[i][j] = 0.0f;
115 /* keep a track of the past frames */
116 o->theta2->data[i][j] = o->theta1->data[i][j];
117 o->theta1->data[i][j] = fftgrain->phas[i][j];
119 /* apply o->histogram */
120 aubio_hist_dyn_notnull(o->histog,o->dev1);
122 aubio_hist_weigth(o->histog);
123 /* its mean is the result */
124 onset->data[i][0] = aubio_hist_mean(o->histog);
125 //onset->data[i][0] = vec_mean(o->dev1);
129 /* Spectral difference method onset detection function */
130 /* moved to /2 032402 */
131 void aubio_onsetdetection_specdiff(aubio_onsetdetection_t *o,
132 cvec_t * fftgrain, fvec_t * onset){
134 uint_t nbins = fftgrain->length;
135 for (i=0;i<fftgrain->channels; i++) {
136 onset->data[i][0] = 0.0f;
137 for (j=0;j<nbins; j++) {
138 o->dev1->data[i][j] = SQRT(
139 ABS(SQR( fftgrain->norm[i][j])
140 - SQR(o->oldmag->data[i][j])));
141 if (o->threshold < fftgrain->norm[i][j] )
142 o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
144 o->dev1->data[i][j] = 0.0f;
145 o->oldmag->data[i][j] = fftgrain->norm[i][j];
148 /* apply o->histogram (act somewhat as a low pass on the
149 * overall function)*/
150 aubio_hist_dyn_notnull(o->histog,o->dev1);
152 aubio_hist_weigth(o->histog);
153 /* its mean is the result */
154 onset->data[i][0] = aubio_hist_mean(o->histog);
159 /* Generic function pointing to the choosen one */
161 aubio_onsetdetection(aubio_onsetdetection_t *o, cvec_t * fftgrain,
163 o->funcpointer(o,fftgrain,onset);
166 /* Allocate memory for an onset detection */
167 aubio_onsetdetection_t *
168 new_aubio_onsetdetection (aubio_onsetdetection_type type,
169 uint_t size, uint_t channels){
170 return aubio_onsetdetection_alloc(type,size,channels);
173 /* depending on the choosen type, allocate memory as needed */
174 aubio_onsetdetection_t *
175 aubio_onsetdetection_alloc (aubio_onsetdetection_type type,
176 uint_t size, uint_t channels){
177 aubio_onsetdetection_t * o = AUBIO_NEW(aubio_onsetdetection_t);
178 uint_t rsize = size/2+1;
180 /* for both energy and hfc, only fftgrain->norm is required */
185 /* the other approaches will need some more memory spaces */
187 o->oldmag = new_fvec(rsize,channels);
188 /** bug: must be complex array */
189 o->meas = AUBIO_ARRAY(fft_data_t,size);
190 o->dev1 = new_fvec(rsize,channels);
191 o->theta1 = new_fvec(rsize,channels);
192 o->theta2 = new_fvec(rsize,channels);
195 o->dev1 = new_fvec(rsize,channels);
196 o->theta1 = new_fvec(rsize,channels);
197 o->theta2 = new_fvec(rsize,channels);
198 o->histog = new_aubio_hist(0.0f, PI, 10, channels);
202 o->oldmag = new_fvec(rsize,channels);
203 o->dev1 = new_fvec(rsize,channels);
204 o->histog = new_aubio_hist(0.0f, PI, 10, channels);
211 /* this switch could be in its own function to change between
212 * detections on the fly. this would need getting rid of the switch
213 * above and always allocate all the structure */
217 o->funcpointer = aubio_onsetdetection_energy;
220 o->funcpointer = aubio_onsetdetection_hfc;
223 o->funcpointer = aubio_onsetdetection_complex;
226 o->funcpointer = aubio_onsetdetection_phase;
229 o->funcpointer = aubio_onsetdetection_specdiff;
238 void aubio_onsetdetection_free (aubio_onsetdetection_t *o){
241 /* for both energy and hfc, only fftgrain->norm is required */
246 /* the other approaches will need some more memory spaces */
258 del_aubio_hist(o->histog);
263 del_aubio_hist(o->histog);