ircam.c
上传用户:shw771010
上传日期:2022-01-05
资源大小:991k
文件大小:8k
源码类别:

Audio

开发平台:

Unix_Linux

  1. /*
  2. ** Copyright (C) 2001-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
  3. **
  4. ** This program is free software; you can redistribute it and/or modify
  5. ** it under the terms of the GNU Lesser General Public License as published by
  6. ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
  13. **
  14. ** You should have received a copy of the GNU Lesser General Public License
  15. ** along with this program; if not, write to the Free Software
  16. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include "sfconfig.h"
  19. #include <stdio.h>
  20. #include <fcntl.h>
  21. #include <string.h>
  22. #include <ctype.h>
  23. #include "sndfile.h"
  24. #include "sfendian.h"
  25. #include "common.h"
  26. /*------------------------------------------------------------------------------
  27. ** Macros to handle big/little endian issues.
  28. */
  29. /* The IRCAM magic number is weird in that one byte in the number can have
  30. ** values of 0x1, 0x2, 0x03 or 0x04. Hence the need for a marker and a mask.
  31. */
  32. #define IRCAM_BE_MASK (MAKE_MARKER (0xFF, 0xFF, 0x00, 0xFF))
  33. #define IRCAM_BE_MARKER (MAKE_MARKER (0x64, 0xA3, 0x00, 0x00))
  34. #define IRCAM_LE_MASK (MAKE_MARKER (0xFF, 0x00, 0xFF, 0xFF))
  35. #define IRCAM_LE_MARKER (MAKE_MARKER (0x00, 0x00, 0xA3, 0x64))
  36. #define IRCAM_02B_MARKER (MAKE_MARKER (0x64, 0xA3, 0x02, 0x00))
  37. #define IRCAM_03L_MARKER (MAKE_MARKER (0x64, 0xA3, 0x03, 0x00))
  38. #define IRCAM_DATA_OFFSET (1024)
  39. /*------------------------------------------------------------------------------
  40. ** Typedefs.
  41. */
  42. enum
  43. { IRCAM_PCM_16 = 0x00002,
  44. IRCAM_FLOAT = 0x00004,
  45. IRCAM_ALAW = 0x10001,
  46. IRCAM_ULAW = 0x20001,
  47. IRCAM_PCM_32 = 0x40004
  48. } ;
  49. /*------------------------------------------------------------------------------
  50. ** Private static functions.
  51. */
  52. static int ircam_close (SF_PRIVATE *psf) ;
  53. static int ircam_write_header (SF_PRIVATE *psf, int calc_length) ;
  54. static int ircam_read_header (SF_PRIVATE *psf) ;
  55. static int get_encoding (int subformat) ;
  56. static const char* get_encoding_str (int encoding) ;
  57. /*------------------------------------------------------------------------------
  58. ** Public function.
  59. */
  60. int
  61. ircam_open (SF_PRIVATE *psf)
  62. { int subformat ;
  63. int error = SFE_NO_ERROR ;
  64. if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
  65. { if ((error = ircam_read_header (psf)))
  66. return error ;
  67. } ;
  68. subformat = SF_CODEC (psf->sf.format) ;
  69. if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
  70. { if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_IRCAM)
  71. return SFE_BAD_OPEN_FORMAT ;
  72. psf->endian = SF_ENDIAN (psf->sf.format) ;
  73. if (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU)
  74. psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ;
  75.   psf->dataoffset = IRCAM_DATA_OFFSET ;
  76. if ((error = ircam_write_header (psf, SF_FALSE)))
  77. return error ;
  78. psf->write_header = ircam_write_header ;
  79. } ;
  80. psf->container_close = ircam_close ;
  81. switch (subformat)
  82. { case SF_FORMAT_ULAW : /* 8-bit Ulaw encoding. */
  83. error = ulaw_init (psf) ;
  84. break ;
  85. case SF_FORMAT_ALAW : /* 8-bit Alaw encoding. */
  86. error = alaw_init (psf) ;
  87. break ;
  88. case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
  89. case SF_FORMAT_PCM_32 : /* 32-bit linear PCM. */
  90. error = pcm_init (psf) ;
  91. break ;
  92. case SF_FORMAT_FLOAT : /* 32-bit linear PCM. */
  93. error = float32_init (psf) ;
  94. break ;
  95. default : break ;
  96. } ;
  97. return error ;
  98. } /* ircam_open */
  99. /*------------------------------------------------------------------------------
  100. */
  101. static int
  102. ircam_read_header (SF_PRIVATE *psf)
  103. { unsigned int marker, encoding ;
  104. float samplerate ;
  105. int error = SFE_NO_ERROR ;
  106. psf_binheader_readf (psf, "epmf44", 0, &marker, &samplerate, &(psf->sf.channels), &encoding) ;
  107. if (((marker & IRCAM_BE_MASK) != IRCAM_BE_MARKER) && ((marker & IRCAM_LE_MASK) != IRCAM_LE_MARKER))
  108. { psf_log_printf (psf, "marker: 0x%Xn", marker) ;
  109. return SFE_IRCAM_NO_MARKER ;
  110. } ;
  111. psf->endian = SF_ENDIAN_LITTLE ;
  112. if (psf->sf.channels > 256)
  113. { psf_binheader_readf (psf, "Epmf44", 0, &marker, &samplerate, &(psf->sf.channels), &encoding) ;
  114. /* Sanity checking for endian-ness detection. */
  115. if (psf->sf.channels > 256)
  116. { psf_log_printf (psf, "marker: 0x%Xn", marker) ;
  117. return SFE_IRCAM_BAD_CHANNELS ;
  118. } ;
  119. psf->endian = SF_ENDIAN_BIG ;
  120. } ;
  121. psf_log_printf (psf, "marker: 0x%Xn", marker) ;
  122. psf->sf.samplerate = (int) samplerate ;
  123. psf_log_printf (psf, "  Sample Rate : %dn"
  124.  "  Channels    : %dn"
  125.  "  Encoding    : %X => %sn", psf->sf.samplerate, psf->sf.channels, encoding, get_encoding_str (encoding)) ;
  126. switch (encoding)
  127. { case IRCAM_PCM_16 :
  128. psf->bytewidth = 2 ;
  129. psf->blockwidth = psf->sf.channels * psf->bytewidth ;
  130. psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_PCM_16 ;
  131. break ;
  132. case IRCAM_PCM_32 :
  133. psf->bytewidth = 4 ;
  134. psf->blockwidth = psf->sf.channels * psf->bytewidth ;
  135. psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_PCM_32 ;
  136. break ;
  137. case IRCAM_FLOAT :
  138. psf->bytewidth = 4 ;
  139. psf->blockwidth = psf->sf.channels * psf->bytewidth ;
  140. psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_FLOAT ;
  141. break ;
  142. case IRCAM_ALAW :
  143. psf->bytewidth = 1 ;
  144. psf->blockwidth = psf->sf.channels * psf->bytewidth ;
  145. psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_ALAW ;
  146. break ;
  147. case IRCAM_ULAW :
  148. psf->bytewidth = 1 ;
  149. psf->blockwidth = psf->sf.channels * psf->bytewidth ;
  150. psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_ULAW ;
  151. break ;
  152. default :
  153. error = SFE_IRCAM_UNKNOWN_FORMAT ;
  154. break ;
  155. } ;
  156. if (psf->endian == SF_ENDIAN_BIG)
  157. psf->sf.format |= SF_ENDIAN_BIG ;
  158. else
  159. psf->sf.format |= SF_ENDIAN_LITTLE ;
  160. if (error)
  161. return error ;
  162. psf->dataoffset = IRCAM_DATA_OFFSET ;
  163. psf->datalength = psf->filelength - psf->dataoffset ;
  164. if (psf->sf.frames == 0 && psf->blockwidth)
  165. psf->sf.frames = psf->datalength / psf->blockwidth ;
  166. psf_log_printf (psf, "  Samples     : %dn", psf->sf.frames) ;
  167. psf_binheader_readf (psf, "p", IRCAM_DATA_OFFSET) ;
  168. return 0 ;
  169. } /* ircam_read_header */
  170. static int
  171. ircam_close (SF_PRIVATE *psf)
  172. {
  173. psf_log_printf (psf, "closen") ;
  174. return 0 ;
  175. } /* ircam_close */
  176. static int
  177. ircam_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
  178. { int encoding ;
  179. float samplerate ;
  180. sf_count_t current ;
  181. if (psf->pipeoffset > 0)
  182. return 0 ;
  183. current = psf_ftell (psf) ;
  184. /* This also sets psf->endian. */
  185. encoding = get_encoding (SF_CODEC (psf->sf.format)) ;
  186. if (encoding == 0)
  187. return SFE_BAD_OPEN_FORMAT ;
  188. /* Reset the current header length to zero. */
  189. psf->header [0] = 0 ;
  190. psf->headindex = 0 ;
  191. if (psf->is_pipe == SF_FALSE)
  192. psf_fseek (psf, 0, SEEK_SET) ;
  193. samplerate = psf->sf.samplerate ;
  194. switch (psf->endian)
  195. { case SF_ENDIAN_BIG :
  196. psf_binheader_writef (psf, "Emf", IRCAM_02B_MARKER, samplerate) ;
  197. psf_binheader_writef (psf, "E44", psf->sf.channels, encoding) ;
  198. break ;
  199. case SF_ENDIAN_LITTLE :
  200. psf_binheader_writef (psf, "emf", IRCAM_03L_MARKER, samplerate) ;
  201. psf_binheader_writef (psf, "e44", psf->sf.channels, encoding) ;
  202. break ;
  203. default : return SFE_BAD_OPEN_FORMAT ;
  204. } ;
  205. psf_binheader_writef (psf, "z", (size_t) (IRCAM_DATA_OFFSET - psf->headindex)) ;
  206. /* Header construction complete so write it out. */
  207. psf_fwrite (psf->header, psf->headindex, 1, psf) ;
  208. if (psf->error)
  209. return psf->error ;
  210. if (current > 0)
  211. psf_fseek (psf, current, SEEK_SET) ;
  212. return psf->error ;
  213. } /* ircam_write_header */
  214. static int
  215. get_encoding (int subformat)
  216. { switch (subformat)
  217. { case SF_FORMAT_PCM_16 : return IRCAM_PCM_16 ;
  218. case SF_FORMAT_PCM_32 : return IRCAM_PCM_32 ;
  219. case SF_FORMAT_FLOAT : return IRCAM_FLOAT ;
  220. case SF_FORMAT_ULAW : return IRCAM_ULAW ;
  221. case SF_FORMAT_ALAW : return IRCAM_ALAW ;
  222. default : break ;
  223. } ;
  224. return 0 ;
  225. } /* get_encoding */
  226. static const char*
  227. get_encoding_str (int encoding)
  228. { switch (encoding)
  229. { case IRCAM_PCM_16 : return "16 bit PCM" ;
  230. case IRCAM_FLOAT : return "32 bit float" ;
  231. case IRCAM_ALAW : return "A law" ;
  232. case IRCAM_ULAW : return "u law" ;
  233. case IRCAM_PCM_32 : return "32 bit PCM" ;
  234. } ;
  235. return "Unknown encoding" ;
  236. } /* get_encoding_str */