19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//#define LOG_NDEBUG 0 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "AudioTrack-JNI" 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20c81d31c3f801ba3d559a22c27b926ace38a7ab49Glenn Kasten#include <JNIHelp.h> 217ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi#include <JniConstants.h> 22c81d31c3f801ba3d559a22c27b926ace38a7ab49Glenn Kasten#include <android_runtime/AndroidRuntime.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 247ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi#include "ScopedBytes.h" 257ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 26c81d31c3f801ba3d559a22c27b926ace38a7ab49Glenn Kasten#include <utils/Log.h> 27c81d31c3f801ba3d559a22c27b926ace38a7ab49Glenn Kasten#include <media/AudioSystem.h> 28c81d31c3f801ba3d559a22c27b926ace38a7ab49Glenn Kasten#include <media/AudioTrack.h> 2937967d46f40c8c52c88ff8c011972a1489d465ecGlenn Kasten#include <audio_utils/primitives.h> 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 310795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopian#include <binder/MemoryHeapBase.h> 320795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopian#include <binder/MemoryBase.h> 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten#include "android_media_AudioFormat.h" 35bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent#include "android_media_AudioErrors.h" 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* const kClassPathName = "android/media/AudioTrack"; 43a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistatic const char* const kAudioAttributesClassPathName = "android/media/AudioAttributes"; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 45a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistruct audio_track_fields_t { 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // these fields provide access from C++ to the... 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jmethodID postNativeEventInJava; //... event post callback method 4883b368505052f59616d29558e65e2250d01fd848Eric Laurent jfieldID nativeTrackInJavaObj; // stores in Java the native AudioTrack object 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID jniData; // stores in Java additional resources used by the native AudioTrack 50a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi jfieldID fieldStreamType; // ... mStreamType field in the AudioTrack Java object 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 52a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistruct audio_attributes_fields_t { 53701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi jfieldID fieldUsage; // AudioAttributes.mUsage 54701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi jfieldID fieldContentType; // AudioAttributes.mContentType 55701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi jfieldID fieldFlags; // AudioAttributes.mFlags 56701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi jfieldID fieldFormattedTags;// AudioAttributes.mFormattedTags 57a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi}; 58a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistatic audio_track_fields_t javaAudioTrackFields; 59a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivistatic audio_attributes_fields_t javaAudioAttrFields; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct audiotrack_callback_cookie { 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass audioTrack_class; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject audioTrack_ref; 64532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent bool busy; 65532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Condition cond; 66532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent}; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 683d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten// keep these values in sync with AudioTrack.java 693d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten#define MODE_STATIC 0 703d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten#define MODE_STREAM 1 713d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass AudioTrackJniStorage { 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public: 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<MemoryHeapBase> mMemHeap; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<MemoryBase> mMemBase; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audiotrack_callback_cookie mCallbackData; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioTrackJniStorage() { 808a1496855cb81a6f2e9e8d51dd6b6ed595047a2aJean-Michel Trivi mCallbackData.audioTrack_class = 0; 818a1496855cb81a6f2e9e8d51dd6b6ed595047a2aJean-Michel Trivi mCallbackData.audioTrack_ref = 0; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ~AudioTrackJniStorage() { 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMemBase.clear(); 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMemHeap.clear(); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool allocSharedMem(int sizeInBytes) { 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMemHeap = new MemoryHeapBase(sizeInBytes, 0, "AudioTrack Heap Base"); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMemHeap->getHeapID() < 0) { 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMemBase = new MemoryBase(mMemHeap, 0, sizeInBytes); 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 99532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurentstatic Mutex sLock; 100532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurentstatic SortedVector <audiotrack_callback_cookie *> sAudioTrackCallBackCookies; 101532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define DEFAULT_OUTPUT_SAMPLE_RATE 44100 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM -16 106fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten#define AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK -17 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT -18 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define AUDIOTRACK_ERROR_SETUP_INVALIDSTREAMTYPE -19 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED -20 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 112e46a86fcb6a0849fc05c4cade6cb94aad0325295Glenn Kastenstatic void audioCallback(int event, void* user, void *info) { 113532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 114532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent audiotrack_callback_cookie *callbackInfo = (audiotrack_callback_cookie *)user; 115532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent { 116532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Mutex::Autolock l(sLock); 117532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (sAudioTrackCallBackCookies.indexOf(callbackInfo) < 0) { 118532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return; 119532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 120532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent callbackInfo->busy = true; 121532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 122532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 1235b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten switch (event) { 1245b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten case AudioTrack::EVENT_MARKER: { 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv *env = AndroidRuntime::getJNIEnv(); 126a667ff30e4fb6f741c2a930e7c31ef7e962d3b40Glenn Kasten if (user != NULL && env != NULL) { 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->CallStaticVoidMethod( 12818db49a46259020387c40fff36d92edc1087a366Glenn Kasten callbackInfo->audioTrack_class, 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.postNativeEventInJava, 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project callbackInfo->audioTrack_ref, event, 0,0, NULL); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionDescribe(); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1365b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten } break; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1385b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten case AudioTrack::EVENT_NEW_POS: { 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JNIEnv *env = AndroidRuntime::getJNIEnv(); 140a667ff30e4fb6f741c2a930e7c31ef7e962d3b40Glenn Kasten if (user != NULL && env != NULL) { 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->CallStaticVoidMethod( 14218db49a46259020387c40fff36d92edc1087a366Glenn Kasten callbackInfo->audioTrack_class, 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.postNativeEventInJava, 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project callbackInfo->audioTrack_ref, event, 0,0, NULL); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionDescribe(); 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1505b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten } break; 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1525b1576ccbd9ab43d5e3238589cf5b43a4834447dGlenn Kasten 153532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent { 154532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Mutex::Autolock l(sLock); 155532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent callbackInfo->busy = false; 156532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent callbackInfo->cond.broadcast(); 157532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 162532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurentstatic sp<AudioTrack> getAudioTrack(JNIEnv* env, jobject thiz) 163532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent{ 164532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Mutex::Autolock l(sLock); 165532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent AudioTrack* const at = 166075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat (AudioTrack*)env->GetLongField(thiz, javaAudioTrackFields.nativeTrackInJavaObj); 167532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return sp<AudioTrack>(at); 168532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent} 169532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 170532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurentstatic sp<AudioTrack> setAudioTrack(JNIEnv* env, jobject thiz, const sp<AudioTrack>& at) 171532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent{ 172532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Mutex::Autolock l(sLock); 173532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> old = 174075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat (AudioTrack*)env->GetLongField(thiz, javaAudioTrackFields.nativeTrackInJavaObj); 175532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (at.get()) { 176b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian at->incStrong((void*)setAudioTrack); 177532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 178532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (old != 0) { 179b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian old->decStrong((void*)setAudioTrack); 180532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 181075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat env->SetLongField(thiz, javaAudioTrackFields.nativeTrackInJavaObj, (jlong)at.get()); 182532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return old; 183532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent} 184532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent// ---------------------------------------------------------------------------- 185075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhatstatic jint 186eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Triviandroid_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, 187a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi jobject jaa, 188a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi jint sampleRateInHertz, jint javaChannelMask, 189a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession) { 190a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 19171f2cf116aab893e224056c38ab146bd1538dd3eSteve Block ALOGV("sampleRate=%d, audioFormat(from Java)=%d, channel mask=%x, buffSize=%d", 192d9ae1c573e37e245c7f4f0480a8fa925e57bd49dJean-Michel Trivi sampleRateInHertz, audioFormat, javaChannelMask, buffSizeInBytes); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 194a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi if (jaa == 0) { 195a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi ALOGE("Error creating AudioTrack: invalid audio attributes"); 196a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi return (jint) AUDIO_JAVA_ERROR; 197a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi } 198a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 199d9ae1c573e37e245c7f4f0480a8fa925e57bd49dJean-Michel Trivi // Java channel masks don't map directly to the native definition, but it's a simple shift 200d9ae1c573e37e245c7f4f0480a8fa925e57bd49dJean-Michel Trivi // to skip the two deprecated channel configurations "default" and "mono". 2015b8fd44365f03601aaba41879ac18e70ce814a0fGlenn Kasten audio_channel_mask_t nativeChannelMask = ((uint32_t)javaChannelMask) >> 2; 202d9ae1c573e37e245c7f4f0480a8fa925e57bd49dJean-Michel Trivi 203d9ae1c573e37e245c7f4f0480a8fa925e57bd49dJean-Michel Trivi if (!audio_is_output_channel(nativeChannelMask)) { 20433c437df39029b70d4ffafac2ca31bd71eafd0c6Glenn Kasten ALOGE("Error creating AudioTrack: invalid channel mask %#x.", javaChannelMask); 205075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK; 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 207d9ae1c573e37e245c7f4f0480a8fa925e57bd49dJean-Michel Trivi 208dbf55665c5c4802cbfc56463198805be48ec75afEric Laurent uint32_t channelCount = audio_channel_count_from_out_mask(nativeChannelMask); 20918db49a46259020387c40fff36d92edc1087a366Glenn Kasten 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // check the format. 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This function was called from Java, so we compare the format against the Java constants 212fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten audio_format_t format = audioFormatToNative(audioFormat); 213fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten if (format == AUDIO_FORMAT_INVALID) { 2148f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten ALOGE("Error creating AudioTrack: unsupported audio format %d.", audioFormat); 215075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT; 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // for the moment 8bitPCM in MODE_STATIC is not supported natively in the AudioTrack C++ class 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so we declare everything as 16bitPCM, the 8->16bit conversion for MODE_STATIC will be handled 22000db1f52b1c12d3670a0419305aa7548f7932aa0Glenn Kasten // in android_media_AudioTrack_native_write_byte() 221fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten if ((format == AUDIO_FORMAT_PCM_8_BIT) 2223d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten && (memoryMode == MODE_STATIC)) { 223eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi ALOGV("android_media_AudioTrack_setup(): requesting MODE_STATIC for 8bit \ 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buff size of %dbytes, switching to 16bit, buff size of %dbytes", 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffSizeInBytes, 2*buffSizeInBytes); 226fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten format = AUDIO_FORMAT_PCM_16_BIT; 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we will need twice the memory to store the data 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffSizeInBytes *= 2; 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // compute the frame count 232ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent size_t frameCount; 233ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent if (audio_is_linear_pcm(format)) { 234ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent const size_t bytesPerSample = audio_bytes_per_sample(format); 235ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent frameCount = buffSizeInBytes / (channelCount * bytesPerSample); 236ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent } else { 237ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent frameCount = buffSizeInBytes; 238ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent } 23918db49a46259020387c40fff36d92edc1087a366Glenn Kasten 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz = env->GetObjectClass(thiz); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clazz == NULL) { 2423762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find %s when setting up callback.", kClassPathName); 243075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2452fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent 2462fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent if (jSession == NULL) { 2473762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error creating AudioTrack: invalid session ID pointer"); 248bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint) AUDIO_JAVA_ERROR; 249619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent } 250619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent 2512fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent jint* nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL); 2522fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent if (nSession == NULL) { 2533762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error creating AudioTrack: Error retrieving session id pointer"); 254bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint) AUDIO_JAVA_ERROR; 2552fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent } 2562fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent int sessionId = nSession[0]; 2572fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); 2582fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent nSession = NULL; 2592fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // create the native AudioTrack object 261532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = new AudioTrack(); 26218db49a46259020387c40fff36d92edc1087a366Glenn Kasten 263a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi audio_attributes_t *paa = NULL; 264a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // read the AudioAttributes values 265a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t)); 266701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi const jstring jtags = 267701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags); 268a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi const char* tags = env->GetStringUTFChars(jtags, NULL); 269a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it 270a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1); 271a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi env->ReleaseStringUTFChars(jtags, tags); 272a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage); 273a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa->content_type = 274a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType); 275a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags); 276a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 277a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi ALOGV("AudioTrack_setup for usage=%d content=%d flags=0x%#x tags=%s", 278a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa->usage, paa->content_type, paa->flags, paa->tags); 279a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 280532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // initialize the callback information: 281532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // this data will be passed with every AudioTrack callback 282532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent AudioTrackJniStorage* lpJniStorage = new AudioTrackJniStorage(); 283532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz); 284532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // we use a weak reference so the AudioTrack object can be garbage collected. 285532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this); 286532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpJniStorage->mCallbackData.busy = false; 287532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // initialize the native AudioTrack object 2892defed988f74c98d5af8d02551ebf7262490cc5bJean-Michel Trivi status_t status = NO_ERROR; 2903d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten switch (memoryMode) { 2913d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten case MODE_STREAM: 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 293c5d142428ad68dd8aa4ffb80719667b13ad5049fGlenn Kasten status = lpTrack->set( 294c8d6b6fc7dd05c10ca301e654f063cc89781c9beJean-Michel Trivi AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument) 295a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi sampleRateInHertz, 296a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi format,// word length, PCM 297a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi nativeChannelMask, 298a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi frameCount, 299a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi AUDIO_OUTPUT_FLAG_NONE, 300a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user) 301a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack 302a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 0,// shared mem 303a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi true,// thread can call Java 304a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi sessionId,// audio session ID 305c8d6b6fc7dd05c10ca301e654f063cc89781c9beJean-Michel Trivi AudioTrack::TRANSFER_SYNC, 306a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi NULL, // default offloadInfo 307a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi -1, -1, // default uid, pid values 308a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa); 3093d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten break; 31018db49a46259020387c40fff36d92edc1087a366Glenn Kasten 3113d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten case MODE_STATIC: 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // AudioTrack is using shared memory 31318db49a46259020387c40fff36d92edc1087a366Glenn Kasten 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!lpJniStorage->allocSharedMem(buffSizeInBytes)) { 3153762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error creating AudioTrack in static mode: error creating mem heap base"); 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto native_init_failure; 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31818db49a46259020387c40fff36d92edc1087a366Glenn Kasten 319c5d142428ad68dd8aa4ffb80719667b13ad5049fGlenn Kasten status = lpTrack->set( 320c8d6b6fc7dd05c10ca301e654f063cc89781c9beJean-Michel Trivi AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument) 321a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi sampleRateInHertz, 322a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi format,// word length, PCM 323a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi nativeChannelMask, 324a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi frameCount, 325a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi AUDIO_OUTPUT_FLAG_NONE, 326a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)); 327a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack 328a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi lpJniStorage->mMemBase,// shared mem 329a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi true,// thread can call Java 330a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi sessionId,// audio session ID 331c8d6b6fc7dd05c10ca301e654f063cc89781c9beJean-Michel Trivi AudioTrack::TRANSFER_SHARED, 332a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi NULL, // default offloadInfo 333a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi -1, -1, // default uid, pid values 334a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa); 3353d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten break; 3363d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten 3373d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten default: 3383d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten ALOGE("Unknown mode %d", memoryMode); 3393d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten goto native_init_failure; 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 342c5d142428ad68dd8aa4ffb80719667b13ad5049fGlenn Kasten if (status != NO_ERROR) { 343c5d142428ad68dd8aa4ffb80719667b13ad5049fGlenn Kasten ALOGE("Error %d initializing AudioTrack", status); 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto native_init_failure; 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3472fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL); 3482fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent if (nSession == NULL) { 3493762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error creating AudioTrack: Error retrieving session id pointer"); 3502fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent goto native_init_failure; 3512fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent } 352619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent // read the audio session ID back from AudioTrack in case we create a new session 353619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent nSession[0] = lpTrack->getSessionId(); 354619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); 355619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent nSession = NULL; 356619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent 357532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent { // scope for the lock 358532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Mutex::Autolock l(sLock); 359532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sAudioTrackCallBackCookies.add(&lpJniStorage->mCallbackData); 360532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 36118db49a46259020387c40fff36d92edc1087a366Glenn Kasten // save our newly created C++ AudioTrack in the "nativeTrackInJavaObj" field 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // of the Java object (in mNativeTrackInJavaObj) 363532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent setAudioTrack(env, thiz, lpTrack); 36418db49a46259020387c40fff36d92edc1087a366Glenn Kasten 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // save the JNI resources so we can free them later 366075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat //ALOGV("storing lpJniStorage: %x\n", (long)lpJniStorage); 367075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat env->SetLongField(thiz, javaAudioTrackFields.jniData, (jlong)lpJniStorage); 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // since we had audio attributes, the stream type was derived from them during the 370a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // creation of the native AudioTrack: push the same value to the Java object 371a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi env->SetIntField(thiz, javaAudioTrackFields.fieldStreamType, (jint) lpTrack->streamType()); 372a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // audio attributes were copied in AudioTrack creation 373a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi free(paa); 374a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa = NULL; 375a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 376a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 377bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint) AUDIO_JAVA_SUCCESS; 37818db49a46259020387c40fff36d92edc1087a366Glenn Kasten 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // failures: 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnative_init_failure: 381a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi if (paa != NULL) { 382a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi free(paa); 383a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi } 384619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent if (nSession != NULL) { 385619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); 386619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent } 3878a1496855cb81a6f2e9e8d51dd6b6ed595047a2aJean-Michel Trivi env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_class); 3888a1496855cb81a6f2e9e8d51dd6b6ed595047a2aJean-Michel Trivi env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_ref); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete lpJniStorage; 390075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat env->SetLongField(thiz, javaAudioTrackFields.jniData, 0); 39118db49a46259020387c40fff36d92edc1087a366Glenn Kasten 392075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_start(JNIEnv *env, jobject thiz) 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 400532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 401532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for start()"); 4047070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 40621dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->start(); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_stop(JNIEnv *env, jobject thiz) 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 415532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 416532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for stop()"); 4197070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->stop(); 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_pause(JNIEnv *env, jobject thiz) 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 430532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 431532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for pause()"); 4347070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->pause(); 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_flush(JNIEnv *env, jobject thiz) 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 445532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 446532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for flush()"); 4497070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->flush(); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_set_volume(JNIEnv *env, jobject thiz, jfloat leftVol, jfloat rightVol ) 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 459532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 460532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setVolume()"); 4637070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->setVolume(leftVol, rightVol); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 47018db49a46259020387c40fff36d92edc1087a366Glenn Kasten 471532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent#define CALLBACK_COND_WAIT_TIMEOUT_MS 1000 472eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivistatic void android_media_AudioTrack_release(JNIEnv *env, jobject thiz) { 473532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = setAudioTrack(env, thiz, 0); 474532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 475532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return; 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 477532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent //ALOGV("deleting lpTrack: %x\n", (int)lpTrack); 478532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpTrack->stop(); 47918db49a46259020387c40fff36d92edc1087a366Glenn Kasten 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // delete the JNI data 481075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetLongField( 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project thiz, javaAudioTrackFields.jniData); 483532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // reset the native resources in the Java object so any attempt to access 484532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // them after a call to release fails. 485075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat env->SetLongField(thiz, javaAudioTrackFields.jniData, 0); 486532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pJniStorage) { 488532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Mutex::Autolock l(sLock); 489532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent audiotrack_callback_cookie *lpCookie = &pJniStorage->mCallbackData; 49071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block //ALOGV("deleting pJniStorage: %x\n", (int)pJniStorage); 491532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent while (lpCookie->busy) { 492532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpCookie->cond.waitRelative(sLock, 493532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent milliseconds(CALLBACK_COND_WAIT_TIMEOUT_MS)) != 494532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent NO_ERROR) { 495532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent break; 496532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 497532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 498532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sAudioTrackCallBackCookies.remove(lpCookie); 499532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // delete global refs created in native_setup 500532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent env->DeleteGlobalRef(lpCookie->audioTrack_class); 501532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent env->DeleteGlobalRef(lpCookie->audioTrack_ref); 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete pJniStorage; 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 50618db49a46259020387c40fff36d92edc1087a366Glenn Kasten 507532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent// ---------------------------------------------------------------------------- 508eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivistatic void android_media_AudioTrack_finalize(JNIEnv *env, jobject thiz) { 509eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi //ALOGV("android_media_AudioTrack_finalize jobject: %x\n", (int)thiz); 510eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi android_media_AudioTrack_release(env, thiz); 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 5147ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivijint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const jbyte* data, 5157ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi jint offsetInBytes, jint sizeInBytes, bool blocking = true) { 51621dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // give the data to the native AudioTrack object (the data starts at the offset) 51721dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi ssize_t written = 0; 51821dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // regular write() or copy the data to the AudioTrack's shared memory? 519532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (track->sharedBuffer() == 0) { 5207ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi written = track->write(data + offsetInBytes, sizeInBytes, blocking); 5219b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten // for compatibility with earlier behavior of write(), return 0 in this case 5229b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten if (written == (ssize_t) WOULD_BLOCK) { 5239b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten written = 0; 5249b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten } 52521dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi } else { 526fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten const audio_format_t format = audioFormatToNative(audioFormat); 527fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten switch (format) { 528fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten 529fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten default: 53054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten case AUDIO_FORMAT_PCM_FLOAT: 531fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten case AUDIO_FORMAT_PCM_16_BIT: { 53221dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // writing to shared memory, check for capacity 533532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if ((size_t)sizeInBytes > track->sharedBuffer()->size()) { 534532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sizeInBytes = track->sharedBuffer()->size(); 53521dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi } 536532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent memcpy(track->sharedBuffer()->pointer(), data + offsetInBytes, sizeInBytes); 53721dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi written = sizeInBytes; 538fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten } break; 539fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten 540fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten case AUDIO_FORMAT_PCM_8_BIT: { 54121dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // data contains 8bit data we need to expand to 16bit before copying 54221dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // to the shared memory 54321dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // writing to shared memory, check for capacity, 54421dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // note that input data will occupy 2X the input space due to 8 to 16bit conversion 545532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (((size_t)sizeInBytes)*2 > track->sharedBuffer()->size()) { 546532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sizeInBytes = track->sharedBuffer()->size() / 2; 54721dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi } 54821dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi int count = sizeInBytes; 549532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent int16_t *dst = (int16_t *)track->sharedBuffer()->pointer(); 55037967d46f40c8c52c88ff8c011972a1489d465ecGlenn Kasten const uint8_t *src = (const uint8_t *)(data + offsetInBytes); 55137967d46f40c8c52c88ff8c011972a1489d465ecGlenn Kasten memcpy_to_i16_from_u8(dst, src, count); 55221dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // even though we wrote 2*sizeInBytes, we only report sizeInBytes as written to hide 55321dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // the 8bit mixer restriction from the user of this function 55421dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi written = sizeInBytes; 555fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten } break; 556fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten 55721dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi } 55821dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi } 55921dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi return written; 56021dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi 56121dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi} 56221dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi 56321dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi// ---------------------------------------------------------------------------- 564eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivistatic jint android_media_AudioTrack_write_byte(JNIEnv *env, jobject thiz, 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray javaAudioData, 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint offsetInBytes, jint sizeInBytes, 5677ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi jint javaAudioFormat, 5687ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi jboolean isWriteBlocking) { 569eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi //ALOGV("android_media_AudioTrack_write_byte(offset=%d, sizeInBytes=%d) called", 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // offsetInBytes, sizeInBytes); 571532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lpTrack == NULL) { 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for write()"); 5757070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return 0; 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // get the pointer for the audio data from the java array 579421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such 580421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent // a way that it becomes much more efficient. When doing so, we will have to prevent the 581421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent // AudioSystem callback to be called while in critical section (in case of media server 582421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent // process crash for instance) 583532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent jbyte* cAudioData = NULL; 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (javaAudioData) { 585421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent cAudioData = (jbyte *)env->GetByteArrayElements(javaAudioData, NULL); 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cAudioData == NULL) { 5873762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error retrieving source of audio data to play, can't play"); 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; // out of memory or no data to load 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5913762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("NULL java array of audio data to play, can't play"); 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5957ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi jint written = writeToTrack(lpTrack, javaAudioFormat, cAudioData, offsetInBytes, sizeInBytes, 5967ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi isWriteBlocking == JNI_TRUE /* blocking */); 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 598421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent env->ReleaseByteArrayElements(javaAudioData, cAudioData, 0); 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 60071f2cf116aab893e224056c38ab146bd1538dd3eSteve Block //ALOGV("write wrote %d (tried %d) bytes in the native AudioTrack with offset %d", 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (int)written, (int)(sizeInBytes), (int)offsetInBytes); 60221dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi return written; 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 6077ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivistatic jint android_media_AudioTrack_write_native_bytes(JNIEnv *env, jobject thiz, 6085d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi jbyteArray javaBytes, jint byteOffset, jint sizeInBytes, 6097ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi jint javaAudioFormat, jboolean isWriteBlocking) { 6107ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi //ALOGV("android_media_AudioTrack_write_native_bytes(offset=%d, sizeInBytes=%d) called", 6117ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi // offsetInBytes, sizeInBytes); 6127ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 6137ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi if (lpTrack == NULL) { 6147ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi jniThrowException(env, "java/lang/IllegalStateException", 6157ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi "Unable to retrieve AudioTrack pointer for write()"); 6167ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi return 0; 6177ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi } 6187ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 6197ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi ScopedBytesRO bytes(env, javaBytes); 6207ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi if (bytes.get() == NULL) { 6217ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi ALOGE("Error retrieving source of audio data to play, can't play"); 622bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_BAD_VALUE; 6237ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi } 6247ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 6255d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi jint written = writeToTrack(lpTrack, javaAudioFormat, bytes.get(), byteOffset, 6267ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi sizeInBytes, isWriteBlocking == JNI_TRUE /* blocking */); 6277ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 6287ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi return written; 6297ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi} 6307ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 6317ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi// ---------------------------------------------------------------------------- 632eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivistatic jint android_media_AudioTrack_write_short(JNIEnv *env, jobject thiz, 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jshortArray javaAudioData, 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint offsetInShorts, jint sizeInShorts, 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint javaAudioFormat) { 6363d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent 6373d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent //ALOGV("android_media_AudioTrack_write_short(offset=%d, sizeInShorts=%d) called", 6383d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent // offsetInShorts, sizeInShorts); 6393d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 6403d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent if (lpTrack == NULL) { 6413d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent jniThrowException(env, "java/lang/IllegalStateException", 6423d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent "Unable to retrieve AudioTrack pointer for write()"); 6433d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent return 0; 6443d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent } 6453d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent 6463d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent // get the pointer for the audio data from the java array 6473d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such 6483d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent // a way that it becomes much more efficient. When doing so, we will have to prevent the 6493d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent // AudioSystem callback to be called while in critical section (in case of media server 6503d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent // process crash for instance) 6513d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent jshort* cAudioData = NULL; 6523d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent if (javaAudioData) { 6533d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent cAudioData = (jshort *)env->GetShortArrayElements(javaAudioData, NULL); 6543d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent if (cAudioData == NULL) { 6553d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent ALOGE("Error retrieving source of audio data to play, can't play"); 6563d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent return 0; // out of memory or no data to load 6573d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent } 6583d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent } else { 6593d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent ALOGE("NULL java array of audio data to play, can't play"); 6603d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent return 0; 6613d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent } 6623d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData, 6633d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent offsetInShorts * sizeof(short), sizeInShorts * sizeof(short), 6643d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent true /*blocking write, legacy behavior*/); 6653d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent env->ReleaseShortArrayElements(javaAudioData, cAudioData, 0); 6663d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent 667f7e0a370e7178f698605165fc362384a42f3547dGlenn Kasten if (written > 0) { 6683d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent written /= sizeof(short); 669f7e0a370e7178f698605165fc362384a42f3547dGlenn Kasten } 6703d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent //ALOGV("write wrote %d (tried %d) shorts in the native AudioTrack with offset %d", 6713d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent // (int)written, (int)(sizeInShorts), (int)offsetInShorts); 6723d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent 673f7e0a370e7178f698605165fc362384a42f3547dGlenn Kasten return written; 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 67854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kastenstatic jint android_media_AudioTrack_write_float(JNIEnv *env, jobject thiz, 67954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten jfloatArray javaAudioData, 68054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten jint offsetInFloats, jint sizeInFloats, 68154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten jint javaAudioFormat, 68254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten jboolean isWriteBlocking) { 68354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 68454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 68554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten if (lpTrack == NULL) { 68654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten jniThrowException(env, "java/lang/IllegalStateException", 68754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten "Unable to retrieve AudioTrack pointer for write()"); 68854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten return 0; 68954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } 69054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 69154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten jfloat* cAudioData = NULL; 69254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten if (javaAudioData) { 69354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten cAudioData = (jfloat *)env->GetFloatArrayElements(javaAudioData, NULL); 69454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten if (cAudioData == NULL) { 69554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten ALOGE("Error retrieving source of audio data to play, can't play"); 69654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten return 0; // out of memory or no data to load 69754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } 69854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } else { 69954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten ALOGE("NULL java array of audio data to play, can't play"); 70054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten return 0; 70154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } 70254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData, 70354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten offsetInFloats * sizeof(float), sizeInFloats * sizeof(float), 70454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten isWriteBlocking == JNI_TRUE /* blocking */); 70554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten env->ReleaseFloatArrayElements(javaAudioData, cAudioData, 0); 70654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 70754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten if (written > 0) { 70854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten written /= sizeof(float); 70954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } 71054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 71154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten return written; 71254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten} 71354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 71454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 71554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten// ---------------------------------------------------------------------------- 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_native_frame_count(JNIEnv *env, jobject thiz) { 717532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 718532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for frameCount()"); 721bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 723532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 724532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return lpTrack->frameCount(); 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 72988e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurentstatic jint android_media_AudioTrack_set_playback_rate(JNIEnv *env, jobject thiz, 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint sampleRateInHz) { 731532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 732532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setSampleRate()"); 735bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 737bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus(lpTrack->setSampleRate(sampleRateInHz)); 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_playback_rate(JNIEnv *env, jobject thiz) { 743532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 744532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for getSampleRate()"); 747bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 749532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return (jint) lpTrack->getSampleRate(); 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 75418db49a46259020387c40fff36d92edc1087a366Glenn Kastenstatic jint android_media_AudioTrack_set_marker_pos(JNIEnv *env, jobject thiz, 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint markerPos) { 756532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 757532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setMarkerPosition()"); 760bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 762bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->setMarkerPosition(markerPos) ); 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_marker_pos(JNIEnv *env, jobject thiz) { 768532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t markerPos = 0; 77018db49a46259020387c40fff36d92edc1087a366Glenn Kasten 771532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for getMarkerPosition()"); 774bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 776532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpTrack->getMarkerPosition(&markerPos); 777532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return (jint)markerPos; 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_set_pos_update_period(JNIEnv *env, jobject thiz, 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint period) { 784532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 785532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setPositionUpdatePeriod()"); 788bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 78918db49a46259020387c40fff36d92edc1087a366Glenn Kasten } 790bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->setPositionUpdatePeriod(period) ); 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_pos_update_period(JNIEnv *env, jobject thiz) { 796532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t period = 0; 79818db49a46259020387c40fff36d92edc1087a366Glenn Kasten 799532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for getPositionUpdatePeriod()"); 802bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 804532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpTrack->getPositionUpdatePeriod(&period); 805532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return (jint)period; 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 81018db49a46259020387c40fff36d92edc1087a366Glenn Kastenstatic jint android_media_AudioTrack_set_position(JNIEnv *env, jobject thiz, 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint position) { 812532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 813532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setPosition()"); 816bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 818bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->setPosition(position) ); 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_position(JNIEnv *env, jobject thiz) { 824532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t position = 0; 82618db49a46259020387c40fff36d92edc1087a366Glenn Kasten 827532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for getPosition()"); 830bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 832532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpTrack->getPosition(&position); 833532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return (jint)position; 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 83861dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodmanstatic jint android_media_AudioTrack_get_latency(JNIEnv *env, jobject thiz) { 83961dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 84061dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman 84161dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman if (lpTrack == NULL) { 84261dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman jniThrowException(env, "java/lang/IllegalStateException", 84361dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman "Unable to retrieve AudioTrack pointer for latency()"); 844bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 84561dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman } 84661dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman return (jint)lpTrack->latency(); 84761dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman} 84861dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman 84961dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman 85061dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman// ---------------------------------------------------------------------------- 851948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kastenstatic jint android_media_AudioTrack_get_timestamp(JNIEnv *env, jobject thiz, jlongArray jTimestamp) { 852948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 853948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten 854948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten if (lpTrack == NULL) { 855948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten ALOGE("Unable to retrieve AudioTrack pointer for getTimestamp()"); 856bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 857948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten } 858948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten AudioTimestamp timestamp; 859948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten status_t status = lpTrack->getTimestamp(timestamp); 860948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten if (status == OK) { 861948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten jlong* nTimestamp = (jlong *) env->GetPrimitiveArrayCritical(jTimestamp, NULL); 862948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten if (nTimestamp == NULL) { 863948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten ALOGE("Unable to get array for getTimestamp()"); 864bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 865948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten } 866948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten nTimestamp[0] = (jlong) timestamp.mPosition; 867948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten nTimestamp[1] = (jlong) ((timestamp.mTime.tv_sec * 1000000000LL) + timestamp.mTime.tv_nsec); 868948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten env->ReleasePrimitiveArrayCritical(jTimestamp, nTimestamp, 0); 869948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten } 870bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint) nativeToJavaStatus(status); 871948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten} 872948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten 873948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten 874948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten// ---------------------------------------------------------------------------- 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_set_loop(JNIEnv *env, jobject thiz, 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint loopStart, jint loopEnd, jint loopCount) { 877532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 878532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setLoop()"); 881bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 883bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->setLoop(loopStart, loopEnd, loopCount) ); 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_reload(JNIEnv *env, jobject thiz) { 889532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 890532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for reload()"); 893bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 895bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->reload() ); 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_output_sample_rate(JNIEnv *env, jobject thiz, 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint javaStreamType) { 90285fbc871ded0f71f9638f85e7d2f03a35bf39ddaGlenn Kasten uint32_t afSamplingRate; 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // convert the stream type from Java to native value 904eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi // FIXME: code duplication with android_media_AudioTrack_setup() 90524fc2fb1c541e954b83fd31ea9f786a5e9b45501Dima Zavin audio_stream_type_t nativeStreamType; 90629a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten switch (javaStreamType) { 90729a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_VOICE_CALL: 90829a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_SYSTEM: 90929a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_RING: 91029a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_MUSIC: 91129a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_ALARM: 91229a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_NOTIFICATION: 91329a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_BLUETOOTH_SCO: 91429a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_DTMF: 91529a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten nativeStreamType = (audio_stream_type_t) javaStreamType; 91629a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten break; 91729a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten default: 91824fc2fb1c541e954b83fd31ea9f786a5e9b45501Dima Zavin nativeStreamType = AUDIO_STREAM_DEFAULT; 91929a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten break; 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9228f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten status_t status = AudioSystem::getOutputSamplingRate(&afSamplingRate, nativeStreamType); 9238f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten if (status != NO_ERROR) { 9248f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten ALOGE("Error %d in AudioSystem::getOutputSamplingRate() for stream type %d " 9258f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten "in AudioTrack JNI", status, nativeStreamType); 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return DEFAULT_OUTPUT_SAMPLE_RATE; 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return afSamplingRate; 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// returns the minimum required size for the successful creation of a streaming AudioTrack 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// returns -1 if there was an error querying the hardware. 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thiz, 9375b8fd44365f03601aaba41879ac18e70ce814a0fGlenn Kasten jint sampleRateInHertz, jint channelCount, jint audioFormat) { 938c3308074cd6f06bbb35c1999b5260f938742a9e7Chia-chi Yeh 939659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten size_t frameCount; 940659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten const status_t status = AudioTrack::getMinFrameCount(&frameCount, AUDIO_STREAM_DEFAULT, 941659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten sampleRateInHertz); 942659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten if (status != NO_ERROR) { 943659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten ALOGE("AudioTrack::getMinFrameCount() for sample rate %d failed with status %d", 944659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten sampleRateInHertz, status); 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 947fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten const audio_format_t format = audioFormatToNative(audioFormat); 948ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent if (audio_is_linear_pcm(format)) { 949ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent const size_t bytesPerSample = audio_bytes_per_sample(format); 950ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent return frameCount * channelCount * bytesPerSample; 951ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent } else { 952ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent return frameCount; 953ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent } 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9567070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent// ---------------------------------------------------------------------------- 9573009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kastenstatic jint 9587070b36549d511d6627538c73dfbab23fbae5b43Eric Laurentandroid_media_AudioTrack_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level ) 9597070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent{ 960532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 9617070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent if (lpTrack == NULL ) { 9627070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent jniThrowException(env, "java/lang/IllegalStateException", 9637070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent "Unable to retrieve AudioTrack pointer for setAuxEffectSendLevel()"); 9643009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten return -1; 9657070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent } 9667070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent 9673009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten status_t status = lpTrack->setAuxEffectSendLevel(level); 9683009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten if (status != NO_ERROR) { 9693009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten ALOGE("AudioTrack::setAuxEffectSendLevel() for level %g failed with status %d", 9703009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten level, status); 9713009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten } 9723009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten return (jint) status; 9737070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent} 9747070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent 9757070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent// ---------------------------------------------------------------------------- 9767070b36549d511d6627538c73dfbab23fbae5b43Eric Laurentstatic jint android_media_AudioTrack_attachAuxEffect(JNIEnv *env, jobject thiz, 9777070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent jint effectId) { 978532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 979532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 9807070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent jniThrowException(env, "java/lang/IllegalStateException", 9817070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent "Unable to retrieve AudioTrack pointer for attachAuxEffect()"); 982bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 9837070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent } 984bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->attachAuxEffect(effectId) ); 9857070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent} 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMethods[] = { 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // name, signature, funcPtr 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_start", "()V", (void *)android_media_AudioTrack_start}, 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_stop", "()V", (void *)android_media_AudioTrack_stop}, 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_pause", "()V", (void *)android_media_AudioTrack_pause}, 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_flush", "()V", (void *)android_media_AudioTrack_flush}, 995a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;IIIII[I)I", 996eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi (void *)android_media_AudioTrack_setup}, 997eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi {"native_finalize", "()V", (void *)android_media_AudioTrack_finalize}, 998eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi {"native_release", "()V", (void *)android_media_AudioTrack_release}, 9997ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi {"native_write_byte", "([BIIIZ)I",(void *)android_media_AudioTrack_write_byte}, 10007ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi {"native_write_native_bytes", 10015d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi "(Ljava/lang/Object;IIIZ)I", 10027ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi (void *)android_media_AudioTrack_write_native_bytes}, 1003eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi {"native_write_short", "([SIII)I", (void *)android_media_AudioTrack_write_short}, 100454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten {"native_write_float", "([FIIIZ)I",(void *)android_media_AudioTrack_write_float}, 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_setVolume", "(FF)V", (void *)android_media_AudioTrack_set_volume}, 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_native_frame_count", 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "()I", (void *)android_media_AudioTrack_get_native_frame_count}, 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_playback_rate", 100988e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent "(I)I", (void *)android_media_AudioTrack_set_playback_rate}, 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_playback_rate", 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "()I", (void *)android_media_AudioTrack_get_playback_rate}, 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_marker_pos","(I)I", (void *)android_media_AudioTrack_set_marker_pos}, 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_marker_pos","()I", (void *)android_media_AudioTrack_get_marker_pos}, 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_pos_update_period", 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "(I)I", (void *)android_media_AudioTrack_set_pos_update_period}, 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_pos_update_period", 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "()I", (void *)android_media_AudioTrack_get_pos_update_period}, 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_position", "(I)I", (void *)android_media_AudioTrack_set_position}, 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_position", "()I", (void *)android_media_AudioTrack_get_position}, 102061dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman {"native_get_latency", "()I", (void *)android_media_AudioTrack_get_latency}, 1021948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten {"native_get_timestamp", "([J)I", (void *)android_media_AudioTrack_get_timestamp}, 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_loop", "(III)I", (void *)android_media_AudioTrack_set_loop}, 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_reload_static", "()I", (void *)android_media_AudioTrack_reload}, 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_output_sample_rate", 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "(I)I", (void *)android_media_AudioTrack_get_output_sample_rate}, 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_min_buff_size", 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "(III)I", (void *)android_media_AudioTrack_get_min_buff_size}, 10287070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent {"native_setAuxEffectSendLevel", 10293009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten "(F)I", (void *)android_media_AudioTrack_setAuxEffectSendLevel}, 10307070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent {"native_attachAuxEffect", 10317070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent "(I)I", (void *)android_media_AudioTrack_attachAuxEffect}, 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// field names found in android/media/AudioTrack.java 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define JAVA_POSTEVENT_CALLBACK_NAME "postEventFromNative" 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME "mNativeTrackInJavaObj" 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define JAVA_JNIDATA_FIELD_NAME "mJniData" 1039a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi#define JAVA_STREAMTYPE_FIELD_NAME "mStreamType" 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// preconditions: 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// theClass is valid 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool android_media_getIntConstantFromClass(JNIEnv* pEnv, jclass theClass, const char* className, 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* constName, int* constVal) { 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID javaConst = NULL; 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaConst = pEnv->GetStaticFieldID(theClass, constName, "I"); 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (javaConst != NULL) { 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *constVal = pEnv->GetStaticIntField(theClass, javaConst); 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10523762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find %s.%s", className, constName); 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_media_AudioTrack(JNIEnv *env) 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.nativeTrackInJavaObj = NULL; 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.postNativeEventInJava = NULL; 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the AudioTrack class 106546e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom jclass audioTrackClass = env->FindClass(kClassPathName); 106646e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom if (audioTrackClass == NULL) { 10673762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find %s", kClassPathName); 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the postEvent method 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.postNativeEventInJava = env->GetStaticMethodID( 107346e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom audioTrackClass, 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JAVA_POSTEVENT_CALLBACK_NAME, "(Ljava/lang/Object;IIILjava/lang/Object;)V"); 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (javaAudioTrackFields.postNativeEventInJava == NULL) { 10763762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find AudioTrack.%s", JAVA_POSTEVENT_CALLBACK_NAME); 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the variables fields 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // nativeTrackInJavaObj 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.nativeTrackInJavaObj = env->GetFieldID( 108346e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom audioTrackClass, 1084075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME, "J"); 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (javaAudioTrackFields.nativeTrackInJavaObj == NULL) { 10863762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find AudioTrack.%s", JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME); 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1089a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // jniData 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.jniData = env->GetFieldID( 109146e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom audioTrackClass, 1092075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat JAVA_JNIDATA_FIELD_NAME, "J"); 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (javaAudioTrackFields.jniData == NULL) { 10943762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find AudioTrack.%s", JAVA_JNIDATA_FIELD_NAME); 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1097a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // fieldStreamType 1098a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi javaAudioTrackFields.fieldStreamType = env->GetFieldID(audioTrackClass, 1099a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi JAVA_STREAMTYPE_FIELD_NAME, "I"); 1100a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi if (javaAudioTrackFields.fieldStreamType == NULL) { 1101a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi ALOGE("Can't find AudioTrack.%s", JAVA_STREAMTYPE_FIELD_NAME); 1102a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi return -1; 1103a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi } 1104a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 1105a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // Get the AudioAttributes class and fields 1106a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi jclass audioAttrClass = env->FindClass(kAudioAttributesClassPathName); 1107a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi if (audioAttrClass == NULL) { 1108a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi ALOGE("Can't find %s", kAudioAttributesClassPathName); 1109a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi return -1; 1110a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi } 1111a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi jclass audioAttributesClassRef = (jclass)env->NewGlobalRef(audioAttrClass); 1112a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi javaAudioAttrFields.fieldUsage = env->GetFieldID(audioAttributesClassRef, "mUsage", "I"); 1113a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi javaAudioAttrFields.fieldContentType 1114a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi = env->GetFieldID(audioAttributesClassRef, "mContentType", "I"); 1115a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi javaAudioAttrFields.fieldFlags = env->GetFieldID(audioAttributesClassRef, "mFlags", "I"); 1116701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi javaAudioAttrFields.fieldFormattedTags = 1117701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi env->GetFieldID(audioAttributesClassRef, "mFormattedTags", "Ljava/lang/String;"); 1118a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi env->DeleteGlobalRef(audioAttributesClassRef); 1119a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi if (javaAudioAttrFields.fieldUsage == NULL || javaAudioAttrFields.fieldContentType == NULL 1120701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi || javaAudioAttrFields.fieldFlags == NULL 1121701d6ff12f36bf5e9de0dafdaced06744fd411ebJean-Michel Trivi || javaAudioAttrFields.fieldFormattedTags == NULL) { 1122a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi ALOGE("Can't initialize AudioAttributes fields"); 1123a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi return -1; 1124a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi } 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 1131