moved jack and sndfile to aubioext
[aubio.git] / ext / sndfileio.c
1 /*
2    Copyright (C) 2003 Paul Brossier
3
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.
8
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.
13
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.
17
18 */
19
20 #include <string.h>
21
22 #include <sndfile.h>
23
24 #include "aubio_priv.h"
25 #include "sample.h"
26 #include "sndfileio.h"
27 #include "mathutils.h"
28
29 #define MAX_CHANNELS 6
30 #define MAX_SIZE 4096
31
32 struct _aubio_file_t {
33         SNDFILE *handle;
34         int samplerate;
35         int channels;
36         int format;
37         float *tmpdata; /** scratch pad for interleaving/deinterleaving. */
38         int size;       /** store the size to check if realloc needed */
39 };
40
41 aubio_file_t * new_file_ro(const char* outputname) {
42         aubio_file_t * f = AUBIO_NEW(aubio_file_t);
43         SF_INFO sfinfo;
44         AUBIO_MEMSET(&sfinfo, 0, sizeof (sfinfo));
45
46         if (! (f->handle = sf_open (outputname, SFM_READ, &sfinfo))) {
47                 AUBIO_ERR("Not able to open input file %s.\n", outputname);
48                 AUBIO_ERR("%s\n",sf_strerror (NULL)); /* libsndfile err msg */
49                 AUBIO_QUIT(AUBIO_FAIL);
50         }       
51
52         if (sfinfo.channels > MAX_CHANNELS) { 
53                 AUBIO_ERR("Not able to process more than %d channels\n", MAX_CHANNELS);
54                 AUBIO_QUIT(AUBIO_FAIL);
55         }
56
57         f->size       = MAX_SIZE*sfinfo.channels;
58         f->tmpdata    = AUBIO_ARRAY(float,f->size);
59         /* get input specs */
60         f->samplerate = sfinfo.samplerate;
61         f->channels   = sfinfo.channels;
62         f->format     = sfinfo.format;
63
64         return f;
65 }
66
67 int file_open_wo(aubio_file_t * f, const char* inputname) {
68         SF_INFO sfinfo;
69         memset (&sfinfo, 0, sizeof (sfinfo));
70
71         /* define file output spec */
72         sfinfo.samplerate = f->samplerate;
73         sfinfo.channels   = f->channels;
74         sfinfo.format     = f->format;
75
76         if (! (f->handle = sf_open (inputname, SFM_WRITE, &sfinfo))) {
77                 AUBIO_ERR("Not able to open output file %s.\n", inputname);
78                 AUBIO_ERR("%s\n",sf_strerror (NULL)); /* libsndfile err msg */
79                 AUBIO_QUIT(AUBIO_FAIL);
80         }       
81
82         if (sfinfo.channels > MAX_CHANNELS) { 
83                 AUBIO_ERR("Not able to process more than %d channels\n", MAX_CHANNELS);
84                 AUBIO_QUIT(AUBIO_FAIL);
85         }
86         f->size       = MAX_SIZE*sfinfo.channels;
87         f->tmpdata    = AUBIO_ARRAY(float,f->size);
88         return AUBIO_OK;
89 }
90
91 /* setup file struct from existing one */
92 aubio_file_t * new_file_wo(aubio_file_t * fmodel, const char *outputname) {
93         aubio_file_t * f = AUBIO_NEW(aubio_file_t);
94         f->samplerate    = fmodel->samplerate;
95         f->channels      = fmodel->channels;
96         f->format        = fmodel->format;
97         file_open_wo(f, outputname);
98         return f;
99 }
100
101
102 /* return 0 if properly closed, 1 otherwise */
103 int del_file(aubio_file_t * f) {
104         if (sf_close(f->handle)) {
105                 AUBIO_ERR("Error closing file.");
106                 puts (sf_strerror (NULL));
107                 return 1;
108         }
109         AUBIO_FREE(f->tmpdata);
110         AUBIO_FREE(f);
111         //AUBIO_DBG("File closed.\n");
112         return 0;
113 }
114
115 /**************************************************************
116  *
117  * Read write methods 
118  *
119  */
120
121
122 /* read frames from file in data 
123  *  return the number of frames actually read */
124 int file_read(aubio_file_t * f, int frames, fvec_t * read) {
125         sf_count_t read_frames;
126         int i,j, channels = f->channels;
127         int nsamples = frames*channels;
128         int aread;
129         float *pread;   
130
131         /* allocate data for de/interleaving reallocated when needed. */
132         if (nsamples >= f->size) {
133                 AUBIO_ERR("Maximum file_read buffer size exceeded.");
134                 return -1;
135                 /*
136                 AUBIO_FREE(f->tmpdata);
137                 f->tmpdata = AUBIO_ARRAY(float,nsamples);
138                 */
139         }
140         //f->size = nsamples;
141
142         /* do actual reading */
143         read_frames = sf_read_float (f->handle, f->tmpdata, nsamples);
144
145         aread = (int)FLOOR(read_frames/(float)channels);
146
147         /* de-interleaving data  */
148         for (i=0; i<channels; i++) {
149                 pread = fvec_get_channel(read,i);
150                 for (j=0; j<aread; j++) {
151                         pread[j] = f->tmpdata[channels*j+i];
152                 }
153         }
154         return aread;
155 }
156
157 /* write 'frames' samples to file from data 
158  *   return the number of frames actually written 
159  */
160 int file_write(aubio_file_t * f, int frames, fvec_t * write) {
161         sf_count_t written_frames = 0;
162         int i, j,       channels = f->channels;
163         int nsamples = channels*frames;
164         float *pwrite;
165
166         /* allocate data for de/interleaving reallocated when needed. */
167         if (nsamples >= f->size) {
168                 AUBIO_ERR("Maximum file_write buffer size exceeded.");
169                 return -1;
170                 /*
171                 AUBIO_FREE(f->tmpdata);
172                 f->tmpdata = AUBIO_ARRAY(float,nsamples);
173                 */
174         }
175         //f->size = nsamples;
176
177         /* interleaving data  */
178         for (i=0; i<channels; i++) {
179                 pwrite = fvec_get_channel(write,i);
180                 for (j=0; j<frames; j++) {
181                         f->tmpdata[channels*j+i] = pwrite[j];
182                 }
183         }
184         written_frames = sf_write_float (f->handle, f->tmpdata, nsamples);
185         return written_frames/channels;
186 }
187
188 /*******************************************************************
189  *
190  * Get object info 
191  *
192  */
193
194 uint_t aubio_file_channels(aubio_file_t * f) {
195         return f->channels;
196 }
197
198 uint_t aubio_file_samplerate(aubio_file_t * f) {
199         return f->samplerate;
200 }
201
202 void file_info(aubio_file_t * f) {
203         AUBIO_DBG("srate    : %d\n", f->samplerate);
204         AUBIO_DBG("channels : %d\n", f->channels);
205         AUBIO_DBG("format   : %d\n", f->format);
206 }
207