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

Audio

开发平台:

Unix_Linux

  1. /*
  2. ** Copyright (C) 2002-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. /*
  19. ** This is the OKI / Dialogic ADPCM encoder/decoder. It converts from
  20. ** 12 bit linear sample data to a 4 bit ADPCM.
  21. */
  22. /*
  23.  * Note: some early Dialogic hardware does not always reset the ADPCM encoder
  24.  * at the start of each vox file. This can result in clipping and/or DC offset
  25.  * problems when it comes to decoding the audio. Whilst little can be done
  26.  * about the clipping, a DC offset can be removed by passing the decoded audio
  27.  * through a high-pass filter at e.g. 10Hz.
  28.  */
  29. #include "sfconfig.h"
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <math.h>
  34. #include "sndfile.h"
  35. #include "sfendian.h"
  36. #include "common.h"
  37. #include "ima_oki_adpcm.h"
  38. static sf_count_t vox_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
  39. static sf_count_t vox_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
  40. static sf_count_t vox_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
  41. static sf_count_t vox_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
  42. static sf_count_t vox_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
  43. static sf_count_t vox_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
  44. static sf_count_t vox_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
  45. static sf_count_t vox_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
  46. static int vox_read_block (SF_PRIVATE *psf, IMA_OKI_ADPCM *pvox, short *ptr, int len) ;
  47. /*------------------------------------------------------------------------------
  48. */
  49. static int
  50. codec_close (SF_PRIVATE * psf)
  51. {
  52. IMA_OKI_ADPCM * p = (IMA_OKI_ADPCM *) psf->codec_data ;
  53. if (p->errors)
  54. psf_log_printf (psf, "*** Warning : ADPCM state errors: %dn", p->errors) ;
  55. return p->errors ;
  56. } /* code_close */
  57. int
  58. vox_adpcm_init (SF_PRIVATE *psf)
  59. { IMA_OKI_ADPCM *pvox = NULL ;
  60. if (psf->file.mode == SFM_RDWR)
  61. return SFE_BAD_MODE_RW ;
  62. if (psf->file.mode == SFM_WRITE && psf->sf.channels != 1)
  63. return SFE_CHANNEL_COUNT ;
  64. if ((pvox = malloc (sizeof (IMA_OKI_ADPCM))) == NULL)
  65. return SFE_MALLOC_FAILED ;
  66. psf->codec_data = (void*) pvox ;
  67. memset (pvox, 0, sizeof (IMA_OKI_ADPCM)) ;
  68. if (psf->file.mode == SFM_WRITE)
  69. { psf->write_short = vox_write_s ;
  70. psf->write_int = vox_write_i ;
  71. psf->write_float = vox_write_f ;
  72. psf->write_double = vox_write_d ;
  73. }
  74. else
  75. { psf_log_printf (psf, "Header-less OKI Dialogic ADPCM encoded file.n") ;
  76. psf_log_printf (psf, "Setting up for 8kHz, mono, Vox ADPCM.n") ;
  77. psf->read_short = vox_read_s ;
  78. psf->read_int = vox_read_i ;
  79. psf->read_float = vox_read_f ;
  80. psf->read_double = vox_read_d ;
  81. } ;
  82. /* Standard sample rate chennels etc. */
  83. if (psf->sf.samplerate < 1)
  84. psf->sf.samplerate = 8000 ;
  85. psf->sf.channels = 1 ;
  86. psf->sf.frames = psf->filelength * 2 ;
  87. psf->sf.seekable = SF_FALSE ;
  88. psf->codec_close = codec_close ;
  89. /* Seek back to start of data. */
  90. if (psf_fseek (psf, 0 , SEEK_SET) == -1)
  91. return SFE_BAD_SEEK ;
  92. ima_oki_adpcm_init (pvox, IMA_OKI_ADPCM_TYPE_OKI) ;
  93. return 0 ;
  94. } /* vox_adpcm_init */
  95. /*==============================================================================
  96. */
  97. static int
  98. vox_read_block (SF_PRIVATE *psf, IMA_OKI_ADPCM *pvox, short *ptr, int len)
  99. { int indx = 0, k ;
  100. while (indx < len)
  101. { pvox->code_count = (len - indx > IMA_OKI_ADPCM_PCM_LEN) ? IMA_OKI_ADPCM_CODE_LEN : (len - indx + 1) / 2 ;
  102. if ((k = psf_fread (pvox->codes, 1, pvox->code_count, psf)) != pvox->code_count)
  103. { if (psf_ftell (psf) != psf->filelength)
  104. psf_log_printf (psf, "*** Warning : short read (%d != %d).n", k, pvox->code_count) ;
  105. if (k == 0)
  106. break ;
  107. } ;
  108. pvox->code_count = k ;
  109. ima_oki_adpcm_decode_block (pvox) ;
  110. memcpy (&(ptr [indx]), pvox->pcm, pvox->pcm_count * sizeof (short)) ;
  111. indx += pvox->pcm_count ;
  112. } ;
  113. return indx ;
  114. } /* vox_read_block */
  115. static sf_count_t
  116. vox_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
  117. { IMA_OKI_ADPCM  *pvox ;
  118. int readcount, count ;
  119. sf_count_t total = 0 ;
  120. if (! psf->codec_data)
  121. return 0 ;
  122. pvox = (IMA_OKI_ADPCM*) psf->codec_data ;
  123. while (len > 0)
  124. { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
  125. count = vox_read_block (psf, pvox, ptr, readcount) ;
  126. total += count ;
  127. len -= count ;
  128. if (count != readcount)
  129. break ;
  130. } ;
  131. return total ;
  132. } /* vox_read_s */
  133. static sf_count_t
  134. vox_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
  135. { IMA_OKI_ADPCM *pvox ;
  136. short *sptr ;
  137. int k, bufferlen, readcount, count ;
  138. sf_count_t total = 0 ;
  139. if (! psf->codec_data)
  140. return 0 ;
  141. pvox = (IMA_OKI_ADPCM*) psf->codec_data ;
  142. sptr = psf->u.sbuf ;
  143. bufferlen = ARRAY_LEN (psf->u.sbuf) ;
  144. while (len > 0)
  145. { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
  146. count = vox_read_block (psf, pvox, sptr, readcount) ;
  147. for (k = 0 ; k < readcount ; k++)
  148. ptr [total + k] = ((int) sptr [k]) << 16 ;
  149. total += count ;
  150. len -= readcount ;
  151. if (count != readcount)
  152. break ;
  153. } ;
  154. return total ;
  155. } /* vox_read_i */
  156. static sf_count_t
  157. vox_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
  158. { IMA_OKI_ADPCM *pvox ;
  159. short *sptr ;
  160. int k, bufferlen, readcount, count ;
  161. sf_count_t total = 0 ;
  162. float normfact ;
  163. if (! psf->codec_data)
  164. return 0 ;
  165. pvox = (IMA_OKI_ADPCM*) psf->codec_data ;
  166. normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
  167. sptr = psf->u.sbuf ;
  168. bufferlen = ARRAY_LEN (psf->u.sbuf) ;
  169. while (len > 0)
  170. { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
  171. count = vox_read_block (psf, pvox, sptr, readcount) ;
  172. for (k = 0 ; k < readcount ; k++)
  173. ptr [total + k] = normfact * (float) (sptr [k]) ;
  174. total += count ;
  175. len -= readcount ;
  176. if (count != readcount)
  177. break ;
  178. } ;
  179. return total ;
  180. } /* vox_read_f */
  181. static sf_count_t
  182. vox_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
  183. { IMA_OKI_ADPCM *pvox ;
  184. short *sptr ;
  185. int k, bufferlen, readcount, count ;
  186. sf_count_t total = 0 ;
  187. double  normfact ;
  188. if (! psf->codec_data)
  189. return 0 ;
  190. pvox = (IMA_OKI_ADPCM*) psf->codec_data ;
  191. normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
  192. sptr = psf->u.sbuf ;
  193. bufferlen = ARRAY_LEN (psf->u.sbuf) ;
  194. while (len > 0)
  195. { readcount = (len >= bufferlen) ? bufferlen : (int) len ;
  196. count = vox_read_block (psf, pvox, sptr, readcount) ;
  197. for (k = 0 ; k < readcount ; k++)
  198. ptr [total + k] = normfact * (double) (sptr [k]) ;
  199. total += count ;
  200. len -= readcount ;
  201. if (count != readcount)
  202. break ;
  203. } ;
  204. return total ;
  205. } /* vox_read_d */
  206. /*------------------------------------------------------------------------------
  207. */
  208. static int
  209. vox_write_block (SF_PRIVATE *psf, IMA_OKI_ADPCM *pvox, const short *ptr, int len)
  210. { int indx = 0, k ;
  211. while (indx < len)
  212. { pvox->pcm_count = (len - indx > IMA_OKI_ADPCM_PCM_LEN) ? IMA_OKI_ADPCM_PCM_LEN : len - indx ;
  213. memcpy (pvox->pcm, &(ptr [indx]), pvox->pcm_count * sizeof (short)) ;
  214. ima_oki_adpcm_encode_block (pvox) ;
  215. if ((k = psf_fwrite (pvox->codes, 1, pvox->code_count, psf)) != pvox->code_count)
  216. psf_log_printf (psf, "*** Warning : short write (%d != %d).n", k, pvox->code_count) ;
  217. indx += pvox->pcm_count ;
  218. } ;
  219. return indx ;
  220. } /* vox_write_block */
  221. static sf_count_t
  222. vox_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
  223. { IMA_OKI_ADPCM  *pvox ;
  224. int writecount, count ;
  225. sf_count_t total = 0 ;
  226. if (! psf->codec_data)
  227. return 0 ;
  228. pvox = (IMA_OKI_ADPCM*) psf->codec_data ;
  229. while (len)
  230. { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
  231. count = vox_write_block (psf, pvox, ptr, writecount) ;
  232. total += count ;
  233. len -= count ;
  234. if (count != writecount)
  235. break ;
  236. } ;
  237. return total ;
  238. } /* vox_write_s */
  239. static sf_count_t
  240. vox_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
  241. { IMA_OKI_ADPCM *pvox ;
  242. short *sptr ;
  243. int k, bufferlen, writecount, count ;
  244. sf_count_t total = 0 ;
  245. if (! psf->codec_data)
  246. return 0 ;
  247. pvox = (IMA_OKI_ADPCM*) psf->codec_data ;
  248. sptr = psf->u.sbuf ;
  249. bufferlen = ARRAY_LEN (psf->u.sbuf) ;
  250. while (len > 0)
  251. { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
  252. for (k = 0 ; k < writecount ; k++)
  253. sptr [k] = ptr [total + k] >> 16 ;
  254. count = vox_write_block (psf, pvox, sptr, writecount) ;
  255. total += count ;
  256. len -= writecount ;
  257. if (count != writecount)
  258. break ;
  259. } ;
  260. return total ;
  261. } /* vox_write_i */
  262. static sf_count_t
  263. vox_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
  264. { IMA_OKI_ADPCM *pvox ;
  265. short *sptr ;
  266. int k, bufferlen, writecount, count ;
  267. sf_count_t total = 0 ;
  268. float normfact ;
  269. if (! psf->codec_data)
  270. return 0 ;
  271. pvox = (IMA_OKI_ADPCM*) psf->codec_data ;
  272. normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
  273. sptr = psf->u.sbuf ;
  274. bufferlen = ARRAY_LEN (psf->u.sbuf) ;
  275. while (len > 0)
  276. { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
  277. for (k = 0 ; k < writecount ; k++)
  278. sptr [k] = lrintf (normfact * ptr [total + k]) ;
  279. count = vox_write_block (psf, pvox, sptr, writecount) ;
  280. total += count ;
  281. len -= writecount ;
  282. if (count != writecount)
  283. break ;
  284. } ;
  285. return total ;
  286. } /* vox_write_f */
  287. static sf_count_t
  288. vox_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
  289. { IMA_OKI_ADPCM *pvox ;
  290. short *sptr ;
  291. int k, bufferlen, writecount, count ;
  292. sf_count_t total = 0 ;
  293. double  normfact ;
  294. if (! psf->codec_data)
  295. return 0 ;
  296. pvox = (IMA_OKI_ADPCM*) psf->codec_data ;
  297. normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
  298. sptr = psf->u.sbuf ;
  299. bufferlen = ARRAY_LEN (psf->u.sbuf) ;
  300. while (len > 0)
  301. { writecount = (len >= bufferlen) ? bufferlen : (int) len ;
  302. for (k = 0 ; k < writecount ; k++)
  303. sptr [k] = lrint (normfact * ptr [total + k]) ;
  304. count = vox_write_block (psf, pvox, sptr, writecount) ;
  305. total += count ;
  306. len -= writecount ;
  307. if (count != writecount)
  308. break ;
  309. } ;
  310. return total ;
  311. } /* vox_write_d */