1 /* 2 * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* TODO: 27 * - move all the conversion code into an own file 28 */ 29 30 #define USE_TRACE 31 #define USE_ERROR 32 33 34 #include <jni.h> 35 // for malloc 36 #include <malloc.h> 37 #include "SoundDefs.h" 38 #include "DirectAudio.h" 39 #include "Utilities.h" 40 #include "com_sun_media_sound_DirectAudioDevice.h" 41 42 43 typedef struct { 44 void* handle; 45 int encoding; 46 int sampleSizeInBits; 47 int frameSize; 48 int channels; 49 int isSigned; 50 int isBigEndian; 51 UINT8* conversionBuffer; 52 int conversionBufferSize; 53 } DAUDIO_Info; 54 55 56 //////////////////////////////////////////// MAP Conversion stuff ///////////////////////////////// 57 58 /* 16 bit signed sample, native endianness, stored in 32-bits */ 59 typedef INT32 MAP_Sample; 60 61 INLINE UINT16 MAP_SWAP16_impl(UINT16 a) { 62 return (a>>8) | (a<<8); 63 } 64 65 INLINE UINT32 MAP_SWAP32_impl(UINT32 a) { 66 return (a>>24) 67 | ((a>>8) & 0xFF00) 68 | ((a<<8) & 0xFF0000) 69 | (a<<24); 70 } 71 72 INLINE UINT32 MAP_SWAP16BIT(UINT32 sh) { 73 return (UINT32) ((sh & 0xFF) << 8) | ((sh & 0xFF00) >> 8); 74 } 75 76 INLINE INT32 MAP_ClipAndConvertToShort(MAP_Sample sample) { 77 if (sample < -32768) { 78 return -32768; 79 } 80 else if (sample > 32767) { 81 return 32767; 82 } 83 return (INT32) sample; 84 } 85 86 87 INLINE INT32 MAP_ClipAndConvertToShort_Swapped(MAP_Sample sample) { 88 if (sample < -32768) { 89 return 0x0080; 90 } 91 else if (sample > 32767) { 92 return 0xFF7F; 93 } 94 return (INT32) (INT16) MAP_SWAP16BIT(sample); 95 } 96 97 INLINE INT8 MAP_ClipAndConvertToByte(MAP_Sample sample) { 98 if (sample < -32768) { 99 return -128; 100 } 101 else if (sample > 32767) { 102 return 127; 103 } 104 return (INT8) (sample >> 8); 105 } 106 107 108 INLINE UINT8 MAP_ClipAndConvertToUByte(MAP_Sample sample) { 109 if (sample < -32768) { 110 return 0; 111 } 112 else if (sample > 32767) { 113 return 255; 114 } 115 return (UINT8) ((sample >> 8) + 128); 116 } 117 118 /* conversion from/to 16 bit signed little endian to native endian samples */ 119 #ifdef _LITTLE_ENDIAN 120 #define MAP_LE_SHORT2SAMPLE(sh) ((MAP_Sample) (sh)) 121 #define MAP_SAMPLE2LE_SHORT(sample) (sample) 122 #define MAP_SAMPLE2LE_SHORT_CLIP(sample) MAP_ClipAndConvertToShort(sample) 123 #else 124 #define MAP_LE_SHORT2SAMPLE(sh) ((MAP_Sample) (INT16) MAP_SWAP16BIT(sh)) 125 #define MAP_SAMPLE2LE_SHORT(sample) (INT16) MAP_SWAP16BIT(sample) 126 #define MAP_SAMPLE2LE_SHORT_CLIP(sample) MAP_ClipAndConvertToShort_Swapped(sample) 127 #endif 128 129 /* conversion from/to 16 bit signed big endian to native endian samples */ 130 #ifndef _LITTLE_ENDIAN 131 #define MAP_BE_SHORT2SAMPLE(sh) ((MAP_Sample) (sh)) 132 #define MAP_SAMPLE2BE_SHORT(sample) (sample) 133 #define MAP_SAMPLE2BE_SHORT_CLIP(sample) MAP_ClipAndConvertToShort(sample) 134 #else 135 #define MAP_BE_SHORT2SAMPLE(sh) ((MAP_Sample) (INT16) MAP_SWAP16BIT(sh)) 136 #define MAP_SAMPLE2BE_SHORT(sample) ((INT16) MAP_SWAP16BIT(sample)) 137 #define MAP_SAMPLE2BE_SHORT_CLIP(sample) MAP_ClipAndConvertToShort_Swapped(sample) 138 #endif 139 140 /* conversion from/to 8 bit samples */ 141 #define MAP_INT82SAMPLE(by) ((MAP_Sample) (((INT32) ((INT8) (by))) << 8)) 142 #define MAP_UINT82SAMPLE(by) ((MAP_Sample) (((INT32) ((UINT8) (by) - 128)) << 8)) 143 #define MAP_SAMPLE2UINT8(sample) ((UINT8) ((((MAP_Sample) (sample)) >> 8) + 128)) 144 #define MAP_SAMPLE2INT8(sample) ((INT8) (((MAP_Sample) (sample)) >> 8)) 145 #define MAP_SAMPLE2UINT8_CLIP(sample) MAP_ClipAndConvertToUByte(sample) 146 #define MAP_SAMPLE2INT8_CLIP(sample) MAP_ClipAndConvertToByte(sample) 147 148 /* macros for endian conversion */ 149 #ifdef _LITTLE_ENDIAN 150 #define MAP_NATIVE2LE16(a) (a) 151 #define MAP_NATIVE2BE16(a) MAP_SWAP16_impl(a) 152 #define MAP_NATIVE2LE32(a) (a) 153 #define MAP_NATIVE2BE32(a) MAP_SWAP32_impl(a) 154 #else 155 #define MAP_NATIVE2LE16(a) MAP_SWAP16_impl(a) 156 #define MAP_NATIVE2BE16(a) (a) 157 #define MAP_NATIVE2LE32(a) MAP_SWAP32_impl(a) 158 #define MAP_NATIVE2BE32(a) (a) 159 #endif 160 #define MAP_LE2NATIVE16(a) MAP_NATIVE2LE16(a) 161 #define MAP_BE2NATIVE16(a) MAP_NATIVE2BE16(a) 162 #define MAP_LE2NATIVE32(a) MAP_NATIVE2LE32(a) 163 #define MAP_BE2NATIVE32(a) MAP_NATIVE2BE32(a) 164 165 166 ////////////////////////////// Utility function ///////////////////////////////// 167 168 /* 169 * conversion of this buffer: 170 * conversion size=1 -> each byte is converted from signed to unsigned or vice versa 171 * conversion size=2,3,4: the order of bytes in a sample is reversed (endianness) 172 * for sign conversion of a 24-bit sample stored in 32bits, 4 should be passed 173 * as conversionSize 174 */ 175 void handleSignEndianConversion(INT8* data, INT8* output, int byteSize, int conversionSize) { 176 TRACE1("conversion with size %d\n", conversionSize); 177 switch (conversionSize) { 178 case 1: { 179 while (byteSize > 0) { 180 *output = *data + (char) 128; // use wrap-around 181 byteSize--; 182 data++; 183 output++; 184 } 185 break; 186 } 187 case 2: { 188 INT8 h; 189 byteSize = byteSize / 2; 190 while (byteSize > 0) { 191 h = *data; 192 data++; 193 *output = *data; 194 output++; 195 *output = h; 196 byteSize--; 197 data++; output++; 198 } 199 break; 200 } 201 case 3: { 202 INT8 h; 203 byteSize = byteSize / 3; 204 while (byteSize > 0) { 205 h = *data; 206 *output = data[2]; 207 data++; output++; 208 *output = *data; 209 data++; output++; 210 *output = h; 211 data++; output++; 212 byteSize--; 213 } 214 break; 215 } 216 case 4: { 217 INT8 h1, h2; 218 byteSize = byteSize / 4; 219 while (byteSize > 0) { 220 h1 = data[0]; 221 h2 = data[1]; 222 *output = data[3]; output++; 223 *output = data[2]; output++; 224 *output = h2; output++; 225 *output = h1; output++; 226 data += 4; 227 byteSize--; 228 } 229 break; 230 } 231 default: 232 ERROR1("DirectAudioDevice.c: wrong conversionSize %d!\n", conversionSize); 233 } 234 } 235 236 /* aply the gain to one sample */ 237 #define CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, FROM_SAMPLE, FACTOR) \ 238 /* convert to MAP_Sample native type */ \ 239 sample = TO_SAMPLE(*INPUT); \ 240 /* apply gain */ \ 241 sample = (MAP_Sample) (sample * FACTOR); \ 242 /* convert to output type */ \ 243 (*OUTPUT) = FROM_SAMPLE(sample); \ 244 INPUT++; OUTPUT++ 245 246 247 /* macro for conversion of a mono block */ 248 #define LOOP_M(INPUT, OUTPUT, TO_SAMPLE, FROM_SAMPLE, FROM_SAMPLE_CLIP) \ 249 if (leftGain > 1.0) { \ 250 for ( ; len > 0; --len) { \ 251 CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \ 252 FROM_SAMPLE_CLIP, leftGain); \ 253 } \ 254 } else { \ 255 for ( ; len > 0; --len) { \ 256 CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \ 257 FROM_SAMPLE, leftGain); \ 258 } \ 259 } \ 260 break 261 262 /* macro for conversion of a stereo block */ 263 #define LOOP_S(INPUT, OUTPUT, TO_SAMPLE, FROM_SAMPLE, FROM_SAMPLE_CLIP) \ 264 if (leftGain > 1.0) { \ 265 if (rightGain > 1.0) { \ 266 for ( ; len > 0; --len) { \ 267 CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \ 268 FROM_SAMPLE_CLIP, leftGain); \ 269 CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \ 270 FROM_SAMPLE_CLIP, rightGain); \ 271 } \ 272 } else { \ 273 for ( ; len > 0; --len) { \ 274 CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \ 275 FROM_SAMPLE_CLIP, leftGain); \ 276 CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \ 277 FROM_SAMPLE, rightGain); \ 278 } \ 279 } \ 280 } else { \ 281 if (rightGain > 1.0) { \ 282 for ( ; len > 0; --len) { \ 283 CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \ 284 FROM_SAMPLE, leftGain); \ 285 CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \ 286 FROM_SAMPLE_CLIP, rightGain); \ 287 } \ 288 } else { \ 289 for ( ; len > 0; --len) { \ 290 CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \ 291 FROM_SAMPLE, leftGain); \ 292 CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \ 293 FROM_SAMPLE, rightGain); \ 294 } \ 295 } \ 296 } \ 297 break 298 299 #define FORMAT2CODE(channels, bits, inSigned, outSigned, inBigEndian, outBigEndian) \ 300 (channels << 20) \ 301 | (bits << 4) \ 302 | ((inSigned & 1) << 3) \ 303 | ((outSigned & 1) << 2) \ 304 | ((inBigEndian & 1) << 1) \ 305 | (outBigEndian & 1) 306 307 #define FORMAT2CODE8(channels, inSigned, outSigned) \ 308 FORMAT2CODE(channels, 8, inSigned, outSigned, 0, 0) 309 310 #define FORMAT2CODE16(channels, inBigEndian, outBigEndian) \ 311 FORMAT2CODE(channels, 16, 1, 1, inBigEndian, outBigEndian) 312 313 314 void handleGainAndConversion(DAUDIO_Info* info, UINT8* input, UINT8* output, 315 int len, float leftGain, float rightGain, 316 int conversionSize) { 317 INT8* input8 = (INT8*) input; 318 INT8* output8 = (INT8*) output; 319 INT16* input16 = (INT16*) input; 320 INT16* output16 = (INT16*) output; 321 MAP_Sample sample; 322 323 int inIsSigned = info->isSigned; 324 int inIsBigEndian = info->isBigEndian; 325 if (conversionSize == 1) { 326 /* 8-bit conversion: change sign */ 327 inIsSigned = !inIsSigned; 328 } 329 else if (conversionSize > 1) { 330 /* > 8-bit conversion: change endianness */ 331 inIsBigEndian = !inIsBigEndian; 332 } 333 if (info->frameSize <= 0) { 334 ERROR1("DirectAudiODevice: invalid framesize=%d\n", info->frameSize); 335 return; 336 } 337 len /= info->frameSize; 338 TRACE3("handleGainAndConversion: len=%d frames, leftGain=%f, rightGain=%f, ", 339 len, leftGain, rightGain); 340 TRACE3("channels=%d, sampleSizeInBits=%d, frameSize=%d, ", 341 (int) info->channels, (int) info->sampleSizeInBits, (int) info->frameSize); 342 TRACE4("signed:%d -> %d, endian: %d -> %d", 343 (int) inIsSigned, (int) info->isSigned, 344 (int) inIsBigEndian, (int) info->isBigEndian); 345 TRACE1("convSize=%d\n", conversionSize); 346 347 switch (FORMAT2CODE(info->channels, 348 info->sampleSizeInBits, 349 inIsSigned, 350 info->isSigned, 351 inIsBigEndian, 352 info->isBigEndian)) { 353 /* 8-bit mono */ 354 case FORMAT2CODE8(1, 0, 0): 355 LOOP_M(input8, output8, MAP_UINT82SAMPLE, 356 MAP_SAMPLE2UINT8, MAP_SAMPLE2UINT8_CLIP); 357 case FORMAT2CODE8(1, 0, 1): 358 LOOP_M(input8, output8, MAP_UINT82SAMPLE, 359 MAP_SAMPLE2INT8, MAP_SAMPLE2INT8_CLIP); 360 case FORMAT2CODE8(1, 1, 0): 361 LOOP_M(input8, output8, MAP_INT82SAMPLE, 362 MAP_SAMPLE2UINT8, MAP_SAMPLE2UINT8_CLIP); 363 case FORMAT2CODE8(1, 1, 1): 364 LOOP_M(input8, output8, MAP_INT82SAMPLE, 365 MAP_SAMPLE2INT8, MAP_SAMPLE2INT8_CLIP); 366 367 /* 8-bit stereo */ 368 case FORMAT2CODE8(2, 0, 0): 369 LOOP_S(input8, output8, MAP_UINT82SAMPLE, 370 MAP_SAMPLE2UINT8, MAP_SAMPLE2UINT8_CLIP); 371 case FORMAT2CODE8(2, 0, 1): 372 LOOP_S(input8, output8, MAP_UINT82SAMPLE, 373 MAP_SAMPLE2INT8, MAP_SAMPLE2INT8_CLIP); 374 case FORMAT2CODE8(2, 1, 0): 375 LOOP_S(input8, output8, MAP_INT82SAMPLE, 376 MAP_SAMPLE2UINT8, MAP_SAMPLE2UINT8_CLIP); 377 case FORMAT2CODE8(2, 1, 1): 378 LOOP_S(input8, output8, MAP_INT82SAMPLE, 379 MAP_SAMPLE2INT8, MAP_SAMPLE2INT8_CLIP); 380 381 /* 16-bit mono (only signed is accepted) */ 382 case FORMAT2CODE16(1, 0, 0): 383 LOOP_M(input16, output16, MAP_LE_SHORT2SAMPLE, 384 MAP_SAMPLE2LE_SHORT, MAP_SAMPLE2LE_SHORT_CLIP); 385 case FORMAT2CODE16(1, 0, 1): 386 LOOP_M(input16, output16, MAP_LE_SHORT2SAMPLE, 387 MAP_SAMPLE2BE_SHORT, MAP_SAMPLE2BE_SHORT_CLIP); 388 case FORMAT2CODE16(1, 1, 0): 389 LOOP_M(input16, output16, MAP_BE_SHORT2SAMPLE, 390 MAP_SAMPLE2LE_SHORT, MAP_SAMPLE2LE_SHORT_CLIP); 391 case FORMAT2CODE16(1, 1, 1): 392 LOOP_M(input16, output16, MAP_BE_SHORT2SAMPLE, 393 MAP_SAMPLE2BE_SHORT, MAP_SAMPLE2BE_SHORT_CLIP); 394 395 /* 16-bit stereo (only signed is accepted) */ 396 case FORMAT2CODE16(2, 0, 0): 397 LOOP_S(input16, output16, MAP_LE_SHORT2SAMPLE, 398 MAP_SAMPLE2LE_SHORT, MAP_SAMPLE2LE_SHORT_CLIP); 399 case FORMAT2CODE16(2, 0, 1): 400 LOOP_S(input16, output16, MAP_LE_SHORT2SAMPLE, 401 MAP_SAMPLE2BE_SHORT, MAP_SAMPLE2BE_SHORT_CLIP); 402 case FORMAT2CODE16(2, 1, 0): 403 LOOP_S(input16, output16, MAP_BE_SHORT2SAMPLE, 404 MAP_SAMPLE2LE_SHORT, MAP_SAMPLE2LE_SHORT_CLIP); 405 case FORMAT2CODE16(2, 1, 1): 406 LOOP_S(input16, output16, MAP_BE_SHORT2SAMPLE, 407 MAP_SAMPLE2BE_SHORT, MAP_SAMPLE2BE_SHORT_CLIP); 408 409 default: 410 ERROR3("DirectAudioDevice: Cannot convert from native format: " 411 "bits=%d, inSigned=%d outSigned=%d, ", 412 (int) info->sampleSizeInBits, 413 (int) inIsSigned, (int) info->isSigned); 414 ERROR2("inBigEndian=%d, outBigEndian=%d\n", 415 (int) inIsBigEndian, (int) info->isBigEndian); 416 } 417 } 418 419 float ABS_VALUE(float a) { 420 return (a < 0)?-a:a; 421 } 422 423 424 //////////////////////////////////////////// DirectAudioDevice //////////////////////////////////////////// 425 426 /* ************************************** native control creation support ********************* */ 427 428 // contains all the needed references so that the platform dependent code can call JNI wrapper functions 429 typedef struct tag_AddFormatCreator { 430 // general JNI variables 431 JNIEnv *env; 432 // the vector to be filled with the formats 433 jobject vector; 434 // the class containing the addFormat method 435 jclass directAudioDeviceClass; 436 // the method to be called to add the format 437 jmethodID addFormat; // signature (Ljava/util/Vector;IIFIBB)V 438 } AddFormatCreator; 439 440 void DAUDIO_AddAudioFormat(void* creatorV, int significantBits, int frameSizeInBytes, 441 int channels, float sampleRate, 442 int encoding, int isSigned, 443 int bigEndian) { 444 AddFormatCreator* creator = (AddFormatCreator*) creatorV; 445 if (frameSizeInBytes <= 0) { 446 if (channels > 0) { 447 frameSizeInBytes = ((significantBits + 7) / 8) * channels; 448 } else { 449 frameSizeInBytes = -1; 450 } 451 } 452 TRACE4("AddAudioFormat with sigBits=%d bits, frameSize=%d bytes, channels=%d, sampleRate=%d ", 453 significantBits, frameSizeInBytes, channels, (int) sampleRate); 454 TRACE3("enc=%d, signed=%d, bigEndian=%d\n", encoding, isSigned, bigEndian); 455 (*creator->env)->CallStaticVoidMethod(creator->env, creator->directAudioDeviceClass, 456 creator->addFormat, creator->vector, significantBits, frameSizeInBytes, 457 channels, sampleRate, encoding, isSigned, bigEndian); 458 } 459 460 ////////////////////////////////////// JNI ///////////////////////////////////////////////////////////////////// 461 462 /* 463 * Class: com_sun_media_sound_DirectAudioDevice 464 * Method: nGetFormats 465 * Signature: (IIZLjava/util/Vector;)V 466 */ 467 JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nGetFormats 468 (JNIEnv *env, jclass clazz, jint mixerIndex, jint deviceID, jboolean isSource, jobject formats) { 469 470 #if USE_DAUDIO == TRUE 471 AddFormatCreator creator; 472 creator.env = env; 473 creator.vector = formats; 474 creator.directAudioDeviceClass = clazz; 475 creator.addFormat = (*env)->GetStaticMethodID(env, clazz, "addFormat", 476 "(Ljava/util/Vector;IIIFIZZ)V"); 477 if (creator.addFormat == NULL) { 478 ERROR0("Could not get method ID for addFormat!\n"); 479 } else { 480 DAUDIO_GetFormats((INT32) mixerIndex, (INT32) deviceID, (int) isSource, &creator); 481 } 482 #endif 483 } 484 485 486 487 /* 488 * Class: com_sun_media_sound_DirectAudioDevice 489 * Method: nOpen 490 * Signature: (IIZIFIIZZI)J 491 */ 492 JNIEXPORT jlong JNICALL Java_com_sun_media_sound_DirectAudioDevice_nOpen 493 (JNIEnv* env, jclass clazz, jint mixerIndex, jint deviceID, jboolean isSource, 494 jint encoding, jfloat sampleRate, jint sampleSizeInBits, jint frameSize, jint channels, 495 jboolean isSigned, jboolean isBigendian, jint bufferSizeInBytes) { 496 497 DAUDIO_Info* info = NULL; 498 #if USE_DAUDIO == TRUE 499 500 info = (DAUDIO_Info*) malloc(sizeof(DAUDIO_Info)); 501 if (info == NULL) { 502 ERROR0("DirectAudioDevice_nOpen: Out of memory!\n"); 503 } else { 504 info->handle =DAUDIO_Open((int) mixerIndex, (INT32) deviceID, (int) isSource, 505 (int) encoding, (float) sampleRate, (int) sampleSizeInBits, 506 (int) frameSize, (int) channels, 507 (int) isSigned, (int) isBigendian, (int) bufferSizeInBytes); 508 if (!info->handle) { 509 free(info); 510 info = NULL; 511 } else { 512 info->encoding = encoding; 513 info->sampleSizeInBits = sampleSizeInBits; 514 info->frameSize = frameSize; 515 info->channels = channels; 516 info->isSigned = isSigned; 517 info->isBigEndian = isBigendian && (sampleSizeInBits > 8); 518 /* will be populated on demand */ 519 info->conversionBuffer = NULL; 520 info->conversionBufferSize = 0; 521 } 522 } 523 #endif 524 return (jlong) (UINT_PTR) info; 525 } 526 527 /* 528 * Class: com_sun_media_sound_DirectAudioDevice 529 * Method: nStart 530 * Signature: (JZ)V 531 */ 532 JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nStart 533 (JNIEnv* env, jclass clazz, jlong id, jboolean isSource) { 534 #if USE_DAUDIO == TRUE 535 DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id; 536 if (info && info->handle) { 537 DAUDIO_Start(info->handle, (int) isSource); 538 } 539 #endif 540 } 541 542 543 /* 544 * Class: com_sun_media_sound_DirectAudioDevice 545 * Method: nStop 546 * Signature: (JZ)V 547 */ 548 JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nStop 549 (JNIEnv* env, jclass clazz, jlong id, jboolean isSource) { 550 #if USE_DAUDIO == TRUE 551 DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id; 552 if (info && info->handle) { 553 DAUDIO_Stop(info->handle, (int) isSource); 554 } 555 #endif 556 } 557 558 559 /* 560 * Class: com_sun_media_sound_DirectAudioDevice 561 * Method: nClose 562 * Signature: (JZ)V 563 */ 564 JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nClose 565 (JNIEnv* env, jclass clazz, jlong id, jboolean isSource) { 566 #if USE_DAUDIO == TRUE 567 DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id; 568 if (info && info->handle) { 569 DAUDIO_Close(info->handle, (int) isSource); 570 if (info->conversionBuffer) { 571 free(info->conversionBuffer); 572 } 573 free(info); 574 } 575 #endif 576 } 577 578 /* 579 * Class: com_sun_media_sound_DirectAudioDevice 580 * Method: nWrite 581 * Signature: (J[BII)I 582 */ 583 JNIEXPORT jint JNICALL Java_com_sun_media_sound_DirectAudioDevice_nWrite 584 (JNIEnv *env, jclass clazz, jlong id, jbyteArray jData, 585 jint offset, jint len, jint conversionSize, jfloat leftGain, jfloat rightGain) { 586 int ret = -1; 587 #if USE_DAUDIO == TRUE 588 UINT8* data; 589 UINT8* dataOffset; 590 UINT8* convertedData; 591 jboolean didCopy; 592 DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id; 593 594 /* a little sanity */ 595 if (offset < 0 || len < 0) { 596 ERROR2("nWrite: wrong parameters: offset=%d, len=%d\n", offset, len); 597 return ret; 598 } 599 if (len == 0) return 0; 600 if (info && info->handle) { 601 data = (UINT8*) ((*env)->GetByteArrayElements(env, jData, &didCopy)); 602 dataOffset = data; 603 dataOffset += (int) offset; 604 convertedData = dataOffset; 605 606 if (conversionSize > 0 || leftGain != 1.0f || rightGain != 1.0f) { 607 /* make sure we have a buffer for the intermediate data */ 608 if (didCopy == JNI_FALSE) { 609 /* let's do our own copy */ 610 if (info->conversionBuffer 611 && info->conversionBufferSize < len) { 612 free(info->conversionBuffer); 613 info->conversionBuffer = NULL; 614 info->conversionBufferSize = 0; 615 } 616 if (!info->conversionBuffer) { 617 info->conversionBuffer = (UINT8*) malloc(len); 618 if (!info->conversionBuffer) { 619 // do not commit the native array 620 (*env)->ReleaseByteArrayElements(env, jData, (jbyte*) data, JNI_ABORT); 621 return -1; 622 } 623 info->conversionBufferSize = len; 624 } 625 convertedData = info->conversionBuffer; 626 } 627 if (((ABS_VALUE(leftGain - 1.0f) < 0.01) 628 && (ABS_VALUE(rightGain - 1.0f) < 0.01)) 629 || info->encoding!=DAUDIO_PCM 630 || ((info->channels * info->sampleSizeInBits / 8) != info->frameSize) 631 || (info->sampleSizeInBits != 8 && info->sampleSizeInBits != 16)) { 632 handleSignEndianConversion((INT8*) dataOffset, (INT8*) convertedData, (int) len, 633 (int) conversionSize); 634 } else { 635 handleGainAndConversion(info, dataOffset, convertedData, 636 (int) len, (float) leftGain, (float) rightGain, 637 (int) conversionSize); 638 } 639 } 640 641 ret = DAUDIO_Write(info->handle, (INT8*) convertedData, (int) len); 642 643 // do not commit the native array 644 (*env)->ReleaseByteArrayElements(env, jData, (jbyte*) data, JNI_ABORT); 645 } 646 #endif 647 return (jint) ret; 648 } 649 650 /* 651 * Class: com_sun_media_sound_DirectAudioDevice 652 * Method: nRead 653 * Signature: (J[BII)I 654 */ 655 JNIEXPORT jint JNICALL Java_com_sun_media_sound_DirectAudioDevice_nRead 656 (JNIEnv* env, jclass clazz, jlong id, jbyteArray jData, jint offset, jint len, jint conversionSize) { 657 int ret = -1; 658 #if USE_DAUDIO == TRUE 659 char* data; 660 char* dataOffset; 661 DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id; 662 663 /* a little sanity */ 664 if (offset < 0 || len < 0) { 665 ERROR2("nRead: wrong parameters: offset=%d, len=%d\n", offset, len); 666 return ret; 667 } 668 if (info && info->handle) { 669 data = (char*) ((*env)->GetByteArrayElements(env, jData, NULL)); 670 dataOffset = data; 671 dataOffset += (int) offset; 672 ret = DAUDIO_Read(info->handle, dataOffset, (int) len); 673 if (conversionSize > 0) { 674 handleSignEndianConversion(dataOffset, dataOffset, (int) len, (int) conversionSize); 675 } 676 // commit the native array 677 (*env)->ReleaseByteArrayElements(env, jData, (jbyte*) data, 0); 678 } 679 #endif 680 return (jint) ret; 681 } 682 683 /* 684 * Class: com_sun_media_sound_DirectAudioDevice 685 * Method: nGetBufferSize 686 * Signature: (JZ)I 687 */ 688 JNIEXPORT jint JNICALL Java_com_sun_media_sound_DirectAudioDevice_nGetBufferSize 689 (JNIEnv* env, jclass clazz, jlong id, jboolean isSource) { 690 int ret = -1; 691 #if USE_DAUDIO == TRUE 692 DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id; 693 if (info && info->handle) { 694 ret = DAUDIO_GetBufferSize(info->handle, (int) isSource); 695 } 696 #endif 697 return (jint) ret; 698 } 699 700 701 /* 702 * Class: com_sun_media_sound_DirectAudioDevice 703 * Method: nIsStillDraining 704 * Signature: (JZ)Z 705 */ 706 JNIEXPORT jboolean JNICALL Java_com_sun_media_sound_DirectAudioDevice_nIsStillDraining 707 (JNIEnv* env, jclass clazz, jlong id, jboolean isSource) { 708 int ret = FALSE; 709 #if USE_DAUDIO == TRUE 710 DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id; 711 if (info && info->handle) { 712 ret = DAUDIO_StillDraining(info->handle, (int) isSource)?TRUE:FALSE; 713 } 714 #endif 715 return (jboolean) ret; 716 } 717 718 719 /* 720 * Class: com_sun_media_sound_DirectAudioDevice 721 * Method: nFlush 722 * Signature: (JZ)V 723 */ 724 JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nFlush 725 (JNIEnv* env, jclass clazz, jlong id, jboolean isSource) { 726 #if USE_DAUDIO == TRUE 727 DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id; 728 if (info && info->handle) { 729 DAUDIO_Flush(info->handle, (int) isSource); 730 } 731 #endif 732 } 733 734 735 /* 736 * Class: com_sun_media_sound_DirectAudioDevice 737 * Method: nAvailable 738 * Signature: (JZ)I 739 */ 740 JNIEXPORT jint JNICALL Java_com_sun_media_sound_DirectAudioDevice_nAvailable 741 (JNIEnv* env, jclass clazz, jlong id, jboolean isSource) { 742 int ret = -1; 743 #if USE_DAUDIO == TRUE 744 DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id; 745 if (info && info->handle) { 746 ret = DAUDIO_GetAvailable(info->handle, (int) isSource); 747 } 748 #endif 749 return (jint) ret; 750 } 751 752 753 /* 754 * Class: com_sun_media_sound_DirectAudioDevice 755 * Method: nGetBytePosition 756 * Signature: (JZJ)J 757 */ 758 JNIEXPORT jlong JNICALL Java_com_sun_media_sound_DirectAudioDevice_nGetBytePosition 759 (JNIEnv* env, jclass clazz, jlong id, jboolean isSource, jlong javaBytePos) { 760 INT64 ret = (INT64) javaBytePos; 761 #if USE_DAUDIO == TRUE 762 DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id; 763 if (info && info->handle) { 764 ret = DAUDIO_GetBytePosition(info->handle, (int) isSource, (INT64) javaBytePos); 765 } 766 #endif 767 return (jlong) ret; 768 } 769 770 /* 771 * Class: com_sun_media_sound_DirectAudioDevice 772 * Method: nSetBytePosition 773 * Signature: (JZJ)V 774 */ 775 JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nSetBytePosition 776 (JNIEnv* env, jclass clazz, jlong id, jboolean isSource, jlong pos) { 777 #if USE_DAUDIO == TRUE 778 DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id; 779 if (info && info->handle) { 780 DAUDIO_SetBytePosition(info->handle, (int) isSource, (INT64) pos); 781 } 782 #endif 783 } 784 785 /* 786 * Class: com_sun_media_sound_DirectAudioDevice 787 * Method: nRequiresServicing 788 * Signature: (JZ)B 789 */ 790 JNIEXPORT jboolean JNICALL Java_com_sun_media_sound_DirectAudioDevice_nRequiresServicing 791 (JNIEnv* env, jclass clazz, jlong id, jboolean isSource) { 792 int ret = FALSE; 793 #if USE_DAUDIO == TRUE 794 DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id; 795 if (info && info->handle) { 796 ret = DAUDIO_RequiresServicing(info->handle, (int) isSource); 797 } 798 #endif 799 return (jboolean) ret; 800 } 801 /* 802 * Class: com_sun_media_sound_DirectAudioDevice 803 * Method: nService 804 * Signature: (JZ)V 805 */ 806 JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nService 807 (JNIEnv* env, jclass clazz, jlong id, jboolean isSource) { 808 #if USE_DAUDIO == TRUE 809 DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id; 810 if (info && info->handle) { 811 DAUDIO_Service(info->handle, (int) isSource); 812 } 813 #endif 814 }