2 Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org>
4 This file is part of aubio.
6 aubio is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 aubio is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with aubio. If not, see <http://www.gnu.org/licenses/>.
29 #include "aubio_priv.h"
31 #include "sndfileio.h"
32 #include "mathutils.h"
34 #define MAX_CHANNELS 6
37 struct _aubio_sndfile_t {
42 float *tmpdata; /** scratch pad for interleaving/deinterleaving. */
43 int size; /** store the size to check if realloc needed */
46 aubio_sndfile_t * new_aubio_sndfile_ro(const char* outputname) {
47 aubio_sndfile_t * f = AUBIO_NEW(aubio_sndfile_t);
49 AUBIO_MEMSET(&sfinfo, 0, sizeof (sfinfo));
51 f->handle = sf_open (outputname, SFM_READ, &sfinfo);
53 if (f->handle == NULL) {
54 AUBIO_ERR("Failed opening %s: %s\n", outputname,
55 sf_strerror (NULL)); /* libsndfile err msg */
59 if (sfinfo.channels > MAX_CHANNELS) {
60 AUBIO_ERR("Not able to process more than %d channels\n", MAX_CHANNELS);
64 f->size = MAX_SIZE*sfinfo.channels;
65 f->tmpdata = AUBIO_ARRAY(float,f->size);
67 f->samplerate = sfinfo.samplerate;
68 f->channels = sfinfo.channels;
69 f->format = sfinfo.format;
74 int aubio_sndfile_open_wo(aubio_sndfile_t * f, const char* inputname) {
76 AUBIO_MEMSET(&sfinfo, 0, sizeof (sfinfo));
78 /* define file output spec */
79 sfinfo.samplerate = f->samplerate;
80 sfinfo.channels = f->channels;
81 sfinfo.format = f->format;
83 if (! (f->handle = sf_open (inputname, SFM_WRITE, &sfinfo))) {
84 AUBIO_ERR("Not able to open output file %s.\n", inputname);
85 AUBIO_ERR("%s\n",sf_strerror (NULL)); /* libsndfile err msg */
86 AUBIO_QUIT(AUBIO_FAIL);
89 if (sfinfo.channels > MAX_CHANNELS) {
90 AUBIO_ERR("Not able to process more than %d channels\n", MAX_CHANNELS);
91 AUBIO_QUIT(AUBIO_FAIL);
93 f->size = MAX_SIZE*sfinfo.channels;
94 f->tmpdata = AUBIO_ARRAY(float,f->size);
98 /* setup file struct from existing one */
99 aubio_sndfile_t * new_aubio_sndfile_wo(aubio_sndfile_t * fmodel, const char *outputname) {
100 aubio_sndfile_t * f = AUBIO_NEW(aubio_sndfile_t);
101 f->samplerate = fmodel->samplerate;
102 f->channels = 1; //fmodel->channels;
103 f->format = fmodel->format;
104 aubio_sndfile_open_wo(f, outputname);
109 /* return 0 if properly closed, 1 otherwise */
110 int del_aubio_sndfile(aubio_sndfile_t * f) {
111 if (sf_close(f->handle)) {
112 AUBIO_ERR("Error closing file.");
113 puts (sf_strerror (NULL));
116 AUBIO_FREE(f->tmpdata);
118 //AUBIO_DBG("File closed.\n");
122 /**************************************************************
129 /* read frames from file in data
130 * return the number of frames actually read */
131 int aubio_sndfile_read(aubio_sndfile_t * f, int frames, fvec_t ** read) {
132 sf_count_t read_frames;
133 int i,j, channels = f->channels;
134 int nsamples = frames*channels;
138 /* allocate data for de/interleaving reallocated when needed. */
139 if (nsamples >= f->size) {
140 AUBIO_ERR("Maximum aubio_sndfile_read buffer size exceeded.");
143 AUBIO_FREE(f->tmpdata);
144 f->tmpdata = AUBIO_ARRAY(float,nsamples);
147 //f->size = nsamples;
149 /* do actual reading */
150 read_frames = sf_read_float (f->handle, f->tmpdata, nsamples);
152 aread = (int)FLOOR(read_frames/(float)channels);
154 /* de-interleaving data */
155 for (i=0; i<channels; i++) {
156 pread = (smpl_t *)fvec_get_data(read[i]);
157 for (j=0; j<aread; j++) {
158 pread[j] = (smpl_t)f->tmpdata[channels*j+i];
165 aubio_sndfile_read_mono (aubio_sndfile_t * f, int frames, fvec_t * read)
167 sf_count_t read_frames;
168 int i, j, channels = f->channels;
169 int nsamples = frames * channels;
173 /* allocate data for de/interleaving reallocated when needed. */
174 if (nsamples >= f->size) {
175 AUBIO_ERR ("Maximum aubio_sndfile_read buffer size exceeded.");
178 AUBIO_FREE(f->tmpdata);
179 f->tmpdata = AUBIO_ARRAY(float,nsamples);
182 //f->size = nsamples;
184 /* do actual reading */
185 read_frames = sf_read_float (f->handle, f->tmpdata, nsamples);
187 aread = (int) FLOOR (read_frames / (float) channels);
189 /* de-interleaving data */
190 pread = (smpl_t *) fvec_get_data (read);
191 for (i = 0; i < channels; i++) {
192 for (j = 0; j < aread; j++) {
193 pread[j] += (smpl_t) f->tmpdata[channels * j + i];
196 for (j = 0; j < aread; j++) {
197 pread[j] /= (smpl_t)channels;
203 /* write 'frames' samples to file from data
204 * return the number of frames actually written
206 int aubio_sndfile_write(aubio_sndfile_t * f, int frames, fvec_t ** write) {
207 sf_count_t written_frames = 0;
208 int i, j, channels = f->channels;
209 int nsamples = channels*frames;
212 /* allocate data for de/interleaving reallocated when needed. */
213 if (nsamples >= f->size) {
214 AUBIO_ERR("Maximum aubio_sndfile_write buffer size exceeded.");
217 AUBIO_FREE(f->tmpdata);
218 f->tmpdata = AUBIO_ARRAY(float,nsamples);
221 //f->size = nsamples;
223 /* interleaving data */
224 for (i=0; i<channels; i++) {
225 pwrite = (smpl_t *)fvec_get_data(write[i]);
226 for (j=0; j<frames; j++) {
227 f->tmpdata[channels*j+i] = (float)pwrite[j];
230 written_frames = sf_write_float (f->handle, f->tmpdata, nsamples);
231 return written_frames/channels;
234 /*******************************************************************
240 uint_t aubio_sndfile_channels(aubio_sndfile_t * f) {
244 uint_t aubio_sndfile_samplerate(aubio_sndfile_t * f) {
245 return f->samplerate;
248 void aubio_sndfile_info(aubio_sndfile_t * f) {
249 AUBIO_DBG("srate : %d\n", f->samplerate);
250 AUBIO_DBG("channels : %d\n", f->channels);
251 AUBIO_DBG("format : %d\n", f->format);
254 #endif /* HAVE_SNDFILE */