From a0fd4e4defd8dbe992d110774b8ee7f239b91e8c Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Sat, 2 Apr 2005 13:29:23 +0000 Subject: [PATCH] merge aubionotes and aubionotesmedian add make_audio_plot to gnuplot.py adds autocorrelation to mathutils adds Makefile.in to junk files --- examples/Makefile.am | 2 - examples/aubionotes.c | 87 +++++++++++- examples/aubionotesmedian.c | 331 -------------------------------------------- examples/utils.h | 1 + python/aubio/gnuplot.py | 19 +-- src/mathutils.c | 15 ++ src/mathutils.h | 4 + 7 files changed, 111 insertions(+), 348 deletions(-) delete mode 100644 examples/aubionotesmedian.c diff --git a/examples/Makefile.am b/examples/Makefile.am index eb03387a..0da729c7 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -8,7 +8,6 @@ AM_LDFLAGS = -L../src -L../ext @LADCCA_LIBS@ -laubioext -laubio # add your programs to this list bin_PROGRAMS = \ aubioonset \ - aubionotesmedian \ aubionotes EXTRA_DIST = utils.h @@ -16,4 +15,3 @@ EXTRA_DIST = utils.h # optionally add sources file for these programs aubioonset_SOURCES = aubioonset.c utils.c aubionotes_SOURCES = aubionotes.c utils.c -aubionotesmedian_SOURCES = aubionotesmedian.c utils.c diff --git a/examples/aubionotes.c b/examples/aubionotes.c index 8fea1307..7a9e7863 100644 --- a/examples/aubionotes.c +++ b/examples/aubionotes.c @@ -21,7 +21,7 @@ #include #include #include -#include // how do i do a floorf with a mask again ? +#include #include "aubio.h" #include "aubioext.h" #include "utils.h" @@ -34,10 +34,11 @@ int verbose = 0; int usejack = 0; int usedoubled = 1; int usemidi = 1; +int median = 0; /* energy,specdiff,hfc,complexdomain,phase */ aubio_onsetdetection_type type_onset = hfc; -aubio_onsetdetection_type type_onset2 = hfc; +aubio_onsetdetection_type type_onset2 = complexdomain; smpl_t threshold = 0.3; smpl_t threshold2 = -90.; uint_t buffer_size = 1024; @@ -60,11 +61,13 @@ int isonset = 0; aubio_pickpeak_t * parms; /* pitch objects */ -int curnote = 0; smpl_t pitch = 0.; aubio_pitchdetection_t * pitchdet; -int bufpos = 0; -smpl_t curlevel = 0; + +fvec_t * note_buffer = NULL; +fvec_t * note_buffer2 = NULL; +uint_t medianfiltlen = 6; +smpl_t curlevel = 0.; smpl_t maxonset = 0.; /* midi objects */ @@ -100,6 +103,34 @@ void send_noteon(aubio_midi_driver_t * d, int pitch, int velo) } } + +/** append new note candidate to the note_buffer and return filtered value. we + * need to copy the input array as vec_median destroy its input data.*/ + +void note_append(fvec_t * note_buffer, smpl_t curnote); +void note_append(fvec_t * note_buffer, smpl_t curnote) { + uint_t i = 0; + for (i = 0; i < note_buffer->length - 1; i++) { + note_buffer->data[0][i] = note_buffer->data[0][i+1]; + } + note_buffer->data[0][note_buffer->length - 1] = curnote; + return; +} + +uint_t get_note(fvec_t *note_buffer, fvec_t *note_buffer2); +uint_t get_note(fvec_t *note_buffer, fvec_t *note_buffer2){ + uint_t i = 0; + for (i = 0; i < note_buffer->length; i++) { + note_buffer2->data[0][i] = note_buffer->data[0][i]; + } + return vec_median(note_buffer2); +} + + +smpl_t curnote = 0.; +smpl_t newnote = 0.; +uint_t isready = 0; + int aubio_process(float **input, float **output, int nframes); int aubio_process(float **input, float **output, int nframes) { unsigned int i; /*channels*/ @@ -125,6 +156,10 @@ int aubio_process(float **input, float **output, int nframes) { isonset = aubio_peakpick_pimrt(onset,parms); pitch = aubio_pitchdetection(pitchdet,ibuf); + if(median){ + newnote = (FLOOR)(bintomidi(pitch,samplerate,buffer_size*4)+.5); + note_append(note_buffer, newnote); + } /* curlevel is negatif or 1 if silence */ curlevel = aubio_level_detection(ibuf, threshold2); @@ -132,9 +167,13 @@ int aubio_process(float **input, float **output, int nframes) { /* test for silence */ if (curlevel == 1.) { isonset=0; + if (median) isready = 0; /* send note off */ send_noteon(mdriver,curnote,0); } else { + if (median) { + isready = 1; + } else { /* kill old note */ send_noteon(mdriver,curnote,0); //curnote = (int)FLOOR(bintomidi(pitch,samplerate,buffer_size*4) + .5); @@ -146,11 +185,37 @@ int aubio_process(float **input, float **output, int nframes) { if (curnote>45){ send_noteon(mdriver,curnote,127+(int)FLOOR(curlevel)); } + } + for (pos = 0; pos < overlap_size; pos++){ obuf->data[0][pos] = woodblock->data[0][pos]; } } } else { + if (median) { +// if (curlevel != 1) { +// if (bufpos == note_buffer->length) +// curnote = aubio_getnote(note_buffer); +// } +// + if (isready > 0) + isready++; + if (isready == note_buffer->length) + { + //outmsg("%d, %f\n", isready, curnote); + send_noteon(mdriver,curnote,0); + /* kill old note */ + newnote = get_note(note_buffer, note_buffer2); + curnote = newnote; + /* get and send new one */ + /*if (curnote<45){ + send_noteon(mdriver,curnote,0); + } else {*/ + if (curnote>45){ + send_noteon(mdriver,curnote,127+(int)FLOOR(curlevel)); + } + } + } // if median for (pos = 0; pos < overlap_size; pos++) obuf->data[0][pos] = 0.; } @@ -187,9 +252,13 @@ int main(int argc, char **argv) { woodblock = new_fvec(buffer_size,1); fftgrain = new_cvec(buffer_size, channels); - pitchdet = new_aubio_pitchdetection(buffer_size*4, overlap_size, channels, samplerate, mcomb, freq); - //pitchdet = new_aubio_pitchdetection(buffer_size*2, overlap_size, channels, samplerate, yin, freq); + aubio_pitchdetection_type mode = yin; // mcomb + pitchdet = new_aubio_pitchdetection(buffer_size*4, overlap_size, channels, samplerate, mode, freq); +if (median) { + note_buffer = new_fvec(medianfiltlen, 1); + note_buffer2= new_fvec(medianfiltlen, 1); +} /* read the output sound once */ file_read(onsetfile, overlap_size, woodblock); /* phase vocoder */ @@ -261,6 +330,10 @@ int main(int argc, char **argv) { del_cvec(fftgrain); del_aubio_pitchdetection(pitchdet); del_fvec(onset); + if (median) { + del_fvec(note_buffer); + del_fvec(note_buffer2); + } debug("End of program.\n"); fflush(stderr); diff --git a/examples/aubionotesmedian.c b/examples/aubionotesmedian.c deleted file mode 100644 index 0cdc31d0..00000000 --- a/examples/aubionotesmedian.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - Copyright (C) 2003 Paul Brossier - - 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 -#include -#include -#include -#include -#include "aubio.h" -#include "aubioext.h" -#include "utils.h" - -#include //required for FLOORF :( - -/* settings */ -const char * output_filename = NULL; -const char * input_filename = NULL; -const char * onset_filename = "/usr/share/sounds/aubio/woodblock.aiff"; -int verbose = 0; -int usejack = 0; -int usedoubled = 1; -int usemidi = 1; - -/* energy,specdiff,hfc,complexdomain,phase */ -aubio_onsetdetection_type type_onset = hfc; -aubio_onsetdetection_type type_onset2 = complexdomain; -smpl_t threshold = 0.3; -smpl_t threshold2 = -90.; -uint_t buffer_size = 1024; -uint_t overlap_size = 512; -uint_t channels = 1; -uint_t samplerate = 44100; - -/* global objects */ -int frames; -aubio_pvoc_t * pv; -fvec_t * ibuf; -fvec_t * obuf; -cvec_t * fftgrain; -fvec_t * woodblock; -aubio_onsetdetection_t *o; -aubio_onsetdetection_t *o2; -fvec_t *onset; -fvec_t *onset2; -int isonset = 0; -aubio_pickpeak_t * parms; - -/* pitch objects */ -smpl_t pitch = 0.; -cvec_t * fftpitch = NULL; -aubio_filter_t * filter = NULL; -aubio_pvoc_t * pvi = NULL; -aubio_pitchmcomb_t * p = NULL; - -fvec_t * note_buffer = NULL; -fvec_t * note_buffer2 = NULL; -uint_t medianfiltlen = 6; -smpl_t curlevel = 0; -smpl_t maxonset = 0.; - -/* midi objects */ -aubio_midi_player_t * mplay; -aubio_midi_driver_t * mdriver; -aubio_midi_event_t * event; - -void send_noteon(aubio_midi_driver_t * d, int pitch, int velo); -void send_noteon(aubio_midi_driver_t * d, int pitch, int velo) -{ - /* we should check if we use midi here, not jack */ -#if ALSA_SUPPORT - if (usejack) { - if (velo==0) { - aubio_midi_event_set_type(event,NOTE_OFF); - } else { - aubio_midi_event_set_type(event,NOTE_ON); - } - aubio_midi_event_set_channel(event,0); - aubio_midi_event_set_pitch(event,pitch); - aubio_midi_event_set_velocity(event,velo); - aubio_midi_direct_output(mdriver,event); - } else -#endif - { - if (velo==0) { - outmsg("%f\n",frames*overlap_size/(float)samplerate); - } else { - outmsg("%d\t%f\t",pitch,frames*overlap_size/(float)samplerate); - } - } -} - - -/** append new note candidate to the note_buffer and return filtered value. we - * need to copy the input array as vec_median destroy its input data.*/ - -void note_append(fvec_t * note_buffer, smpl_t curnote); -void note_append(fvec_t * note_buffer, smpl_t curnote) { - uint_t i = 0; - for (i = 0; i < note_buffer->length - 1; i++) { - note_buffer->data[0][i] = note_buffer->data[0][i+1]; - } - note_buffer->data[0][note_buffer->length - 1] = curnote; - return; -} - -uint_t get_note(fvec_t *note_buffer, fvec_t *note_buffer2); -uint_t get_note(fvec_t *note_buffer, fvec_t *note_buffer2){ - uint_t i = 0; - for (i = 0; i < note_buffer->length; i++) { - note_buffer2->data[0][i] = note_buffer->data[0][i]; - } - return vec_median(note_buffer2); -} - - -smpl_t curnote = 0.; -smpl_t newnote = 0.; -uint_t isready = 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*/ - unsigned int pos = 0; /*frames%dspblocksize*/ - for (j=0;jdata[0][0] *= onset2->data[0][0]; - } - isonset = aubio_peakpick_pimrt(onset,parms); - - aubio_filter_do(filter,ibuf); - aubio_filter_do(filter,ibuf); - aubio_pvoc_do(pvi,ibuf, fftpitch); - pitch = aubio_pitchmcomb_detect(p,fftpitch); - newnote = (FLOOR)(bintomidi(pitch,samplerate,buffer_size*4)+.5); - note_append(note_buffer, newnote); - - //outmsg("%f %f\n", pitch, newnote); - - /* curlevel is negatif or 1 if silence */ - curlevel = aubio_level_detection(ibuf, threshold2); - if (isonset) { - /* test for silence */ - if (curlevel == 1.) { - isonset=0; - isready=0; - /* send note off */ - send_noteon(mdriver,curnote,0); - } else { - isready = 1; - for (pos = 0; pos < overlap_size; pos++){ - obuf->data[0][pos] = woodblock->data[0][pos]; - } - } - } else { -// if (curlevel != 1) { -// if (bufpos == note_buffer->length) -// curnote = aubio_getnote(note_buffer); -// } -// - if (isready > 0) - isready++; - if (isready == note_buffer->length) - { - //outmsg("%d, %f\n", isready, curnote); - send_noteon(mdriver,curnote,0); - /* kill old note */ - newnote = get_note(note_buffer, note_buffer2); - curnote = newnote; - /* get and send new one */ - /*if (curnote<45){ - send_noteon(mdriver,curnote,0); - } else {*/ - if (curnote>45){ - send_noteon(mdriver,curnote,127+(int)FLOOR(curlevel)); - } - } - for (pos = 0; pos < overlap_size; pos++) - obuf->data[0][pos] = 0.; - } - /* end of block loop */ - //aubio_pvoc_rdo(pv,fftgrain, obuf); - pos = -1; /* so it will be zero next j loop */ - } - pos++; - } - return 1; -} - -int main(int argc, char **argv) { - - aubio_file_t * file = NULL; - aubio_file_t * fileout = NULL; - - aubio_file_t * onsetfile = new_file_ro(onset_filename); - /* parse command line arguments */ - parse_args(argc, argv); - - if(!usejack) - { - debug("Opening files ...\n"); - file = new_file_ro (input_filename); - file_info(file); - channels = aubio_file_channels(file); - if (output_filename != NULL) - fileout = new_file_wo(file, output_filename); - } - - ibuf = new_fvec(overlap_size, channels); - obuf = new_fvec(overlap_size, channels); - woodblock = new_fvec(buffer_size,1); - fftgrain = new_cvec(buffer_size, channels); - - pvi = new_aubio_pvoc(buffer_size*4, overlap_size, channels); - fftpitch = new_cvec(buffer_size*4, channels); - filter = new_aubio_adsgn_filter((smpl_t)samplerate); - p = new_aubio_pitchmcomb(buffer_size*4,channels); - - note_buffer = new_fvec(medianfiltlen, 1); - note_buffer2= new_fvec(medianfiltlen, 1); - /* read the output sound once */ - file_read(onsetfile, overlap_size, woodblock); - - /* phase vocoder */ - debug("Phase voc init ... \n"); - pv = new_aubio_pvoc(buffer_size, overlap_size, channels); - - /* onsets */ - parms = new_aubio_peakpicker(threshold); - o = new_aubio_onsetdetection(type_onset,buffer_size,channels); - onset = new_fvec(1, channels); - if (usedoubled) { - o2 = new_aubio_onsetdetection(type_onset2,buffer_size,channels); - onset2 = new_fvec(1 , channels); - } - - if(usejack) { -#ifdef JACK_SUPPORT - aubio_jack_t * jack_setup; - debug("Midi init ...\n"); - debug("Jack init ...\n"); - jack_setup = new_aubio_jack(channels, channels, - (aubio_process_func_t)aubio_process); - - mplay = new_aubio_midi_player(); - - mdriver = new_aubio_midi_driver("alsa_seq", - (handle_midi_event_func_t)aubio_midi_send_event, mplay); - - event = new_aubio_midi_event(); - - debug("Jack activation ...\n"); - aubio_jack_activate(jack_setup); - debug("Processing (Ctrl+C to quit) ...\n"); - pause(); - send_noteon(mdriver,curnote,0); - aubio_jack_close(jack_setup); - del_aubio_midi_driver(mdriver); -#else - outmsg("Compiled without jack output, exiting."); -#endif - - } else { - /* phasevoc */ - debug("Processing ...\n"); - - frames = 0; - - while (overlap_size == file_read(file, overlap_size, ibuf)) - { - isonset=0; - aubio_process(ibuf->data, obuf->data, overlap_size); - if (output_filename != NULL) { - file_write(fileout,overlap_size,obuf); - } - frames++; - } - send_noteon(mdriver,curnote,0); - - debug("Processed %d frames of %d samples.\n", frames, buffer_size); - del_file(file); - - if (output_filename != NULL) - del_file(fileout); - - } - - del_aubio_pvoc(pv); - del_fvec(obuf); - del_fvec(ibuf); - del_cvec(fftgrain); - del_cvec(fftpitch); - del_aubio_pvoc(pvi); - del_fvec(onset); - del_fvec(note_buffer); - del_fvec(note_buffer2); - - debug("End of program.\n"); - fflush(stderr); - return 0; -} - diff --git a/examples/utils.h b/examples/utils.h index d001c22d..50ac100c 100644 --- a/examples/utils.h +++ b/examples/utils.h @@ -24,6 +24,7 @@ extern int verbose; extern int usejack; extern int usedoubled; +extern int median; extern const char * output_filename; extern const char * input_filename; /* defined in utils.c */ diff --git a/python/aubio/gnuplot.py b/python/aubio/gnuplot.py index 583f4827..33041d81 100644 --- a/python/aubio/gnuplot.py +++ b/python/aubio/gnuplot.py @@ -108,15 +108,10 @@ def audio_to_array(filename): while (curpos < readsize): data.append(myvec.get(curpos,i)) curpos+=1 - # FIXME again for the last frame - curpos = 0 - while (curpos < readsize): - data.append(myvec.get(curpos,i)) - curpos+=1 time = arange(len(data))*framestep return time,data -def plot_audio(filenames, fileout=None, start=0, end=None, noaxis=None, task=audio_to_array): +def plot_audio(filenames, fileout=None, start=0, end=None, noaxis=None): g = Gnuplot.Gnuplot(debug=1, persist=1) d = [] todraw = len(filenames) @@ -124,8 +119,7 @@ def plot_audio(filenames, fileout=None, start=0, end=None, noaxis=None, task=aud xsize = 1./todraw g.gnuplot('set multiplot;') while (len(filenames)): - b,a = task(filenames.pop(0)) - d.append(Gnuplot.Data(b,a)) + d.append(plot_audio_make(filenames.pop(0))) if not noaxis and todraw==1: g.xlabel('Time (s)') g.ylabel('Amplitude') @@ -140,3 +134,12 @@ def plot_audio(filenames, fileout=None, start=0, end=None, noaxis=None, task=aud if fileout != None: g.hardcopy(fileout, enhanced=1, color=0) +def make_audio_plot(time,data,maxpoints=10000): + """ create gnuplot plot from an audio file """ + import numarray + length = len(time) + downsample = length/maxpoints + if downsample == 0: downsample = 1 + x = numarray.array(time).resize(length)[0:-1:downsample] + y = numarray.array(data).resize(length)[0:-1:downsample] + return Gnuplot.Data(x,y,with='lines') diff --git a/src/mathutils.c b/src/mathutils.c index 00714a7f..1c80a356 100644 --- a/src/mathutils.c +++ b/src/mathutils.c @@ -400,3 +400,18 @@ smpl_t aubio_level_detection(fvec_t * ibuf, smpl_t threshold) { else return loudness; } + +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