b16594ec81eb38057003d820590ecfe8af685467
[Faustine.git] / interpretor / libsndfile-1.0.25 / src / gsm610.c
1 /*
2 ** Copyright (C) 1999-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 #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 "wav_w64.h"
30 #include "GSM610/gsm.h"
31
32 #define GSM610_BLOCKSIZE 33
33 #define GSM610_SAMPLES 160
34
35 typedef struct gsm610_tag
36 { int blocks ;
37 int blockcount, samplecount ;
38 int samplesperblock, blocksize ;
39
40 int (*decode_block) (SF_PRIVATE *psf, struct gsm610_tag *pgsm610) ;
41 int (*encode_block) (SF_PRIVATE *psf, struct gsm610_tag *pgsm610) ;
42
43 short samples [WAV_W64_GSM610_SAMPLES] ;
44 unsigned char block [WAV_W64_GSM610_BLOCKSIZE] ;
45
46 /* Damn I hate typedef-ed pointers; yes, gsm is a pointer type. */
47 gsm gsm_data ;
48 } GSM610_PRIVATE ;
49
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) ;
54
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) ;
59
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) ;
62
63 static int gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ;
64 static int gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ;
65
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) ;
68
69 static sf_count_t gsm610_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
70
71 static int gsm610_close (SF_PRIVATE *psf) ;
72
73 /*============================================================================================
74 ** WAV GSM610 initialisation function.
75 */
76
77 int
78 gsm610_init (SF_PRIVATE *psf)
79 { GSM610_PRIVATE *pgsm610 ;
80 int true_flag = 1 ;
81
82 if (psf->codec_data != NULL)
83 { psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ;
84 return SFE_INTERNAL ;
85 } ;
86
87 if (psf->file.mode == SFM_RDWR)
88 return SFE_BAD_MODE_RW ;
89
90 psf->sf.seekable = SF_FALSE ;
91
92 if ((pgsm610 = calloc (1, sizeof (GSM610_PRIVATE))) == NULL)
93 return SFE_MALLOC_FAILED ;
94
95 psf->codec_data = pgsm610 ;
96
97 memset (pgsm610, 0, sizeof (GSM610_PRIVATE)) ;
98
99 /*============================================================
100
101 Need separate gsm_data structs for encode and decode.
102
103 ============================================================*/
104
105 if ((pgsm610->gsm_data = gsm_create ()) == NULL)
106 return SFE_MALLOC_FAILED ;
107
108 switch (SF_CONTAINER (psf->sf.format))
109 { case SF_FORMAT_WAV :
110 case SF_FORMAT_WAVEX :
111 case SF_FORMAT_W64 :
112 gsm_option (pgsm610->gsm_data, GSM_OPT_WAV49, &true_flag) ;
113
114 pgsm610->encode_block = gsm610_wav_encode_block ;
115 pgsm610->decode_block = gsm610_wav_decode_block ;
116
117 pgsm610->samplesperblock = WAV_W64_GSM610_SAMPLES ;
118 pgsm610->blocksize = WAV_W64_GSM610_BLOCKSIZE ;
119 break ;
120
121 case SF_FORMAT_AIFF :
122 case SF_FORMAT_RAW :
123 pgsm610->encode_block = gsm610_encode_block ;
124 pgsm610->decode_block = gsm610_decode_block ;
125
126 pgsm610->samplesperblock = GSM610_SAMPLES ;
127 pgsm610->blocksize = GSM610_BLOCKSIZE ;
128 break ;
129
130 default :
131 return SFE_INTERNAL ;
132 break ;
133 } ;
134
135 if (psf->file.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)
139 { /*
140 ** Weird AIFF specific case.
141 ** AIFF chunks must be at an even 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.
145 */
146 pgsm610->blocks = psf->datalength / pgsm610->blocksize ;
147 }
148 else
149 { psf_log_printf (psf, "*** Warning : data chunk seems to be truncated.\n") ;
150 pgsm610->blocks = psf->datalength / pgsm610->blocksize + 1 ;
151 } ;
152
153 psf->sf.frames = pgsm610->samplesperblock * pgsm610->blocks ;
154
155 psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
156
157 pgsm610->decode_block (psf, pgsm610) ; /* Read first block. */
158
159 psf->read_short = gsm610_read_s ;
160 psf->read_int = gsm610_read_i ;
161 psf->read_float = gsm610_read_f ;
162 psf->read_double = gsm610_read_d ;
163 } ;
164
165 if (psf->file.mode == SFM_WRITE)
166 { pgsm610->blockcount = 0 ;
167 pgsm610->samplecount = 0 ;
168
169 psf->write_short = gsm610_write_s ;
170 psf->write_int = gsm610_write_i ;
171 psf->write_float = gsm610_write_f ;
172 psf->write_double = gsm610_write_d ;
173 } ;
174
175 psf->codec_close = gsm610_close ;
176
177 psf->seek = gsm610_seek ;
178
179 psf->filelength = psf_get_filelen (psf) ;
180 psf->datalength = psf->filelength - psf->dataoffset ;
181
182 return 0 ;
183 } /* gsm610_init */
184
185 /*============================================================================================
186 ** GSM 6.10 Read Functions.
187 */
188
189 static int
190 gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
191 { int k ;
192
193 pgsm610->blockcount ++ ;
194 pgsm610->samplecount = 0 ;
195
196 if (pgsm610->blockcount > pgsm610->blocks)
197 { memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
198 return 1 ;
199 } ;
200
201 if ((k = psf_fread (pgsm610->block, 1, WAV_W64_GSM610_BLOCKSIZE, psf)) != WAV_W64_GSM610_BLOCKSIZE)
202 psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, WAV_W64_GSM610_BLOCKSIZE) ;
203
204 if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0)
205 { psf_log_printf (psf, "Error from WAV gsm_decode() on frame : %d\n", pgsm610->blockcount) ;
206 return 0 ;
207 } ;
208
209 if (gsm_decode (pgsm610->gsm_data, pgsm610->block + (WAV_W64_GSM610_BLOCKSIZE + 1) / 2, pgsm610->samples + WAV_W64_GSM610_SAMPLES / 2) < 0)
210 { psf_log_printf (psf, "Error from WAV gsm_decode() on frame : %d.5\n", pgsm610->blockcount) ;
211 return 0 ;
212 } ;
213
214 return 1 ;
215 } /* gsm610_wav_decode_block */
216
217 static int
218 gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
219 { int k ;
220
221 pgsm610->blockcount ++ ;
222 pgsm610->samplecount = 0 ;
223
224 if (pgsm610->blockcount > pgsm610->blocks)
225 { memset (pgsm610->samples, 0, GSM610_SAMPLES * sizeof (short)) ;
226 return 1 ;
227 } ;
228
229 if ((k = psf_fread (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE)
230 psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, GSM610_BLOCKSIZE) ;
231
232 if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0)
233 { psf_log_printf (psf, "Error from standard gsm_decode() on frame : %d\n", pgsm610->blockcount) ;
234 return 0 ;
235 } ;
236
237 return 1 ;
238 } /* gsm610_decode_block */
239
240 static int
241 gsm610_read_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len)
242 { int count, total = 0, indx = 0 ;
243
244 while (indx < len)
245 { if (pgsm610->blockcount >= pgsm610->blocks && pgsm610->samplecount >= pgsm610->samplesperblock)
246 { memset (&(ptr [indx]), 0, (len - indx) * sizeof (short)) ;
247 return total ;
248 } ;
249
250 if (pgsm610->samplecount >= pgsm610->samplesperblock)
251 pgsm610->decode_block (psf, pgsm610) ;
252
253 count = pgsm610->samplesperblock - pgsm610->samplecount ;
254 count = (len - indx > count) ? count : len - indx ;
255
256 memcpy (&(ptr [indx]), &(pgsm610->samples [pgsm610->samplecount]), count * sizeof (short)) ;
257 indx += count ;
258 pgsm610->samplecount += count ;
259 total = indx ;
260 } ;
261
262 return total ;
263 } /* gsm610_read_block */
264
265 static sf_count_t
266 gsm610_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
267 { GSM610_PRIVATE *pgsm610 ;
268 int readcount, count ;
269 sf_count_t total = 0 ;
270
271 if (psf->codec_data == NULL)
272 return 0 ;
273 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
274
275 while (len > 0)
276 { readcount = (len > 0x10000000) ? 0x1000000 : (int) len ;
277
278 count = gsm610_read_block (psf, pgsm610, ptr, readcount) ;
279
280 total += count ;
281 len -= count ;
282
283 if (count != readcount)
284 break ;
285 } ;
286
287 return total ;
288 } /* gsm610_read_s */
289
290 static sf_count_t
291 gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
292 { GSM610_PRIVATE *pgsm610 ;
293 short *sptr ;
294 int k, bufferlen, readcount = 0, count ;
295 sf_count_t total = 0 ;
296
297 if (psf->codec_data == NULL)
298 return 0 ;
299 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
300
301 sptr = psf->u.sbuf ;
302 bufferlen = ARRAY_LEN (psf->u.sbuf) ;
303 while (len > 0)
304 { readcount = (len >= bufferlen) ? bufferlen : len ;
305 count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
306 for (k = 0 ; k < readcount ; k++)
307 ptr [total + k] = sptr [k] << 16 ;
308
309 total += count ;
310 len -= readcount ;
311 } ;
312 return total ;
313 } /* gsm610_read_i */
314
315 static sf_count_t
316 gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
317 { GSM610_PRIVATE *pgsm610 ;
318 short *sptr ;
319 int k, bufferlen, readcount = 0, count ;
320 sf_count_t total = 0 ;
321 float normfact ;
322
323 if (psf->codec_data == NULL)
324 return 0 ;
325 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
326
327 normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
328
329 sptr = psf->u.sbuf ;
330 bufferlen = ARRAY_LEN (psf->u.sbuf) ;
331 while (len > 0)
332 { readcount = (len >= bufferlen) ? bufferlen : len ;
333 count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
334 for (k = 0 ; k < readcount ; k++)
335 ptr [total + k] = normfact * sptr [k] ;
336
337 total += count ;
338 len -= readcount ;
339 } ;
340 return total ;
341 } /* gsm610_read_f */
342
343 static sf_count_t
344 gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
345 { GSM610_PRIVATE *pgsm610 ;
346 short *sptr ;
347 int k, bufferlen, readcount = 0, count ;
348 sf_count_t total = 0 ;
349 double normfact ;
350
351 normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
352
353 if (psf->codec_data == NULL)
354 return 0 ;
355 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
356
357 sptr = psf->u.sbuf ;
358 bufferlen = ARRAY_LEN (psf->u.sbuf) ;
359 while (len > 0)
360 { readcount = (len >= bufferlen) ? bufferlen : len ;
361 count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
362 for (k = 0 ; k < readcount ; k++)
363 ptr [total + k] = normfact * sptr [k] ;
364
365 total += count ;
366 len -= readcount ;
367 } ;
368 return total ;
369 } /* gsm610_read_d */
370
371 static sf_count_t
372 gsm610_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset)
373 { GSM610_PRIVATE *pgsm610 ;
374 int newblock, newsample ;
375
376 if (psf->codec_data == NULL)
377 return 0 ;
378 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
379
380 if (psf->dataoffset < 0)
381 { psf->error = SFE_BAD_SEEK ;
382 return PSF_SEEK_ERROR ;
383 } ;
384
385 if (offset == 0)
386 { int true_flag = 1 ;
387
388 psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
389 pgsm610->blockcount = 0 ;
390
391 gsm_init (pgsm610->gsm_data) ;
392 if ((SF_CONTAINER (psf->sf.format)) == SF_FORMAT_WAV ||
393 (SF_CONTAINER (psf->sf.format)) == SF_FORMAT_W64)
394 gsm_option (pgsm610->gsm_data, GSM_OPT_WAV49, &true_flag) ;
395
396 pgsm610->decode_block (psf, pgsm610) ;
397 pgsm610->samplecount = 0 ;
398 return 0 ;
399 } ;
400
401 if (offset < 0 || offset > pgsm610->blocks * pgsm610->samplesperblock)
402 { psf->error = SFE_BAD_SEEK ;
403 return PSF_SEEK_ERROR ;
404 } ;
405
406 newblock = offset / pgsm610->samplesperblock ;
407 newsample = offset % pgsm610->samplesperblock ;
408
409 if (psf->file.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 ;
415 } ;
416
417 return newblock * pgsm610->samplesperblock + newsample ;
418 } ;
419
420 /* What to do about write??? */
421 psf->error = SFE_BAD_SEEK ;
422 return PSF_SEEK_ERROR ;
423 } /* gsm610_seek */
424
425 /*==========================================================================================
426 ** GSM 6.10 Write Functions.
427 */
428
429 static int
430 gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
431 { int k ;
432
433 /* Encode the samples. */
434 gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ;
435
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) ;
439
440 pgsm610->samplecount = 0 ;
441 pgsm610->blockcount ++ ;
442
443 /* Set samples to zero for next block. */
444 memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
445
446 return 1 ;
447 } /* gsm610_encode_block */
448
449 static int
450 gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
451 { int k ;
452
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) ;
456
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) ;
460
461 pgsm610->samplecount = 0 ;
462 pgsm610->blockcount ++ ;
463
464 /* Set samples to zero for next block. */
465 memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
466
467 return 1 ;
468 } /* gsm610_wav_encode_block */
469
470 static int
471 gsm610_write_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, const short *ptr, int len)
472 { int count, total = 0, indx = 0 ;
473
474 while (indx < len)
475 { count = pgsm610->samplesperblock - pgsm610->samplecount ;
476
477 if (count > len - indx)
478 count = len - indx ;
479
480 memcpy (&(pgsm610->samples [pgsm610->samplecount]), &(ptr [indx]), count * sizeof (short)) ;
481 indx += count ;
482 pgsm610->samplecount += count ;
483 total = indx ;
484
485 if (pgsm610->samplecount >= pgsm610->samplesperblock)
486 pgsm610->encode_block (psf, pgsm610) ;
487 } ;
488
489 return total ;
490 } /* gsm610_write_block */
491
492 static sf_count_t
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 ;
497
498 if (psf->codec_data == NULL)
499 return 0 ;
500 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
501
502 while (len > 0)
503 { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
504
505 count = gsm610_write_block (psf, pgsm610, ptr, writecount) ;
506
507 total += count ;
508 len -= count ;
509
510 if (count != writecount)
511 break ;
512 } ;
513
514 return total ;
515 } /* gsm610_write_s */
516
517 static sf_count_t
518 gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
519 { GSM610_PRIVATE *pgsm610 ;
520 short *sptr ;
521 int k, bufferlen, writecount = 0, count ;
522 sf_count_t total = 0 ;
523
524 if (psf->codec_data == NULL)
525 return 0 ;
526 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
527
528 sptr = psf->u.sbuf ;
529 bufferlen = ARRAY_LEN (psf->u.sbuf) ;
530 while (len > 0)
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) ;
535
536 total += count ;
537 len -= writecount ;
538 } ;
539 return total ;
540 } /* gsm610_write_i */
541
542 static sf_count_t
543 gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
544 { GSM610_PRIVATE *pgsm610 ;
545 short *sptr ;
546 int k, bufferlen, writecount = 0, count ;
547 sf_count_t total = 0 ;
548 float normfact ;
549
550 if (psf->codec_data == NULL)
551 return 0 ;
552 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
553
554 normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
555
556 sptr = psf->u.sbuf ;
557 bufferlen = ARRAY_LEN (psf->u.sbuf) ;
558 while (len > 0)
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) ;
563
564 total += count ;
565 len -= writecount ;
566 } ;
567 return total ;
568 } /* gsm610_write_f */
569
570 static sf_count_t
571 gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
572 { GSM610_PRIVATE *pgsm610 ;
573 short *sptr ;
574 int k, bufferlen, writecount = 0, count ;
575 sf_count_t total = 0 ;
576 double normfact ;
577
578 if (psf->codec_data == NULL)
579 return 0 ;
580 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
581
582 normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
583
584 sptr = psf->u.sbuf ;
585 bufferlen = ARRAY_LEN (psf->u.sbuf) ;
586 while (len > 0)
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) ;
591
592 total += count ;
593 len -= writecount ;
594 } ;
595 return total ;
596 } /* gsm610_write_d */
597
598 static int
599 gsm610_close (SF_PRIVATE *psf)
600 { GSM610_PRIVATE *pgsm610 ;
601
602 if (psf->codec_data == NULL)
603 return 0 ;
604
605 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
606
607 if (psf->file.mode == SFM_WRITE)
608 { /* If a block has been partially assembled, write it out
609 ** as the final block.
610 */
611
612 if (pgsm610->samplecount && pgsm610->samplecount < pgsm610->samplesperblock)
613 pgsm610->encode_block (psf, pgsm610) ;
614 } ;
615
616 if (pgsm610->gsm_data)
617 gsm_destroy (pgsm610->gsm_data) ;
618
619 return 0 ;
620 } /* gsm610_close */
621