jdk

Форк
0
/
DirectAudioDevice.c 
821 строка · 29.1 Кб
1
/*
2
 * Copyright (c) 2002, 2014, 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
#include <jni_util.h>
36
// for malloc
37
#ifdef _ALLBSD_SOURCE
38
#include <stdlib.h>
39
#else
40
#include <malloc.h>
41
#endif
42
#include "SoundDefs.h"
43
#include "DirectAudio.h"
44
#include "Utilities.h"
45
#include "com_sun_media_sound_DirectAudioDevice.h"
46

47

48
typedef struct {
49
    void* handle;
50
    int encoding;
51
    int sampleSizeInBits;
52
    int frameSize;
53
    int channels;
54
    int isSigned;
55
    int isBigEndian;
56
    UINT8* conversionBuffer;
57
    int conversionBufferSize;
58
} DAUDIO_Info;
59

60

61
//////////////////////////////////////////// MAP Conversion stuff /////////////////////////////////
62

63
/* 16 bit signed sample, native endianness, stored in 32-bits */
64
typedef INT32 MAP_Sample;
65

66
static INLINE UINT16 MAP_SWAP16_impl(UINT16 a) {
67
    return (a>>8) | (a<<8);
68
}
69

70
static INLINE UINT32 MAP_SWAP32_impl(UINT32 a) {
71
    return (a>>24)
72
        | ((a>>8) & 0xFF00)
73
        | ((a<<8) & 0xFF0000)
74
        | (a<<24);
75
}
76

77
static INLINE UINT32 MAP_SWAP16BIT(UINT32 sh) {
78
    return (UINT32) ((sh & 0xFF) << 8) | ((sh & 0xFF00) >> 8);
79
}
80

81
static INLINE INT32 MAP_ClipAndConvertToShort(MAP_Sample sample) {
82
    if (sample < -32768) {
83
        return -32768;
84
    }
85
    else if (sample > 32767) {
86
        return 32767;
87
    }
88
    return (INT32) sample;
89
}
90

91

92
static INLINE INT32 MAP_ClipAndConvertToShort_Swapped(MAP_Sample sample) {
93
    if (sample < -32768) {
94
        return 0x0080;
95
    }
96
    else if (sample > 32767) {
97
        return 0xFF7F;
98
    }
99
    return (INT32) (INT16) MAP_SWAP16BIT(sample);
100
}
101

102
static INLINE INT8 MAP_ClipAndConvertToByte(MAP_Sample sample) {
103
    if (sample < -32768) {
104
        return -128;
105
    }
106
    else if (sample > 32767) {
107
        return 127;
108
    }
109
    return (INT8) (sample >> 8);
110
}
111

112

113
static INLINE UINT8 MAP_ClipAndConvertToUByte(MAP_Sample sample) {
114
    if (sample < -32768) {
115
        return 0;
116
    }
117
    else if (sample > 32767) {
118
        return 255;
119
    }
120
    return (UINT8) ((sample >> 8) + 128);
121
}
122

123
/* conversion from/to 16 bit signed little endian to native endian samples */
124
#ifdef _LITTLE_ENDIAN
125
#define MAP_LE_SHORT2SAMPLE(sh) ((MAP_Sample) (sh))
126
#define MAP_SAMPLE2LE_SHORT(sample) (sample)
127
#define MAP_SAMPLE2LE_SHORT_CLIP(sample) MAP_ClipAndConvertToShort(sample)
128
#else
129
#define MAP_LE_SHORT2SAMPLE(sh) ((MAP_Sample) (INT16) MAP_SWAP16BIT(sh))
130
#define MAP_SAMPLE2LE_SHORT(sample) (INT16) MAP_SWAP16BIT(sample)
131
#define MAP_SAMPLE2LE_SHORT_CLIP(sample) MAP_ClipAndConvertToShort_Swapped(sample)
132
#endif
133

134
/* conversion from/to 16 bit signed big endian to native endian samples */
135
#ifndef _LITTLE_ENDIAN
136
#define MAP_BE_SHORT2SAMPLE(sh) ((MAP_Sample) (sh))
137
#define MAP_SAMPLE2BE_SHORT(sample) (sample)
138
#define MAP_SAMPLE2BE_SHORT_CLIP(sample) MAP_ClipAndConvertToShort(sample)
139
#else
140
#define MAP_BE_SHORT2SAMPLE(sh) ((MAP_Sample) (INT16) MAP_SWAP16BIT(sh))
141
#define MAP_SAMPLE2BE_SHORT(sample) ((INT16) MAP_SWAP16BIT(sample))
142
#define MAP_SAMPLE2BE_SHORT_CLIP(sample) MAP_ClipAndConvertToShort_Swapped(sample)
143
#endif
144

145
/* conversion from/to 8 bit samples */
146
#define MAP_INT82SAMPLE(by) ((MAP_Sample) (((INT32) ((INT8) (by))) << 8))
147
#define MAP_UINT82SAMPLE(by) ((MAP_Sample) (((INT32) ((UINT8) (by) - 128)) << 8))
148
#define MAP_SAMPLE2UINT8(sample) ((UINT8) ((((MAP_Sample) (sample)) >> 8) + 128))
149
#define MAP_SAMPLE2INT8(sample) ((INT8) (((MAP_Sample) (sample)) >> 8))
150
#define MAP_SAMPLE2UINT8_CLIP(sample) MAP_ClipAndConvertToUByte(sample)
151
#define MAP_SAMPLE2INT8_CLIP(sample) MAP_ClipAndConvertToByte(sample)
152

153
/* macros for endian conversion */
154
#ifdef _LITTLE_ENDIAN
155
#define MAP_NATIVE2LE16(a) (a)
156
#define MAP_NATIVE2BE16(a) MAP_SWAP16_impl(a)
157
#define MAP_NATIVE2LE32(a) (a)
158
#define MAP_NATIVE2BE32(a) MAP_SWAP32_impl(a)
159
#else
160
#define MAP_NATIVE2LE16(a) MAP_SWAP16_impl(a)
161
#define MAP_NATIVE2BE16(a) (a)
162
#define MAP_NATIVE2LE32(a) MAP_SWAP32_impl(a)
163
#define MAP_NATIVE2BE32(a) (a)
164
#endif
165
#define MAP_LE2NATIVE16(a) MAP_NATIVE2LE16(a)
166
#define MAP_BE2NATIVE16(a) MAP_NATIVE2BE16(a)
167
#define MAP_LE2NATIVE32(a) MAP_NATIVE2LE32(a)
168
#define MAP_BE2NATIVE32(a) MAP_NATIVE2BE32(a)
169

170

171
////////////////////////////// Utility function /////////////////////////////////
172

173
/*
174
 * conversion of this buffer:
175
 * conversion size=1 -> each byte is converted from signed to unsigned or vice versa
176
 * conversion size=2,3,4: the order of bytes in a sample is reversed (endianness)
177
 * for sign conversion of a 24-bit sample stored in 32bits, 4 should be passed
178
 * as conversionSize
179
 */
180
void handleSignEndianConversion(INT8* data, INT8* output, int byteSize, int conversionSize) {
181
    TRACE1("conversion with size %d\n", conversionSize);
182
    switch (conversionSize) {
183
    case 1: {
184
        while (byteSize > 0) {
185
            *output = *data + (char) 128; // use wrap-around
186
            byteSize--;
187
            data++;
188
            output++;
189
        }
190
        break;
191
    }
192
    case 2: {
193
        INT8 h;
194
        byteSize = byteSize / 2;
195
        while (byteSize > 0) {
196
            h = *data;
197
            data++;
198
            *output = *data;
199
            output++;
200
            *output = h;
201
            byteSize--;
202
            data++; output++;
203
        }
204
        break;
205
    }
206
    case 3: {
207
        INT8 h;
208
        byteSize = byteSize / 3;
209
        while (byteSize > 0) {
210
            h = *data;
211
            *output = data[2];
212
            data++; output++;
213
            *output = *data;
214
            data++; output++;
215
            *output = h;
216
            data++; output++;
217
            byteSize--;
218
        }
219
        break;
220
    }
221
    case 4: {
222
        INT8 h1, h2;
223
        byteSize = byteSize / 4;
224
        while (byteSize > 0) {
225
            h1 = data[0];
226
            h2 = data[1];
227
            *output = data[3]; output++;
228
            *output = data[2]; output++;
229
            *output = h2; output++;
230
            *output = h1; output++;
231
            data += 4;
232
            byteSize--;
233
        }
234
        break;
235
    }
236
    default:
237
        ERROR1("DirectAudioDevice.c: wrong conversionSize %d!\n", conversionSize);
238
    }
239
}
240

241
/* aply the gain to one sample */
242
#define CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE, FROM_SAMPLE, FACTOR) \
243
    /* convert to MAP_Sample native type */     \
244
    sample = TO_SAMPLE(*INPUT);                 \
245
    /* apply gain */                            \
246
    sample = (MAP_Sample) (sample * FACTOR);    \
247
    /* convert to output type */                \
248
    (*OUTPUT) = FROM_SAMPLE(sample);            \
249
    INPUT++; OUTPUT++
250

251

252
/* macro for conversion of a mono block */
253
#define LOOP_M(INPUT, OUTPUT, TO_SAMPLE, FROM_SAMPLE, FROM_SAMPLE_CLIP) \
254
    if (leftGain > 1.0) {                                               \
255
        for ( ; len > 0; --len) {                                       \
256
            CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE,                    \
257
                           FROM_SAMPLE_CLIP, leftGain);                 \
258
        }                                                               \
259
    } else {                                                            \
260
        for ( ; len > 0; --len) {                                       \
261
            CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE,                    \
262
                           FROM_SAMPLE, leftGain);                      \
263
        }                                                               \
264
    }                                                                   \
265
    break
266

267
/* macro for conversion of a stereo block */
268
#define LOOP_S(INPUT, OUTPUT, TO_SAMPLE, FROM_SAMPLE, FROM_SAMPLE_CLIP) \
269
    if (leftGain > 1.0) {                                               \
270
        if (rightGain > 1.0) {                                          \
271
            for ( ; len > 0; --len) {                                   \
272
                CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE,                \
273
                               FROM_SAMPLE_CLIP, leftGain);             \
274
                CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE,                \
275
                               FROM_SAMPLE_CLIP, rightGain);            \
276
            }                                                           \
277
        } else {                                                        \
278
            for ( ; len > 0; --len) {                                   \
279
                CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE,                \
280
                               FROM_SAMPLE_CLIP, leftGain);             \
281
                CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE,                \
282
                               FROM_SAMPLE, rightGain);                 \
283
            }                                                           \
284
        }                                                               \
285
    } else {                                                            \
286
        if (rightGain > 1.0) {                                          \
287
            for ( ; len > 0; --len) {                                   \
288
                CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE,                \
289
                               FROM_SAMPLE, leftGain);                  \
290
                CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE,                \
291
                               FROM_SAMPLE_CLIP, rightGain);            \
292
            }                                                           \
293
        } else {                                                        \
294
            for ( ; len > 0; --len) {                                   \
295
                CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE,                \
296
                               FROM_SAMPLE, leftGain);                  \
297
                CONVERT_SAMPLE(INPUT, OUTPUT, TO_SAMPLE,                \
298
                               FROM_SAMPLE, rightGain);                 \
299
            }                                                           \
300
        }                                                               \
301
    }                                                                   \
302
    break
303

304
#define FORMAT2CODE(channels, bits, inSigned, outSigned, inBigEndian, outBigEndian) \
305
      (channels << 20)                                                  \
306
    | (bits << 4)                                                       \
307
    | ((inSigned & 1) << 3)                                             \
308
    | ((outSigned & 1) << 2)                                            \
309
    | ((inBigEndian & 1) << 1)                                          \
310
    | (outBigEndian & 1)
311

312
#define FORMAT2CODE8(channels, inSigned, outSigned)           \
313
    FORMAT2CODE(channels, 8, inSigned, outSigned, 0, 0)
314

315
#define FORMAT2CODE16(channels, inBigEndian, outBigEndian)    \
316
    FORMAT2CODE(channels, 16, 1, 1, inBigEndian, outBigEndian)
317

318

319
void handleGainAndConversion(DAUDIO_Info* info, UINT8* input, UINT8* output,
320
                             int len, float leftGain, float rightGain,
321
                             int conversionSize) {
322
    INT8* input8 = (INT8*) input;
323
    INT8* output8 = (INT8*) output;
324
    INT16* input16 = (INT16*) input;
325
    INT16* output16 = (INT16*) output;
326
    MAP_Sample sample;
327

328
    int inIsSigned = info->isSigned;
329
    int inIsBigEndian = info->isBigEndian;
330
    if (conversionSize == 1) {
331
        /* 8-bit conversion: change sign */
332
        inIsSigned = !inIsSigned;
333
    }
334
    else if (conversionSize > 1) {
335
        /* > 8-bit conversion: change endianness */
336
        inIsBigEndian = !inIsBigEndian;
337
    }
338
    if (info->frameSize <= 0) {
339
        ERROR1("DirectAudiODevice: invalid framesize=%d\n", info->frameSize);
340
        return;
341
    }
342
    len /= info->frameSize;
343
    TRACE3("handleGainAndConversion: len=%d frames, leftGain=%f, rightGain=%f, ",
344
           len, leftGain, rightGain);
345
    TRACE3("channels=%d, sampleSizeInBits=%d, frameSize=%d, ",
346
           (int) info->channels, (int) info->sampleSizeInBits, (int) info->frameSize);
347
    TRACE4("signed:%d -> %d, endian: %d -> %d",
348
           (int) inIsSigned, (int) info->isSigned,
349
           (int) inIsBigEndian, (int) info->isBigEndian);
350
    TRACE1("convSize=%d\n", conversionSize);
351

352
    switch (FORMAT2CODE(info->channels,
353
                        info->sampleSizeInBits,
354
                        inIsSigned,
355
                        info->isSigned,
356
                        inIsBigEndian,
357
                        info->isBigEndian)) {
358
        /* 8-bit mono */
359
    case FORMAT2CODE8(1, 0, 0):
360
        LOOP_M(input8, output8, MAP_UINT82SAMPLE,
361
               MAP_SAMPLE2UINT8, MAP_SAMPLE2UINT8_CLIP);
362
    case FORMAT2CODE8(1, 0, 1):
363
        LOOP_M(input8, output8, MAP_UINT82SAMPLE,
364
               MAP_SAMPLE2INT8, MAP_SAMPLE2INT8_CLIP);
365
    case FORMAT2CODE8(1, 1, 0):
366
        LOOP_M(input8, output8, MAP_INT82SAMPLE,
367
               MAP_SAMPLE2UINT8, MAP_SAMPLE2UINT8_CLIP);
368
    case FORMAT2CODE8(1, 1, 1):
369
        LOOP_M(input8, output8, MAP_INT82SAMPLE,
370
               MAP_SAMPLE2INT8, MAP_SAMPLE2INT8_CLIP);
371

372
    /* 8-bit stereo */
373
    case FORMAT2CODE8(2, 0, 0):
374
        LOOP_S(input8, output8, MAP_UINT82SAMPLE,
375
               MAP_SAMPLE2UINT8, MAP_SAMPLE2UINT8_CLIP);
376
    case FORMAT2CODE8(2, 0, 1):
377
        LOOP_S(input8, output8, MAP_UINT82SAMPLE,
378
               MAP_SAMPLE2INT8, MAP_SAMPLE2INT8_CLIP);
379
    case FORMAT2CODE8(2, 1, 0):
380
        LOOP_S(input8, output8, MAP_INT82SAMPLE,
381
               MAP_SAMPLE2UINT8, MAP_SAMPLE2UINT8_CLIP);
382
    case FORMAT2CODE8(2, 1, 1):
383
        LOOP_S(input8, output8, MAP_INT82SAMPLE,
384
               MAP_SAMPLE2INT8, MAP_SAMPLE2INT8_CLIP);
385

386
    /* 16-bit mono (only signed is accepted) */
387
    case FORMAT2CODE16(1, 0, 0):
388
        LOOP_M(input16, output16, MAP_LE_SHORT2SAMPLE,
389
               MAP_SAMPLE2LE_SHORT, MAP_SAMPLE2LE_SHORT_CLIP);
390
    case FORMAT2CODE16(1, 0, 1):
391
        LOOP_M(input16, output16, MAP_LE_SHORT2SAMPLE,
392
               MAP_SAMPLE2BE_SHORT, MAP_SAMPLE2BE_SHORT_CLIP);
393
    case FORMAT2CODE16(1, 1, 0):
394
        LOOP_M(input16, output16, MAP_BE_SHORT2SAMPLE,
395
               MAP_SAMPLE2LE_SHORT, MAP_SAMPLE2LE_SHORT_CLIP);
396
    case FORMAT2CODE16(1, 1, 1):
397
        LOOP_M(input16, output16, MAP_BE_SHORT2SAMPLE,
398
               MAP_SAMPLE2BE_SHORT, MAP_SAMPLE2BE_SHORT_CLIP);
399

400
    /* 16-bit stereo (only signed is accepted) */
401
    case FORMAT2CODE16(2, 0, 0):
402
        LOOP_S(input16, output16, MAP_LE_SHORT2SAMPLE,
403
               MAP_SAMPLE2LE_SHORT, MAP_SAMPLE2LE_SHORT_CLIP);
404
    case FORMAT2CODE16(2, 0, 1):
405
        LOOP_S(input16, output16, MAP_LE_SHORT2SAMPLE,
406
               MAP_SAMPLE2BE_SHORT, MAP_SAMPLE2BE_SHORT_CLIP);
407
    case FORMAT2CODE16(2, 1, 0):
408
        LOOP_S(input16, output16, MAP_BE_SHORT2SAMPLE,
409
               MAP_SAMPLE2LE_SHORT, MAP_SAMPLE2LE_SHORT_CLIP);
410
    case FORMAT2CODE16(2, 1, 1):
411
        LOOP_S(input16, output16, MAP_BE_SHORT2SAMPLE,
412
               MAP_SAMPLE2BE_SHORT, MAP_SAMPLE2BE_SHORT_CLIP);
413

414
    default:
415
        ERROR3("DirectAudioDevice: Cannot convert from native format: "
416
               "bits=%d, inSigned=%d  outSigned=%d, ",
417
               (int) info->sampleSizeInBits,
418
               (int) inIsSigned, (int) info->isSigned);
419
        ERROR2("inBigEndian=%d, outBigEndian=%d\n",
420
               (int) inIsBigEndian, (int) info->isBigEndian);
421
    }
422
}
423

424
float ABS_VALUE(float a) {
425
    return (a < 0)?-a:a;
426
}
427

428

429
//////////////////////////////////////////// DirectAudioDevice ////////////////////////////////////////////
430

431
/* ************************************** native control creation support ********************* */
432

433
// contains all the needed references so that the platform dependent code can call JNI wrapper functions
434
typedef struct tag_AddFormatCreator {
435
    // general JNI variables
436
    JNIEnv *env;
437
    // the vector to be filled with the formats
438
    jobject vector;
439
    // the class containing the addFormat method
440
    jclass directAudioDeviceClass;
441
    // the method to be called to add the format
442
    jmethodID addFormat; // signature (Ljava/util/Vector;IIFIBB)V
443
} AddFormatCreator;
444

445
void DAUDIO_AddAudioFormat(void* creatorV, int significantBits, int frameSizeInBytes,
446
                           int channels, float sampleRate,
447
                           int encoding, int isSigned,
448
                           int bigEndian) {
449
    AddFormatCreator* creator = (AddFormatCreator*) creatorV;
450
    if (frameSizeInBytes <= 0) {
451
        if (channels > 0) {
452
            frameSizeInBytes = ((significantBits + 7) / 8) * channels;
453
        } else {
454
            frameSizeInBytes = -1;
455
        }
456
    }
457
    TRACE4("AddAudioFormat with sigBits=%d bits, frameSize=%d bytes, channels=%d, sampleRate=%d ",
458
           significantBits, frameSizeInBytes, channels, (int) sampleRate);
459
    TRACE3("enc=%d, signed=%d, bigEndian=%d\n", encoding, isSigned, bigEndian);
460
    (*creator->env)->CallStaticVoidMethod(creator->env, creator->directAudioDeviceClass,
461
                                          creator->addFormat, creator->vector, significantBits, frameSizeInBytes,
462
                                          channels, sampleRate, encoding, isSigned, bigEndian);
463
}
464

465
////////////////////////////////////// JNI /////////////////////////////////////////////////////////////////////
466

467
/*
468
 * Class:     com_sun_media_sound_DirectAudioDevice
469
 * Method:    nGetFormats
470
 * Signature: (IIZLjava/util/Vector;)V
471
 */
472
JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nGetFormats
473
(JNIEnv *env, jclass clazz, jint mixerIndex, jint deviceID, jboolean isSource, jobject formats) {
474

475
#if USE_DAUDIO == TRUE
476
    AddFormatCreator creator;
477
    creator.env = env;
478
    creator.vector = formats;
479
    creator.directAudioDeviceClass = clazz;
480
    creator.addFormat = (*env)->GetStaticMethodID(env, clazz, "addFormat",
481
                                                  "(Ljava/util/Vector;IIIFIZZ)V");
482
    if (creator.addFormat == NULL) {
483
        ERROR0("Could not get method ID for addFormat!\n");
484
    } else {
485
        DAUDIO_GetFormats((INT32) mixerIndex, (INT32) deviceID, (int) isSource, &creator);
486
    }
487
#endif
488
}
489

490

491

492
/*
493
 * Class:     com_sun_media_sound_DirectAudioDevice
494
 * Method:    nOpen
495
 * Signature: (IIZIFIIZZI)J
496
 */
497
JNIEXPORT jlong JNICALL Java_com_sun_media_sound_DirectAudioDevice_nOpen
498
(JNIEnv* env, jclass clazz, jint mixerIndex, jint deviceID, jboolean isSource,
499
 jint encoding, jfloat sampleRate, jint sampleSizeInBits, jint frameSize, jint channels,
500
 jboolean isSigned, jboolean isBigendian, jint bufferSizeInBytes) {
501

502
    DAUDIO_Info* info = NULL;
503
#if USE_DAUDIO == TRUE
504

505
    info = (DAUDIO_Info*) malloc(sizeof(DAUDIO_Info));
506
    if (info == NULL) {
507
        ERROR0("DirectAudioDevice_nOpen: Out of memory!\n");
508
    } else {
509
        info->handle =DAUDIO_Open((int) mixerIndex, (INT32) deviceID, (int) isSource,
510
                                  (int) encoding, (float) sampleRate, (int) sampleSizeInBits,
511
                                  (int) frameSize, (int) channels,
512
                                  (int) isSigned, (int) isBigendian, (int) bufferSizeInBytes);
513
        if (!info->handle) {
514
            free(info);
515
            info = NULL;
516
        } else {
517
            info->encoding = encoding;
518
            info->sampleSizeInBits = sampleSizeInBits;
519
            info->frameSize = frameSize;
520
            info->channels = channels;
521
            info->isSigned = isSigned;
522
            info->isBigEndian = isBigendian && (sampleSizeInBits > 8);
523
            /* will be populated on demand */
524
            info->conversionBuffer = NULL;
525
            info->conversionBufferSize = 0;
526
        }
527
    }
528
#endif
529
    return (jlong) (UINT_PTR) info;
530
}
531

532
/*
533
 * Class:     com_sun_media_sound_DirectAudioDevice
534
 * Method:    nStart
535
 * Signature: (JZ)V
536
 */
537
JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nStart
538
(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {
539
#if USE_DAUDIO == TRUE
540
    DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;
541
    if (info && info->handle) {
542
        DAUDIO_Start(info->handle, (int) isSource);
543
    }
544
#endif
545
}
546

547

548
/*
549
 * Class:     com_sun_media_sound_DirectAudioDevice
550
 * Method:    nStop
551
 * Signature: (JZ)V
552
 */
553
JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nStop
554
(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {
555
#if USE_DAUDIO == TRUE
556
    DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;
557
    if (info && info->handle) {
558
        DAUDIO_Stop(info->handle, (int) isSource);
559
    }
560
#endif
561
}
562

563

564
/*
565
 * Class:     com_sun_media_sound_DirectAudioDevice
566
 * Method:    nClose
567
 * Signature: (JZ)V
568
 */
569
JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nClose
570
(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {
571
#if USE_DAUDIO == TRUE
572
    DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;
573
    if (info && info->handle) {
574
        DAUDIO_Close(info->handle, (int) isSource);
575
        if (info->conversionBuffer) {
576
            free(info->conversionBuffer);
577
        }
578
        free(info);
579
    }
580
#endif
581
}
582

583
/*
584
 * Class:     com_sun_media_sound_DirectAudioDevice
585
 * Method:    nWrite
586
 * Signature: (J[BII)I
587
 */
588
JNIEXPORT jint JNICALL Java_com_sun_media_sound_DirectAudioDevice_nWrite
589
(JNIEnv *env, jclass clazz, jlong id, jbyteArray jData,
590
 jint offset, jint len, jint conversionSize, jfloat leftGain, jfloat rightGain) {
591
    int ret = -1;
592
#if USE_DAUDIO == TRUE
593
    UINT8* data;
594
    UINT8* dataOffset;
595
    UINT8* convertedData;
596
    jboolean didCopy;
597
    DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;
598

599
    /* a little sanity */
600
    if (offset < 0 || len < 0) {
601
        ERROR2("nWrite: wrong parameters: offset=%d, len=%d\n", offset, len);
602
        return ret;
603
    }
604
    if (len == 0) return 0;
605
    if (info && info->handle) {
606
        data = (UINT8*) ((*env)->GetByteArrayElements(env, jData, &didCopy));
607
        CHECK_NULL_RETURN(data, ret);
608
        dataOffset = data;
609
        dataOffset += (int) offset;
610
        convertedData = dataOffset;
611

612
        if (conversionSize > 0 || leftGain != 1.0f || rightGain != 1.0f) {
613
            /* make sure we have a buffer for the intermediate data */
614
            if (didCopy == JNI_FALSE) {
615
                /* let's do our own copy */
616
                if (info->conversionBuffer
617
                    && info->conversionBufferSize < len) {
618
                    free(info->conversionBuffer);
619
                    info->conversionBuffer = NULL;
620
                    info->conversionBufferSize = 0;
621
                }
622
                if (!info->conversionBuffer) {
623
                    info->conversionBuffer = (UINT8*) malloc(len);
624
                    if (!info->conversionBuffer) {
625
                        // do not commit the native array
626
                        (*env)->ReleaseByteArrayElements(env, jData, (jbyte*) data, JNI_ABORT);
627
                        return -1;
628
                    }
629
                    info->conversionBufferSize = len;
630
                }
631
                convertedData = info->conversionBuffer;
632
            }
633
            if (((ABS_VALUE(leftGain - 1.0f) < 0.01)
634
                 && (ABS_VALUE(rightGain - 1.0f) < 0.01))
635
                || info->encoding!=DAUDIO_PCM
636
                || ((info->channels * info->sampleSizeInBits / 8) != info->frameSize)
637
                || (info->sampleSizeInBits != 8 && info->sampleSizeInBits != 16)) {
638
                handleSignEndianConversion((INT8*) dataOffset, (INT8*) convertedData, (int) len,
639
                                           (int) conversionSize);
640
            } else {
641
                handleGainAndConversion(info, dataOffset, convertedData,
642
                                        (int) len, (float) leftGain, (float) rightGain,
643
                                        (int) conversionSize);
644
            }
645
        }
646

647
        ret = DAUDIO_Write(info->handle, (INT8*) convertedData, (int) len);
648

649
        // do not commit the native array
650
        (*env)->ReleaseByteArrayElements(env, jData, (jbyte*) data, JNI_ABORT);
651
    }
652
#endif
653
    return (jint) ret;
654
}
655

656
/*
657
 * Class:     com_sun_media_sound_DirectAudioDevice
658
 * Method:    nRead
659
 * Signature: (J[BII)I
660
 */
661
JNIEXPORT jint JNICALL Java_com_sun_media_sound_DirectAudioDevice_nRead
662
(JNIEnv* env, jclass clazz, jlong id, jbyteArray jData, jint offset, jint len, jint conversionSize) {
663
    int ret = -1;
664
#if USE_DAUDIO == TRUE
665
    char* data;
666
    char* dataOffset;
667
    DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;
668

669
    /* a little sanity */
670
    if (offset < 0 || len < 0) {
671
        ERROR2("nRead: wrong parameters: offset=%d, len=%d\n", offset, len);
672
        return ret;
673
    }
674
    if (info && info->handle) {
675
        data = (char*) ((*env)->GetByteArrayElements(env, jData, NULL));
676
        CHECK_NULL_RETURN(data, ret);
677
        dataOffset = data;
678
        dataOffset += (int) offset;
679
        ret = DAUDIO_Read(info->handle, dataOffset, (int) len);
680
        if (conversionSize > 0) {
681
            handleSignEndianConversion(dataOffset, dataOffset, (int) len, (int) conversionSize);
682
        }
683
        // commit the native array
684
        (*env)->ReleaseByteArrayElements(env, jData, (jbyte*) data, 0);
685
    }
686
#endif
687
    return (jint) ret;
688
}
689

690
/*
691
 * Class:     com_sun_media_sound_DirectAudioDevice
692
 * Method:    nGetBufferSize
693
 * Signature: (JZ)I
694
 */
695
JNIEXPORT jint JNICALL Java_com_sun_media_sound_DirectAudioDevice_nGetBufferSize
696
(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {
697
    int ret = -1;
698
#if USE_DAUDIO == TRUE
699
    DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;
700
    if (info && info->handle) {
701
        ret = DAUDIO_GetBufferSize(info->handle, (int) isSource);
702
    }
703
#endif
704
    return (jint) ret;
705
}
706

707

708
/*
709
 * Class:     com_sun_media_sound_DirectAudioDevice
710
 * Method:    nIsStillDraining
711
 * Signature: (JZ)Z
712
 */
713
JNIEXPORT jboolean JNICALL Java_com_sun_media_sound_DirectAudioDevice_nIsStillDraining
714
(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {
715
    int ret = FALSE;
716
#if USE_DAUDIO == TRUE
717
    DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;
718
    if (info && info->handle) {
719
        ret = DAUDIO_StillDraining(info->handle, (int) isSource)?TRUE:FALSE;
720
    }
721
#endif
722
    return (jboolean) ret;
723
}
724

725

726
/*
727
 * Class:     com_sun_media_sound_DirectAudioDevice
728
 * Method:    nFlush
729
 * Signature: (JZ)V
730
 */
731
JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nFlush
732
(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {
733
#if USE_DAUDIO == TRUE
734
    DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;
735
    if (info && info->handle) {
736
        DAUDIO_Flush(info->handle, (int) isSource);
737
    }
738
#endif
739
}
740

741

742
/*
743
 * Class:     com_sun_media_sound_DirectAudioDevice
744
 * Method:    nAvailable
745
 * Signature: (JZ)I
746
 */
747
JNIEXPORT jint JNICALL Java_com_sun_media_sound_DirectAudioDevice_nAvailable
748
(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {
749
    int ret = -1;
750
#if USE_DAUDIO == TRUE
751
    DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;
752
    if (info && info->handle) {
753
        ret = DAUDIO_GetAvailable(info->handle, (int) isSource);
754
    }
755
#endif
756
    return (jint) ret;
757
}
758

759

760
/*
761
 * Class:     com_sun_media_sound_DirectAudioDevice
762
 * Method:    nGetBytePosition
763
 * Signature: (JZJ)J
764
 */
765
JNIEXPORT jlong JNICALL Java_com_sun_media_sound_DirectAudioDevice_nGetBytePosition
766
(JNIEnv* env, jclass clazz, jlong id, jboolean isSource, jlong javaBytePos) {
767
    INT64 ret = (INT64) javaBytePos;
768
#if USE_DAUDIO == TRUE
769
    DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;
770
    if (info && info->handle) {
771
        ret = DAUDIO_GetBytePosition(info->handle, (int) isSource, (INT64) javaBytePos);
772
    }
773
#endif
774
    return (jlong) ret;
775
}
776

777
/*
778
 * Class:     com_sun_media_sound_DirectAudioDevice
779
 * Method:    nSetBytePosition
780
 * Signature: (JZJ)V
781
 */
782
JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nSetBytePosition
783
(JNIEnv* env, jclass clazz, jlong id, jboolean isSource, jlong pos) {
784
#if USE_DAUDIO == TRUE
785
    DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;
786
    if (info && info->handle) {
787
        DAUDIO_SetBytePosition(info->handle, (int) isSource, (INT64) pos);
788
    }
789
#endif
790
}
791

792
/*
793
 * Class:     com_sun_media_sound_DirectAudioDevice
794
 * Method:    nRequiresServicing
795
 * Signature: (JZ)B
796
 */
797
JNIEXPORT jboolean JNICALL Java_com_sun_media_sound_DirectAudioDevice_nRequiresServicing
798
(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {
799
    int ret = FALSE;
800
#if USE_DAUDIO == TRUE
801
    DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;
802
    if (info && info->handle) {
803
        ret = DAUDIO_RequiresServicing(info->handle, (int) isSource);
804
    }
805
#endif
806
    return (jboolean) ret;
807
}
808
/*
809
 * Class:     com_sun_media_sound_DirectAudioDevice
810
 * Method:    nService
811
 * Signature: (JZ)V
812
 */
813
JNIEXPORT void JNICALL Java_com_sun_media_sound_DirectAudioDevice_nService
814
(JNIEnv* env, jclass clazz, jlong id, jboolean isSource) {
815
#if USE_DAUDIO == TRUE
816
    DAUDIO_Info* info = (DAUDIO_Info*) (UINT_PTR) id;
817
    if (info && info->handle) {
818
        DAUDIO_Service(info->handle, (int) isSource);
819
    }
820
#endif
821
}
822

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.