From: Paul Brossier Date: Fri, 13 Jul 2012 23:33:45 +0000 (-0600) Subject: src/io/source_sndfile.{c,h}: added sndfile source X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=afbd7e7adf53deda218ac4111682191dd83d34f6;p=aubio.git src/io/source_sndfile.{c,h}: added sndfile source --- diff --git a/src/aubio.h b/src/aubio.h index a589a016..746336bd 100644 --- a/src/aubio.h +++ b/src/aubio.h @@ -174,9 +174,11 @@ extern "C" #include "onset/onset.h" #include "onset/peakpicker.h" #include "tempo/tempo.h" +#include "io/sndfileio.h" #include "io/source.h" -#include "io/sink.h" +#include "io/source_sndfile.h" #include "io/source_apple_audio.h" +#include "io/sink.h" #if AUBIO_UNSTABLE #include "vecutils.h" diff --git a/src/io/source.c b/src/io/source.c index dd8e0728..208c411a 100644 --- a/src/io/source.c +++ b/src/io/source.c @@ -25,29 +25,45 @@ #ifdef __APPLE__ #include "io/source_apple_audio_file.h" #endif /* __APPLE__ */ +#ifdef HAVE_SNDFILE +#include "io/source_sndfile.h" +#endif struct _aubio_source_t { void *source; }; -aubio_source_t * new_aubio_source(char_t * uri, uint_t hop_size, uint_t samplerate) { +aubio_source_t * new_aubio_source(char_t * uri, uint_t samplerate, uint_t hop_size) { aubio_source_t * s = AUBIO_NEW(aubio_source_t); #ifdef __APPLE__ - s->source= (void *)new_aubio_source_apple_audio(uri, hop_size, samplerate); + s->source= (void *)new_aubio_source_apple_audio(uri, samplerate, hop_size); + if (s->source) return s; +#else /* __APPLE__ */ +#if HAVE_SNDFILE + s->source= (void *)new_aubio_source_sndfile(uri, samplerate, hop_size); + if (s->source) return s; +#endif /* HAVE_SNDFILE */ #endif /* __APPLE__ */ if (s->source == NULL) return NULL; - return s; } void aubio_source_do(aubio_source_t * s, fvec_t * data, uint_t * read) { #ifdef __APPLE__ aubio_source_apple_audio_do((aubio_source_apple_audio_t *)s->source, data, read); +#else /* __APPLE__ */ +#if HAVE_SNDFILE + aubio_source_sndfile_do((aubio_source_sndfile_t *)s->source, data, read); +#endif /* HAVE_SNDFILE */ #endif /* __APPLE__ */ } void del_aubio_source(aubio_source_t * s) { #ifdef __APPLE__ del_aubio_source_apple_audio((aubio_source_apple_audio_t *)s->source); +#else /* __APPLE__ */ +#if HAVE_SNDFILE + del_aubio_source_sndfile((aubio_source_sndfile_t *)s->source); +#endif /* HAVE_SNDFILE */ #endif /* __APPLE__ */ AUBIO_FREE(s); } diff --git a/src/io/source_sndfile.c b/src/io/source_sndfile.c new file mode 100644 index 00000000..839126a7 --- /dev/null +++ b/src/io/source_sndfile.c @@ -0,0 +1,130 @@ +/* + Copyright (C) 2012 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 "config.h" + +#ifdef HAVE_SNDFILE + +#include + +#include "aubio_priv.h" +#include "source_sndfile.h" +#include "fvec.h" +#include "mathutils.h" + +#define MAX_CHANNELS 6 +#define MAX_SIZE 4096 + +struct _aubio_source_sndfile_t { + uint_t hop_size; + uint_t samplerate; + uint_t channels; + int input_samplerate; + int input_channels; + int input_format; + char_t *path; + SNDFILE *handle; + uint_t scratch_size; + smpl_t *scratch_data; +}; + +aubio_source_sndfile_t * new_aubio_source_sndfile(char_t * path, uint_t samplerate, uint_t hop_size) { + aubio_source_sndfile_t * s = AUBIO_NEW(aubio_source_sndfile_t); + + if (path == NULL) { + AUBIO_ERR("Aborted opening null path\n"); + return NULL; + } + + s->hop_size = hop_size; + s->samplerate = samplerate; + s->channels = 1; + s->path = path; + + // try opening the file, geting the info in sfinfo + SF_INFO sfinfo; + AUBIO_MEMSET(&sfinfo, 0, sizeof (sfinfo)); + s->handle = sf_open (s->path, SFM_READ, &sfinfo); + + if (s->handle == NULL) { + /* show libsndfile err msg */ + AUBIO_ERR("Failed opening %s: %s\n", s->path, sf_strerror (NULL)); + return NULL; + } + + if (sfinfo.channels > MAX_CHANNELS) { + AUBIO_ERR("Not able to process more than %d channels\n", MAX_CHANNELS); + return NULL; + } + + /* get input specs */ + s->input_samplerate = sfinfo.samplerate; + s->input_channels = sfinfo.channels; + s->input_format = sfinfo.format; + + if (s->samplerate != s->input_samplerate) { + AUBIO_ERR("resampling not implemented yet\n"); + return NULL; + } + + s->scratch_size = s->hop_size*s->input_channels; + s->scratch_data = AUBIO_ARRAY(float,s->scratch_size); + + /* allocate data for de/interleaving reallocated when needed. */ + if (s->scratch_size >= MAX_SIZE * MAX_CHANNELS) { + AUBIO_ERR("%d exceeds maximum aubio_source_sndfile buffer size %d\n", s->scratch_size, MAX_CHANNELS * MAX_CHANNELS); + return NULL; + } + + return s; +} + +void aubio_source_sndfile_do(aubio_source_sndfile_t * s, fvec_t * read_data, uint_t * read){ + sf_count_t read_frames; + int i,j, input_channels = s->input_channels; + int aread; + smpl_t *pread; + + /* do actual reading */ + read_frames = sf_read_float (s->handle, s->scratch_data, s->scratch_size); + + aread = (int)FLOOR(read_frames/(float)input_channels); + + /* de-interleaving and down-mixing data */ + for (j = 0; j < aread; j++) { + read_data->data[j] = 0; + for (i = 0; i < input_channels; i++) { + read_data->data[j] += (smpl_t)s->scratch_data[input_channels*j+i]; + } + read_data->data[j] /= (smpl_t)input_channels; + } + *read = aread; +} + +void del_aubio_source_sndfile(aubio_source_sndfile_t * s){ + if (sf_close(s->handle)) { + AUBIO_ERR("Error closing file %s: %s", s->path, sf_strerror (NULL)); + } + AUBIO_FREE(s->scratch_data); + AUBIO_FREE(s); +} + +#endif /* HAVE_SNDFILE */ diff --git a/src/io/source_sndfile.h b/src/io/source_sndfile.h new file mode 100644 index 00000000..eac27719 --- /dev/null +++ b/src/io/source_sndfile.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2012 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 . + +*/ + +#ifndef _AUBIO_SOURCE_SNDFILE_H +#define _AUBIO_SOURCE_SNDFILE_H + +typedef struct _aubio_source_sndfile_t aubio_source_sndfile_t; +aubio_source_sndfile_t * new_aubio_source_sndfile(char_t * path, uint_t samplerate, uint_t block_size); +void aubio_source_sndfile_do(aubio_source_sndfile_t * s, fvec_t * read_to, uint_t * read); +void del_aubio_source_sndfile(aubio_source_sndfile_t * s); + +#endif /* _AUBIO_SOURCE_SNDFILE_H */ diff --git a/src/wscript_build b/src/wscript_build index ae241da2..5333b8a0 100644 --- a/src/wscript_build +++ b/src/wscript_build @@ -10,6 +10,9 @@ if 'HAVE_FFTW3' in conf.get_env(): if 'HAVE_SAMPLERATE': uselib += ['SAMPLERATE'] +if 'HAVE_SNDFILE': + uselib += ['SNDFILE'] + # build libaubio ctx.shlib( includes = ['.'], diff --git a/tests/src/io/test-source_apple_audio_file.c b/tests/src/io/test-source_apple_audio_file.c index a449010f..18b9a4bf 100644 --- a/tests/src/io/test-source_apple_audio_file.c +++ b/tests/src/io/test-source_apple_audio_file.c @@ -21,7 +21,7 @@ int main(){ del_aubio_source_apple_audio(s); #else - fprintf(stderr, "was not compiled with aubio_source_apple_audio"); + fprintf(stderr, "ERR: aubio was not compiled with aubio_source_apple_audio\n"); #endif /* __APPLE__ */ return 0; } diff --git a/tests/src/io/test-source_sndfile.c b/tests/src/io/test-source_sndfile.c new file mode 100644 index 00000000..c4c014b1 --- /dev/null +++ b/tests/src/io/test-source_sndfile.c @@ -0,0 +1,29 @@ +#include +#include +#include "config.h" + +char_t *path = "/home/piem/archives/drum_Chocolate_Milk_-_Ation_Speaks_Louder_Than_Words.wav"; + +int main(){ +#ifdef HAVE_SNDFILE + uint_t samplerate = 44100; + uint_t hop_size = 512; + uint_t read = hop_size; + fvec_t *vec = new_fvec(hop_size); + aubio_source_sndfile_t * s = new_aubio_source_sndfile(path, samplerate, hop_size); + + if (!s) return -1; + + while ( read == hop_size ) { + aubio_source_sndfile_do(s, vec, &read); + if (read == 0) break; + fprintf(stdout, "%d [%f, %f, ..., %f]\n", read, vec->data[0], vec->data[1], vec->data[read - 1]); + } + + del_aubio_source_sndfile(s); +#else + fprintf(stderr, "ERR: aubio was not compiled with aubio_source_sndfile\n"); +#endif /* HAVE_SNDFILE */ + return 0; +} +