1 /*
2 ** Copyright (C) 1999-2014 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 #include "sfconfig.h"
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <math.h>
25
26 #include "sndfile.h"
27 #include "sfendian.h"
28 #include "common.h"
29 #include "G72x/g72x.h"
30
31 /* This struct is private to the G72x code. */
32 struct g72x_state ;
33 typedef struct g72x_state G72x_STATE ;
34
35 typedef struct
36 { /* Private data. Don't mess with it. */
37 struct g72x_state * private ;
38
39 /* Public data. Read only. */
40 int blocksize, samplesperblock, bytesperblock ;
41
42 /* Public data. Read and write. */
43 int blocks_total, block_curr, sample_curr ;
44 unsigned char block [G72x_BLOCK_SIZE] ;
45 short samples [G72x_BLOCK_SIZE] ;
46 } G72x_PRIVATE ;
47
48 static int psf_g72x_decode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x) ;
49 static int psf_g72x_encode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x) ;
50
51 static sf_count_t g72x_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
52 static sf_count_t g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
53 static sf_count_t g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
54 static sf_count_t g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
55
56 static sf_count_t g72x_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
57 static sf_count_t g72x_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
58 static sf_count_t g72x_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
59 static sf_count_t g72x_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
60
61 static sf_count_t g72x_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
62
63 static int g72x_close (SF_PRIVATE *psf) ;
64
65
66 /*============================================================================================
67 ** WAV G721 Reader initialisation function.
68 */
69
70 int
g72x_init(SF_PRIVATE * psf)71 g72x_init (SF_PRIVATE * psf)
72 { G72x_PRIVATE *pg72x ;
73 int bitspersample, bytesperblock, codec ;
74
75 if (psf->codec_data != NULL)
76 { psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ;
77 return SFE_INTERNAL ;
78 } ;
79
80 psf->sf.seekable = SF_FALSE ;
81
82 if (psf->sf.channels != 1)
83 return SFE_G72X_NOT_MONO ;
84
85 if ((pg72x = calloc (1, sizeof (G72x_PRIVATE))) == NULL)
86 return SFE_MALLOC_FAILED ;
87
88 psf->codec_data = (void*) pg72x ;
89
90 pg72x->block_curr = 0 ;
91 pg72x->sample_curr = 0 ;
92
93 switch (SF_CODEC (psf->sf.format))
94 { case SF_FORMAT_G721_32 :
95 codec = G721_32_BITS_PER_SAMPLE ;
96 bytesperblock = G721_32_BYTES_PER_BLOCK ;
97 bitspersample = G721_32_BITS_PER_SAMPLE ;
98 break ;
99
100 case SF_FORMAT_G723_24:
101 codec = G723_24_BITS_PER_SAMPLE ;
102 bytesperblock = G723_24_BYTES_PER_BLOCK ;
103 bitspersample = G723_24_BITS_PER_SAMPLE ;
104 break ;
105
106 case SF_FORMAT_G723_40:
107 codec = G723_40_BITS_PER_SAMPLE ;
108 bytesperblock = G723_40_BYTES_PER_BLOCK ;
109 bitspersample = G723_40_BITS_PER_SAMPLE ;
110 break ;
111
112 default : return SFE_UNIMPLEMENTED ;
113 } ;
114
115 psf->filelength = psf_get_filelen (psf) ;
116 if (psf->filelength < psf->dataoffset)
117 psf->filelength = psf->dataoffset ;
118
119 psf->datalength = psf->filelength - psf->dataoffset ;
120 if (psf->dataend > 0)
121 psf->datalength -= psf->filelength - psf->dataend ;
122
123 if (psf->file.mode == SFM_READ)
124 { pg72x->private = g72x_reader_init (codec, &(pg72x->blocksize), &(pg72x->samplesperblock)) ;
125 if (pg72x->private == NULL)
126 return SFE_MALLOC_FAILED ;
127
128 pg72x->bytesperblock = bytesperblock ;
129
130 psf->read_short = g72x_read_s ;
131 psf->read_int = g72x_read_i ;
132 psf->read_float = g72x_read_f ;
133 psf->read_double = g72x_read_d ;
134
135 psf->seek = g72x_seek ;
136
137 if (psf->datalength % pg72x->blocksize)
138 { psf_log_printf (psf, "*** Odd psf->datalength (%D) should be a multiple of %d\n", psf->datalength, pg72x->blocksize) ;
139 pg72x->blocks_total = (psf->datalength / pg72x->blocksize) + 1 ;
140 }
141 else
142 pg72x->blocks_total = psf->datalength / pg72x->blocksize ;
143
144 psf->sf.frames = pg72x->blocks_total * pg72x->samplesperblock ;
145
146 psf_g72x_decode_block (psf, pg72x) ;
147 }
148 else if (psf->file.mode == SFM_WRITE)
149 { pg72x->private = g72x_writer_init (codec, &(pg72x->blocksize), &(pg72x->samplesperblock)) ;
150 if (pg72x->private == NULL)
151 return SFE_MALLOC_FAILED ;
152
153 pg72x->bytesperblock = bytesperblock ;
154
155 psf->write_short = g72x_write_s ;
156 psf->write_int = g72x_write_i ;
157 psf->write_float = g72x_write_f ;
158 psf->write_double = g72x_write_d ;
159
160 if (psf->datalength % pg72x->blocksize)
161 pg72x->blocks_total = (psf->datalength / pg72x->blocksize) + 1 ;
162 else
163 pg72x->blocks_total = psf->datalength / pg72x->blocksize ;
164
165 if (psf->datalength > 0)
166 psf->sf.frames = (8 * psf->datalength) / bitspersample ;
167
168 if ((psf->sf.frames * bitspersample) / 8 != psf->datalength)
169 psf_log_printf (psf, "*** Warning : weird psf->datalength.\n") ;
170 } ;
171
172 psf->codec_close = g72x_close ;
173
174 return 0 ;
175 } /* g72x_init */
176
177 /*============================================================================================
178 ** G721 Read Functions.
179 */
180
181 static int
psf_g72x_decode_block(SF_PRIVATE * psf,G72x_PRIVATE * pg72x)182 psf_g72x_decode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x)
183 { int k ;
184
185 pg72x->block_curr ++ ;
186 pg72x->sample_curr = 0 ;
187
188 if (pg72x->block_curr > pg72x->blocks_total)
189 { memset (pg72x->samples, 0, G72x_BLOCK_SIZE * sizeof (short)) ;
190 return 1 ;
191 } ;
192
193 if ((k = psf_fread (pg72x->block, 1, pg72x->bytesperblock, psf)) != pg72x->bytesperblock)
194 psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pg72x->bytesperblock) ;
195
196 pg72x->blocksize = k ;
197 g72x_decode_block (pg72x->private, pg72x->block, pg72x->samples) ;
198
199 return 1 ;
200 } /* psf_g72x_decode_block */
201
202 static int
g72x_read_block(SF_PRIVATE * psf,G72x_PRIVATE * pg72x,short * ptr,int len)203 g72x_read_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x, short *ptr, int len)
204 { int count, total = 0, indx = 0 ;
205
206 while (indx < len)
207 { if (pg72x->block_curr > pg72x->blocks_total)
208 { memset (&(ptr [indx]), 0, (len - indx) * sizeof (short)) ;
209 return total ;
210 } ;
211
212 if (pg72x->sample_curr >= pg72x->samplesperblock)
213 psf_g72x_decode_block (psf, pg72x) ;
214
215 count = pg72x->samplesperblock - pg72x->sample_curr ;
216 count = (len - indx > count) ? count : len - indx ;
217
218 memcpy (&(ptr [indx]), &(pg72x->samples [pg72x->sample_curr]), count * sizeof (short)) ;
219 indx += count ;
220 pg72x->sample_curr += count ;
221 total = indx ;
222 } ;
223
224 return total ;
225 } /* g72x_read_block */
226
227 static sf_count_t
g72x_read_s(SF_PRIVATE * psf,short * ptr,sf_count_t len)228 g72x_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
229 { G72x_PRIVATE *pg72x ;
230 int readcount, count ;
231 sf_count_t total = 0 ;
232
233 if (psf->codec_data == NULL)
234 return 0 ;
235 pg72x = (G72x_PRIVATE*) psf->codec_data ;
236
237 while (len > 0)
238 { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
239
240 count = g72x_read_block (psf, pg72x, ptr, readcount) ;
241
242 total += count ;
243 len -= count ;
244
245 if (count != readcount)
246 break ;
247 } ;
248
249 return total ;
250 } /* g72x_read_s */
251
252 static sf_count_t
g72x_read_i(SF_PRIVATE * psf,int * ptr,sf_count_t len)253 g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
254 { BUF_UNION ubuf ;
255 G72x_PRIVATE *pg72x ;
256 short *sptr ;
257 int k, bufferlen, readcount = 0, count ;
258 sf_count_t total = 0 ;
259
260 if (psf->codec_data == NULL)
261 return 0 ;
262 pg72x = (G72x_PRIVATE*) psf->codec_data ;
263
264 sptr = ubuf.sbuf ;
265 bufferlen = SF_BUFFER_LEN / sizeof (short) ;
266 while (len > 0)
267 { readcount = (len >= bufferlen) ? bufferlen : len ;
268 count = g72x_read_block (psf, pg72x, sptr, readcount) ;
269
270 for (k = 0 ; k < readcount ; k++)
271 ptr [total + k] = arith_shift_left (sptr [k], 16) ;
272
273 total += count ;
274 len -= readcount ;
275 if (count != readcount)
276 break ;
277 } ;
278
279 return total ;
280 } /* g72x_read_i */
281
282 static sf_count_t
g72x_read_f(SF_PRIVATE * psf,float * ptr,sf_count_t len)283 g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
284 { BUF_UNION ubuf ;
285 G72x_PRIVATE *pg72x ;
286 short *sptr ;
287 int k, bufferlen, readcount = 0, count ;
288 sf_count_t total = 0 ;
289 float normfact ;
290
291 if (psf->codec_data == NULL)
292 return 0 ;
293 pg72x = (G72x_PRIVATE*) psf->codec_data ;
294
295 normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
296
297 sptr = ubuf.sbuf ;
298 bufferlen = SF_BUFFER_LEN / sizeof (short) ;
299 while (len > 0)
300 { readcount = (len >= bufferlen) ? bufferlen : len ;
301 count = g72x_read_block (psf, pg72x, sptr, readcount) ;
302 for (k = 0 ; k < readcount ; k++)
303 ptr [total + k] = normfact * sptr [k] ;
304
305 total += count ;
306 len -= readcount ;
307 if (count != readcount)
308 break ;
309 } ;
310
311 return total ;
312 } /* g72x_read_f */
313
314 static sf_count_t
g72x_read_d(SF_PRIVATE * psf,double * ptr,sf_count_t len)315 g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
316 { BUF_UNION ubuf ;
317 G72x_PRIVATE *pg72x ;
318 short *sptr ;
319 int k, bufferlen, readcount = 0, count ;
320 sf_count_t total = 0 ;
321 double normfact ;
322
323 if (psf->codec_data == NULL)
324 return 0 ;
325 pg72x = (G72x_PRIVATE*) psf->codec_data ;
326
327 normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
328
329 sptr = ubuf.sbuf ;
330 bufferlen = SF_BUFFER_LEN / sizeof (short) ;
331 while (len > 0)
332 { readcount = (len >= bufferlen) ? bufferlen : len ;
333 count = g72x_read_block (psf, pg72x, sptr, readcount) ;
334 for (k = 0 ; k < readcount ; k++)
335 ptr [total + k] = normfact * (double) (sptr [k]) ;
336
337 total += count ;
338 len -= readcount ;
339 if (count != readcount)
340 break ;
341 } ;
342
343 return total ;
344 } /* g72x_read_d */
345
346 static sf_count_t
g72x_seek(SF_PRIVATE * psf,int UNUSED (mode),sf_count_t UNUSED (offset))347 g72x_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t UNUSED (offset))
348 {
349 psf_log_printf (psf, "seek unsupported\n") ;
350
351 /* No simple solution. To do properly, would need to seek
352 ** to start of file and decode everything up to seek position.
353 ** Maybe implement SEEK_SET to 0 only?
354 */
355 return 0 ;
356
357 /*
358 ** G72x_PRIVATE *pg72x ;
359 ** int newblock, newsample, sample_curr ;
360 **
361 ** if (psf->codec_data == NULL)
362 ** return 0 ;
363 ** pg72x = (G72x_PRIVATE*) psf->codec_data ;
364 **
365 ** if (! (psf->datalength && psf->dataoffset))
366 ** { psf->error = SFE_BAD_SEEK ;
367 ** return PSF_SEEK_ERROR ;
368 ** } ;
369 **
370 ** sample_curr = (8 * psf->datalength) / G721_32_BITS_PER_SAMPLE ;
371 **
372 ** switch (whence)
373 ** { case SEEK_SET :
374 ** if (offset < 0 || offset > sample_curr)
375 ** { psf->error = SFE_BAD_SEEK ;
376 ** return PSF_SEEK_ERROR ;
377 ** } ;
378 ** newblock = offset / pg72x->samplesperblock ;
379 ** newsample = offset % pg72x->samplesperblock ;
380 ** break ;
381 **
382 ** case SEEK_CUR :
383 ** if (psf->current + offset < 0 || psf->current + offset > sample_curr)
384 ** { psf->error = SFE_BAD_SEEK ;
385 ** return PSF_SEEK_ERROR ;
386 ** } ;
387 ** newblock = (8 * (psf->current + offset)) / pg72x->samplesperblock ;
388 ** newsample = (8 * (psf->current + offset)) % pg72x->samplesperblock ;
389 ** break ;
390 **
391 ** case SEEK_END :
392 ** if (offset > 0 || sample_curr + offset < 0)
393 ** { psf->error = SFE_BAD_SEEK ;
394 ** return PSF_SEEK_ERROR ;
395 ** } ;
396 ** newblock = (sample_curr + offset) / pg72x->samplesperblock ;
397 ** newsample = (sample_curr + offset) % pg72x->samplesperblock ;
398 ** break ;
399 **
400 ** default :
401 ** psf->error = SFE_BAD_SEEK ;
402 ** return PSF_SEEK_ERROR ;
403 ** } ;
404 **
405 ** if (psf->file.mode == SFM_READ)
406 ** { psf_fseek (psf, psf->dataoffset + newblock * pg72x->blocksize, SEEK_SET) ;
407 ** pg72x->block_curr = newblock ;
408 ** psf_g72x_decode_block (psf, pg72x) ;
409 ** pg72x->sample_curr = newsample ;
410 ** }
411 ** else
412 ** { /+* What to do about write??? *+/
413 ** psf->error = SFE_BAD_SEEK ;
414 ** return PSF_SEEK_ERROR ;
415 ** } ;
416 **
417 ** psf->current = newblock * pg72x->samplesperblock + newsample ;
418 ** return psf->current ;
419 **
420 */
421 } /* g72x_seek */
422
423 /*==========================================================================================
424 ** G72x Write Functions.
425 */
426
427 static int
psf_g72x_encode_block(SF_PRIVATE * psf,G72x_PRIVATE * pg72x)428 psf_g72x_encode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x)
429 { int k ;
430
431 /* Encode the samples. */
432 g72x_encode_block (pg72x->private, pg72x->samples, pg72x->block) ;
433
434 /* Write the block to disk. */
435 if ((k = psf_fwrite (pg72x->block, 1, pg72x->blocksize, psf)) != pg72x->blocksize)
436 psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pg72x->blocksize) ;
437
438 pg72x->sample_curr = 0 ;
439 pg72x->block_curr ++ ;
440
441 /* Set samples to zero for next block. */
442 memset (pg72x->samples, 0, G72x_BLOCK_SIZE * sizeof (short)) ;
443
444 return 1 ;
445 } /* psf_g72x_encode_block */
446
447 static int
g72x_write_block(SF_PRIVATE * psf,G72x_PRIVATE * pg72x,const short * ptr,int len)448 g72x_write_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x, const short *ptr, int len)
449 { int count, total = 0, indx = 0 ;
450
451 while (indx < len)
452 { count = pg72x->samplesperblock - pg72x->sample_curr ;
453
454 if (count > len - indx)
455 count = len - indx ;
456
457 memcpy (&(pg72x->samples [pg72x->sample_curr]), &(ptr [indx]), count * sizeof (short)) ;
458 indx += count ;
459 pg72x->sample_curr += count ;
460 total = indx ;
461
462 if (pg72x->sample_curr >= pg72x->samplesperblock)
463 psf_g72x_encode_block (psf, pg72x) ;
464 } ;
465
466 return total ;
467 } /* g72x_write_block */
468
469 static sf_count_t
g72x_write_s(SF_PRIVATE * psf,const short * ptr,sf_count_t len)470 g72x_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
471 { G72x_PRIVATE *pg72x ;
472 int writecount, count ;
473 sf_count_t total = 0 ;
474
475 if (psf->codec_data == NULL)
476 return 0 ;
477 pg72x = (G72x_PRIVATE*) psf->codec_data ;
478
479 while (len > 0)
480 { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
481
482 count = g72x_write_block (psf, pg72x, ptr, writecount) ;
483
484 total += count ;
485 len -= count ;
486 if (count != writecount)
487 break ;
488 } ;
489
490 return total ;
491 } /* g72x_write_s */
492
493 static sf_count_t
g72x_write_i(SF_PRIVATE * psf,const int * ptr,sf_count_t len)494 g72x_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
495 { BUF_UNION ubuf ;
496 G72x_PRIVATE *pg72x ;
497 short *sptr ;
498 int k, bufferlen, writecount = 0, count ;
499 sf_count_t total = 0 ;
500
501 if (psf->codec_data == NULL)
502 return 0 ;
503 pg72x = (G72x_PRIVATE*) psf->codec_data ;
504
505 sptr = ubuf.sbuf ;
506 bufferlen = SF_BUFFER_LEN / sizeof (short) ;
507 while (len > 0)
508 { writecount = (len >= bufferlen) ? bufferlen : len ;
509 for (k = 0 ; k < writecount ; k++)
510 sptr [k] = ptr [total + k] >> 16 ;
511 count = g72x_write_block (psf, pg72x, sptr, writecount) ;
512
513 total += count ;
514 len -= writecount ;
515 if (count != writecount)
516 break ;
517 } ;
518 return total ;
519 } /* g72x_write_i */
520
521 static sf_count_t
g72x_write_f(SF_PRIVATE * psf,const float * ptr,sf_count_t len)522 g72x_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
523 { BUF_UNION ubuf ;
524 G72x_PRIVATE *pg72x ;
525 short *sptr ;
526 int k, bufferlen, writecount = 0, count ;
527 sf_count_t total = 0 ;
528 float normfact ;
529
530 if (psf->codec_data == NULL)
531 return 0 ;
532 pg72x = (G72x_PRIVATE*) psf->codec_data ;
533
534 normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ;
535
536 sptr = ubuf.sbuf ;
537 bufferlen = SF_BUFFER_LEN / sizeof (short) ;
538 while (len > 0)
539 { writecount = (len >= bufferlen) ? bufferlen : len ;
540 for (k = 0 ; k < writecount ; k++)
541 sptr [k] = psf_lrintf (normfact * ptr [total + k]) ;
542 count = g72x_write_block (psf, pg72x, sptr, writecount) ;
543
544 total += count ;
545 len -= writecount ;
546 if (count != writecount)
547 break ;
548 } ;
549
550 return total ;
551 } /* g72x_write_f */
552
553 static sf_count_t
g72x_write_d(SF_PRIVATE * psf,const double * ptr,sf_count_t len)554 g72x_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
555 { BUF_UNION ubuf ;
556 G72x_PRIVATE *pg72x ;
557 short *sptr ;
558 int k, bufferlen, writecount = 0, count ;
559 sf_count_t total = 0 ;
560 double normfact ;
561
562 if (psf->codec_data == NULL)
563 return 0 ;
564 pg72x = (G72x_PRIVATE*) psf->codec_data ;
565
566 normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ;
567
568 sptr = ubuf.sbuf ;
569 bufferlen = SF_BUFFER_LEN / sizeof (short) ;
570 while (len > 0)
571 { writecount = (len >= bufferlen) ? bufferlen : len ;
572 for (k = 0 ; k < writecount ; k++)
573 sptr [k] = psf_lrint (normfact * ptr [total + k]) ;
574 count = g72x_write_block (psf, pg72x, sptr, writecount) ;
575
576 total += count ;
577 len -= writecount ;
578 if (count != writecount)
579 break ;
580 } ;
581
582 return total ;
583 } /* g72x_write_d */
584
585 static int
g72x_close(SF_PRIVATE * psf)586 g72x_close (SF_PRIVATE *psf)
587 { G72x_PRIVATE *pg72x ;
588
589 pg72x = (G72x_PRIVATE*) psf->codec_data ;
590
591 if (psf->file.mode == SFM_WRITE)
592 { /* If a block has been partially assembled, write it out
593 ** as the final block.
594 */
595
596 if (pg72x->sample_curr && pg72x->sample_curr < G72x_BLOCK_SIZE)
597 psf_g72x_encode_block (psf, pg72x) ;
598
599 if (psf->write_header)
600 psf->write_header (psf, SF_FALSE) ;
601 } ;
602
603 /* Only free the pointer allocated by g72x_(reader|writer)_init. */
604 free (pg72x->private) ;
605
606 return 0 ;
607 } /* g72x_close */
608
609