/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* TODO:
* - move all the conversion code into an own file
*/
//#define USE_TRACE
//#define USE_ERROR
#include <jni.h>
// for malloc
#ifdef _ALLBSD_SOURCE
#include <stdlib.h>
#else
#include <malloc.h>
#endif
#include "SoundDefs.h"
#include "DirectAudio.h"
#include "Utilities.h"
#include "com_sun_media_sound_DirectAudioDevice.h"
typedef struct {
void* handle;
int encoding;
int sampleSizeInBits;
int frameSize;
int channels;
int isSigned;
int isBigEndian;
int conversionBufferSize;
} DAUDIO_Info;
//////////////////////////////////////////// MAP Conversion stuff /////////////////////////////////
/* 16 bit signed sample, native endianness, stored in 32-bits */
return (a>>8) | (a<<8);
}
return (a>>24)
| ((a>>8) & 0xFF00)
| ((a<<8) & 0xFF0000)
| (a<<24);
}
}
if (sample < -32768) {
return -32768;
}
else if (sample > 32767) {
return 32767;
}
}
if (sample < -32768) {
return 0x0080;
}
else if (sample > 32767) {
return 0xFF7F;
}
}
if (sample < -32768) {
return -128;
}
else if (sample > 32767) {
return 127;
}
}
if (sample < -32768) {
return 0;
}
else if (sample > 32767) {
return 255;
}
}
#ifdef _LITTLE_ENDIAN
#else
#endif
#ifndef _LITTLE_ENDIAN
#else
#endif
/* macros for endian conversion */
#ifdef _LITTLE_ENDIAN
#define MAP_NATIVE2LE16(a) (a)
#define MAP_NATIVE2LE32(a) (a)
#else
#define MAP_NATIVE2BE16(a) (a)
#define MAP_NATIVE2BE32(a) (a)
#endif
////////////////////////////// Utility function /////////////////////////////////
/*
* conversion of this buffer:
* conversion size=1 -> each byte is converted from signed to unsigned or vice versa
* conversion size=2,3,4: the order of bytes in a sample is reversed (endianness)
* for sign conversion of a 24-bit sample stored in 32bits, 4 should be passed
* as conversionSize
*/
switch (conversionSize) {
case 1: {
while (byteSize > 0) {
byteSize--;
data++;
output++;
}
break;
}
case 2: {
INT8 h;
while (byteSize > 0) {
h = *data;
data++;
output++;
*output = h;
byteSize--;
}
break;
}
case 3: {
INT8 h;
while (byteSize > 0) {
h = *data;
*output = h;
byteSize--;
}
break;
}
case 4: {
while (byteSize > 0) {
data += 4;
byteSize--;
}
break;
}
default:
}
}
/* aply the gain to one sample */
/* convert to MAP_Sample native type */ \
/* apply gain */ \
/* convert to output type */ \
/* macro for conversion of a mono block */
if (leftGain > 1.0) { \
FROM_SAMPLE_CLIP, leftGain); \
} \
} else { \
FROM_SAMPLE, leftGain); \
} \
} \
break
/* macro for conversion of a stereo block */
if (leftGain > 1.0) { \
if (rightGain > 1.0) { \
FROM_SAMPLE_CLIP, leftGain); \
} \
} else { \
FROM_SAMPLE_CLIP, leftGain); \
FROM_SAMPLE, rightGain); \
} \
} \
} else { \
if (rightGain > 1.0) { \
FROM_SAMPLE, leftGain); \
} \
} else { \
FROM_SAMPLE, leftGain); \
FROM_SAMPLE, rightGain); \
} \
} \
} \
break
(channels << 20) \
| (bits << 4) \
| (outBigEndian & 1)
int conversionSize) {
if (conversionSize == 1) {
/* 8-bit conversion: change sign */
inIsSigned = !inIsSigned;
}
else if (conversionSize > 1) {
/* > 8-bit conversion: change endianness */
}
return;
}
TRACE3("handleGainAndConversion: len=%d frames, leftGain=%f, rightGain=%f, ",
TRACE3("channels=%d, sampleSizeInBits=%d, frameSize=%d, ",
TRACE4("signed:%d -> %d, endian: %d -> %d",
info->isBigEndian)) {
/* 8-bit mono */
case FORMAT2CODE8(1, 0, 0):
/* 8-bit stereo */
case FORMAT2CODE8(2, 0, 0):
/* 16-bit mono (only signed is accepted) */
case FORMAT2CODE16(1, 0, 0):
/* 16-bit stereo (only signed is accepted) */
case FORMAT2CODE16(2, 0, 0):
default:
ERROR3("DirectAudioDevice: Cannot convert from native format: "
"bits=%d, inSigned=%d outSigned=%d, ",
(int) info->sampleSizeInBits,
ERROR2("inBigEndian=%d, outBigEndian=%d\n",
}
}
float ABS_VALUE(float a) {
return (a < 0)?-a:a;
}
//////////////////////////////////////////// DirectAudioDevice ////////////////////////////////////////////
/* ************************************** native control creation support ********************* */
// contains all the needed references so that the platform dependent code can call JNI wrapper functions
typedef struct tag_AddFormatCreator {
// general JNI variables
// the vector to be filled with the formats
// the class containing the addFormat method
// the method to be called to add the format
int channels, float sampleRate,
int bigEndian) {
if (frameSizeInBytes <= 0) {
if (channels > 0) {
} else {
frameSizeInBytes = -1;
}
}
TRACE4("AddAudioFormat with sigBits=%d bits, frameSize=%d bytes, channels=%d, sampleRate=%d ",
}
////////////////////////////////////// JNI /////////////////////////////////////////////////////////////////////
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nGetFormats
*/
#if USE_DAUDIO == TRUE
ERROR0("Could not get method ID for addFormat!\n");
} else {
}
#endif
}
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nOpen
* Signature: (IIZIFIIZZI)J
*/
#if USE_DAUDIO == TRUE
ERROR0("DirectAudioDevice_nOpen: Out of memory!\n");
} else {
} else {
/* will be populated on demand */
info->conversionBufferSize = 0;
}
}
#endif
}
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nStart
* Signature: (JZ)V
*/
#if USE_DAUDIO == TRUE
}
#endif
}
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nStop
* Signature: (JZ)V
*/
#if USE_DAUDIO == TRUE
}
#endif
}
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nClose
* Signature: (JZ)V
*/
#if USE_DAUDIO == TRUE
if (info->conversionBuffer) {
}
}
#endif
}
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nWrite
* Signature: (J[BII)I
*/
#if USE_DAUDIO == TRUE
/* a little sanity */
return ret;
}
if (len == 0) return 0;
dataOffset = data;
dataOffset += (int) offset;
/* make sure we have a buffer for the intermediate data */
/* let's do our own copy */
if (info->conversionBuffer
info->conversionBufferSize = 0;
}
if (!info->conversionBuffer) {
if (!info->conversionBuffer) {
// do not commit the native array
return -1;
}
}
}
(int) conversionSize);
} else {
(int) conversionSize);
}
}
// do not commit the native array
}
#endif
}
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nRead
* Signature: (J[BII)I
*/
(JNIEnv* env, jclass clazz, jlong id, jbyteArray jData, jint offset, jint len, jint conversionSize) {
#if USE_DAUDIO == TRUE
char* data;
char* dataOffset;
/* a little sanity */
return ret;
}
dataOffset = data;
dataOffset += (int) offset;
if (conversionSize > 0) {
}
// commit the native array
}
#endif
}
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nGetBufferSize
* Signature: (JZ)I
*/
#if USE_DAUDIO == TRUE
}
#endif
}
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nIsStillDraining
* Signature: (JZ)Z
*/
#if USE_DAUDIO == TRUE
}
#endif
}
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nFlush
* Signature: (JZ)V
*/
#if USE_DAUDIO == TRUE
}
#endif
}
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nAvailable
* Signature: (JZ)I
*/
#if USE_DAUDIO == TRUE
}
#endif
}
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nGetBytePosition
* Signature: (JZJ)J
*/
#if USE_DAUDIO == TRUE
}
#endif
}
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nSetBytePosition
* Signature: (JZJ)V
*/
#if USE_DAUDIO == TRUE
}
#endif
}
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nRequiresServicing
* Signature: (JZ)B
*/
#if USE_DAUDIO == TRUE
}
#endif
}
/*
* Class: com_sun_media_sound_DirectAudioDevice
* Method: nService
* Signature: (JZ)V
*/
#if USE_DAUDIO == TRUE
}
#endif
}