Path: blob/master/src/java.desktop/share/native/libjsound/DirectAudioDevice.c
41149 views
/*1* Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/* TODO:26* - move all the conversion code into an own file27*/2829//#define USE_TRACE30//#define USE_ERROR313233#include <jni.h>34#include <jni_util.h>35// for malloc36#ifdef _ALLBSD_SOURCE37#include <stdlib.h>38#else39#include <malloc.h>40#endif41#include "SoundDefs.h"42#include "DirectAudio.h"43#include "Utilities.h"44#include "com_sun_media_sound_DirectAudioDevice.h"454647typedef struct {48void* handle;49int encoding;50int sampleSizeInBits;51int frameSize;52int channels;53int isSigned;54int isBigEndian;55UINT8* conversionBuffer;56int conversionBufferSize;57} DAUDIO_Info;585960//////////////////////////////////////////// MAP Conversion stuff /////////////////////////////////6162/* 16 bit signed sample, native endianness, stored in 32-bits */63typedef INT32 MAP_Sample;6465static INLINE UINT16 MAP_SWAP16_impl(UINT16 a) {66return (a>>8) | (a<<8);67}6869static INLINE UINT32 MAP_SWAP32_impl(UINT32 a) {70return (a>>24)71| ((a>>8) & 0xFF00)72| ((a<<8) & 0xFF0000)73| (a<<24);74}7576static INLINE UINT32 MAP_SWAP16BIT(UINT32 sh) {77return (UINT32) ((sh & 0xFF) << 8) | ((sh & 0xFF00) >> 8);78}7980static INLINE INT32 MAP_ClipAndConvertToShort(MAP_Sample sample) {81if (sample < -32768) {82return -32768;83}84else if (sample > 32767) {85return 32767;86}87return (INT32) sample;88}899091static INLINE INT32 MAP_ClipAndConvertToShort_Swapped(MAP_Sample sample) {92if (sample < -32768) {93return 0x0080;94}95else if (sample > 32767) {96return 0xFF7F;97}98return (INT32) (INT16) MAP_SWAP16BIT(sample);99}100101static INLINE INT8 MAP_ClipAndConvertToByte(MAP_Sample sample) {102if (sample < -32768) {103return -128;104}105else if (sample > 32767) {106return 127;107}108return (INT8) (sample >> 8);109}110111112static INLINE UINT8 MAP_ClipAndConvertToUByte(MAP_Sample sample) {113if (sample < -32768) {114return 0;115}116else if (sample > 32767) {117return 255;118}119return (UINT8) ((sample >> 8) + 128);120}121122/* conversion from/to 16 bit signed little endian to native endian samples */123#ifdef _LITTLE_ENDIAN124#define MAP_LE_SHORT2SAMPLE(sh) ((MAP_Sample) (sh))125#define MAP_SAMPLE2LE_SHORT(sample) (sample)126#define MAP_SAMPLE2LE_SHORT_CLIP(sample) MAP_ClipAndConvertToShort(sample)127#else128#define MAP_LE_SHORT2SAMPLE(sh) ((MAP_Sample) (INT16) MAP_SWAP16BIT(sh))129#define MAP_SAMPLE2LE_SHORT(sample) (INT16) MAP_SWAP16BIT(sample)130#define MAP_SAMPLE2LE_SHORT_CLIP(sample) MAP_ClipAndConvertToShort_Swapped(sample)131#endif132133/* conversion from/to 16 bit signed big endian to native endian samples */134#ifndef _LITTLE_ENDIAN135#define MAP_BE_SHORT2SAMPLE(sh) ((MAP_Sample) (sh))136#define MAP_SAMPLE2BE_SHORT(sample) (sample)137#define MAP_SAMPLE2BE_SHORT_CLIP(sample) MAP_ClipAndConvertToShort(sample)138#else139#define MAP_BE_SHORT2SAMPLE(sh) ((MAP_Sample) (INT16) MAP_SWAP16BIT(sh))140#define MAP_SAMPLE2BE_SHORT(sample) ((INT16) MAP_SWAP16BIT(sample))141#define MAP_SAMPLE2BE_SHORT_CLIP(sample) MAP_ClipAndConvertToShort_Swapped(sample)142#endif143144/* conversion from/to 8 bit samples */145#define MAP_INT82SAMPLE(by) ((MAP_Sample) (((INT32) ((INT8) (by))) << 8))146#define MAP_UINT82SAMPLE(by) ((MAP_Sample) (((INT32) ((UINT8) (by) - 128)) << 8))147#define MAP_SAMPLE2UINT8(sample) ((UINT8) ((((MAP_Sample) (sample)) >> 8) + 128))148#define MAP_SAMPLE2INT8(sample) ((INT8) (((MAP_Sample) (sample)) >> 8))149#define MAP_SAMPLE2UINT8_CLIP(sample) MAP_ClipAndConvertToUByte(sample)150#define MAP_SAMPLE2INT8_CLIP(sample) MAP_ClipAndConvertToByte(sample)151152/* macros for endian conversion */153#ifdef _LITTLE_ENDIAN154#define MAP_NATIVE2LE16(a) (a)155#define MAP_NATIVE2BE16(a) MAP_SWAP16_impl(a)156#define MAP_NATIVE2LE32(a) (a)157#define MAP_NATIVE2BE32(a) MAP_SWAP32_impl(a)158#else159#define MAP_NATIVE2LE16(a) MAP_SWAP16_impl(a)160#define MAP_NATIVE2BE16(a) (a)161#define MAP_NATIVE2LE32(a) MAP_SWAP32_impl(a)162#define MAP_NATIVE2BE32(a) (a)163#endif164#define MAP_LE2NATIVE16(a) MAP_NATIVE2LE16(a)165#define MAP_BE2NATIVE16(a) MAP_NATIVE2BE16(a)166#define MAP_LE2NATIVE32(a) MAP_NATIVE2LE32(a)167#define MAP_BE2NATIVE32(a) MAP_NATIVE2BE32(a)168169170////////////////////////////// Utility function /////////////////////////////////171172/*173* conversion of this buffer:174* conversion size=1 -> each byte is converted from signed to unsigned or vice versa175* conversion size=2,3,4: the order of bytes in a sample is reversed (endianness)176* for sign conversion of a 24-bit sample stored in 32bits, 4 should be passed177* as conversionSize178*/179void handleSignEndianConversion(INT8* data, INT8* output, int byteSize, int conversionSize) {180TRACE1("conversion with size %d\n", conversionSize);181switch (conversionSize) {182case 1: {183while (byteSize > 0) {184*output = *data + (char) 128; // use wrap-around185byteSize--;186data++;187output++;188}189break;190}191case 2: {192INT8 h;193byteSize = byteSize / 2;194while (byteSize > 0) {195h = *data;196data++;197*output = *data;198output++;199*output = h;200byteSize--;201data++; output++;202}203break;204}205case 3: {206INT8 h;207byteSize = byteSize / 3;208while (byteSize > 0) {209h = *data;210*output = data[2];211data++; output++;212*output = *data;213data++; output++;214*output = h;215data++; output++;216byteSize--;217}218break;219}220case 4: {221INT8 h1, h2;222byteSize = byteSize / 4;223while (byteSize > 0) {224h1 = data[0];225h2 = data[1];226*output = data[3]; output++;227*output = data[2]; output++;228*output = h2; output++;229*output = h1; output++;230data += 4;231byteSize--;232}233break;234}235default:236ERROR1("DirectAudioDevice.c: wrong conversionSize %d!\n", conversionSize);237}238}239240/* aply the gain to one sample */241#define CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, FROM_SAMPLE, FACTOR) \242/* convert to MAP_Sample native type */ \243sample = TO_SAMPLE(*INPUT); \244/* apply gain */ \245sample = (MAP_Sample) (sample * FACTOR); \246/* convert to output type */ \247(*OUTPUT) = FROM_SAMPLE(sample); \248INPUT++; OUTPUT++249250251/* macro for conversion of a mono block */252#define LOOP_M(INPUT, OUTPUT, TO_SAMPLE, FROM_SAMPLE, FROM_SAMPLE_CLIP) \253if (leftGain > 1.0) { \254for ( ; len > 0; --len) { \255CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \256FROM_SAMPLE_CLIP, leftGain); \257} \258} else { \259for ( ; len > 0; --len) { \260CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \261FROM_SAMPLE, leftGain); \262} \263} \264break265266/* macro for conversion of a stereo block */267#define LOOP_S(INPUT, OUTPUT, TO_SAMPLE, FROM_SAMPLE, FROM_SAMPLE_CLIP) \268if (leftGain > 1.0) { \269if (rightGain > 1.0) { \270for ( ; len > 0; --len) { \271CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \272FROM_SAMPLE_CLIP, leftGain); \273CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \274FROM_SAMPLE_CLIP, rightGain); \275} \276} else { \277for ( ; len > 0; --len) { \278CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \279FROM_SAMPLE_CLIP, leftGain); \280CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \281FROM_SAMPLE, rightGain); \282} \283} \284} else { \285if (rightGain > 1.0) { \286for ( ; len > 0; --len) { \287CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \288FROM_SAMPLE, leftGain); \289CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \290FROM_SAMPLE_CLIP, rightGain); \291} \292} else { \293for ( ; len > 0; --len) { \294CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \295FROM_SAMPLE, leftGain); \296CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, \297FROM_SAMPLE, rightGain); \298} \299} \300} \301break302303#define FORMAT2CODE(channels, bits, inSigned, outSigned, inBigEndian, outBigEndian) \304(channels << 20) \305| (bits << 4) \306| ((inSigned & 1) << 3) \307| ((outSigned & 1) << 2) \308| ((inBigEndian & 1) << 1) \309| (outBigEndian & 1)310311#define FORMAT2CODE8(channels, inSigned, outSigned) \312FORMAT2CODE(channels, 8, inSigned, outSigned, 0, 0)313314#define FORMAT2CODE16(channels, inBigEndian, outBigEndian) \315FORMAT2CODE(channels, 16, 1, 1, inBigEndian, outBigEndian)316317318void handleGainAndConversion(DAUDIO_Info* info, UINT8* input, UINT8* output,319int len, float leftGain, float rightGain,320int conversionSize) {321INT8* input8 = (INT8*) input;322INT8* output8 = (INT8*) output;323INT16* input16 = (INT16*) input;324INT16* output16 = (INT16*) output;325MAP_Sample sample;326327int inIsSigned = info->isSigned;328int inIsBigEndian = info->isBigEndian;329if (conversionSize == 1) {330/* 8-bit conversion: change sign */331inIsSigned = !inIsSigned;332}333else if (conversionSize > 1) {334/* > 8-bit conversion: change endianness */335inIsBigEndian = !inIsBigEndian;336}337if (info->frameSize <= 0) {338ERROR1("DirectAudiODevice: invalid framesize=%d\n", info->frameSize);339return;340}341len /= info->frameSize;342TRACE3("handleGainAndConversion: len=%d frames, leftGain=%f, rightGain=%f, ",343len, leftGain, rightGain);344TRACE3("channels=%d, sampleSizeInBits=%d, frameSize=%d, ",345(int) info->channels, (int) info->sampleSizeInBits, (int) info->frameSize);346TRACE4("signed:%d -> %d, endian: %d -> %d",347(int) inIsSigned, (int) info->isSigned,348(int) inIsBigEndian, (int) info->isBigEndian);349TRACE1("convSize=%d\n", conversionSize);350351switch (FORMAT2CODE(info->channels,352info->sampleSizeInBits,353inIsSigned,354info->isSigned,355inIsBigEndian,356info->isBigEndian)) {357/* 8-bit mono */358case FORMAT2CODE8(1, 0, 0):359LOOP_M(input8, output8, MAP_UINT82SAMPLE,360MAP_SAMPLE2UINT8, MAP_SAMPLE2UINT8_CLIP);361case FORMAT2CODE8(1, 0, 1):362LOOP_M(input8, output8, MAP_UINT82SAMPLE,363MAP_SAMPLE2INT8, MAP_SAMPLE2INT8_CLIP);364case FORMAT2CODE8(1, 1, 0):365LOOP_M(input8, output8, MAP_INT82SAMPLE,366MAP_SAMPLE2UINT8, MAP_SAMPLE2UINT8_CLIP);367case FORMAT2CODE8(1, 1, 1):368LOOP_M(input8, output8, MAP_INT82SAMPLE,369MAP_SAMPLE2INT8, MAP_SAMPLE2INT8_CLIP);370371/* 8-bit stereo */372case FORMAT2CODE8(2, 0, 0):373LOOP_S(input8, output8, MAP_UINT82SAMPLE,374MAP_SAMPLE2UINT8, MAP_SAMPLE2UINT8_CLIP);375case FORMAT2CODE8(2, 0, 1):376LOOP_S(input8, output8, MAP_UINT82SAMPLE,377MAP_SAMPLE2INT8, MAP_SAMPLE2INT8_CLIP);378case FORMAT2CODE8(2, 1, 0):379LOOP_S(input8, output8, MAP_INT82SAMPLE,380MAP_SAMPLE2UINT8, MAP_SAMPLE2UINT8_CLIP);381case FORMAT2CODE8(2, 1, 1):382LOOP_S(input8, output8, MAP_INT82SAMPLE,383MAP_SAMPLE2INT8, MAP_SAMPLE2INT8_CLIP);384385/* 16-bit mono (only signed is accepted) */386case FORMAT2CODE16(1, 0, 0):387LOOP_M(input16, output16, MAP_LE_SHORT2SAMPLE,388MAP_SAMPLE2LE_SHORT, MAP_SAMPLE2LE_SHORT_CLIP);389case FORMAT2CODE16(1, 0, 1):390LOOP_M(input16, output16, MAP_LE_SHORT2SAMPLE,391MAP_SAMPLE2BE_SHORT, MAP_SAMPLE2BE_SHORT_CLIP);392case FORMAT2CODE16(1, 1, 0):393LOOP_M(input16, output16, MAP_BE_SHORT2SAMPLE,394MAP_SAMPLE2LE_SHORT, MAP_SAMPLE2LE_SHORT_CLIP);395case FORMAT2CODE16(1, 1, 1):396LOOP_M(input16, output16, MAP_BE_SHORT2SAMPLE,397MAP_SAMPLE2BE_SHORT, MAP_SAMPLE2BE_SHORT_CLIP);398399/* 16-bit stereo (only signed is accepted) */400case FORMAT2CODE16(2, 0, 0):401LOOP_S(input16, output16, MAP_LE_SHORT2SAMPLE,402MAP_SAMPLE2LE_SHORT, MAP_SAMPLE2LE_SHORT_CLIP);403case FORMAT2CODE16(2, 0, 1):404LOOP_S(input16, output16, MAP_LE_SHORT2SAMPLE,405MAP_SAMPLE2BE_SHORT, MAP_SAMPLE2BE_SHORT_CLIP);406case FORMAT2CODE16(2, 1, 0):407LOOP_S(input16, output16, MAP_BE_SHORT2SAMPLE,408MAP_SAMPLE2LE_SHORT, MAP_SAMPLE2LE_SHORT_CLIP);409case FORMAT2CODE16(2, 1, 1):410LOOP_S(input16, output16, MAP_BE_SHORT2SAMPLE,411MAP_SAMPLE2BE_SHORT, MAP_SAMPLE2BE_SHORT_CLIP);412413default:414ERROR3("DirectAudioDevice: Cannot convert from native format: "415"bits=%d, inSigned=%d outSigned=%d, ",416(int) info->sampleSizeInBits,417(int) inIsSigned, (int) info->isSigned);418ERROR2("inBigEndian=%d, outBigEndian=%d\n",419(int) inIsBigEndian, (int) info->isBigEndian);420}421}422423float ABS_VALUE(float a) {424return (a < 0)?-a:a;425}426427428//////////////////////////////////////////// DirectAudioDevice ////////////////////////////////////////////429430/* ************************************** native control creation support ********************* */431432// contains all the needed references so that the platform dependent code can call JNI wrapper functions433typedef struct tag_AddFormatCreator {434// general JNI variables435JNIEnv *env;436// the vector to be filled with the formats437jobject vector;438// the class containing the addFormat method439jclass directAudioDeviceClass;440// the method to be called to add the format441jmethodID addFormat; // signature (Ljava/util/Vector;IIFIBB)V442} AddFormatCreator;443444void DAUDIO_AddAudioFormat(void* creatorV, int significantBits, int frameSizeInBytes,445int channels, float sampleRate,446int encoding, int isSigned,447int bigEndian) {448AddFormatCreator* creator = (AddFormatCreator*) creatorV;449if (frameSizeInBytes <= 0) {450if (channels > 0) {451frameSizeInBytes = ((significantBits + 7) / 8) * channels;452} else {453frameSizeInBytes = -1;454}455}456TRACE4("AddAudioFormat with sigBits=%d bits, frameSize=%d bytes, channels=%d, sampleRate=%d ",457significantBits, frameSizeInBytes, channels, (int) sampleRate);458TRACE3("enc=%d, signed=%d, bigEndian=%d\n", encoding, isSigned, bigEndian);459(*creator->env)->CallStaticVoidMethod(creator->env, creator->directAudioDeviceClass,460creator->addFormat, creator->vector, significantBits, frameSizeInBytes,461channels, sampleRate, encoding, isSigned, bigEndian);462}463464////////////////////////////////////// JNI /////////////////////////////////////////////////////////////////////465466/*467* Class: com_sun_media_sound_DirectAudioDevice468* Method: nGetFormats469* Signature: (IIZLjava/util/Vector;)V470*/471JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nGetFormats472(JNIEnv *env, jclass clazz, jint mixerIndex, jint deviceID, jboolean isSource, jobject formats) {473474#if USE_DAUDIO == TRUE475AddFormatCreator creator;476creator.env = env;477creator.vector = formats;478creator.directAudioDeviceClass = clazz;479creator.addFormat = (*env)->GetStaticMethodID(env, clazz, "addFormat",480"(Ljava/util/Vector;IIIFIZZ)V");481if (creator.addFormat == NULL) {482ERROR0("Could not get method ID for addFormat!\n");483} else {484DAUDIO_GetFormats((INT32) mixerIndex, (INT32) deviceID, (int) isSource, &creator);485}486#endif487}488489490491/*492* Class: com_sun_media_sound_DirectAudioDevice493* Method: nOpen494* Signature: (IIZIFIIZZI)J495*/496JNIEXPORT jlong JNICALL Java_com_sun_media_sound_DirectAudioDevice_nOpen497(JNIEnv* env, jclass clazz, jint mixerIndex, jint deviceID, jboolean isSource,498jint encoding, jfloat sampleRate, jint sampleSizeInBits, jint frameSize, jint channels,499jboolean isSigned, jboolean isBigendian, jint bufferSizeInBytes) {500501DAUDIO_Info* info = NULL;502#if USE_DAUDIO == TRUE503504info = (DAUDIO_Info*) malloc(sizeof(DAUDIO_Info));505if (info == NULL) {506ERROR0("DirectAudioDevice_nOpen: Out of memory!\n");507} else {508info->handle =DAUDIO_Open((int) mixerIndex, (INT32) deviceID, (int) isSource,509(int) encoding, (float) sampleRate, (int) sampleSizeInBits,510(int) frameSize, (int) channels,511(int) isSigned, (int) isBigendian, (int) bufferSizeInBytes);512if (!info->handle) {513free(info);514info = NULL;515} else {516info->encoding = encoding;517info->sampleSizeInBits = sampleSizeInBits;518info->frameSize = frameSize;519info->channels = channels;520info->isSigned = isSigned;521info->isBigEndian = isBigendian && (sampleSizeInBits > 8);522/* will be populated on demand */523info->conversionBuffer = NULL;524info->conversionBufferSize = 0;525}526}527#endif528return (jlong) (UINT_PTR) info;529}530531/*532* Class: com_sun_media_sound_DirectAudioDevice533* Method: nStart534* Signature: (JZ)V535*/536JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nStart537(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {538#if USE_DAUDIO == TRUE539DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;540if (info && info->handle) {541DAUDIO_Start(info->handle, (int) isSource);542}543#endif544}545546547/*548* Class: com_sun_media_sound_DirectAudioDevice549* Method: nStop550* Signature: (JZ)V551*/552JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nStop553(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {554#if USE_DAUDIO == TRUE555DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;556if (info && info->handle) {557DAUDIO_Stop(info->handle, (int) isSource);558}559#endif560}561562563/*564* Class: com_sun_media_sound_DirectAudioDevice565* Method: nClose566* Signature: (JZ)V567*/568JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nClose569(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {570#if USE_DAUDIO == TRUE571DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;572if (info && info->handle) {573DAUDIO_Close(info->handle, (int) isSource);574if (info->conversionBuffer) {575free(info->conversionBuffer);576}577free(info);578}579#endif580}581582/*583* Class: com_sun_media_sound_DirectAudioDevice584* Method: nWrite585* Signature: (J[BII)I586*/587JNIEXPORT jint JNICALL Java_com_sun_media_sound_DirectAudioDevice_nWrite588(JNIEnv *env, jclass clazz, jlong id, jbyteArray jData,589jint offset, jint len, jint conversionSize, jfloat leftGain, jfloat rightGain) {590int ret = -1;591#if USE_DAUDIO == TRUE592UINT8* data;593UINT8* dataOffset;594UINT8* convertedData;595jboolean didCopy;596DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;597598/* a little sanity */599if (offset < 0 || len < 0) {600ERROR2("nWrite: wrong parameters: offset=%d, len=%d\n", offset, len);601return ret;602}603if (len == 0) return 0;604if (info && info->handle) {605data = (UINT8*) ((*env)->GetByteArrayElements(env, jData, &didCopy));606CHECK_NULL_RETURN(data, ret);607dataOffset = data;608dataOffset += (int) offset;609convertedData = dataOffset;610611if (conversionSize > 0 || leftGain != 1.0f || rightGain != 1.0f) {612/* make sure we have a buffer for the intermediate data */613if (didCopy == JNI_FALSE) {614/* let's do our own copy */615if (info->conversionBuffer616&& info->conversionBufferSize < len) {617free(info->conversionBuffer);618info->conversionBuffer = NULL;619info->conversionBufferSize = 0;620}621if (!info->conversionBuffer) {622info->conversionBuffer = (UINT8*) malloc(len);623if (!info->conversionBuffer) {624// do not commit the native array625(*env)->ReleaseByteArrayElements(env, jData, (jbyte*) data, JNI_ABORT);626return -1;627}628info->conversionBufferSize = len;629}630convertedData = info->conversionBuffer;631}632if (((ABS_VALUE(leftGain - 1.0f) < 0.01)633&& (ABS_VALUE(rightGain - 1.0f) < 0.01))634|| info->encoding!=DAUDIO_PCM635|| ((info->channels * info->sampleSizeInBits / 8) != info->frameSize)636|| (info->sampleSizeInBits != 8 && info->sampleSizeInBits != 16)) {637handleSignEndianConversion((INT8*) dataOffset, (INT8*) convertedData, (int) len,638(int) conversionSize);639} else {640handleGainAndConversion(info, dataOffset, convertedData,641(int) len, (float) leftGain, (float) rightGain,642(int) conversionSize);643}644}645646ret = DAUDIO_Write(info->handle, (INT8*) convertedData, (int) len);647648// do not commit the native array649(*env)->ReleaseByteArrayElements(env, jData, (jbyte*) data, JNI_ABORT);650}651#endif652return (jint) ret;653}654655/*656* Class: com_sun_media_sound_DirectAudioDevice657* Method: nRead658* Signature: (J[BII)I659*/660JNIEXPORT jint JNICALL Java_com_sun_media_sound_DirectAudioDevice_nRead661(JNIEnv* env, jclass clazz, jlong id, jbyteArray jData, jint offset, jint len, jint conversionSize) {662int ret = -1;663#if USE_DAUDIO == TRUE664char* data;665char* dataOffset;666DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;667668/* a little sanity */669if (offset < 0 || len < 0) {670ERROR2("nRead: wrong parameters: offset=%d, len=%d\n", offset, len);671return ret;672}673if (info && info->handle) {674data = (char*) ((*env)->GetByteArrayElements(env, jData, NULL));675CHECK_NULL_RETURN(data, ret);676dataOffset = data;677dataOffset += (int) offset;678ret = DAUDIO_Read(info->handle, dataOffset, (int) len);679if (conversionSize > 0) {680handleSignEndianConversion(dataOffset, dataOffset, (int) len, (int) conversionSize);681}682// commit the native array683(*env)->ReleaseByteArrayElements(env, jData, (jbyte*) data, 0);684}685#endif686return (jint) ret;687}688689/*690* Class: com_sun_media_sound_DirectAudioDevice691* Method: nGetBufferSize692* Signature: (JZ)I693*/694JNIEXPORT jint JNICALL Java_com_sun_media_sound_DirectAudioDevice_nGetBufferSize695(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {696int ret = -1;697#if USE_DAUDIO == TRUE698DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;699if (info && info->handle) {700ret = DAUDIO_GetBufferSize(info->handle, (int) isSource);701}702#endif703return (jint) ret;704}705706707/*708* Class: com_sun_media_sound_DirectAudioDevice709* Method: nIsStillDraining710* Signature: (JZ)Z711*/712JNIEXPORT jboolean JNICALL Java_com_sun_media_sound_DirectAudioDevice_nIsStillDraining713(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {714int ret = FALSE;715#if USE_DAUDIO == TRUE716DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;717if (info && info->handle) {718ret = DAUDIO_StillDraining(info->handle, (int) isSource)?TRUE:FALSE;719}720#endif721return (jboolean) ret;722}723724725/*726* Class: com_sun_media_sound_DirectAudioDevice727* Method: nFlush728* Signature: (JZ)V729*/730JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nFlush731(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {732#if USE_DAUDIO == TRUE733DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;734if (info && info->handle) {735DAUDIO_Flush(info->handle, (int) isSource);736}737#endif738}739740741/*742* Class: com_sun_media_sound_DirectAudioDevice743* Method: nAvailable744* Signature: (JZ)I745*/746JNIEXPORT jint JNICALL Java_com_sun_media_sound_DirectAudioDevice_nAvailable747(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {748int ret = -1;749#if USE_DAUDIO == TRUE750DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;751if (info && info->handle) {752ret = DAUDIO_GetAvailable(info->handle, (int) isSource);753}754#endif755return (jint) ret;756}757758759/*760* Class: com_sun_media_sound_DirectAudioDevice761* Method: nGetBytePosition762* Signature: (JZJ)J763*/764JNIEXPORT jlong JNICALL Java_com_sun_media_sound_DirectAudioDevice_nGetBytePosition765(JNIEnv* env, jclass clazz, jlong id, jboolean isSource, jlong javaBytePos) {766INT64 ret = (INT64) javaBytePos;767#if USE_DAUDIO == TRUE768DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;769if (info && info->handle) {770ret = DAUDIO_GetBytePosition(info->handle, (int) isSource, (INT64) javaBytePos);771}772#endif773return (jlong) ret;774}775776/*777* Class: com_sun_media_sound_DirectAudioDevice778* Method: nSetBytePosition779* Signature: (JZJ)V780*/781JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nSetBytePosition782(JNIEnv* env, jclass clazz, jlong id, jboolean isSource, jlong pos) {783#if USE_DAUDIO == TRUE784DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;785if (info && info->handle) {786DAUDIO_SetBytePosition(info->handle, (int) isSource, (INT64) pos);787}788#endif789}790791/*792* Class: com_sun_media_sound_DirectAudioDevice793* Method: nRequiresServicing794* Signature: (JZ)B795*/796JNIEXPORT jboolean JNICALL Java_com_sun_media_sound_DirectAudioDevice_nRequiresServicing797(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {798int ret = FALSE;799#if USE_DAUDIO == TRUE800DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;801if (info && info->handle) {802ret = DAUDIO_RequiresServicing(info->handle, (int) isSource);803}804#endif805return (jboolean) ret;806}807/*808* Class: com_sun_media_sound_DirectAudioDevice809* Method: nService810* Signature: (JZ)V811*/812JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nService813(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {814#if USE_DAUDIO == TRUE815DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;816if (info && info->handle) {817DAUDIO_Service(info->handle, (int) isSource);818}819#endif820}821822823