PageRenderTime 43ms CodeModel.GetById 9ms app.highlight 29ms RepoModel.GetById 2ms app.codeStats 0ms

/project/jni/sndfile/src/vox_adpcm.c

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