1/* 2** Copyright (C) 1999-2020 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 30typedef struct IMA_ADPCM_PRIVATE_tag 31{ int (*decode_block) (SF_PRIVATE *psf, struct IMA_ADPCM_PRIVATE_tag *pima) ; 32 int (*encode_block) (SF_PRIVATE *psf, struct IMA_ADPCM_PRIVATE_tag *pima) ; 33 34 int channels, blocksize, samplesperblock, blocks ; 35 int blockcount, samplecount ; 36 int previous [2] ; 37 int stepindx [2] ; 38 unsigned char *block ; 39 short *samples ; 40 short data [] ; /* ISO C99 struct flexible array. */ 41} IMA_ADPCM_PRIVATE ; 42 43/*============================================================================================ 44** Predefined IMA ADPCM data. 45*/ 46 47static int ima_indx_adjust [16] = 48{ -1, -1, -1, -1, /* +0 - +3, decrease the step size */ 49 +2, +4, +6, +8, /* +4 - +7, increase the step size */ 50 -1, -1, -1, -1, /* -0 - -3, decrease the step size */ 51 +2, +4, +6, +8, /* -4 - -7, increase the step size */ 52} ; 53 54static int ima_step_size [89] = 55{ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 56 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 57 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 58 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 59 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, 60 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 61 32767 62} ; 63 64static int ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ; 65static int ima_writer_init (SF_PRIVATE *psf, int blockalign) ; 66 67static int ima_read_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, short *ptr, int len) ; 68static int ima_write_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, const short *ptr, int len) ; 69 70static sf_count_t ima_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; 71static sf_count_t ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; 72static sf_count_t ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; 73static sf_count_t ima_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; 74 75static sf_count_t ima_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; 76static sf_count_t ima_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; 77static sf_count_t ima_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; 78static sf_count_t ima_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; 79 80static sf_count_t aiff_ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; 81static sf_count_t wavlike_ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; 82 83static int ima_close (SF_PRIVATE *psf) ; 84 85static int wavlike_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ; 86static int wavlike_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ; 87 88/*-static int aiff_ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;-*/ 89static int aiff_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ; 90static int aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ; 91 92 93static inline int 94clamp_ima_step_index (int indx) 95{ if (indx < 0) 96 return 0 ; 97 if (indx >= ARRAY_LEN (ima_step_size)) 98 return ARRAY_LEN (ima_step_size) - 1 ; 99 100 return indx ; 101} /* clamp_ima_step_index */ 102 103/*============================================================================================ 104** IMA ADPCM Reader initialisation function. 105*/ 106 107int 108wavlike_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) 109{ int error ; 110 111 if (psf->codec_data != NULL) 112 { psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ; 113 return SFE_INTERNAL ; 114 } ; 115 116 if (psf->file.mode == SFM_RDWR) 117 return SFE_BAD_MODE_RW ; 118 119 if (psf->file.mode == SFM_READ) 120 if ((error = ima_reader_init (psf, blockalign, samplesperblock))) 121 return error ; 122 123 if (psf->file.mode == SFM_WRITE) 124 if ((error = ima_writer_init (psf, blockalign))) 125 return error ; 126 127 psf->codec_close = ima_close ; 128 psf->seek = wavlike_ima_seek ; 129 130 return 0 ; 131} /* wavlike_ima_init */ 132 133int 134aiff_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) 135{ int error ; 136 137 if (psf->file.mode == SFM_RDWR) 138 return SFE_BAD_MODE_RW ; 139 140 if (psf->file.mode == SFM_READ) 141 if ((error = ima_reader_init (psf, blockalign, samplesperblock))) 142 return error ; 143 144 if (psf->file.mode == SFM_WRITE) 145 if ((error = ima_writer_init (psf, blockalign))) 146 return error ; 147 148 psf->codec_close = ima_close ; 149 psf->seek = aiff_ima_seek ; 150 151 return 0 ; 152} /* aiff_ima_init */ 153 154static int 155ima_close (SF_PRIVATE *psf) 156{ IMA_ADPCM_PRIVATE *pima ; 157 158 pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; 159 160 if (psf->file.mode == SFM_WRITE) 161 { /* If a block has been partially assembled, write it out 162 ** as the final block. 163 */ 164 if (pima->samplecount && pima->samplecount < pima->samplesperblock) 165 pima->encode_block (psf, pima) ; 166 167 psf->sf.frames = pima->samplesperblock * pima->blockcount / psf->sf.channels ; 168 } ; 169 170 return 0 ; 171} /* ima_close */ 172 173/*============================================================================================ 174** IMA ADPCM Read Functions. 175*/ 176 177static int 178ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) 179{ IMA_ADPCM_PRIVATE *pima ; 180 int pimasize, count ; 181 182 if (psf->file.mode != SFM_READ) 183 return SFE_BAD_MODE_RW ; 184 185 /* 186 ** Allocate enough space for 1 more than a multiple of 8 samples 187 ** to avoid having to branch when pulling apart the nibbles. 188 */ 189 count = ((samplesperblock - 2) | 7) + 2 ; 190 pimasize = sizeof (IMA_ADPCM_PRIVATE) + psf->sf.channels * (blockalign + samplesperblock + sizeof(short) * count) ; 191 192 if (! (pima = calloc (1, pimasize))) 193 return SFE_MALLOC_FAILED ; 194 195 psf->codec_data = (void*) pima ; 196 197 pima->samples = pima->data ; 198 pima->block = (unsigned char*) (pima->data + samplesperblock * psf->sf.channels) ; 199 200 pima->channels = psf->sf.channels ; 201 pima->blocksize = blockalign ; 202 pima->samplesperblock = samplesperblock ; 203 204 psf->filelength = psf_get_filelen (psf) ; 205 psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset : 206 psf->filelength - psf->dataoffset ; 207 208 if (pima->blocksize <= 0) 209 { psf_log_printf (psf, "*** Error : pima->blocksize should be > 0.\n") ; 210 return SFE_INTERNAL ; 211 } ; 212 213 if (pima->samplesperblock <= 0) 214 { psf_log_printf (psf, "*** Error : pima->samplesperblock should be > 0.\n") ; 215 return SFE_INTERNAL ; 216 } ; 217 218 if (psf->datalength % pima->blocksize) 219 pima->blocks = psf->datalength / pima->blocksize + 1 ; 220 else 221 pima->blocks = psf->datalength / pima->blocksize ; 222 223 switch (SF_CONTAINER (psf->sf.format)) 224 { case SF_FORMAT_WAV : 225 case SF_FORMAT_W64 : 226 count = 2 * (pima->blocksize - 4 * pima->channels) / pima->channels + 1 ; 227 228 if (pima->samplesperblock != count) 229 { psf_log_printf (psf, "*** Error : samplesperblock should be %d.\n", count) ; 230 return SFE_INTERNAL ; 231 } ; 232 233 pima->decode_block = wavlike_ima_decode_block ; 234 235 psf->sf.frames = pima->samplesperblock * pima->blocks ; 236 break ; 237 238 case SF_FORMAT_AIFF : 239 psf_log_printf (psf, "still need to check block count\n") ; 240 pima->decode_block = aiff_ima_decode_block ; 241 psf->sf.frames = pima->samplesperblock * pima->blocks / pima->channels ; 242 break ; 243 244 default : 245 psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ; 246 return SFE_INTERNAL ; 247 } ; 248 249 pima->decode_block (psf, pima) ; /* Read first block. */ 250 251 psf->read_short = ima_read_s ; 252 psf->read_int = ima_read_i ; 253 psf->read_float = ima_read_f ; 254 psf->read_double = ima_read_d ; 255 256 return 0 ; 257} /* ima_reader_init */ 258 259static int 260aiff_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) 261{ unsigned char *blockdata ; 262 int chan, k, diff, bytecode, predictor ; 263 short step, stepindx, *sampledata ; 264 265static int count = 0 ; 266count ++ ; 267 268 pima->blockcount += pima->channels ; 269 pima->samplecount = 0 ; 270 271 if (pima->blockcount > pima->blocks) 272 { memset (pima->samples, 0, pima->samplesperblock * pima->channels * sizeof (short)) ; 273 return 1 ; 274 } ; 275 276 if ((k = (int) psf_fread (pima->block, 1, pima->blocksize * pima->channels, psf)) != pima->blocksize * pima->channels) 277 psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ; 278 279 /* Read and check the block header. */ 280 for (chan = 0 ; chan < pima->channels ; chan++) 281 { blockdata = pima->block + chan * 34 ; 282 sampledata = pima->samples + chan ; 283 284 /* Sign-extend from 16 bits to 32. */ 285 predictor = (int) ((short) ((blockdata [0] << 8) | (blockdata [1] & 0x80))) ; 286 287 stepindx = blockdata [1] & 0x7F ; 288 stepindx = clamp_ima_step_index (stepindx) ; 289 290 /* 291 ** Pull apart the packed 4 bit samples and store them in their 292 ** correct sample positions. 293 */ 294 for (k = 0 ; k < pima->blocksize - 2 ; k++) 295 { bytecode = blockdata [k + 2] ; 296 sampledata [pima->channels * (2 * k + 0)] = bytecode & 0xF ; 297 sampledata [pima->channels * (2 * k + 1)] = (bytecode >> 4) & 0xF ; 298 } ; 299 300 /* Decode the encoded 4 bit samples. */ 301 for (k = 0 ; k < pima->samplesperblock ; k ++) 302 { step = ima_step_size [stepindx] ; 303 304 bytecode = pima->samples [pima->channels * k + chan] ; 305 306 stepindx += ima_indx_adjust [bytecode] ; 307 stepindx = clamp_ima_step_index (stepindx) ; 308 309 diff = step >> 3 ; 310 if (bytecode & 1) diff += step >> 2 ; 311 if (bytecode & 2) diff += step >> 1 ; 312 if (bytecode & 4) diff += step ; 313 if (bytecode & 8) diff = -diff ; 314 315 predictor += diff ; 316 if (predictor < -32768) 317 predictor = -32768 ; 318 else if (predictor > 32767) 319 predictor = 32767 ; 320 321 pima->samples [pima->channels * k + chan] = predictor ; 322 } ; 323 } ; 324 325 return 1 ; 326} /* aiff_ima_decode_block */ 327 328static int 329aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) 330{ int chan, k, step, diff, vpdiff, blockindx, indx ; 331 short bytecode, mask ; 332 333 k = 0 ; 334 for (chan = 0 ; chan < pima->channels ; chan ++) 335 { blockindx = chan * pima->blocksize ; 336 /* Encode the block header. */ 337 pima->block [blockindx++] = (pima->previous [chan] >> 8) & 0xFF ; 338 pima->block [blockindx++] = (pima->previous [chan] & 0x80) + (pima->stepindx [chan] & 0x7F) ; 339 340 /* Encode the samples as 4 bit. */ 341 for (indx = chan ; indx < pima->samplesperblock * pima->channels ; indx += pima->channels) 342 { diff = pima->samples [indx] - pima->previous [chan] ; 343 344 bytecode = 0 ; 345 step = ima_step_size [pima->stepindx [chan]] ; 346 vpdiff = step >> 3 ; 347 if (diff < 0) 348 { bytecode = 8 ; 349 diff = -diff ; 350 } ; 351 mask = 4 ; 352 while (mask) 353 { if (diff >= step) 354 { bytecode |= mask ; 355 diff -= step ; 356 vpdiff += step ; 357 } ; 358 step >>= 1 ; 359 mask >>= 1 ; 360 } ; 361 362 if (bytecode & 8) 363 vpdiff = -vpdiff ; 364 pima->previous [chan] += vpdiff ; 365 366 if (pima->previous [chan] > 32767) 367 pima->previous [chan] = 32767 ; 368 else if (pima->previous [chan] < -32768) 369 pima->previous [chan] = -32768 ; 370 371 pima->stepindx [chan] += ima_indx_adjust [bytecode] ; 372 373 pima->stepindx [chan] = clamp_ima_step_index (pima->stepindx [chan]) ; 374 pima->block [blockindx] = (bytecode << (4 * k)) | pima->block [blockindx] ; 375 blockindx += k ; 376 k = 1 - k ; 377 } ; 378 } ; 379 380 /* Write the block to disk. */ 381 if ((k = (int) psf_fwrite (pima->block, 1, pima->channels * pima->blocksize, psf)) != pima->channels * pima->blocksize) 382 psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->channels * pima->blocksize) ; 383 384 memset (pima->block, 0, pima->channels * pima->blocksize) ; 385 pima->samplecount = 0 ; 386 pima->blockcount ++ ; 387 388 return 1 ; 389} /* aiff_ima_encode_block */ 390 391static int 392wavlike_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) 393{ int chan, k, predictor, blockindx, indx, indxstart, diff ; 394 short step, bytecode, stepindx [2] = { 0 }; 395 396 pima->blockcount ++ ; 397 pima->samplecount = 0 ; 398 399 if (pima->blockcount > pima->blocks) 400 { memset (pima->samples, 0, pima->samplesperblock * pima->channels * sizeof (short)) ; 401 return 1 ; 402 } ; 403 404 if ((k = (int) psf_fread (pima->block, 1, pima->blocksize, psf)) != pima->blocksize) 405 psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ; 406 407 /* Read and check the block header. */ 408 409 for (chan = 0 ; chan < pima->channels ; chan++) 410 { predictor = pima->block [chan*4] | (pima->block [chan*4+1] << 8) ; 411 if (predictor & 0x8000) 412 predictor -= 0x10000 ; 413 414 stepindx [chan] = pima->block [chan*4+2] ; 415 stepindx [chan] = clamp_ima_step_index (stepindx [chan]) ; 416 417 418 if (pima->block [chan*4+3] != 0) 419 psf_log_printf (psf, "IMA ADPCM synchronisation error.\n") ; 420 421 pima->samples [chan] = predictor ; 422 } ; 423 424 /* 425 ** Pull apart the packed 4 bit samples and store them in their 426 ** correct sample positions. 427 */ 428 429 blockindx = 4 * pima->channels ; 430 431 indxstart = pima->channels ; 432 while (blockindx < pima->blocksize) 433 { for (chan = 0 ; chan < pima->channels ; chan++) 434 { indx = indxstart + chan ; 435 for (k = 0 ; k < 4 ; k++) 436 { bytecode = pima->block [blockindx++] ; 437 pima->samples [indx] = bytecode & 0x0F ; 438 indx += pima->channels ; 439 pima->samples [indx] = (bytecode >> 4) & 0x0F ; 440 indx += pima->channels ; 441 } ; 442 } ; 443 indxstart += 8 * pima->channels ; 444 } ; 445 446 /* Decode the encoded 4 bit samples. */ 447 448 for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++) 449 { chan = (pima->channels > 1) ? (k % 2) : 0 ; 450 451 bytecode = pima->samples [k] & 0xF ; 452 453 step = ima_step_size [stepindx [chan]] ; 454 predictor = pima->samples [k - pima->channels] ; 455 456 diff = step >> 3 ; 457 if (bytecode & 1) 458 diff += step >> 2 ; 459 if (bytecode & 2) 460 diff += step >> 1 ; 461 if (bytecode & 4) 462 diff += step ; 463 if (bytecode & 8) 464 diff = -diff ; 465 466 predictor += diff ; 467 468 if (predictor > 32767) 469 predictor = 32767 ; 470 else if (predictor < -32768) 471 predictor = -32768 ; 472 473 stepindx [chan] += ima_indx_adjust [bytecode] ; 474 stepindx [chan] = clamp_ima_step_index (stepindx [chan]) ; 475 476 pima->samples [k] = predictor ; 477 } ; 478 479 return 1 ; 480} /* wavlike_ima_decode_block */ 481 482static int 483wavlike_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) 484{ int chan, k, step, diff, vpdiff, blockindx, indx, indxstart ; 485 short bytecode, mask ; 486 487 /* Encode the block header. */ 488 for (chan = 0 ; chan < pima->channels ; chan++) 489 { pima->block [chan*4] = pima->samples [chan] & 0xFF ; 490 pima->block [chan*4+1] = (pima->samples [chan] >> 8) & 0xFF ; 491 492 pima->block [chan*4+2] = pima->stepindx [chan] ; 493 pima->block [chan*4+3] = 0 ; 494 495 pima->previous [chan] = pima->samples [chan] ; 496 } ; 497 498 /* Encode the samples as 4 bit. */ 499 500 for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++) 501 { chan = (pima->channels > 1) ? (k % 2) : 0 ; 502 503 diff = pima->samples [k] - pima->previous [chan] ; 504 505 bytecode = 0 ; 506 step = ima_step_size [pima->stepindx [chan]] ; 507 vpdiff = step >> 3 ; 508 if (diff < 0) 509 { bytecode = 8 ; 510 diff = -diff ; 511 } ; 512 mask = 4 ; 513 while (mask) 514 { if (diff >= step) 515 { bytecode |= mask ; 516 diff -= step ; 517 vpdiff += step ; 518 } ; 519 step >>= 1 ; 520 mask >>= 1 ; 521 } ; 522 523 if (bytecode & 8) 524 pima->previous [chan] -= vpdiff ; 525 else 526 pima->previous [chan] += vpdiff ; 527 528 if (pima->previous [chan] > 32767) 529 pima->previous [chan] = 32767 ; 530 else if (pima->previous [chan] < -32768) 531 pima->previous [chan] = -32768 ; 532 533 pima->stepindx [chan] += ima_indx_adjust [bytecode] ; 534 pima->stepindx [chan] = clamp_ima_step_index (pima->stepindx [chan]) ; 535 536 pima->samples [k] = bytecode ; 537 } ; 538 539 /* Pack the 4 bit encoded samples. */ 540 541 blockindx = 4 * pima->channels ; 542 543 indxstart = pima->channels ; 544 while (blockindx < pima->blocksize) 545 { for (chan = 0 ; chan < pima->channels ; chan++) 546 { indx = indxstart + chan ; 547 for (k = 0 ; k < 4 ; k++) 548 { pima->block [blockindx] = pima->samples [indx] & 0x0F ; 549 indx += pima->channels ; 550 pima->block [blockindx] |= (pima->samples [indx] << 4) & 0xF0 ; 551 indx += pima->channels ; 552 blockindx ++ ; 553 } ; 554 } ; 555 indxstart += 8 * pima->channels ; 556 } ; 557 558 /* Write the block to disk. */ 559 560 if ((k = (int) psf_fwrite (pima->block, 1, pima->blocksize, psf)) != pima->blocksize) 561 psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->blocksize) ; 562 563 memset (pima->samples, 0, pima->samplesperblock * sizeof (short)) ; 564 pima->samplecount = 0 ; 565 pima->blockcount ++ ; 566 567 return 1 ; 568} /* wavlike_ima_encode_block */ 569 570static int 571ima_read_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, short *ptr, int len) 572{ int count, total = 0, indx = 0 ; 573 574 while (indx < len) 575 { if (pima->blockcount >= pima->blocks && pima->samplecount >= pima->samplesperblock) 576 { memset (&(ptr [indx]), 0, (size_t) ((len - indx) * sizeof (short))) ; 577 return total ; 578 } ; 579 580 if (pima->samplecount >= pima->samplesperblock) 581 pima->decode_block (psf, pima) ; 582 583 count = (pima->samplesperblock - pima->samplecount) * pima->channels ; 584 count = (len - indx > count) ? count : len - indx ; 585 586 memcpy (&(ptr [indx]), &(pima->samples [pima->samplecount * pima->channels]), count * sizeof (short)) ; 587 indx += count ; 588 pima->samplecount += count / pima->channels ; 589 total = indx ; 590 } ; 591 592 return total ; 593} /* ima_read_block */ 594 595static sf_count_t 596ima_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) 597{ IMA_ADPCM_PRIVATE *pima ; 598 int readcount, count ; 599 sf_count_t total = 0 ; 600 601 if (! psf->codec_data) 602 return 0 ; 603 pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; 604 605 while (len > 0) 606 { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; 607 608 count = ima_read_block (psf, pima, ptr, readcount) ; 609 610 total += count ; 611 len -= count ; 612 if (count != readcount) 613 break ; 614 } ; 615 616 return total ; 617} /* ima_read_s */ 618 619static sf_count_t 620ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) 621{ IMA_ADPCM_PRIVATE *pima ; 622 BUF_UNION ubuf ; 623 short *sptr ; 624 int k, bufferlen, readcount, count ; 625 sf_count_t total = 0 ; 626 627 if (! psf->codec_data) 628 return 0 ; 629 pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; 630 631 sptr = ubuf.sbuf ; 632 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 633 while (len > 0) 634 { readcount = (len >= bufferlen) ? bufferlen : (int) len ; 635 count = ima_read_block (psf, pima, sptr, readcount) ; 636 for (k = 0 ; k < readcount ; k++) 637 ptr [total + k] = arith_shift_left (sptr [k], 16) ; 638 total += count ; 639 len -= readcount ; 640 if (count != readcount) 641 break ; 642 } ; 643 644 return total ; 645} /* ima_read_i */ 646 647static sf_count_t 648ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) 649{ IMA_ADPCM_PRIVATE *pima ; 650 BUF_UNION ubuf ; 651 short *sptr ; 652 int k, bufferlen, readcount, count ; 653 sf_count_t total = 0 ; 654 float normfact ; 655 656 if (! psf->codec_data) 657 return 0 ; 658 pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; 659 660 normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; 661 662 sptr = ubuf.sbuf ; 663 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 664 while (len > 0) 665 { readcount = (len >= bufferlen) ? bufferlen : (int) len ; 666 count = ima_read_block (psf, pima, sptr, readcount) ; 667 for (k = 0 ; k < readcount ; k++) 668 ptr [total + k] = normfact * (float) (sptr [k]) ; 669 total += count ; 670 len -= readcount ; 671 if (count != readcount) 672 break ; 673 } ; 674 675 return total ; 676} /* ima_read_f */ 677 678static sf_count_t 679ima_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) 680{ IMA_ADPCM_PRIVATE *pima ; 681 BUF_UNION ubuf ; 682 short *sptr ; 683 int k, bufferlen, readcount, count ; 684 sf_count_t total = 0 ; 685 double normfact ; 686 687 if (! psf->codec_data) 688 return 0 ; 689 pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; 690 691 normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; 692 693 sptr = ubuf.sbuf ; 694 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 695 while (len > 0) 696 { readcount = (len >= bufferlen) ? bufferlen : (int) len ; 697 count = ima_read_block (psf, pima, sptr, readcount) ; 698 for (k = 0 ; k < readcount ; k++) 699 ptr [total + k] = normfact * (double) (sptr [k]) ; 700 total += count ; 701 len -= readcount ; 702 if (count != readcount) 703 break ; 704 } ; 705 706 return total ; 707} /* ima_read_d */ 708 709static sf_count_t 710aiff_ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) 711{ IMA_ADPCM_PRIVATE *pima ; 712 int newblock, newsample, newblockaiff ; 713 714 if (! psf->codec_data) 715 return 0 ; 716 pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; 717 718 if (psf->datalength < 0 || psf->dataoffset < 0) 719 { psf->error = SFE_BAD_SEEK ; 720 return PSF_SEEK_ERROR ; 721 } ; 722 723 if (offset == 0) 724 { psf_fseek (psf, psf->dataoffset, SEEK_SET) ; 725 pima->blockcount = 0 ; 726 pima->decode_block (psf, pima) ; 727 pima->samplecount = 0 ; 728 return 0 ; 729 } ; 730 731 if (offset < 0 || offset > pima->blocks * pima->samplesperblock) 732 { psf->error = SFE_BAD_SEEK ; 733 return PSF_SEEK_ERROR ; 734 } ; 735 736 newblock = offset / pima->samplesperblock ; 737 newsample = offset % pima->samplesperblock ; 738 newblockaiff = newblock * psf->sf.channels ; 739 740 if (mode == SFM_READ) 741 { psf_fseek (psf, psf->dataoffset + newblockaiff * pima->blocksize, SEEK_SET) ; 742 pima->blockcount = newblockaiff ; 743 pima->decode_block (psf, pima) ; 744 pima->samplecount = newsample ; 745 } 746 else 747 { /* What to do about write??? */ 748 psf->error = SFE_BAD_SEEK ; 749 return PSF_SEEK_ERROR ; 750 } ; 751 752 return newblock * pima->samplesperblock + newsample ; 753} /* aiff_ima_seek */ 754 755static sf_count_t 756wavlike_ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) 757{ IMA_ADPCM_PRIVATE *pima ; 758 int newblock, newsample ; 759 760 if (! psf->codec_data) 761 return 0 ; 762 pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; 763 764 if (psf->datalength < 0 || psf->dataoffset < 0) 765 { psf->error = SFE_BAD_SEEK ; 766 return PSF_SEEK_ERROR ; 767 } ; 768 769 if (offset == 0) 770 { psf_fseek (psf, psf->dataoffset, SEEK_SET) ; 771 pima->blockcount = 0 ; 772 if (!pima->decode_block) 773 return PSF_SEEK_ERROR ; 774 775 pima->decode_block (psf, pima) ; 776 pima->samplecount = 0 ; 777 return 0 ; 778 } ; 779 780 if (offset < 0 || offset > pima->blocks * pima->samplesperblock) 781 { psf->error = SFE_BAD_SEEK ; 782 return PSF_SEEK_ERROR ; 783 } ; 784 785 newblock = offset / pima->samplesperblock ; 786 newsample = offset % pima->samplesperblock ; 787 788 if (mode == SFM_READ) 789 { psf_fseek (psf, psf->dataoffset + newblock * pima->blocksize, SEEK_SET) ; 790 pima->blockcount = newblock ; 791 pima->decode_block (psf, pima) ; 792 pima->samplecount = newsample ; 793 } 794 else 795 { /* What to do about write??? */ 796 psf->error = SFE_BAD_SEEK ; 797 return PSF_SEEK_ERROR ; 798 } ; 799 800 return newblock * pima->samplesperblock + newsample ; 801} /* wavlike_ima_seek */ 802 803/*========================================================================================== 804** IMA ADPCM Write Functions. 805*/ 806 807static int 808ima_writer_init (SF_PRIVATE *psf, int blockalign) 809{ IMA_ADPCM_PRIVATE *pima ; 810 int samplesperblock ; 811 unsigned int pimasize ; 812 813 if (psf->file.mode != SFM_WRITE) 814 return SFE_BAD_MODE_RW ; 815 816 switch (SF_CONTAINER (psf->sf.format)) 817 { case SF_FORMAT_WAV : 818 case SF_FORMAT_W64 : 819 samplesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ; 820 break ; 821 822 case SF_FORMAT_AIFF : 823 samplesperblock = 2 * ((blockalign - 2) * psf->sf.channels) / psf->sf.channels ; 824 break ; 825 826 default : 827 psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ; 828 return SFE_INTERNAL ; 829 } ; 830 831 pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign + 3 * psf->sf.channels * samplesperblock ; 832 833 if ((pima = calloc (1, pimasize)) == NULL) 834 return SFE_MALLOC_FAILED ; 835 836 psf->codec_data = (void*) pima ; 837 838 pima->channels = psf->sf.channels ; 839 pima->blocksize = blockalign ; 840 pima->samplesperblock = samplesperblock ; 841 842 pima->block = (unsigned char*) pima->data ; 843 pima->samples = (short*) (pima->data + blockalign) ; 844 845 pima->samplecount = 0 ; 846 847 switch (SF_CONTAINER (psf->sf.format)) 848 { case SF_FORMAT_WAV : 849 case SF_FORMAT_W64 : 850 pima->encode_block = wavlike_ima_encode_block ; 851 break ; 852 853 case SF_FORMAT_AIFF : 854 pima->encode_block = aiff_ima_encode_block ; 855 break ; 856 857 default : 858 psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ; 859 return SFE_INTERNAL ; 860 } ; 861 862 psf->write_short = ima_write_s ; 863 psf->write_int = ima_write_i ; 864 psf->write_float = ima_write_f ; 865 psf->write_double = ima_write_d ; 866 867 return 0 ; 868} /* ima_writer_init */ 869 870/*========================================================================================== 871*/ 872 873static int 874ima_write_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, const short *ptr, int len) 875{ int count, total = 0, indx = 0 ; 876 877 while (indx < len) 878 { count = (pima->samplesperblock - pima->samplecount) * pima->channels ; 879 880 if (count > len - indx) 881 count = len - indx ; 882 883 memcpy (&(pima->samples [pima->samplecount * pima->channels]), &(ptr [total]), count * sizeof (short)) ; 884 indx += count ; 885 pima->samplecount += count / pima->channels ; 886 total = indx ; 887 888 if (pima->samplecount >= pima->samplesperblock) 889 pima->encode_block (psf, pima) ; 890 } ; 891 892 return total ; 893} /* ima_write_block */ 894 895static sf_count_t 896ima_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) 897{ IMA_ADPCM_PRIVATE *pima ; 898 int writecount, count ; 899 sf_count_t total = 0 ; 900 901 if (! psf->codec_data) 902 return 0 ; 903 pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; 904 905 while (len) 906 { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; 907 908 count = ima_write_block (psf, pima, ptr, writecount) ; 909 910 total += count ; 911 len -= count ; 912 if (count != writecount) 913 break ; 914 } ; 915 916 return total ; 917} /* ima_write_s */ 918 919static sf_count_t 920ima_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) 921{ IMA_ADPCM_PRIVATE *pima ; 922 BUF_UNION ubuf ; 923 short *sptr ; 924 int k, bufferlen, writecount, count ; 925 sf_count_t total = 0 ; 926 927 if (! psf->codec_data) 928 return 0 ; 929 pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; 930 931 sptr = ubuf.sbuf ; 932 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 933 while (len > 0) 934 { writecount = (len >= bufferlen) ? bufferlen : (int) len ; 935 for (k = 0 ; k < writecount ; k++) 936 sptr [k] = ptr [total + k] >> 16 ; 937 count = ima_write_block (psf, pima, sptr, writecount) ; 938 total += count ; 939 len -= writecount ; 940 if (count != writecount) 941 break ; 942 } ; 943 944 return total ; 945} /* ima_write_i */ 946 947static sf_count_t 948ima_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) 949{ IMA_ADPCM_PRIVATE *pima ; 950 BUF_UNION ubuf ; 951 short *sptr ; 952 int k, bufferlen, writecount, count ; 953 sf_count_t total = 0 ; 954 float normfact ; 955 956 if (! psf->codec_data) 957 return 0 ; 958 pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; 959 960 normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; 961 962 sptr = ubuf.sbuf ; 963 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 964 while (len > 0) 965 { writecount = (len >= bufferlen) ? bufferlen : (int) len ; 966 for (k = 0 ; k < writecount ; k++) 967 sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; 968 count = ima_write_block (psf, pima, sptr, writecount) ; 969 total += count ; 970 len -= writecount ; 971 if (count != writecount) 972 break ; 973 } ; 974 975 return total ; 976} /* ima_write_f */ 977 978static sf_count_t 979ima_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) 980{ IMA_ADPCM_PRIVATE *pima ; 981 BUF_UNION ubuf ; 982 short *sptr ; 983 int k, bufferlen, writecount, count ; 984 sf_count_t total = 0 ; 985 double normfact ; 986 987 if (! psf->codec_data) 988 return 0 ; 989 pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ; 990 991 normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; 992 993 sptr = ubuf.sbuf ; 994 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 995 while (len > 0) 996 { writecount = (len >= bufferlen) ? bufferlen : (int) len ; 997 for (k = 0 ; k < writecount ; k++) 998 sptr [k] = psf_lrint (normfact * ptr [total + k]) ; 999 count = ima_write_block (psf, pima, sptr, writecount) ; 1000 total += count ; 1001 len -= writecount ; 1002 if (count != writecount) 1003 break ; 1004 } ; 1005 1006 return total ; 1007} /* ima_write_d */ 1008 1009