Prepare for additional formats beyond 8-bit and 16-bit PCM
This CL does the same thing for AudioTrack, that an earlier CL did for AudioRecord: > Change-Id: Ic3525f049e939bdf125d9f87ed39abd2690dcf9f Pull out the common parts of that earlier CL and move them to new header file android_media_AudioFormat.h. Use the new function audioFormatToNative() to convert from Java ENCODING_PCM_* to native AUDIO_FORMAT_*. Use audio_bytes_per_sample() instead of hard-coding the size of various formats. Use size_t for memory sizes. Change-Id: I7992dd6a2c9500126a6d7ae5fc1ed9f3312962d6
This commit is contained in:
38
core/jni/android_media_AudioFormat.h
Normal file
38
core/jni/android_media_AudioFormat.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_MEDIA_AUDIOFORMAT_H
|
||||
#define ANDROID_MEDIA_AUDIOFORMAT_H
|
||||
|
||||
#include <system/audio.h>
|
||||
|
||||
// keep these values in sync with AudioFormat.java
|
||||
#define ENCODING_PCM_16BIT 2
|
||||
#define ENCODING_PCM_8BIT 3
|
||||
|
||||
static inline audio_format_t audioFormatToNative(int audioFormat)
|
||||
{
|
||||
switch (audioFormat) {
|
||||
case ENCODING_PCM_16BIT:
|
||||
return AUDIO_FORMAT_PCM_16_BIT;
|
||||
case ENCODING_PCM_8BIT:
|
||||
return AUDIO_FORMAT_PCM_8_BIT;
|
||||
default:
|
||||
return AUDIO_FORMAT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ANDROID_MEDIA_AUDIOFORMAT_H
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <utils/Log.h>
|
||||
#include <media/AudioRecord.h>
|
||||
|
||||
#include <system/audio.h>
|
||||
#include "android_media_AudioFormat.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -49,10 +49,6 @@ struct audiorecord_callback_cookie {
|
||||
Condition cond;
|
||||
};
|
||||
|
||||
// keep these values in sync with AudioFormat.java
|
||||
#define ENCODING_PCM_16BIT 2
|
||||
#define ENCODING_PCM_8BIT 3
|
||||
|
||||
static Mutex sLock;
|
||||
static SortedVector <audiorecord_callback_cookie *> sAudioRecordCallBackCookies;
|
||||
|
||||
@@ -81,18 +77,6 @@ jint android_media_translateRecorderErrorCode(int code) {
|
||||
}
|
||||
}
|
||||
|
||||
static audio_format_t audioFormatToNative(int audioFormat)
|
||||
{
|
||||
switch (audioFormat) {
|
||||
case ENCODING_PCM_16BIT:
|
||||
return AUDIO_FORMAT_PCM_16_BIT;
|
||||
case ENCODING_PCM_8BIT:
|
||||
return AUDIO_FORMAT_PCM_8_BIT;
|
||||
default:
|
||||
return AUDIO_FORMAT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
static void recorderCallback(int event, void* user, void *info) {
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <binder/MemoryHeapBase.h>
|
||||
#include <binder/MemoryBase.h>
|
||||
|
||||
#include <system/audio.h>
|
||||
#include "android_media_AudioFormat.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -55,9 +55,6 @@ struct audiotrack_callback_cookie {
|
||||
// keep these values in sync with AudioTrack.java
|
||||
#define MODE_STATIC 0
|
||||
#define MODE_STREAM 1
|
||||
// keep these values in sync with AudioFormat.java
|
||||
#define ENCODING_PCM_16BIT 2
|
||||
#define ENCODING_PCM_8BIT 3
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
class AudioTrackJniStorage {
|
||||
@@ -244,7 +241,8 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
|
||||
|
||||
// check the format.
|
||||
// This function was called from Java, so we compare the format against the Java constants
|
||||
if ((audioFormat != ENCODING_PCM_16BIT) && (audioFormat != ENCODING_PCM_8BIT)) {
|
||||
audio_format_t format = audioFormatToNative(audioFormat);
|
||||
if (format == AUDIO_FORMAT_INVALID) {
|
||||
|
||||
ALOGE("Error creating AudioTrack: unsupported audio format.");
|
||||
return AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT;
|
||||
@@ -253,20 +251,18 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
|
||||
// for the moment 8bitPCM in MODE_STATIC is not supported natively in the AudioTrack C++ class
|
||||
// so we declare everything as 16bitPCM, the 8->16bit conversion for MODE_STATIC will be handled
|
||||
// in android_media_AudioTrack_native_write_byte()
|
||||
if ((audioFormat == ENCODING_PCM_8BIT)
|
||||
if ((format == AUDIO_FORMAT_PCM_8_BIT)
|
||||
&& (memoryMode == MODE_STATIC)) {
|
||||
ALOGV("android_media_AudioTrack_native_setup(): requesting MODE_STATIC for 8bit \
|
||||
buff size of %dbytes, switching to 16bit, buff size of %dbytes",
|
||||
buffSizeInBytes, 2*buffSizeInBytes);
|
||||
audioFormat = ENCODING_PCM_16BIT;
|
||||
format = AUDIO_FORMAT_PCM_16_BIT;
|
||||
// we will need twice the memory to store the data
|
||||
buffSizeInBytes *= 2;
|
||||
}
|
||||
|
||||
// compute the frame count
|
||||
int bytesPerSample = audioFormat == ENCODING_PCM_16BIT ? 2 : 1;
|
||||
audio_format_t format = audioFormat == ENCODING_PCM_16BIT ?
|
||||
AUDIO_FORMAT_PCM_16_BIT : AUDIO_FORMAT_PCM_8_BIT;
|
||||
const size_t bytesPerSample = audio_bytes_per_sample(format);
|
||||
int frameCount = buffSizeInBytes / (nbChannels * bytesPerSample);
|
||||
|
||||
jclass clazz = env->GetObjectClass(thiz);
|
||||
@@ -519,14 +515,26 @@ jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, jbyte* data,
|
||||
written = 0;
|
||||
}
|
||||
} else {
|
||||
if (audioFormat == ENCODING_PCM_16BIT) {
|
||||
const audio_format_t format = audioFormatToNative(audioFormat);
|
||||
switch (format) {
|
||||
|
||||
default:
|
||||
// TODO Currently the only possible values for format are AUDIO_FORMAT_PCM_16_BIT
|
||||
// and AUDIO_FORMAT_PCM_8_BIT, due to the limited set of values for audioFormat.
|
||||
// The next section of the switch will probably work for more formats, but it has only
|
||||
// been tested for AUDIO_FORMAT_PCM_16_BIT, so that's why the "default" case fails.
|
||||
break;
|
||||
|
||||
case AUDIO_FORMAT_PCM_16_BIT: {
|
||||
// writing to shared memory, check for capacity
|
||||
if ((size_t)sizeInBytes > track->sharedBuffer()->size()) {
|
||||
sizeInBytes = track->sharedBuffer()->size();
|
||||
}
|
||||
memcpy(track->sharedBuffer()->pointer(), data + offsetInBytes, sizeInBytes);
|
||||
written = sizeInBytes;
|
||||
} else if (audioFormat == ENCODING_PCM_8BIT) {
|
||||
} break;
|
||||
|
||||
case AUDIO_FORMAT_PCM_8_BIT: {
|
||||
// data contains 8bit data we need to expand to 16bit before copying
|
||||
// to the shared memory
|
||||
// writing to shared memory, check for capacity,
|
||||
@@ -543,6 +551,8 @@ jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, jbyte* data,
|
||||
// even though we wrote 2*sizeInBytes, we only report sizeInBytes as written to hide
|
||||
// the 8bit mixer restriction from the user of this function
|
||||
written = sizeInBytes;
|
||||
} break;
|
||||
|
||||
}
|
||||
}
|
||||
return written;
|
||||
@@ -837,7 +847,9 @@ static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thi
|
||||
sampleRateInHertz, status);
|
||||
return -1;
|
||||
}
|
||||
return frameCount * nbChannels * (audioFormat == ENCODING_PCM_16BIT ? 2 : 1);
|
||||
const audio_format_t format = audioFormatToNative(audioFormat);
|
||||
const size_t bytesPerSample = audio_bytes_per_sample(format);
|
||||
return frameCount * nbChannels * bytesPerSample;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -31,7 +31,8 @@ public class AudioFormat {
|
||||
public static final int ENCODING_INVALID = 0;
|
||||
/** Default audio data format */
|
||||
public static final int ENCODING_DEFAULT = 1;
|
||||
// These two values must be kept in sync with JNI code for AudioTrack, AudioRecord
|
||||
|
||||
// These two values must be kept in sync with core/jni/android_media_AudioFormat.h
|
||||
/** Audio data format: PCM 16 bit per sample. Guaranteed to be supported by devices. */
|
||||
public static final int ENCODING_PCM_16BIT = 2;
|
||||
/** Audio data format: PCM 8 bit per sample. Not guaranteed to be supported by devices. */
|
||||
|
||||
Reference in New Issue
Block a user