sndfile.hh 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. /*
  2. ** Copyright (C) 2005-2017 Erik de Castro Lopo <[email protected]>
  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. ** The above modified BSD style license (GPL and LGPL compatible) applies to
  34. ** this file. It does not apply to libsndfile itself which is released under
  35. ** the GNU LGPL or the libsndfile test suite which is released under the GNU
  36. ** GPL.
  37. ** This means that this header file can be used under this modified BSD style
  38. ** license, but the LGPL still holds for the libsndfile library itself.
  39. */
  40. /*
  41. ** sndfile.hh -- A lightweight C++ wrapper for the libsndfile API.
  42. **
  43. ** All the methods are inlines and all functionality is contained in this
  44. ** file. There is no separate implementation file.
  45. **
  46. ** API documentation is in the doc/ directory of the source code tarball
  47. ** and at http://libsndfile.github.io/libsndfile/api.html.
  48. **
  49. ** This file is intended to compile with C++98 and newer.
  50. */
  51. #ifndef SNDFILE_HH
  52. #define SNDFILE_HH
  53. #include <sndfile.h>
  54. #include <string>
  55. #include <new> // for std::nothrow
  56. #if ((defined (_MSC_VER) && (_MSC_VER >= 1600)) || (__cplusplus >= 201100L))
  57. #define SF_NULL nullptr
  58. #else
  59. #define SF_NULL NULL
  60. #endif
  61. class SndfileHandle
  62. { private :
  63. struct SNDFILE_ref
  64. { SNDFILE_ref (void) ;
  65. ~SNDFILE_ref (void) ;
  66. SNDFILE *sf ;
  67. SF_INFO sfinfo ;
  68. int ref ;
  69. } ;
  70. SNDFILE_ref *p ;
  71. public :
  72. /* Default constructor */
  73. SndfileHandle (void) : p (SF_NULL) {} ;
  74. SndfileHandle (const char *path, int mode = SFM_READ,
  75. int format = 0, int channels = 0, int samplerate = 0) ;
  76. SndfileHandle (std::string const & path, int mode = SFM_READ,
  77. int format = 0, int channels = 0, int samplerate = 0) ;
  78. SndfileHandle (int fd, bool close_desc, int mode = SFM_READ,
  79. int format = 0, int channels = 0, int samplerate = 0) ;
  80. SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode = SFM_READ,
  81. int format = 0, int channels = 0, int samplerate = 0) ;
  82. #ifdef _WIN32
  83. SndfileHandle (const wchar_t *wpath, int mode = SFM_READ,
  84. int format = 0, int channels = 0, int samplerate = 0) ;
  85. #endif
  86. ~SndfileHandle (void) ;
  87. SndfileHandle (const SndfileHandle &orig) ;
  88. SndfileHandle & operator = (const SndfileHandle &rhs) ;
  89. #if (__cplusplus >= 201100L)
  90. SndfileHandle (SndfileHandle &&orig) noexcept ;
  91. SndfileHandle & operator = (SndfileHandle &&rhs) noexcept ;
  92. #endif
  93. /* Mainly for debugging/testing. */
  94. int refCount (void) const { return (p == SF_NULL) ? 0 : p->ref ; }
  95. operator bool () const { return (p != SF_NULL) ; }
  96. bool operator == (const SndfileHandle &rhs) const { return (p == rhs.p) ; }
  97. sf_count_t frames (void) const { return p ? p->sfinfo.frames : 0 ; }
  98. int format (void) const { return p ? p->sfinfo.format : 0 ; }
  99. int channels (void) const { return p ? p->sfinfo.channels : 0 ; }
  100. int samplerate (void) const { return p ? p->sfinfo.samplerate : 0 ; }
  101. int error (void) const ;
  102. const char * strError (void) const ;
  103. int command (int cmd, void *data, int datasize) ;
  104. sf_count_t seek (sf_count_t frames, int whence) ;
  105. void writeSync (void) ;
  106. int setString (int str_type, const char* str) ;
  107. const char* getString (int str_type) const ;
  108. static int formatCheck (int format, int channels, int samplerate) ;
  109. sf_count_t read (short *ptr, sf_count_t items) ;
  110. sf_count_t read (int *ptr, sf_count_t items) ;
  111. sf_count_t read (float *ptr, sf_count_t items) ;
  112. sf_count_t read (double *ptr, sf_count_t items) ;
  113. sf_count_t write (const short *ptr, sf_count_t items) ;
  114. sf_count_t write (const int *ptr, sf_count_t items) ;
  115. sf_count_t write (const float *ptr, sf_count_t items) ;
  116. sf_count_t write (const double *ptr, sf_count_t items) ;
  117. sf_count_t readf (short *ptr, sf_count_t frames) ;
  118. sf_count_t readf (int *ptr, sf_count_t frames) ;
  119. sf_count_t readf (float *ptr, sf_count_t frames) ;
  120. sf_count_t readf (double *ptr, sf_count_t frames) ;
  121. sf_count_t writef (const short *ptr, sf_count_t frames) ;
  122. sf_count_t writef (const int *ptr, sf_count_t frames) ;
  123. sf_count_t writef (const float *ptr, sf_count_t frames) ;
  124. sf_count_t writef (const double *ptr, sf_count_t frames) ;
  125. sf_count_t readRaw (void *ptr, sf_count_t bytes) ;
  126. sf_count_t writeRaw (const void *ptr, sf_count_t bytes) ;
  127. /**< Raw access to the handle. SndfileHandle keeps ownership. */
  128. SNDFILE * rawHandle (void) ;
  129. /**< Take ownership of handle, if reference count is 1. */
  130. SNDFILE * takeOwnership (void) ;
  131. } ;
  132. /*==============================================================================
  133. ** Nothing but implementation below.
  134. */
  135. inline
  136. SndfileHandle::SNDFILE_ref::SNDFILE_ref (void)
  137. : sf (SF_NULL), sfinfo (), ref (1)
  138. {}
  139. inline
  140. SndfileHandle::SNDFILE_ref::~SNDFILE_ref (void)
  141. { if (sf != SF_NULL) sf_close (sf) ; }
  142. inline
  143. SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, int srate)
  144. : p (SF_NULL)
  145. {
  146. p = new (std::nothrow) SNDFILE_ref () ;
  147. if (p != SF_NULL)
  148. { p->ref = 1 ;
  149. p->sfinfo.frames = 0 ;
  150. p->sfinfo.channels = chans ;
  151. p->sfinfo.format = fmt ;
  152. p->sfinfo.samplerate = srate ;
  153. p->sfinfo.sections = 0 ;
  154. p->sfinfo.seekable = 0 ;
  155. p->sf = sf_open (path, mode, &p->sfinfo) ;
  156. } ;
  157. return ;
  158. } /* SndfileHandle const char * constructor */
  159. inline
  160. SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int chans, int srate)
  161. : p (SF_NULL)
  162. {
  163. p = new (std::nothrow) SNDFILE_ref () ;
  164. if (p != SF_NULL)
  165. { p->ref = 1 ;
  166. p->sfinfo.frames = 0 ;
  167. p->sfinfo.channels = chans ;
  168. p->sfinfo.format = fmt ;
  169. p->sfinfo.samplerate = srate ;
  170. p->sfinfo.sections = 0 ;
  171. p->sfinfo.seekable = 0 ;
  172. p->sf = sf_open (path.c_str (), mode, &p->sfinfo) ;
  173. } ;
  174. return ;
  175. } /* SndfileHandle std::string constructor */
  176. inline
  177. SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int chans, int srate)
  178. : p (SF_NULL)
  179. {
  180. if (fd < 0)
  181. return ;
  182. p = new (std::nothrow) SNDFILE_ref () ;
  183. if (p != SF_NULL)
  184. { p->ref = 1 ;
  185. p->sfinfo.frames = 0 ;
  186. p->sfinfo.channels = chans ;
  187. p->sfinfo.format = fmt ;
  188. p->sfinfo.samplerate = srate ;
  189. p->sfinfo.sections = 0 ;
  190. p->sfinfo.seekable = 0 ;
  191. p->sf = sf_open_fd (fd, mode, &p->sfinfo, close_desc) ;
  192. } ;
  193. return ;
  194. } /* SndfileHandle fd constructor */
  195. inline
  196. SndfileHandle::SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode, int fmt, int chans, int srate)
  197. : p (SF_NULL)
  198. {
  199. p = new (std::nothrow) SNDFILE_ref () ;
  200. if (p != SF_NULL)
  201. { p->ref = 1 ;
  202. p->sfinfo.frames = 0 ;
  203. p->sfinfo.channels = chans ;
  204. p->sfinfo.format = fmt ;
  205. p->sfinfo.samplerate = srate ;
  206. p->sfinfo.sections = 0 ;
  207. p->sfinfo.seekable = 0 ;
  208. p->sf = sf_open_virtual (&sfvirtual, mode, &p->sfinfo, user_data) ;
  209. } ;
  210. return ;
  211. } /* SndfileHandle std::string constructor */
  212. inline
  213. SndfileHandle::~SndfileHandle (void)
  214. { if (p != SF_NULL && -- p->ref == 0)
  215. delete p ;
  216. } /* SndfileHandle destructor */
  217. inline
  218. SndfileHandle::SndfileHandle (const SndfileHandle &orig)
  219. : p (orig.p)
  220. { if (p != SF_NULL)
  221. ++ p->ref ;
  222. } /* SndfileHandle copy constructor */
  223. inline SndfileHandle &
  224. SndfileHandle::operator = (const SndfileHandle &rhs)
  225. {
  226. if (&rhs == this)
  227. return *this ;
  228. if (p != SF_NULL && -- p->ref == 0)
  229. delete p ;
  230. p = rhs.p ;
  231. if (p != SF_NULL)
  232. ++ p->ref ;
  233. return *this ;
  234. } /* SndfileHandle copy assignment */
  235. #if (__cplusplus >= 201100L)
  236. inline
  237. SndfileHandle::SndfileHandle (SndfileHandle &&orig) noexcept
  238. : p (orig.p)
  239. {
  240. orig.p = SF_NULL ;
  241. } /* SndfileHandle move constructor */
  242. inline SndfileHandle &
  243. SndfileHandle::operator = (SndfileHandle &&rhs) noexcept
  244. {
  245. if (&rhs == this)
  246. return *this ;
  247. if (p != SF_NULL && -- p->ref == 0)
  248. delete p ;
  249. p = rhs.p ;
  250. rhs.p = SF_NULL ;
  251. return *this ;
  252. } /* SndfileHandle move assignment */
  253. #endif
  254. inline int
  255. SndfileHandle::error (void) const
  256. { return sf_error (p->sf) ; }
  257. inline const char *
  258. SndfileHandle::strError (void) const
  259. { return sf_strerror (p->sf) ; }
  260. inline int
  261. SndfileHandle::command (int cmd, void *data, int datasize)
  262. { return sf_command (p->sf, cmd, data, datasize) ; }
  263. inline sf_count_t
  264. SndfileHandle::seek (sf_count_t frame_count, int whence)
  265. { return sf_seek (p->sf, frame_count, whence) ; }
  266. inline void
  267. SndfileHandle::writeSync (void)
  268. { sf_write_sync (p->sf) ; }
  269. inline int
  270. SndfileHandle::setString (int str_type, const char* str)
  271. { return sf_set_string (p->sf, str_type, str) ; }
  272. inline const char*
  273. SndfileHandle::getString (int str_type) const
  274. { return sf_get_string (p->sf, str_type) ; }
  275. inline int
  276. SndfileHandle::formatCheck (int fmt, int chans, int srate)
  277. {
  278. SF_INFO sfinfo ;
  279. sfinfo.frames = 0 ;
  280. sfinfo.channels = chans ;
  281. sfinfo.format = fmt ;
  282. sfinfo.samplerate = srate ;
  283. sfinfo.sections = 0 ;
  284. sfinfo.seekable = 0 ;
  285. return sf_format_check (&sfinfo) ;
  286. }
  287. /*---------------------------------------------------------------------*/
  288. inline sf_count_t
  289. SndfileHandle::read (short *ptr, sf_count_t items)
  290. { return sf_read_short (p->sf, ptr, items) ; }
  291. inline sf_count_t
  292. SndfileHandle::read (int *ptr, sf_count_t items)
  293. { return sf_read_int (p->sf, ptr, items) ; }
  294. inline sf_count_t
  295. SndfileHandle::read (float *ptr, sf_count_t items)
  296. { return sf_read_float (p->sf, ptr, items) ; }
  297. inline sf_count_t
  298. SndfileHandle::read (double *ptr, sf_count_t items)
  299. { return sf_read_double (p->sf, ptr, items) ; }
  300. inline sf_count_t
  301. SndfileHandle::write (const short *ptr, sf_count_t items)
  302. { return sf_write_short (p->sf, ptr, items) ; }
  303. inline sf_count_t
  304. SndfileHandle::write (const int *ptr, sf_count_t items)
  305. { return sf_write_int (p->sf, ptr, items) ; }
  306. inline sf_count_t
  307. SndfileHandle::write (const float *ptr, sf_count_t items)
  308. { return sf_write_float (p->sf, ptr, items) ; }
  309. inline sf_count_t
  310. SndfileHandle::write (const double *ptr, sf_count_t items)
  311. { return sf_write_double (p->sf, ptr, items) ; }
  312. inline sf_count_t
  313. SndfileHandle::readf (short *ptr, sf_count_t frame_count)
  314. { return sf_readf_short (p->sf, ptr, frame_count) ; }
  315. inline sf_count_t
  316. SndfileHandle::readf (int *ptr, sf_count_t frame_count)
  317. { return sf_readf_int (p->sf, ptr, frame_count) ; }
  318. inline sf_count_t
  319. SndfileHandle::readf (float *ptr, sf_count_t frame_count)
  320. { return sf_readf_float (p->sf, ptr, frame_count) ; }
  321. inline sf_count_t
  322. SndfileHandle::readf (double *ptr, sf_count_t frame_count)
  323. { return sf_readf_double (p->sf, ptr, frame_count) ; }
  324. inline sf_count_t
  325. SndfileHandle::writef (const short *ptr, sf_count_t frame_count)
  326. { return sf_writef_short (p->sf, ptr, frame_count) ; }
  327. inline sf_count_t
  328. SndfileHandle::writef (const int *ptr, sf_count_t frame_count)
  329. { return sf_writef_int (p->sf, ptr, frame_count) ; }
  330. inline sf_count_t
  331. SndfileHandle::writef (const float *ptr, sf_count_t frame_count)
  332. { return sf_writef_float (p->sf, ptr, frame_count) ; }
  333. inline sf_count_t
  334. SndfileHandle::writef (const double *ptr, sf_count_t frame_count)
  335. { return sf_writef_double (p->sf, ptr, frame_count) ; }
  336. inline sf_count_t
  337. SndfileHandle::readRaw (void *ptr, sf_count_t bytes)
  338. { return sf_read_raw (p->sf, ptr, bytes) ; }
  339. inline sf_count_t
  340. SndfileHandle::writeRaw (const void *ptr, sf_count_t bytes)
  341. { return sf_write_raw (p->sf, ptr, bytes) ; }
  342. inline SNDFILE *
  343. SndfileHandle::rawHandle (void)
  344. { return (p ? p->sf : SF_NULL) ; }
  345. inline SNDFILE *
  346. SndfileHandle::takeOwnership (void)
  347. {
  348. if (p == SF_NULL || (p->ref != 1))
  349. return SF_NULL ;
  350. SNDFILE * sf = p->sf ;
  351. p->sf = SF_NULL ;
  352. delete p ;
  353. p = SF_NULL ;
  354. return sf ;
  355. }
  356. #ifdef _WIN32
  357. inline
  358. SndfileHandle::SndfileHandle (const wchar_t *wpath, int mode, int fmt, int chans, int srate)
  359. : p (SF_NULL)
  360. {
  361. p = new (std::nothrow) SNDFILE_ref () ;
  362. if (p != SF_NULL)
  363. { p->ref = 1 ;
  364. p->sfinfo.frames = 0 ;
  365. p->sfinfo.channels = chans ;
  366. p->sfinfo.format = fmt ;
  367. p->sfinfo.samplerate = srate ;
  368. p->sfinfo.sections = 0 ;
  369. p->sfinfo.seekable = 0 ;
  370. p->sf = sf_wchar_open (wpath, mode, &p->sfinfo) ;
  371. } ;
  372. return ;
  373. } /* SndfileHandle const wchar_t * constructor */
  374. #endif
  375. #endif /* SNDFILE_HH */