1 | /* |
2 | ** Copyright (C) 2005-2011 Erik de Castro Lopo <erikd@mega-nerd.com> |
3 | ** |
4 | ** All rights reserved. |
5 | ** |
6 | ** Redistribution and use in source and binary forms, with or without |
7 | ** modification, are permitted provided that the following conditions are |
8 | ** met: |
9 | ** |
10 | ** * Redistributions of source code must retain the above copyright |
11 | ** notice, this list of conditions and the following disclaimer. |
12 | ** * Redistributions in binary form must reproduce the above copyright |
13 | ** notice, this list of conditions and the following disclaimer in |
14 | ** the documentation and/or other materials provided with the |
15 | ** distribution. |
16 | ** * Neither the author nor the names of any contributors may be used |
17 | ** to endorse or promote products derived from this software without |
18 | ** specific prior written permission. |
19 | ** |
20 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
21 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
22 | ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
23 | ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
24 | ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
25 | ** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
26 | ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
27 | ** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
28 | ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
29 | ** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
30 | ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | */ |
32 | |
33 | /* |
34 | ** The above modified BSD style license (GPL and LGPL compatible) applies to |
35 | ** this file. It does not apply to libsndfile itself which is released under |
36 | ** the GNU LGPL or the libsndfile test suite which is released under the GNU |
37 | ** GPL. |
38 | ** This means that this header file can be used under this modified BSD style |
39 | ** license, but the LGPL still holds for the libsndfile library itself. |
40 | */ |
41 | |
42 | /* |
43 | ** sndfile.hh -- A lightweight C++ wrapper for the libsndfile API. |
44 | ** |
45 | ** All the methods are inlines and all functionality is contained in this |
46 | ** file. There is no separate implementation file. |
47 | ** |
48 | ** API documentation is in the doc/ directory of the source code tarball |
49 | ** and at http://www.mega-nerd.com/libsndfile/api.html. |
50 | */ |
51 | |
52 | #ifndef SNDFILE_HH |
53 | #define SNDFILE_HH |
54 | |
55 | #include <sndfile.h> |
56 | |
57 | #include <string> |
58 | #include <new> // for std::nothrow |
59 | |
60 | class SndfileHandle |
61 | { private : |
62 | struct SNDFILE_ref |
63 | { SNDFILE_ref (void) ; |
64 | ~SNDFILE_ref (void) ; |
65 | |
66 | SNDFILE *sf ; |
67 | SF_INFO sfinfo ; |
68 | int ref ; |
69 | } ; |
70 | |
71 | SNDFILE_ref *p ; |
72 | |
73 | public : |
74 | /* Default constructor */ |
75 | SndfileHandle (void) : p (NULL) {} ; |
76 | SndfileHandle (const char *path, int mode = SFM_READ, |
77 | int format = 0, int channels = 0, int samplerate = 0) ; |
78 | SndfileHandle (std::string const & path, int mode = SFM_READ, |
79 | int format = 0, int channels = 0, int samplerate = 0) ; |
80 | SndfileHandle (int fd, bool close_desc, int mode = SFM_READ, |
81 | int format = 0, int channels = 0, int samplerate = 0) ; |
82 | |
83 | #ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES |
84 | SndfileHandle (LPCWSTR wpath, int mode = SFM_READ, |
85 | int format = 0, int channels = 0, int samplerate = 0) ; |
86 | #endif |
87 | |
88 | ~SndfileHandle (void) ; |
89 | |
90 | SndfileHandle (const SndfileHandle &orig) ; |
91 | SndfileHandle & operator = (const SndfileHandle &rhs) ; |
92 | |
93 | /* Mainly for debugging/testing. */ |
94 | int refCount (void) const { return (p == NULL) ? 0 : p->ref ; } |
95 | |
96 | operator bool () const { return (p != NULL) ; } |
97 | |
98 | bool operator == (const SndfileHandle &rhs) const { return (p == rhs.p) ; } |
99 | |
100 | sf_count_t frames (void) const { return p ? p->sfinfo.frames : 0 ; } |
101 | int format (void) const { return p ? p->sfinfo.format : 0 ; } |
102 | int channels (void) const { return p ? p->sfinfo.channels : 0 ; } |
103 | int samplerate (void) const { return p ? p->sfinfo.samplerate : 0 ; } |
104 | |
105 | int error (void) const ; |
106 | const char * strError (void) const ; |
107 | |
108 | int command (int cmd, void *data, int datasize) ; |
109 | |
110 | sf_count_t seek (sf_count_t frames, int whence) ; |
111 | |
112 | void writeSync (void) ; |
113 | |
114 | int setString (int str_type, const char* str) ; |
115 | |
116 | const char* getString (int str_type) const ; |
117 | |
118 | static int formatCheck (int format, int channels, int samplerate) ; |
119 | |
120 | sf_count_t read (short *ptr, sf_count_t items) ; |
121 | sf_count_t read (int *ptr, sf_count_t items) ; |
122 | sf_count_t read (float *ptr, sf_count_t items) ; |
123 | sf_count_t read (double *ptr, sf_count_t items) ; |
124 | |
125 | sf_count_t write (const short *ptr, sf_count_t items) ; |
126 | sf_count_t write (const int *ptr, sf_count_t items) ; |
127 | sf_count_t write (const float *ptr, sf_count_t items) ; |
128 | sf_count_t write (const double *ptr, sf_count_t items) ; |
129 | |
130 | sf_count_t readf (short *ptr, sf_count_t frames) ; |
131 | sf_count_t readf (int *ptr, sf_count_t frames) ; |
132 | sf_count_t readf (float *ptr, sf_count_t frames) ; |
133 | sf_count_t readf (double *ptr, sf_count_t frames) ; |
134 | |
135 | sf_count_t writef (const short *ptr, sf_count_t frames) ; |
136 | sf_count_t writef (const int *ptr, sf_count_t frames) ; |
137 | sf_count_t writef (const float *ptr, sf_count_t frames) ; |
138 | sf_count_t writef (const double *ptr, sf_count_t frames) ; |
139 | |
140 | sf_count_t readRaw (void *ptr, sf_count_t bytes) ; |
141 | sf_count_t writeRaw (const void *ptr, sf_count_t bytes) ; |
142 | |
143 | /**< Raw access to the handle. SndfileHandle keeps ownership. */ |
144 | SNDFILE * rawHandle (void) ; |
145 | |
146 | /**< Take ownership of handle, iff reference count is 1. */ |
147 | SNDFILE * takeOwnership (void) ; |
148 | } ; |
149 | |
150 | /*============================================================================== |
151 | ** Nothing but implementation below. |
152 | */ |
153 | |
154 | inline |
155 | SndfileHandle::SNDFILE_ref::SNDFILE_ref (void) |
156 | : ref (1) |
157 | {} |
158 | |
159 | inline |
160 | SndfileHandle::SNDFILE_ref::~SNDFILE_ref (void) |
161 | { if (sf != NULL) sf_close (sf) ; } |
162 | |
163 | inline |
164 | SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, int srate) |
165 | : p (NULL) |
166 | { |
167 | p = new (std::nothrow) SNDFILE_ref () ; |
168 | |
169 | if (p != NULL) |
170 | { p->ref = 1 ; |
171 | |
172 | p->sfinfo.frames = 0 ; |
173 | p->sfinfo.channels = chans ; |
174 | p->sfinfo.format = fmt ; |
175 | p->sfinfo.samplerate = srate ; |
176 | p->sfinfo.sections = 0 ; |
177 | p->sfinfo.seekable = 0 ; |
178 | |
179 | p->sf = sf_open (path, mode, &p->sfinfo) ; |
180 | } ; |
181 | |
182 | return ; |
183 | } /* SndfileHandle const char * constructor */ |
184 | |
185 | inline |
186 | SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int chans, int srate) |
187 | : p (NULL) |
188 | { |
189 | p = new (std::nothrow) SNDFILE_ref () ; |
190 | |
191 | if (p != NULL) |
192 | { p->ref = 1 ; |
193 | |
194 | p->sfinfo.frames = 0 ; |
195 | p->sfinfo.channels = chans ; |
196 | p->sfinfo.format = fmt ; |
197 | p->sfinfo.samplerate = srate ; |
198 | p->sfinfo.sections = 0 ; |
199 | p->sfinfo.seekable = 0 ; |
200 | |
201 | p->sf = sf_open (path.c_str (), mode, &p->sfinfo) ; |
202 | } ; |
203 | |
204 | return ; |
205 | } /* SndfileHandle std::string constructor */ |
206 | |
207 | inline |
208 | SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int chans, int srate) |
209 | : p (NULL) |
210 | { |
211 | if (fd < 0) |
212 | return ; |
213 | |
214 | p = new (std::nothrow) SNDFILE_ref () ; |
215 | |
216 | if (p != NULL) |
217 | { p->ref = 1 ; |
218 | |
219 | p->sfinfo.frames = 0 ; |
220 | p->sfinfo.channels = chans ; |
221 | p->sfinfo.format = fmt ; |
222 | p->sfinfo.samplerate = srate ; |
223 | p->sfinfo.sections = 0 ; |
224 | p->sfinfo.seekable = 0 ; |
225 | |
226 | p->sf = sf_open_fd (fd, mode, &p->sfinfo, close_desc) ; |
227 | } ; |
228 | |
229 | return ; |
230 | } /* SndfileHandle fd constructor */ |
231 | |
232 | inline |
233 | SndfileHandle::~SndfileHandle (void) |
234 | { if (p != NULL && --p->ref == 0) |
235 | delete p ; |
236 | } /* SndfileHandle destructor */ |
237 | |
238 | |
239 | inline |
240 | SndfileHandle::SndfileHandle (const SndfileHandle &orig) |
241 | : p (orig.p) |
242 | { if (p != NULL) |
243 | ++p->ref ; |
244 | } /* SndfileHandle copy constructor */ |
245 | |
246 | inline SndfileHandle & |
247 | SndfileHandle::operator = (const SndfileHandle &rhs) |
248 | { |
249 | if (&rhs == this) |
250 | return *this ; |
251 | if (p != NULL && --p->ref == 0) |
252 | delete p ; |
253 | |
254 | p = rhs.p ; |
255 | if (p != NULL) |
256 | ++p->ref ; |
257 | |
258 | return *this ; |
259 | } /* SndfileHandle assignment operator */ |
260 | |
261 | inline int |
262 | SndfileHandle::error (void) const |
263 | { return sf_error (p->sf) ; } |
264 | |
265 | inline const char * |
266 | SndfileHandle::strError (void) const |
267 | { return sf_strerror (p->sf) ; } |
268 | |
269 | inline int |
270 | SndfileHandle::command (int cmd, void *data, int datasize) |
271 | { return sf_command (p->sf, cmd, data, datasize) ; } |
272 | |
273 | inline sf_count_t |
274 | SndfileHandle::seek (sf_count_t frame_count, int whence) |
275 | { return sf_seek (p->sf, frame_count, whence) ; } |
276 | |
277 | inline void |
278 | SndfileHandle::writeSync (void) |
279 | { sf_write_sync (p->sf) ; } |
280 | |
281 | inline int |
282 | SndfileHandle::setString (int str_type, const char* str) |
283 | { return sf_set_string (p->sf, str_type, str) ; } |
284 | |
285 | inline const char* |
286 | SndfileHandle::getString (int str_type) const |
287 | { return sf_get_string (p->sf, str_type) ; } |
288 | |
289 | inline int |
290 | SndfileHandle::formatCheck (int fmt, int chans, int srate) |
291 | { |
292 | SF_INFO sfinfo ; |
293 | |
294 | sfinfo.frames = 0 ; |
295 | sfinfo.channels = chans ; |
296 | sfinfo.format = fmt ; |
297 | sfinfo.samplerate = srate ; |
298 | sfinfo.sections = 0 ; |
299 | sfinfo.seekable = 0 ; |
300 | |
301 | return sf_format_check (&sfinfo) ; |
302 | } |
303 | |
304 | /*---------------------------------------------------------------------*/ |
305 | |
306 | inline sf_count_t |
307 | SndfileHandle::read (short *ptr, sf_count_t items) |
308 | { return sf_read_short (p->sf, ptr, items) ; } |
309 | |
310 | inline sf_count_t |
311 | SndfileHandle::read (int *ptr, sf_count_t items) |
312 | { return sf_read_int (p->sf, ptr, items) ; } |
313 | |
314 | inline sf_count_t |
315 | SndfileHandle::read (float *ptr, sf_count_t items) |
316 | { return sf_read_float (p->sf, ptr, items) ; } |
317 | |
318 | inline sf_count_t |
319 | SndfileHandle::read (double *ptr, sf_count_t items) |
320 | { return sf_read_double (p->sf, ptr, items) ; } |
321 | |
322 | inline sf_count_t |
323 | SndfileHandle::write (const short *ptr, sf_count_t items) |
324 | { return sf_write_short (p->sf, ptr, items) ; } |
325 | |
326 | inline sf_count_t |
327 | SndfileHandle::write (const int *ptr, sf_count_t items) |
328 | { return sf_write_int (p->sf, ptr, items) ; } |
329 | |
330 | inline sf_count_t |
331 | SndfileHandle::write (const float *ptr, sf_count_t items) |
332 | { return sf_write_float (p->sf, ptr, items) ; } |
333 | |
334 | inline sf_count_t |
335 | SndfileHandle::write (const double *ptr, sf_count_t items) |
336 | { return sf_write_double (p->sf, ptr, items) ; } |
337 | |
338 | inline sf_count_t |
339 | SndfileHandle::readf (short *ptr, sf_count_t frame_count) |
340 | { return sf_readf_short (p->sf, ptr, frame_count) ; } |
341 | |
342 | inline sf_count_t |
343 | SndfileHandle::readf (int *ptr, sf_count_t frame_count) |
344 | { return sf_readf_int (p->sf, ptr, frame_count) ; } |
345 | |
346 | inline sf_count_t |
347 | SndfileHandle::readf (float *ptr, sf_count_t frame_count) |
348 | { return sf_readf_float (p->sf, ptr, frame_count) ; } |
349 | |
350 | inline sf_count_t |
351 | SndfileHandle::readf (double *ptr, sf_count_t frame_count) |
352 | { return sf_readf_double (p->sf, ptr, frame_count) ; } |
353 | |
354 | inline sf_count_t |
355 | SndfileHandle::writef (const short *ptr, sf_count_t frame_count) |
356 | { return sf_writef_short (p->sf, ptr, frame_count) ; } |
357 | |
358 | inline sf_count_t |
359 | SndfileHandle::writef (const int *ptr, sf_count_t frame_count) |
360 | { return sf_writef_int (p->sf, ptr, frame_count) ; } |
361 | |
362 | inline sf_count_t |
363 | SndfileHandle::writef (const float *ptr, sf_count_t frame_count) |
364 | { return sf_writef_float (p->sf, ptr, frame_count) ; } |
365 | |
366 | inline sf_count_t |
367 | SndfileHandle::writef (const double *ptr, sf_count_t frame_count) |
368 | { return sf_writef_double (p->sf, ptr, frame_count) ; } |
369 | |
370 | inline sf_count_t |
371 | SndfileHandle::readRaw (void *ptr, sf_count_t bytes) |
372 | { return sf_read_raw (p->sf, ptr, bytes) ; } |
373 | |
374 | inline sf_count_t |
375 | SndfileHandle::writeRaw (const void *ptr, sf_count_t bytes) |
376 | { return sf_write_raw (p->sf, ptr, bytes) ; } |
377 | |
378 | inline SNDFILE * |
379 | SndfileHandle::rawHandle (void) |
380 | { return (p ? p->sf : NULL) ; } |
381 | |
382 | inline SNDFILE * |
383 | SndfileHandle::takeOwnership (void) |
384 | { |
385 | if (p == NULL || (p->ref != 1)) |
386 | return NULL ; |
387 | |
388 | SNDFILE * sf = p->sf ; |
389 | p->sf = NULL ; |
390 | delete p ; |
391 | p = NULL ; |
392 | return sf ; |
393 | } |
394 | |
395 | #ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES |
396 | |
397 | inline |
398 | SndfileHandle::SndfileHandle (LPCWSTR wpath, int mode, int fmt, int chans, int srate) |
399 | : p (NULL) |
400 | { |
401 | p = new (std::nothrow) SNDFILE_ref () ; |
402 | |
403 | if (p != NULL) |
404 | { p->ref = 1 ; |
405 | |
406 | p->sfinfo.frames = 0 ; |
407 | p->sfinfo.channels = chans ; |
408 | p->sfinfo.format = fmt ; |
409 | p->sfinfo.samplerate = srate ; |
410 | p->sfinfo.sections = 0 ; |
411 | p->sfinfo.seekable = 0 ; |
412 | |
413 | p->sf = sf_wchar_open (wpath, mode, &p->sfinfo) ; |
414 | } ; |
415 | |
416 | return ; |
417 | } /* SndfileHandle const wchar_t * constructor */ |
418 | |
419 | #endif |
420 | |
421 | #endif /* SNDFILE_HH */ |
422 | |
423 | |