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.
24 #include "aubio_priv.h"
26 #include "sndfileio.h"
27 #include "mathutils.h"
29 #define MAX_CHANNELS 6
32 struct _aubio_sndfile_t {
37 float *tmpdata; /** scratch pad for interleaving/deinterleaving. */
38 int size; /** store the size to check if realloc needed */
41 aubio_sndfile_t * new_aubio_sndfile_ro(const char* outputname) {
42 aubio_sndfile_t * f = AUBIO_NEW(aubio_sndfile_t);
44 AUBIO_MEMSET(&sfinfo, 0, sizeof (sfinfo));
46 f->handle = sf_open (outputname, SFM_READ, &sfinfo);
48 if (f->handle == NULL) {
49 AUBIO_ERR("Unable to open input file %s.\n", outputname);
50 AUBIO_ERR("%s\n",sf_strerror (NULL)); /* libsndfile err msg */
54 if (sfinfo.channels > MAX_CHANNELS) {
55 AUBIO_ERR("Not able to process more than %d channels\n", MAX_CHANNELS);
59 f->size = MAX_SIZE*sfinfo.channels;
60 f->tmpdata = AUBIO_ARRAY(float,f->size);
62 f->samplerate = sfinfo.samplerate;
63 f->channels = sfinfo.channels;
64 f->format = sfinfo.format;
69 int aubio_sndfile_open_wo(aubio_sndfile_t * f, const char* inputname) {
71 AUBIO_MEMSET(&sfinfo, 0, sizeof (sfinfo));
73 /* define file output spec */
74 sfinfo.samplerate = f->samplerate;
75 sfinfo.channels = f->channels;
76 sfinfo.format = f->format;
78 if (! (f->handle = sf_open (inputname, SFM_WRITE, &sfinfo))) {
79 AUBIO_ERR("Not able to open output file %s.\n", inputname);
80 AUBIO_ERR("%s\n",sf_strerror (NULL)); /* libsndfile err msg */
81 AUBIO_QUIT(AUBIO_FAIL);
84 if (sfinfo.channels > MAX_CHANNELS) {
85 AUBIO_ERR("Not able to process more than %d channels\n", MAX_CHANNELS);
86 AUBIO_QUIT(AUBIO_FAIL);
88 f->size = MAX_SIZE*sfinfo.channels;
89 f->tmpdata = AUBIO_ARRAY(float,f->size);
93 /* setup file struct from existing one */
94 aubio_sndfile_t * new_aubio_sndfile_wo(aubio_sndfile_t * fmodel, const char *outputname) {
95 aubio_sndfile_t * f = AUBIO_NEW(aubio_sndfile_t);
96 f->samplerate = fmodel->samplerate;
97 f->channels = fmodel->channels;
98 f->format = fmodel->format;
99 aubio_sndfile_open_wo(f, outputname);
104 /* return 0 if properly closed, 1 otherwise */
105 int del_aubio_sndfile(aubio_sndfile_t * f) {
106 if (sf_close(f->handle)) {
107 AUBIO_ERR("Error closing file.");
108 puts (sf_strerror (NULL));
111 AUBIO_FREE(f->tmpdata);
113 //AUBIO_DBG("File closed.\n");
117 /**************************************************************
124 /* read frames from file in data
125 * return the number of frames actually read */
126 int aubio_sndfile_read(aubio_sndfile_t * f, int frames, fvec_t * read) {
127 sf_count_t read_frames;
128 int i,j, channels = f->channels;
129 int nsamples = frames*channels;
133 /* allocate data for de/interleaving reallocated when needed. */
134 if (nsamples >= f->size) {
135 AUBIO_ERR("Maximum aubio_sndfile_read buffer size exceeded.");
138 AUBIO_FREE(f->tmpdata);
139 f->tmpdata = AUBIO_ARRAY(float,nsamples);
142 //f->size = nsamples;
144 /* do actual reading */
145 read_frames = sf_read_float (f->handle, f->tmpdata, nsamples);
147 aread = (int)FLOOR(read_frames/(float)channels);
149 /* de-interleaving data */
150 for (i=0; i<channels; i++) {
151 pread = fvec_get_channel(read,i);
152 for (j=0; j<aread; j++) {
153 pread[j] = f->tmpdata[channels*j+i];
159 /* write 'frames' samples to file from data
160 * return the number of frames actually written
162 int aubio_sndfile_write(aubio_sndfile_t * f, int frames, fvec_t * write) {
163 sf_count_t written_frames = 0;
164 int i, j, channels = f->channels;
165 int nsamples = channels*frames;
168 /* allocate data for de/interleaving reallocated when needed. */
169 if (nsamples >= f->size) {
170 AUBIO_ERR("Maximum aubio_sndfile_write buffer size exceeded.");
173 AUBIO_FREE(f->tmpdata);
174 f->tmpdata = AUBIO_ARRAY(float,nsamples);
177 //f->size = nsamples;
179 /* interleaving data */
180 for (i=0; i<channels; i++) {
181 pwrite = fvec_get_channel(write,i);
182 for (j=0; j<frames; j++) {
183 f->tmpdata[channels*j+i] = pwrite[j];
186 written_frames = sf_write_float (f->handle, f->tmpdata, nsamples);
187 return written_frames/channels;
190 /*******************************************************************
196 uint_t aubio_sndfile_channels(aubio_sndfile_t * f) {
200 uint_t aubio_sndfile_samplerate(aubio_sndfile_t * f) {
201 return f->samplerate;
204 void aubio_sndfile_info(aubio_sndfile_t * f) {
205 AUBIO_DBG("srate : %d\n", f->samplerate);
206 AUBIO_DBG("channels : %d\n", f->channels);
207 AUBIO_DBG("format : %d\n", f->format);