From 2c3d4ca499ac72775c9ce04c0be286ee1bf2bbe3 Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Sat, 14 Jul 2012 13:13:20 -0600 Subject: [PATCH] added sink_sndfile.c draft --- src/aubio.h | 1 + src/io/sink_sndfile.c | 113 +++++++++++++++++++++++++++++++ src/io/sink_sndfile.h | 43 ++++++++++++ tests/src/io/test-sink_sndfile.c | 39 +++++++++++ 4 files changed, 196 insertions(+) create mode 100644 src/io/sink_sndfile.c create mode 100644 src/io/sink_sndfile.h create mode 100644 tests/src/io/test-sink_sndfile.c diff --git a/src/aubio.h b/src/aubio.h index 746336bd..ec26ed04 100644 --- a/src/aubio.h +++ b/src/aubio.h @@ -179,6 +179,7 @@ extern "C" #include "io/source_sndfile.h" #include "io/source_apple_audio.h" #include "io/sink.h" +#include "io/sink_sndfile.h" #if AUBIO_UNSTABLE #include "vecutils.h" diff --git a/src/io/sink_sndfile.c b/src/io/sink_sndfile.c new file mode 100644 index 00000000..155af55b --- /dev/null +++ b/src/io/sink_sndfile.c @@ -0,0 +1,113 @@ +/* + 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 "sink_sndfile.h" +#include "fvec.h" + +#define MAX_CHANNELS 6 +#define MAX_SIZE 4096 + +struct _aubio_sink_sndfile_t { + uint_t hop_size; + uint_t samplerate; + uint_t channels; + char_t *path; + SNDFILE *handle; + uint_t scratch_size; + smpl_t *scratch_data; +}; + +aubio_sink_sndfile_t * new_aubio_sink_sndfile(char_t * path, uint_t samplerate, uint_t hop_size) { + aubio_sink_sndfile_t * s = AUBIO_NEW(aubio_sink_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; + + /* set output format */ + SF_INFO sfinfo; + AUBIO_MEMSET(&sfinfo, 0, sizeof (sfinfo)); + sfinfo.samplerate = s->samplerate; + sfinfo.channels = s->channels; + sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; + + /* try creating the file */ + s->handle = sf_open (s->path, SFM_WRITE, &sfinfo); + + if (s->handle == NULL) { + /* show libsndfile err msg */ + AUBIO_ERR("Failed opening %s. %s\n", s->path, sf_strerror (NULL)); + return NULL; + } + + s->scratch_size = s->hop_size*s->channels; + /* allocate data for de/interleaving reallocated when needed. */ + if (s->scratch_size >= MAX_SIZE * MAX_CHANNELS) { + AUBIO_ERR("%d x %d exceeds maximum aubio_sink_sndfile buffer size %d\n", + s->hop_size, s->channels, MAX_CHANNELS * MAX_CHANNELS); + return NULL; + } + s->scratch_data = AUBIO_ARRAY(float,s->scratch_size); + + return s; +} + +void aubio_sink_sndfile_do(aubio_sink_sndfile_t *s, fvec_t * write, uint_t * written){ + sf_count_t written_frames = 0; + int i, j, channels = s->channels; + int nsamples = channels*(*written); + smpl_t *pwrite; + + /* interleaving data */ + for ( i = 0; i < channels; i++) { + pwrite = (smpl_t *)write->data; + for (j=0; j < s->hop_size; j++) { + s->scratch_data[channels*j+i] = pwrite[j]; + } + } + written_frames = sf_write_float (s->handle, s->scratch_data, nsamples); + *written = written_frames/channels; + return; +} + +void del_aubio_sink_sndfile(aubio_sink_sndfile_t * s){ + if (!s) return; + 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/sink_sndfile.h b/src/io/sink_sndfile.h new file mode 100644 index 00000000..b9ee89d4 --- /dev/null +++ b/src/io/sink_sndfile.h @@ -0,0 +1,43 @@ +/* + 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_SINK_SNDFILE_H +#define _AUBIO_SINK_SNDFILE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file + + sndfile sink + +*/ + +typedef struct _aubio_sink_sndfile_t aubio_sink_sndfile_t; +aubio_sink_sndfile_t * new_aubio_sink_sndfile(char_t * method, uint_t hop_size, uint_t samplerate); +void aubio_sink_sndfile_do(aubio_sink_sndfile_t * s, fvec_t * write_data, uint_t * written); +void del_aubio_sink_sndfile(aubio_sink_sndfile_t * s); + +#ifdef __cplusplus +} +#endif + +#endif /* _AUBIO_SINK_SNDFILE_H */ diff --git a/tests/src/io/test-sink_sndfile.c b/tests/src/io/test-sink_sndfile.c new file mode 100644 index 00000000..b3684600 --- /dev/null +++ b/tests/src/io/test-sink_sndfile.c @@ -0,0 +1,39 @@ +#include +#include +#include "config.h" + +char_t *path = "/home/piem/archives/drum_Chocolate_Milk_-_Ation_Speaks_Louder_Than_Words.wav"; +char_t *outpath = "/var/tmp/test.wav"; + +int main(){ + int err = 0; +#ifdef HAVE_SNDFILE + uint_t samplerate = 44100; + uint_t hop_size = 512; + uint_t read = hop_size; + uint_t written = 512; + fvec_t *vec = new_fvec(hop_size); + aubio_source_sndfile_t * i = new_aubio_source_sndfile(path, samplerate, hop_size); + aubio_sink_sndfile_t * o = new_aubio_sink_sndfile(outpath, samplerate, hop_size); + + if (!i || !o) { err = -1; goto beach; } + + while ( read == hop_size ) { + aubio_source_sndfile_do(i, vec, &read); + if (read == 0) break; + written = read; + aubio_sink_sndfile_do(o, vec, &written); + if (read != written) + fprintf(stderr, "ERR: read %d, but wrote %d\n", read, written); + } + +beach: + del_aubio_source_sndfile(i); + del_aubio_sink_sndfile(o); + del_fvec(vec); +#else + fprintf(stderr, "ERR: aubio was not compiled with aubio_source_sndfile\n"); +#endif /* HAVE_SNDFILE */ + return err; +} + -- 2.26.2