1/* 2** Copyright (C) 1999-2019 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 "wavlike.h" 30#include "GSM610/gsm.h" 31 32#define GSM610_BLOCKSIZE 33 33#define GSM610_SAMPLES 160 34 35typedef 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 [WAVLIKE_GSM610_SAMPLES] ; 44 unsigned char block [WAVLIKE_GSM610_BLOCKSIZE] ; 45 46 /* Damn I hate typedef-ed pointers; yes, gsm is a pointer type. */ 47 gsm gsm_data ; 48} GSM610_PRIVATE ; 49 50static sf_count_t gsm610_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; 51static sf_count_t gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; 52static sf_count_t gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; 53static sf_count_t gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; 54 55static sf_count_t gsm610_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; 56static sf_count_t gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; 57static sf_count_t gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; 58static sf_count_t gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; 59 60static int gsm610_read_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len) ; 61static int gsm610_write_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, const short *ptr, int len) ; 62 63static int gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ; 64static int gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ; 65 66static int gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ; 67static int gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ; 68 69static sf_count_t gsm610_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; 70 71static int gsm610_close (SF_PRIVATE *psf) ; 72 73/*============================================================================================ 74** WAV GSM610 initialisation function. 75*/ 76 77int 78gsm610_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 101Need 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 = WAVLIKE_GSM610_SAMPLES ; 118 pgsm610->blocksize = WAVLIKE_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 = (sf_count_t) 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 189static int 190gsm610_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, sizeof (pgsm610->samples)) ; 198 return 1 ; 199 } ; 200 201 if ((k = (int) psf_fread (pgsm610->block, 1, WAVLIKE_GSM610_BLOCKSIZE, psf)) != WAVLIKE_GSM610_BLOCKSIZE) 202 psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, WAVLIKE_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 + (WAVLIKE_GSM610_BLOCKSIZE + 1) / 2, pgsm610->samples + WAVLIKE_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 217static int 218gsm610_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, sizeof (pgsm610->samples)) ; 226 return 1 ; 227 } ; 228 229 if ((k = (int) 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 240static int 241gsm610_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 265static sf_count_t 266gsm610_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 290static sf_count_t 291gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) 292{ GSM610_PRIVATE *pgsm610 ; 293 BUF_UNION ubuf ; 294 short *sptr ; 295 int k, bufferlen, readcount = 0, count ; 296 sf_count_t total = 0 ; 297 298 if (psf->codec_data == NULL) 299 return 0 ; 300 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; 301 302 sptr = ubuf.sbuf ; 303 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 304 while (len > 0) 305 { readcount = (len >= bufferlen) ? bufferlen : (int) len ; 306 count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; 307 for (k = 0 ; k < readcount ; k++) 308 ptr [total + k] = arith_shift_left (sptr [k], 16) ; 309 310 total += count ; 311 len -= readcount ; 312 } ; 313 return total ; 314} /* gsm610_read_i */ 315 316static sf_count_t 317gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) 318{ GSM610_PRIVATE *pgsm610 ; 319 BUF_UNION ubuf ; 320 short *sptr ; 321 int k, bufferlen, readcount = 0, count ; 322 sf_count_t total = 0 ; 323 float normfact ; 324 325 if (psf->codec_data == NULL) 326 return 0 ; 327 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; 328 329 normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; 330 331 sptr = ubuf.sbuf ; 332 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 333 while (len > 0) 334 { readcount = (len >= bufferlen) ? bufferlen : (int) len ; 335 count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; 336 for (k = 0 ; k < readcount ; k++) 337 ptr [total + k] = normfact * sptr [k] ; 338 339 total += count ; 340 len -= readcount ; 341 } ; 342 return total ; 343} /* gsm610_read_f */ 344 345static sf_count_t 346gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) 347{ GSM610_PRIVATE *pgsm610 ; 348 BUF_UNION ubuf ; 349 short *sptr ; 350 int k, bufferlen, readcount = 0, count ; 351 sf_count_t total = 0 ; 352 double normfact ; 353 354 normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; 355 356 if (psf->codec_data == NULL) 357 return 0 ; 358 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; 359 360 sptr = ubuf.sbuf ; 361 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 362 while (len > 0) 363 { readcount = (len >= bufferlen) ? bufferlen : (int) len ; 364 count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; 365 for (k = 0 ; k < readcount ; k++) 366 ptr [total + k] = normfact * sptr [k] ; 367 368 total += count ; 369 len -= readcount ; 370 } ; 371 return total ; 372} /* gsm610_read_d */ 373 374static sf_count_t 375gsm610_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset) 376{ GSM610_PRIVATE *pgsm610 ; 377 int newblock, newsample ; 378 379 if (psf->codec_data == NULL) 380 return 0 ; 381 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; 382 383 if (psf->dataoffset < 0) 384 { psf->error = SFE_BAD_SEEK ; 385 return PSF_SEEK_ERROR ; 386 } ; 387 388 if (offset == 0) 389 { int true_flag = 1 ; 390 391 psf_fseek (psf, psf->dataoffset, SEEK_SET) ; 392 pgsm610->blockcount = 0 ; 393 394 gsm_init (pgsm610->gsm_data) ; 395 if ((SF_CONTAINER (psf->sf.format)) == SF_FORMAT_WAV || 396 (SF_CONTAINER (psf->sf.format)) == SF_FORMAT_W64) 397 gsm_option (pgsm610->gsm_data, GSM_OPT_WAV49, &true_flag) ; 398 399 pgsm610->decode_block (psf, pgsm610) ; 400 pgsm610->samplecount = 0 ; 401 return 0 ; 402 } ; 403 404 if (offset < 0 || offset > pgsm610->blocks * pgsm610->samplesperblock) 405 { psf->error = SFE_BAD_SEEK ; 406 return PSF_SEEK_ERROR ; 407 } ; 408 409 newblock = offset / pgsm610->samplesperblock ; 410 newsample = offset % pgsm610->samplesperblock ; 411 412 if (psf->file.mode == SFM_READ) 413 { if (psf->read_current != newblock * pgsm610->samplesperblock + newsample) 414 { psf_fseek (psf, psf->dataoffset + newblock * pgsm610->samplesperblock, SEEK_SET) ; 415 pgsm610->blockcount = newblock ; 416 pgsm610->decode_block (psf, pgsm610) ; 417 pgsm610->samplecount = newsample ; 418 } ; 419 420 return newblock * pgsm610->samplesperblock + newsample ; 421 } ; 422 423 /* What to do about write??? */ 424 psf->error = SFE_BAD_SEEK ; 425 return PSF_SEEK_ERROR ; 426} /* gsm610_seek */ 427 428/*========================================================================================== 429** GSM 6.10 Write Functions. 430*/ 431 432static int 433gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) 434{ int k ; 435 436 /* Encode the samples. */ 437 gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ; 438 439 /* Write the block to disk. */ 440 if ((k = (int) psf_fwrite (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE) 441 psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, GSM610_BLOCKSIZE) ; 442 443 pgsm610->samplecount = 0 ; 444 pgsm610->blockcount ++ ; 445 446 /* Set samples to zero for next block. */ 447 memset (pgsm610->samples, 0, sizeof (pgsm610->samples)) ; 448 449 return 1 ; 450} /* gsm610_encode_block */ 451 452static int 453gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) 454{ int k ; 455 456 /* Encode the samples. */ 457 gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ; 458 gsm_encode (pgsm610->gsm_data, pgsm610->samples+WAVLIKE_GSM610_SAMPLES / 2, pgsm610->block+WAVLIKE_GSM610_BLOCKSIZE / 2) ; 459 460 /* Write the block to disk. */ 461 if ((k = (int) psf_fwrite (pgsm610->block, 1, WAVLIKE_GSM610_BLOCKSIZE, psf)) != WAVLIKE_GSM610_BLOCKSIZE) 462 psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, WAVLIKE_GSM610_BLOCKSIZE) ; 463 464 pgsm610->samplecount = 0 ; 465 pgsm610->blockcount ++ ; 466 467 /* Set samples to zero for next block. */ 468 memset (pgsm610->samples, 0, sizeof (pgsm610->samples)) ; 469 470 return 1 ; 471} /* gsm610_wav_encode_block */ 472 473static int 474gsm610_write_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, const short *ptr, int len) 475{ int count, total = 0, indx = 0 ; 476 477 while (indx < len) 478 { count = pgsm610->samplesperblock - pgsm610->samplecount ; 479 480 if (count > len - indx) 481 count = len - indx ; 482 483 memcpy (&(pgsm610->samples [pgsm610->samplecount]), &(ptr [indx]), count * sizeof (short)) ; 484 indx += count ; 485 pgsm610->samplecount += count ; 486 total = indx ; 487 488 if (pgsm610->samplecount >= pgsm610->samplesperblock) 489 pgsm610->encode_block (psf, pgsm610) ; 490 } ; 491 492 return total ; 493} /* gsm610_write_block */ 494 495static sf_count_t 496gsm610_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) 497{ GSM610_PRIVATE *pgsm610 ; 498 int writecount, count ; 499 sf_count_t total = 0 ; 500 501 if (psf->codec_data == NULL) 502 return 0 ; 503 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; 504 505 while (len > 0) 506 { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; 507 508 count = gsm610_write_block (psf, pgsm610, ptr, writecount) ; 509 510 total += count ; 511 len -= count ; 512 513 if (count != writecount) 514 break ; 515 } ; 516 517 return total ; 518} /* gsm610_write_s */ 519 520static sf_count_t 521gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) 522{ GSM610_PRIVATE *pgsm610 ; 523 BUF_UNION ubuf ; 524 short *sptr ; 525 int k, bufferlen, writecount = 0, count ; 526 sf_count_t total = 0 ; 527 528 if (psf->codec_data == NULL) 529 return 0 ; 530 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; 531 532 sptr = ubuf.sbuf ; 533 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 534 while (len > 0) 535 { writecount = (len >= bufferlen) ? bufferlen : (int) len ; 536 for (k = 0 ; k < writecount ; k++) 537 sptr [k] = ptr [total + k] >> 16 ; 538 count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; 539 540 total += count ; 541 len -= writecount ; 542 } ; 543 return total ; 544} /* gsm610_write_i */ 545 546static sf_count_t 547gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) 548{ GSM610_PRIVATE *pgsm610 ; 549 BUF_UNION ubuf ; 550 short *sptr ; 551 int k, bufferlen, writecount = 0, count ; 552 sf_count_t total = 0 ; 553 float normfact ; 554 555 if (psf->codec_data == NULL) 556 return 0 ; 557 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; 558 559 normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; 560 561 sptr = ubuf.sbuf ; 562 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 563 while (len > 0) 564 { writecount = (len >= bufferlen) ? bufferlen : (int) len ; 565 for (k = 0 ; k < writecount ; k++) 566 sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; 567 count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; 568 569 total += count ; 570 len -= writecount ; 571 if (count != writecount) 572 break ; 573 } ; 574 return total ; 575} /* gsm610_write_f */ 576 577static sf_count_t 578gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) 579{ GSM610_PRIVATE *pgsm610 ; 580 BUF_UNION ubuf ; 581 short *sptr ; 582 int k, bufferlen, writecount = 0, count ; 583 sf_count_t total = 0 ; 584 double normfact ; 585 586 if (psf->codec_data == NULL) 587 return 0 ; 588 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; 589 590 normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; 591 592 sptr = ubuf.sbuf ; 593 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 594 while (len > 0) 595 { writecount = (len >= bufferlen) ? bufferlen : (int) len ; 596 for (k = 0 ; k < writecount ; k++) 597 sptr [k] = psf_lrint (normfact * ptr [total + k]) ; 598 count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; 599 600 total += count ; 601 len -= writecount ; 602 } ; 603 return total ; 604} /* gsm610_write_d */ 605 606static int 607gsm610_close (SF_PRIVATE *psf) 608{ GSM610_PRIVATE *pgsm610 ; 609 610 if (psf->codec_data == NULL) 611 return 0 ; 612 613 pgsm610 = (GSM610_PRIVATE*) psf->codec_data ; 614 615 if (psf->file.mode == SFM_WRITE) 616 { /* If a block has been partially assembled, write it out 617 ** as the final block. 618 */ 619 620 if (pgsm610->samplecount && pgsm610->samplecount < pgsm610->samplesperblock) 621 pgsm610->encode_block (psf, pgsm610) ; 622 } ; 623 624 if (pgsm610->gsm_data) 625 gsm_destroy (pgsm610->gsm_data) ; 626 627 return 0 ; 628} /* gsm610_close */ 629 630