2 ** Copyright (C) 1999-2006 Erik de Castro Lopo <erikd@mega-nerd.com>
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.
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.
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.
27 #include "float_cast.h"
30 #include "GSM610/gsm.h"
32 #define GSM610_BLOCKSIZE 33
33 #define GSM610_SAMPLES 160
35 typedef struct gsm610_tag
37 int blockcount, samplecount ;
38 int samplesperblock, blocksize ;
40 int (*decode_block) (SF_PRIVATE *psf, struct gsm610_tag *pgsm610) ;
41 int (*encode_block) (SF_PRIVATE *psf, struct gsm610_tag *pgsm610) ;
43 short samples [WAV_W64_GSM610_SAMPLES] ;
44 unsigned char block [WAV_W64_GSM610_BLOCKSIZE] ;
46 /* Damn I hate typedef-ed pointers; yes, gsm is a pointer type. */
50 static sf_count_t gsm610_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
51 static sf_count_t gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
52 static sf_count_t gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
53 static sf_count_t gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
55 static sf_count_t gsm610_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
56 static sf_count_t gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
57 static sf_count_t gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
58 static sf_count_t gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
60 static int gsm610_read_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len) ;
61 static int gsm610_write_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, const short *ptr, int len) ;
63 static int gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ;
64 static int gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ;
66 static int gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ;
67 static int gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ;
69 static sf_count_t gsm610_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
71 static int gsm610_close (SF_PRIVATE *psf) ;
73 /*============================================================================================
74 ** WAV GSM610 initialisation function.
78 gsm610_init (SF_PRIVATE *psf)
79 { GSM610_PRIVATE *pgsm610 ;
82 if (psf->fdata != NULL)
83 { psf_log_printf (psf, "*** psf->fdata is not NULL.\n") ;
87 if (psf->mode == SFM_RDWR)
88 return SFE_BAD_MODE_RW ;
90 psf->sf.seekable = SF_FALSE ;
92 if ((pgsm610 = calloc (1, sizeof (GSM610_PRIVATE))) == NULL)
93 return SFE_MALLOC_FAILED ;
95 psf->fdata = (void*) pgsm610 ;
97 memset (pgsm610, 0, sizeof (GSM610_PRIVATE)) ;
99 /*============================================================
101 Need separate gsm_data structs for encode and decode.
103 ============================================================*/
105 if ((pgsm610->gsm_data = gsm_create ()) == NULL)
106 return SFE_MALLOC_FAILED ;
108 switch (psf->sf.format & SF_FORMAT_TYPEMASK)
109 { case SF_FORMAT_WAV :
110 case SF_FORMAT_WAVEX :
112 gsm_option (pgsm610->gsm_data, GSM_OPT_WAV49, &true_flag) ;
114 pgsm610->encode_block = gsm610_wav_encode_block ;
115 pgsm610->decode_block = gsm610_wav_decode_block ;
117 pgsm610->samplesperblock = WAV_W64_GSM610_SAMPLES ;
118 pgsm610->blocksize = WAV_W64_GSM610_BLOCKSIZE ;
121 case SF_FORMAT_AIFF :
123 pgsm610->encode_block = gsm610_encode_block ;
124 pgsm610->decode_block = gsm610_decode_block ;
126 pgsm610->samplesperblock = GSM610_SAMPLES ;
127 pgsm610->blocksize = GSM610_BLOCKSIZE ;
131 return SFE_INTERNAL ;
135 if (psf->mode == SFM_READ)
136 { if (psf->datalength % pgsm610->blocksize == 0)
137 pgsm610->blocks = psf->datalength / pgsm610->blocksize ;
138 else if (psf->datalength % pgsm610->blocksize == 1 && pgsm610->blocksize == GSM610_BLOCKSIZE)
140 ** Weird AIFF specific case.
141 ** AIFF chunks must be at an odd offset from the start of file and
142 ** GSM610_BLOCKSIZE is odd which can result in an odd length SSND
143 ** chunk. The SSND chunk then gets padded on write which means that
144 ** when it is read the datalength is too big by 1.
146 pgsm610->blocks = psf->datalength / pgsm610->blocksize ;
149 { psf_log_printf (psf, "*** Warning : data chunk seems to be truncated.\n") ;
150 pgsm610->blocks = psf->datalength / pgsm610->blocksize + 1 ;
153 psf->sf.frames = pgsm610->samplesperblock * pgsm610->blocks ;
155 pgsm610->decode_block (psf, pgsm610) ; /* Read first block. */
157 psf->read_short = gsm610_read_s ;
158 psf->read_int = gsm610_read_i ;
159 psf->read_float = gsm610_read_f ;
160 psf->read_double = gsm610_read_d ;
163 if (psf->mode == SFM_WRITE)
164 { pgsm610->blockcount = 0 ;
165 pgsm610->samplecount = 0 ;
167 psf->write_short = gsm610_write_s ;
168 psf->write_int = gsm610_write_i ;
169 psf->write_float = gsm610_write_f ;
170 psf->write_double = gsm610_write_d ;
173 psf->codec_close = gsm610_close ;
175 psf->seek = gsm610_seek ;
177 psf->filelength = psf_get_filelen (psf) ;
178 psf->datalength = psf->filelength - psf->dataoffset ;
183 /*============================================================================================
184 ** GSM 6.10 Read Functions.
188 gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
191 pgsm610->blockcount ++ ;
192 pgsm610->samplecount = 0 ;
194 if (pgsm610->blockcount > pgsm610->blocks)
195 { memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
199 if ((k = psf_fread (pgsm610->block, 1, WAV_W64_GSM610_BLOCKSIZE, psf)) != WAV_W64_GSM610_BLOCKSIZE)
200 psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, WAV_W64_GSM610_BLOCKSIZE) ;
202 if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0)
203 { psf_log_printf (psf, "Error from gsm_decode() on frame : %d\n", pgsm610->blockcount) ;
207 if (gsm_decode (pgsm610->gsm_data, pgsm610->block + (WAV_W64_GSM610_BLOCKSIZE + 1) / 2, pgsm610->samples + WAV_W64_GSM610_SAMPLES / 2) < 0)
208 { psf_log_printf (psf, "Error from gsm_decode() on frame : %d.5\n", pgsm610->blockcount) ;
213 } /* gsm610_wav_decode_block */
216 gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
219 pgsm610->blockcount ++ ;
220 pgsm610->samplecount = 0 ;
222 if (pgsm610->blockcount > pgsm610->blocks)
223 { memset (pgsm610->samples, 0, GSM610_SAMPLES * sizeof (short)) ;
227 if ((k = psf_fread (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE)
228 psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, GSM610_BLOCKSIZE) ;
230 if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0)
231 { psf_log_printf (psf, "Error from gsm_decode() on frame : %d\n", pgsm610->blockcount) ;
236 } /* gsm610_decode_block */
239 gsm610_read_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len)
240 { int count, total = 0, indx = 0 ;
243 { if (pgsm610->blockcount >= pgsm610->blocks && pgsm610->samplecount >= pgsm610->samplesperblock)
244 { memset (&(ptr [indx]), 0, (len - indx) * sizeof (short)) ;
248 if (pgsm610->samplecount >= pgsm610->samplesperblock)
249 pgsm610->decode_block (psf, pgsm610) ;
251 count = pgsm610->samplesperblock - pgsm610->samplecount ;
252 count = (len - indx > count) ? count : len - indx ;
254 memcpy (&(ptr [indx]), &(pgsm610->samples [pgsm610->samplecount]), count * sizeof (short)) ;
256 pgsm610->samplecount += count ;
261 } /* gsm610_read_block */
264 gsm610_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
265 { GSM610_PRIVATE *pgsm610 ;
266 int readcount, count ;
267 sf_count_t total = 0 ;
269 if (psf->fdata == NULL)
271 pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
274 { readcount = (len > 0x10000000) ? 0x1000000 : (int) len ;
276 count = gsm610_read_block (psf, pgsm610, ptr, readcount) ;
281 if (count != readcount)
286 } /* gsm610_read_s */
289 gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
290 { GSM610_PRIVATE *pgsm610 ;
292 int k, bufferlen, readcount = 0, count ;
293 sf_count_t total = 0 ;
295 if (psf->fdata == NULL)
297 pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
300 bufferlen = ARRAY_LEN (psf->u.sbuf) ;
302 { readcount = (len >= bufferlen) ? bufferlen : len ;
303 count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
304 for (k = 0 ; k < readcount ; k++)
305 ptr [total + k] = sptr [k] << 16 ;
311 } /* gsm610_read_i */
314 gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
315 { GSM610_PRIVATE *pgsm610 ;
317 int k, bufferlen, readcount = 0, count ;
318 sf_count_t total = 0 ;
321 if (psf->fdata == NULL)
323 pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
325 normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
328 bufferlen = ARRAY_LEN (psf->u.sbuf) ;
330 { readcount = (len >= bufferlen) ? bufferlen : len ;
331 count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
332 for (k = 0 ; k < readcount ; k++)
333 ptr [total + k] = normfact * sptr [k] ;
339 } /* gsm610_read_f */
342 gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
343 { GSM610_PRIVATE *pgsm610 ;
345 int k, bufferlen, readcount = 0, count ;
346 sf_count_t total = 0 ;
349 normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
351 if (psf->fdata == NULL)
353 pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
356 bufferlen = ARRAY_LEN (psf->u.sbuf) ;
358 { readcount = (len >= bufferlen) ? bufferlen : len ;
359 count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
360 for (k = 0 ; k < readcount ; k++)
361 ptr [total + k] = normfact * sptr [k] ;
367 } /* gsm610_read_d */
370 gsm610_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
371 { GSM610_PRIVATE *pgsm610 ;
372 int newblock, newsample ;
376 if (psf->fdata == NULL)
378 pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
380 if (psf->dataoffset < 0)
381 { psf->error = SFE_BAD_SEEK ;
382 return PSF_SEEK_ERROR ;
386 { int true_flag = 1 ;
388 psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
389 pgsm610->blockcount = 0 ;
391 gsm_init (pgsm610->gsm_data) ;
392 if ((psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV ||
393 (psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_W64)
394 gsm_option (pgsm610->gsm_data, GSM_OPT_WAV49, &true_flag) ;
396 pgsm610->decode_block (psf, pgsm610) ;
397 pgsm610->samplecount = 0 ;
401 if (offset < 0 || offset > pgsm610->blocks * pgsm610->samplesperblock)
402 { psf->error = SFE_BAD_SEEK ;
403 return PSF_SEEK_ERROR ;
406 newblock = offset / pgsm610->samplesperblock ;
407 newsample = offset % pgsm610->samplesperblock ;
409 if (psf->mode == SFM_READ)
410 { if (psf->read_current != newblock * pgsm610->samplesperblock + newsample)
411 { psf_fseek (psf, psf->dataoffset + newblock * pgsm610->samplesperblock, SEEK_SET) ;
412 pgsm610->blockcount = newblock ;
413 pgsm610->decode_block (psf, pgsm610) ;
414 pgsm610->samplecount = newsample ;
417 return newblock * pgsm610->samplesperblock + newsample ;
420 /* What to do about write??? */
421 psf->error = SFE_BAD_SEEK ;
422 return PSF_SEEK_ERROR ;
425 /*==========================================================================================
426 ** GSM 6.10 Write Functions.
430 gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
433 /* Encode the samples. */
434 gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ;
436 /* Write the block to disk. */
437 if ((k = psf_fwrite (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE)
438 psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, GSM610_BLOCKSIZE) ;
440 pgsm610->samplecount = 0 ;
441 pgsm610->blockcount ++ ;
443 /* Set samples to zero for next block. */
444 memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
447 } /* gsm610_encode_block */
450 gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
453 /* Encode the samples. */
454 gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ;
455 gsm_encode (pgsm610->gsm_data, pgsm610->samples+WAV_W64_GSM610_SAMPLES/2, pgsm610->block+WAV_W64_GSM610_BLOCKSIZE/2) ;
457 /* Write the block to disk. */
458 if ((k = psf_fwrite (pgsm610->block, 1, WAV_W64_GSM610_BLOCKSIZE, psf)) != WAV_W64_GSM610_BLOCKSIZE)
459 psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, WAV_W64_GSM610_BLOCKSIZE) ;
461 pgsm610->samplecount = 0 ;
462 pgsm610->blockcount ++ ;
464 /* Set samples to zero for next block. */
465 memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
468 } /* gsm610_wav_encode_block */
471 gsm610_write_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, const short *ptr, int len)
472 { int count, total = 0, indx = 0 ;
475 { count = pgsm610->samplesperblock - pgsm610->samplecount ;
477 if (count > len - indx)
480 memcpy (&(pgsm610->samples [pgsm610->samplecount]), &(ptr [indx]), count * sizeof (short)) ;
482 pgsm610->samplecount += count ;
485 if (pgsm610->samplecount >= pgsm610->samplesperblock)
486 pgsm610->encode_block (psf, pgsm610) ;
490 } /* gsm610_write_block */
493 gsm610_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
494 { GSM610_PRIVATE *pgsm610 ;
495 int writecount, count ;
496 sf_count_t total = 0 ;
498 if (psf->fdata == NULL)
500 pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
503 { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
505 count = gsm610_write_block (psf, pgsm610, ptr, writecount) ;
510 if (count != writecount)
515 } /* gsm610_write_s */
518 gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
519 { GSM610_PRIVATE *pgsm610 ;
521 int k, bufferlen, writecount = 0, count ;
522 sf_count_t total = 0 ;
524 if (psf->fdata == NULL)
526 pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
529 bufferlen = ARRAY_LEN (psf->u.sbuf) ;
531 { writecount = (len >= bufferlen) ? bufferlen : len ;
532 for (k = 0 ; k < writecount ; k++)
533 sptr [k] = ptr [total + k] >> 16 ;
534 count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;
540 } /* gsm610_write_i */
543 gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
544 { GSM610_PRIVATE *pgsm610 ;
546 int k, bufferlen, writecount = 0, count ;
547 sf_count_t total = 0 ;
550 if (psf->fdata == NULL)
552 pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
554 normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
557 bufferlen = ARRAY_LEN (psf->u.sbuf) ;
559 { writecount = (len >= bufferlen) ? bufferlen : len ;
560 for (k = 0 ; k < writecount ; k++)
561 sptr [k] = lrintf (normfact * ptr [total + k]) ;
562 count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;
568 } /* gsm610_write_f */
571 gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
572 { GSM610_PRIVATE *pgsm610 ;
574 int k, bufferlen, writecount = 0, count ;
575 sf_count_t total = 0 ;
578 if (psf->fdata == NULL)
580 pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
582 normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
585 bufferlen = ARRAY_LEN (psf->u.sbuf) ;
587 { writecount = (len >= bufferlen) ? bufferlen : len ;
588 for (k = 0 ; k < writecount ; k++)
589 sptr [k] = lrint (normfact * ptr [total + k]) ;
590 count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;
596 } /* gsm610_write_d */
599 gsm610_close (SF_PRIVATE *psf)
600 { GSM610_PRIVATE *pgsm610 ;
602 if (psf->fdata == NULL)
605 pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
607 if (psf->mode == SFM_WRITE)
608 { /* If a block has been partially assembled, write it out
609 ** as the final block.
612 if (pgsm610->samplecount && pgsm610->samplecount < pgsm610->samplesperblock)
613 pgsm610->encode_block (psf, pgsm610) ;
616 if (pgsm610->gsm_data)
617 gsm_destroy (pgsm610->gsm_data) ;
623 ** Do not edit or modify anything in this comment block.
624 ** The arch-tag line is a file identity tag for the GNU Arch
625 ** revision control system.
627 ** arch-tag: 8575187d-af4f-4acf-b9dd-6ff705628345