1/* 2** Copyright (C) 2002-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/* 20** This is the OKI / Dialogic ADPCM encoder/decoder. It converts from 21** 12 bit linear sample data to a 4 bit ADPCM. 22*/ 23 24/* 25 * Note: some early Dialogic hardware does not always reset the ADPCM encoder 26 * at the start of each vox file. This can result in clipping and/or DC offset 27 * problems when it comes to decoding the audio. Whilst little can be done 28 * about the clipping, a DC offset can be removed by passing the decoded audio 29 * through a high-pass filter at e.g. 10Hz. 30 */ 31 32#include "sfconfig.h" 33 34#include <stdio.h> 35#include <stdlib.h> 36#include <string.h> 37#include <math.h> 38 39#include "sndfile.h" 40#include "sfendian.h" 41#include "common.h" 42#include "ima_oki_adpcm.h" 43 44 45static sf_count_t vox_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; 46static sf_count_t vox_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; 47static sf_count_t vox_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; 48static sf_count_t vox_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; 49 50static sf_count_t vox_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; 51static sf_count_t vox_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; 52static sf_count_t vox_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; 53static sf_count_t vox_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; 54 55static int vox_read_block (SF_PRIVATE *psf, IMA_OKI_ADPCM *pvox, short *ptr, int len) ; 56 57/*------------------------------------------------------------------------------ 58*/ 59 60static int 61codec_close (SF_PRIVATE * psf) 62{ 63 IMA_OKI_ADPCM * p = (IMA_OKI_ADPCM *) psf->codec_data ; 64 65 if (p->errors) 66 psf_log_printf (psf, "*** Warning : ADPCM state errors: %d\n", p->errors) ; 67 return p->errors ; 68} /* code_close */ 69 70int 71vox_adpcm_init (SF_PRIVATE *psf) 72{ IMA_OKI_ADPCM *pvox = NULL ; 73 74 if (psf->file.mode == SFM_RDWR) 75 return SFE_BAD_MODE_RW ; 76 77 if (psf->file.mode == SFM_WRITE && psf->sf.channels != 1) 78 return SFE_CHANNEL_COUNT ; 79 80 if ((pvox = malloc (sizeof (IMA_OKI_ADPCM))) == NULL) 81 return SFE_MALLOC_FAILED ; 82 83 psf->codec_data = (void*) pvox ; 84 memset (pvox, 0, sizeof (IMA_OKI_ADPCM)) ; 85 86 if (psf->file.mode == SFM_WRITE) 87 { psf->write_short = vox_write_s ; 88 psf->write_int = vox_write_i ; 89 psf->write_float = vox_write_f ; 90 psf->write_double = vox_write_d ; 91 } 92 else 93 { psf_log_printf (psf, "Header-less OKI Dialogic ADPCM encoded file.\n") ; 94 psf_log_printf (psf, "Setting up for 8kHz, mono, Vox ADPCM.\n") ; 95 96 psf->read_short = vox_read_s ; 97 psf->read_int = vox_read_i ; 98 psf->read_float = vox_read_f ; 99 psf->read_double = vox_read_d ; 100 } ; 101 102 /* Standard sample rate chennels etc. */ 103 if (psf->sf.samplerate < 1) 104 psf->sf.samplerate = 8000 ; 105 psf->sf.channels = 1 ; 106 107 psf->sf.frames = psf->filelength * 2 ; 108 109 psf->sf.seekable = SF_FALSE ; 110 psf->codec_close = codec_close ; 111 112 /* Seek back to start of data. */ 113 if (psf_fseek (psf, 0 , SEEK_SET) == -1) 114 return SFE_BAD_SEEK ; 115 116 ima_oki_adpcm_init (pvox, IMA_OKI_ADPCM_TYPE_OKI) ; 117 118 return 0 ; 119} /* vox_adpcm_init */ 120 121/*============================================================================== 122*/ 123 124static int 125vox_read_block (SF_PRIVATE *psf, IMA_OKI_ADPCM *pvox, short *ptr, int len) 126{ int indx = 0, k ; 127 128 while (indx < len) 129 { pvox->code_count = (len - indx > IMA_OKI_ADPCM_PCM_LEN) ? IMA_OKI_ADPCM_CODE_LEN : (len - indx + 1) / 2 ; 130 131 if ((k = (int) psf_fread (pvox->codes, 1, pvox->code_count, psf)) != pvox->code_count) 132 { if (psf_ftell (psf) != psf->filelength) 133 psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pvox->code_count) ; 134 if (k == 0) 135 break ; 136 } ; 137 138 pvox->code_count = k ; 139 140 ima_oki_adpcm_decode_block (pvox) ; 141 142 memcpy (&(ptr [indx]), pvox->pcm, pvox->pcm_count * sizeof (short)) ; 143 indx += pvox->pcm_count ; 144 } ; 145 146 return indx ; 147} /* vox_read_block */ 148 149 150static sf_count_t 151vox_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) 152{ IMA_OKI_ADPCM *pvox ; 153 int readcount, count ; 154 sf_count_t total = 0 ; 155 156 if (! psf->codec_data) 157 return 0 ; 158 pvox = (IMA_OKI_ADPCM*) psf->codec_data ; 159 160 while (len > 0) 161 { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; 162 163 count = vox_read_block (psf, pvox, ptr, readcount) ; 164 165 total += count ; 166 len -= count ; 167 if (count != readcount) 168 break ; 169 } ; 170 171 return total ; 172} /* vox_read_s */ 173 174static sf_count_t 175vox_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) 176{ IMA_OKI_ADPCM *pvox ; 177 BUF_UNION ubuf ; 178 short *sptr ; 179 int k, bufferlen, readcount, count ; 180 sf_count_t total = 0 ; 181 182 if (! psf->codec_data) 183 return 0 ; 184 pvox = (IMA_OKI_ADPCM*) psf->codec_data ; 185 186 sptr = ubuf.sbuf ; 187 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 188 while (len > 0) 189 { readcount = (len >= bufferlen) ? bufferlen : (int) len ; 190 count = vox_read_block (psf, pvox, sptr, readcount) ; 191 for (k = 0 ; k < readcount ; k++) 192 ptr [total + k] = arith_shift_left (sptr [k], 16) ; 193 total += count ; 194 len -= readcount ; 195 if (count != readcount) 196 break ; 197 } ; 198 199 return total ; 200} /* vox_read_i */ 201 202static sf_count_t 203vox_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) 204{ IMA_OKI_ADPCM *pvox ; 205 BUF_UNION ubuf ; 206 short *sptr ; 207 int k, bufferlen, readcount, count ; 208 sf_count_t total = 0 ; 209 float normfact ; 210 211 if (! psf->codec_data) 212 return 0 ; 213 pvox = (IMA_OKI_ADPCM*) psf->codec_data ; 214 215 normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; 216 217 sptr = ubuf.sbuf ; 218 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 219 while (len > 0) 220 { readcount = (len >= bufferlen) ? bufferlen : (int) len ; 221 count = vox_read_block (psf, pvox, sptr, readcount) ; 222 for (k = 0 ; k < readcount ; k++) 223 ptr [total + k] = normfact * (float) (sptr [k]) ; 224 total += count ; 225 len -= readcount ; 226 if (count != readcount) 227 break ; 228 } ; 229 230 return total ; 231} /* vox_read_f */ 232 233static sf_count_t 234vox_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) 235{ IMA_OKI_ADPCM *pvox ; 236 BUF_UNION ubuf ; 237 short *sptr ; 238 int k, bufferlen, readcount, count ; 239 sf_count_t total = 0 ; 240 double normfact ; 241 242 if (! psf->codec_data) 243 return 0 ; 244 pvox = (IMA_OKI_ADPCM*) psf->codec_data ; 245 246 normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; 247 248 sptr = ubuf.sbuf ; 249 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 250 while (len > 0) 251 { readcount = (len >= bufferlen) ? bufferlen : (int) len ; 252 count = vox_read_block (psf, pvox, sptr, readcount) ; 253 for (k = 0 ; k < readcount ; k++) 254 ptr [total + k] = normfact * (double) (sptr [k]) ; 255 total += count ; 256 len -= readcount ; 257 if (count != readcount) 258 break ; 259 } ; 260 261 return total ; 262} /* vox_read_d */ 263 264/*------------------------------------------------------------------------------ 265*/ 266 267static int 268vox_write_block (SF_PRIVATE *psf, IMA_OKI_ADPCM *pvox, const short *ptr, int len) 269{ int indx = 0, k ; 270 271 while (indx < len) 272 { pvox->pcm_count = (len - indx > IMA_OKI_ADPCM_PCM_LEN) ? IMA_OKI_ADPCM_PCM_LEN : len - indx ; 273 274 memcpy (pvox->pcm, &(ptr [indx]), pvox->pcm_count * sizeof (short)) ; 275 276 ima_oki_adpcm_encode_block (pvox) ; 277 278 if ((k = (int) psf_fwrite (pvox->codes, 1, pvox->code_count, psf)) != pvox->code_count) 279 psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pvox->code_count) ; 280 281 indx += pvox->pcm_count ; 282 } ; 283 284 return indx ; 285} /* vox_write_block */ 286 287static sf_count_t 288vox_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) 289{ IMA_OKI_ADPCM *pvox ; 290 int writecount, count ; 291 sf_count_t total = 0 ; 292 293 if (! psf->codec_data) 294 return 0 ; 295 pvox = (IMA_OKI_ADPCM*) psf->codec_data ; 296 297 while (len) 298 { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; 299 300 count = vox_write_block (psf, pvox, ptr, writecount) ; 301 302 total += count ; 303 len -= count ; 304 if (count != writecount) 305 break ; 306 } ; 307 308 return total ; 309} /* vox_write_s */ 310 311static sf_count_t 312vox_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) 313{ IMA_OKI_ADPCM *pvox ; 314 BUF_UNION ubuf ; 315 short *sptr ; 316 int k, bufferlen, writecount, count ; 317 sf_count_t total = 0 ; 318 319 if (! psf->codec_data) 320 return 0 ; 321 pvox = (IMA_OKI_ADPCM*) psf->codec_data ; 322 323 sptr = ubuf.sbuf ; 324 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 325 while (len > 0) 326 { writecount = (len >= bufferlen) ? bufferlen : (int) len ; 327 for (k = 0 ; k < writecount ; k++) 328 sptr [k] = ptr [total + k] >> 16 ; 329 count = vox_write_block (psf, pvox, sptr, writecount) ; 330 total += count ; 331 len -= writecount ; 332 if (count != writecount) 333 break ; 334 } ; 335 336 return total ; 337} /* vox_write_i */ 338 339static sf_count_t 340vox_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) 341{ IMA_OKI_ADPCM *pvox ; 342 BUF_UNION ubuf ; 343 short *sptr ; 344 int k, bufferlen, writecount, count ; 345 sf_count_t total = 0 ; 346 float normfact ; 347 348 if (! psf->codec_data) 349 return 0 ; 350 pvox = (IMA_OKI_ADPCM*) psf->codec_data ; 351 352 normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; 353 354 sptr = ubuf.sbuf ; 355 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 356 while (len > 0) 357 { writecount = (len >= bufferlen) ? bufferlen : (int) len ; 358 for (k = 0 ; k < writecount ; k++) 359 sptr [k] = psf_lrintf (normfact * ptr [total + k]) ; 360 count = vox_write_block (psf, pvox, sptr, writecount) ; 361 total += count ; 362 len -= writecount ; 363 if (count != writecount) 364 break ; 365 } ; 366 367 return total ; 368} /* vox_write_f */ 369 370static sf_count_t 371vox_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) 372{ IMA_OKI_ADPCM *pvox ; 373 BUF_UNION ubuf ; 374 short *sptr ; 375 int k, bufferlen, writecount, count ; 376 sf_count_t total = 0 ; 377 double normfact ; 378 379 if (! psf->codec_data) 380 return 0 ; 381 pvox = (IMA_OKI_ADPCM*) psf->codec_data ; 382 383 normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; 384 385 sptr = ubuf.sbuf ; 386 bufferlen = ARRAY_LEN (ubuf.sbuf) ; 387 while (len > 0) 388 { writecount = (len >= bufferlen) ? bufferlen : (int) len ; 389 for (k = 0 ; k < writecount ; k++) 390 sptr [k] = psf_lrint (normfact * ptr [total + k]) ; 391 count = vox_write_block (psf, pvox, sptr, writecount) ; 392 total += count ; 393 len -= writecount ; 394 if (count != writecount) 395 break ; 396 } ; 397 398 return total ; 399} /* vox_write_d */ 400 401