android_media_AudioTrack.cpp revision dbf55665c5c4802cbfc56463198805be48ec75af
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 { 53a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi jfieldID fieldUsage; // AudioAttributes.mUsage 54a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi jfieldID fieldContentType; // AudioAttributes.mContentType 55a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi jfieldID fieldFlags; // AudioAttributes.mFlags 56a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi jfieldID fieldTags; // AudioAttributes.mTags 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)); 266a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi const jstring jtags = (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldTags); 267a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi const char* tags = env->GetStringUTFChars(jtags, NULL); 268a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it 269a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1); 270a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi env->ReleaseStringUTFChars(jtags, tags); 271a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage); 272a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa->content_type = 273a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType); 274a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags); 275a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 276a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi ALOGV("AudioTrack_setup for usage=%d content=%d flags=0x%#x tags=%s", 277a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa->usage, paa->content_type, paa->flags, paa->tags); 278a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 279532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // initialize the callback information: 280532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // this data will be passed with every AudioTrack callback 281532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent AudioTrackJniStorage* lpJniStorage = new AudioTrackJniStorage(); 282532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz); 283532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // we use a weak reference so the AudioTrack object can be garbage collected. 284532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this); 285532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpJniStorage->mCallbackData.busy = false; 286532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // initialize the native AudioTrack object 2882defed988f74c98d5af8d02551ebf7262490cc5bJean-Michel Trivi status_t status = NO_ERROR; 2893d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten switch (memoryMode) { 2903d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten case MODE_STREAM: 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 292c5d142428ad68dd8aa4ffb80719667b13ad5049fGlenn Kasten status = lpTrack->set( 293a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi AUDIO_STREAM_DEFAULT,// stream type 294a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi sampleRateInHertz, 295a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi format,// word length, PCM 296a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi nativeChannelMask, 297a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi frameCount, 298a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi AUDIO_OUTPUT_FLAG_NONE, 299a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user) 300a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack 301a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 0,// shared mem 302a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi true,// thread can call Java 303a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi sessionId,// audio session ID 304a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi AudioTrack::TRANSFER_DEFAULT, // default transfer mode 305a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi NULL, // default offloadInfo 306a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi -1, -1, // default uid, pid values 307a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa); 3083d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten break; 30918db49a46259020387c40fff36d92edc1087a366Glenn Kasten 3103d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten case MODE_STATIC: 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // AudioTrack is using shared memory 31218db49a46259020387c40fff36d92edc1087a366Glenn Kasten 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!lpJniStorage->allocSharedMem(buffSizeInBytes)) { 3143762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error creating AudioTrack in static mode: error creating mem heap base"); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto native_init_failure; 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31718db49a46259020387c40fff36d92edc1087a366Glenn Kasten 318c5d142428ad68dd8aa4ffb80719667b13ad5049fGlenn Kasten status = lpTrack->set( 319a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi AUDIO_STREAM_DEFAULT,// stream type 320a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi sampleRateInHertz, 321a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi format,// word length, PCM 322a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi nativeChannelMask, 323a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi frameCount, 324a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi AUDIO_OUTPUT_FLAG_NONE, 325a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)); 326a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack 327a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi lpJniStorage->mMemBase,// shared mem 328a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi true,// thread can call Java 329a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi sessionId,// audio session ID 330a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi AudioTrack::TRANSFER_DEFAULT, // default transfer mode 331a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi NULL, // default offloadInfo 332a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi -1, -1, // default uid, pid values 333a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa); 3343d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten break; 3353d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten 3363d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten default: 3373d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten ALOGE("Unknown mode %d", memoryMode); 3383d301cb2b1d9e61c3af8a8b0b9db370d3d7abf77Glenn Kasten goto native_init_failure; 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 341c5d142428ad68dd8aa4ffb80719667b13ad5049fGlenn Kasten if (status != NO_ERROR) { 342c5d142428ad68dd8aa4ffb80719667b13ad5049fGlenn Kasten ALOGE("Error %d initializing AudioTrack", status); 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto native_init_failure; 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3462fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL); 3472fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent if (nSession == NULL) { 3483762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error creating AudioTrack: Error retrieving session id pointer"); 3492fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent goto native_init_failure; 3502fb43ef8c0b922c1bd0d7cb6867e30d702d4bdb8Eric Laurent } 351619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent // read the audio session ID back from AudioTrack in case we create a new session 352619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent nSession[0] = lpTrack->getSessionId(); 353619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); 354619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent nSession = NULL; 355619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent 356532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent { // scope for the lock 357532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Mutex::Autolock l(sLock); 358532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sAudioTrackCallBackCookies.add(&lpJniStorage->mCallbackData); 359532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 36018db49a46259020387c40fff36d92edc1087a366Glenn Kasten // save our newly created C++ AudioTrack in the "nativeTrackInJavaObj" field 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // of the Java object (in mNativeTrackInJavaObj) 362532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent setAudioTrack(env, thiz, lpTrack); 36318db49a46259020387c40fff36d92edc1087a366Glenn Kasten 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // save the JNI resources so we can free them later 365075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat //ALOGV("storing lpJniStorage: %x\n", (long)lpJniStorage); 366075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat env->SetLongField(thiz, javaAudioTrackFields.jniData, (jlong)lpJniStorage); 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 368a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // since we had audio attributes, the stream type was derived from them during the 369a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // creation of the native AudioTrack: push the same value to the Java object 370a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi env->SetIntField(thiz, javaAudioTrackFields.fieldStreamType, (jint) lpTrack->streamType()); 371a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // audio attributes were copied in AudioTrack creation 372a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi free(paa); 373a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi paa = NULL; 374a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 375a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 376bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint) AUDIO_JAVA_SUCCESS; 37718db49a46259020387c40fff36d92edc1087a366Glenn Kasten 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // failures: 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnative_init_failure: 380a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi if (paa != NULL) { 381a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi free(paa); 382a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi } 383619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent if (nSession != NULL) { 384619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); 385619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent } 3868a1496855cb81a6f2e9e8d51dd6b6ed595047a2aJean-Michel Trivi env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_class); 3878a1496855cb81a6f2e9e8d51dd6b6ed595047a2aJean-Michel Trivi env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_ref); 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete lpJniStorage; 389075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat env->SetLongField(thiz, javaAudioTrackFields.jniData, 0); 39018db49a46259020387c40fff36d92edc1087a366Glenn Kasten 391075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED; 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_start(JNIEnv *env, jobject thiz) 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 399532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 400532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for start()"); 4037070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 40521dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->start(); 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_stop(JNIEnv *env, jobject thiz) 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 414532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 415532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for stop()"); 4187070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->stop(); 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_pause(JNIEnv *env, jobject thiz) 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 429532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 430532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for pause()"); 4337070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->pause(); 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_flush(JNIEnv *env, jobject thiz) 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 444532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 445532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for flush()"); 4487070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->flush(); 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectandroid_media_AudioTrack_set_volume(JNIEnv *env, jobject thiz, jfloat leftVol, jfloat rightVol ) 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 458532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 459532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setVolume()"); 4627070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return; 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lpTrack->setVolume(leftVol, rightVol); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 46918db49a46259020387c40fff36d92edc1087a366Glenn Kasten 470532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent#define CALLBACK_COND_WAIT_TIMEOUT_MS 1000 471eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivistatic void android_media_AudioTrack_release(JNIEnv *env, jobject thiz) { 472532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = setAudioTrack(env, thiz, 0); 473532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 474532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return; 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 476532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent //ALOGV("deleting lpTrack: %x\n", (int)lpTrack); 477532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpTrack->stop(); 47818db49a46259020387c40fff36d92edc1087a366Glenn Kasten 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // delete the JNI data 480075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat AudioTrackJniStorage* pJniStorage = (AudioTrackJniStorage *)env->GetLongField( 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project thiz, javaAudioTrackFields.jniData); 482532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // reset the native resources in the Java object so any attempt to access 483532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // them after a call to release fails. 484075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat env->SetLongField(thiz, javaAudioTrackFields.jniData, 0); 485532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pJniStorage) { 487532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent Mutex::Autolock l(sLock); 488532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent audiotrack_callback_cookie *lpCookie = &pJniStorage->mCallbackData; 48971f2cf116aab893e224056c38ab146bd1538dd3eSteve Block //ALOGV("deleting pJniStorage: %x\n", (int)pJniStorage); 490532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent while (lpCookie->busy) { 491532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpCookie->cond.waitRelative(sLock, 492532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent milliseconds(CALLBACK_COND_WAIT_TIMEOUT_MS)) != 493532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent NO_ERROR) { 494532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent break; 495532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 496532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent } 497532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sAudioTrackCallBackCookies.remove(lpCookie); 498532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent // delete global refs created in native_setup 499532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent env->DeleteGlobalRef(lpCookie->audioTrack_class); 500532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent env->DeleteGlobalRef(lpCookie->audioTrack_ref); 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete pJniStorage; 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 50518db49a46259020387c40fff36d92edc1087a366Glenn Kasten 506532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent// ---------------------------------------------------------------------------- 507eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivistatic void android_media_AudioTrack_finalize(JNIEnv *env, jobject thiz) { 508eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi //ALOGV("android_media_AudioTrack_finalize jobject: %x\n", (int)thiz); 509eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi android_media_AudioTrack_release(env, thiz); 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 5137ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivijint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const jbyte* data, 5147ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi jint offsetInBytes, jint sizeInBytes, bool blocking = true) { 51521dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // give the data to the native AudioTrack object (the data starts at the offset) 51621dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi ssize_t written = 0; 51721dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // regular write() or copy the data to the AudioTrack's shared memory? 518532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (track->sharedBuffer() == 0) { 5197ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi written = track->write(data + offsetInBytes, sizeInBytes, blocking); 5209b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten // for compatibility with earlier behavior of write(), return 0 in this case 5219b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten if (written == (ssize_t) WOULD_BLOCK) { 5229b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten written = 0; 5239b53db378aa76c3c24bd423113a46e696fa9af22Glenn Kasten } 52421dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi } else { 525fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten const audio_format_t format = audioFormatToNative(audioFormat); 526fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten switch (format) { 527fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten 528fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten default: 52954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten case AUDIO_FORMAT_PCM_FLOAT: 530fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten case AUDIO_FORMAT_PCM_16_BIT: { 53121dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // writing to shared memory, check for capacity 532532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if ((size_t)sizeInBytes > track->sharedBuffer()->size()) { 533532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sizeInBytes = track->sharedBuffer()->size(); 53421dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi } 535532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent memcpy(track->sharedBuffer()->pointer(), data + offsetInBytes, sizeInBytes); 53621dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi written = sizeInBytes; 537fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten } break; 538fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten 539fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten case AUDIO_FORMAT_PCM_8_BIT: { 54021dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // data contains 8bit data we need to expand to 16bit before copying 54121dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // to the shared memory 54221dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // writing to shared memory, check for capacity, 54321dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // note that input data will occupy 2X the input space due to 8 to 16bit conversion 544532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (((size_t)sizeInBytes)*2 > track->sharedBuffer()->size()) { 545532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sizeInBytes = track->sharedBuffer()->size() / 2; 54621dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi } 54721dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi int count = sizeInBytes; 548532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent int16_t *dst = (int16_t *)track->sharedBuffer()->pointer(); 54937967d46f40c8c52c88ff8c011972a1489d465ecGlenn Kasten const uint8_t *src = (const uint8_t *)(data + offsetInBytes); 55037967d46f40c8c52c88ff8c011972a1489d465ecGlenn Kasten memcpy_to_i16_from_u8(dst, src, count); 55121dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // even though we wrote 2*sizeInBytes, we only report sizeInBytes as written to hide 55221dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi // the 8bit mixer restriction from the user of this function 55321dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi written = sizeInBytes; 554fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten } break; 555fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten 55621dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi } 55721dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi } 55821dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi return written; 55921dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi 56021dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi} 56121dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi 56221dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi// ---------------------------------------------------------------------------- 563eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivistatic jint android_media_AudioTrack_write_byte(JNIEnv *env, jobject thiz, 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray javaAudioData, 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint offsetInBytes, jint sizeInBytes, 5667ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi jint javaAudioFormat, 5677ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi jboolean isWriteBlocking) { 568eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi //ALOGV("android_media_AudioTrack_write_byte(offset=%d, sizeInBytes=%d) called", 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // offsetInBytes, sizeInBytes); 570532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lpTrack == NULL) { 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for write()"); 5747070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return 0; 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // get the pointer for the audio data from the java array 578421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such 579421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent // a way that it becomes much more efficient. When doing so, we will have to prevent the 580421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent // AudioSystem callback to be called while in critical section (in case of media server 581421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent // process crash for instance) 582532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent jbyte* cAudioData = NULL; 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (javaAudioData) { 584421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent cAudioData = (jbyte *)env->GetByteArrayElements(javaAudioData, NULL); 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cAudioData == NULL) { 5863762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Error retrieving source of audio data to play, can't play"); 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; // out of memory or no data to load 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5903762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("NULL java array of audio data to play, can't play"); 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5947ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi jint written = writeToTrack(lpTrack, javaAudioFormat, cAudioData, offsetInBytes, sizeInBytes, 5957ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi isWriteBlocking == JNI_TRUE /* blocking */); 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 597421ddc014b31478ba0ef115e098d8780a35af331Eric Laurent env->ReleaseByteArrayElements(javaAudioData, cAudioData, 0); 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 59971f2cf116aab893e224056c38ab146bd1538dd3eSteve Block //ALOGV("write wrote %d (tried %d) bytes in the native AudioTrack with offset %d", 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (int)written, (int)(sizeInBytes), (int)offsetInBytes); 60121dc037e7e7c51e33b5808320f47339ee3a2b103Jean-Michel Trivi return written; 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 6067ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivistatic jint android_media_AudioTrack_write_native_bytes(JNIEnv *env, jobject thiz, 6075d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi jbyteArray javaBytes, jint byteOffset, jint sizeInBytes, 6087ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi jint javaAudioFormat, jboolean isWriteBlocking) { 6097ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi //ALOGV("android_media_AudioTrack_write_native_bytes(offset=%d, sizeInBytes=%d) called", 6107ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi // offsetInBytes, sizeInBytes); 6117ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 6127ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi if (lpTrack == NULL) { 6137ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi jniThrowException(env, "java/lang/IllegalStateException", 6147ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi "Unable to retrieve AudioTrack pointer for write()"); 6157ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi return 0; 6167ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi } 6177ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 6187ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi ScopedBytesRO bytes(env, javaBytes); 6197ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi if (bytes.get() == NULL) { 6207ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi ALOGE("Error retrieving source of audio data to play, can't play"); 621bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_BAD_VALUE; 6227ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi } 6237ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 6245d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi jint written = writeToTrack(lpTrack, javaAudioFormat, bytes.get(), byteOffset, 6257ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi sizeInBytes, isWriteBlocking == JNI_TRUE /* blocking */); 6267ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 6277ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi return written; 6287ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi} 6297ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 6307ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi// ---------------------------------------------------------------------------- 631eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivistatic jint android_media_AudioTrack_write_short(JNIEnv *env, jobject thiz, 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jshortArray javaAudioData, 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint offsetInShorts, jint sizeInShorts, 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint javaAudioFormat) { 6353d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent 6363d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent //ALOGV("android_media_AudioTrack_write_short(offset=%d, sizeInShorts=%d) called", 6373d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent // offsetInShorts, sizeInShorts); 6383d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 6393d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent if (lpTrack == NULL) { 6403d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent jniThrowException(env, "java/lang/IllegalStateException", 6413d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent "Unable to retrieve AudioTrack pointer for write()"); 6423d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent return 0; 6433d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent } 6443d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent 6453d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent // get the pointer for the audio data from the java array 6463d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such 6473d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent // a way that it becomes much more efficient. When doing so, we will have to prevent the 6483d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent // AudioSystem callback to be called while in critical section (in case of media server 6493d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent // process crash for instance) 6503d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent jshort* cAudioData = NULL; 6513d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent if (javaAudioData) { 6523d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent cAudioData = (jshort *)env->GetShortArrayElements(javaAudioData, NULL); 6533d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent if (cAudioData == NULL) { 6543d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent ALOGE("Error retrieving source of audio data to play, can't play"); 6553d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent return 0; // out of memory or no data to load 6563d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent } 6573d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent } else { 6583d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent ALOGE("NULL java array of audio data to play, can't play"); 6593d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent return 0; 6603d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent } 6613d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData, 6623d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent offsetInShorts * sizeof(short), sizeInShorts * sizeof(short), 6633d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent true /*blocking write, legacy behavior*/); 6643d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent env->ReleaseShortArrayElements(javaAudioData, cAudioData, 0); 6653d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent 666f7e0a370e7178f698605165fc362384a42f3547dGlenn Kasten if (written > 0) { 6673d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent written /= sizeof(short); 668f7e0a370e7178f698605165fc362384a42f3547dGlenn Kasten } 6693d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent //ALOGV("write wrote %d (tried %d) shorts in the native AudioTrack with offset %d", 6703d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent // (int)written, (int)(sizeInShorts), (int)offsetInShorts); 6713d4c64191a181aac0922abbd56f4046d6b7ec31cEric Laurent 672f7e0a370e7178f698605165fc362384a42f3547dGlenn Kasten return written; 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 67754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kastenstatic jint android_media_AudioTrack_write_float(JNIEnv *env, jobject thiz, 67854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten jfloatArray javaAudioData, 67954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten jint offsetInFloats, jint sizeInFloats, 68054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten jint javaAudioFormat, 68154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten jboolean isWriteBlocking) { 68254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 68354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 68454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten if (lpTrack == NULL) { 68554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten jniThrowException(env, "java/lang/IllegalStateException", 68654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten "Unable to retrieve AudioTrack pointer for write()"); 68754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten return 0; 68854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } 68954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 69054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten jfloat* cAudioData = NULL; 69154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten if (javaAudioData) { 69254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten cAudioData = (jfloat *)env->GetFloatArrayElements(javaAudioData, NULL); 69354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten if (cAudioData == NULL) { 69454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten ALOGE("Error retrieving source of audio data to play, can't play"); 69554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten return 0; // out of memory or no data to load 69654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } 69754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } else { 69854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten ALOGE("NULL java array of audio data to play, can't play"); 69954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten return 0; 70054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } 70154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData, 70254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten offsetInFloats * sizeof(float), sizeInFloats * sizeof(float), 70354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten isWriteBlocking == JNI_TRUE /* blocking */); 70454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten env->ReleaseFloatArrayElements(javaAudioData, cAudioData, 0); 70554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 70654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten if (written > 0) { 70754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten written /= sizeof(float); 70854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } 70954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 71054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten return written; 71154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten} 71254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 71354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 71454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten// ---------------------------------------------------------------------------- 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_native_frame_count(JNIEnv *env, jobject thiz) { 716532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 717532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for frameCount()"); 720bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 722532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent 723532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return lpTrack->frameCount(); 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 72888e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurentstatic jint android_media_AudioTrack_set_playback_rate(JNIEnv *env, jobject thiz, 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint sampleRateInHz) { 730532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 731532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setSampleRate()"); 734bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 736bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus(lpTrack->setSampleRate(sampleRateInHz)); 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_playback_rate(JNIEnv *env, jobject thiz) { 742532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 743532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for getSampleRate()"); 746bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 748532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return (jint) lpTrack->getSampleRate(); 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 75318db49a46259020387c40fff36d92edc1087a366Glenn Kastenstatic jint android_media_AudioTrack_set_marker_pos(JNIEnv *env, jobject thiz, 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint markerPos) { 755532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 756532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setMarkerPosition()"); 759bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 761bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->setMarkerPosition(markerPos) ); 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_marker_pos(JNIEnv *env, jobject thiz) { 767532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t markerPos = 0; 76918db49a46259020387c40fff36d92edc1087a366Glenn Kasten 770532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for getMarkerPosition()"); 773bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 775532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpTrack->getMarkerPosition(&markerPos); 776532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return (jint)markerPos; 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_set_pos_update_period(JNIEnv *env, jobject thiz, 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint period) { 783532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 784532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setPositionUpdatePeriod()"); 787bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 78818db49a46259020387c40fff36d92edc1087a366Glenn Kasten } 789bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->setPositionUpdatePeriod(period) ); 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_pos_update_period(JNIEnv *env, jobject thiz) { 795532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t period = 0; 79718db49a46259020387c40fff36d92edc1087a366Glenn Kasten 798532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for getPositionUpdatePeriod()"); 801bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 803532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpTrack->getPositionUpdatePeriod(&period); 804532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return (jint)period; 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 80918db49a46259020387c40fff36d92edc1087a366Glenn Kastenstatic jint android_media_AudioTrack_set_position(JNIEnv *env, jobject thiz, 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint position) { 811532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 812532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setPosition()"); 815bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 817bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->setPosition(position) ); 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_position(JNIEnv *env, jobject thiz) { 823532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t position = 0; 82518db49a46259020387c40fff36d92edc1087a366Glenn Kasten 826532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for getPosition()"); 829bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 831532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent lpTrack->getPosition(&position); 832532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent return (jint)position; 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 83761dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodmanstatic jint android_media_AudioTrack_get_latency(JNIEnv *env, jobject thiz) { 83861dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 83961dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman 84061dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman if (lpTrack == NULL) { 84161dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman jniThrowException(env, "java/lang/IllegalStateException", 84261dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman "Unable to retrieve AudioTrack pointer for latency()"); 843bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 84461dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman } 84561dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman return (jint)lpTrack->latency(); 84661dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman} 84761dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman 84861dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman 84961dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman// ---------------------------------------------------------------------------- 850948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kastenstatic jint android_media_AudioTrack_get_timestamp(JNIEnv *env, jobject thiz, jlongArray jTimestamp) { 851948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 852948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten 853948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten if (lpTrack == NULL) { 854948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten ALOGE("Unable to retrieve AudioTrack pointer for getTimestamp()"); 855bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 856948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten } 857948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten AudioTimestamp timestamp; 858948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten status_t status = lpTrack->getTimestamp(timestamp); 859948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten if (status == OK) { 860948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten jlong* nTimestamp = (jlong *) env->GetPrimitiveArrayCritical(jTimestamp, NULL); 861948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten if (nTimestamp == NULL) { 862948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten ALOGE("Unable to get array for getTimestamp()"); 863bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 864948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten } 865948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten nTimestamp[0] = (jlong) timestamp.mPosition; 866948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten nTimestamp[1] = (jlong) ((timestamp.mTime.tv_sec * 1000000000LL) + timestamp.mTime.tv_nsec); 867948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten env->ReleasePrimitiveArrayCritical(jTimestamp, nTimestamp, 0); 868948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten } 869bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint) nativeToJavaStatus(status); 870948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten} 871948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten 872948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten 873948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten// ---------------------------------------------------------------------------- 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_set_loop(JNIEnv *env, jobject thiz, 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint loopStart, jint loopEnd, jint loopCount) { 876532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 877532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for setLoop()"); 880bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 882bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->setLoop(loopStart, loopEnd, loopCount) ); 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_reload(JNIEnv *env, jobject thiz) { 888532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 889532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Unable to retrieve AudioTrack pointer for reload()"); 892bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 894bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->reload() ); 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_output_sample_rate(JNIEnv *env, jobject thiz, 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint javaStreamType) { 90185fbc871ded0f71f9638f85e7d2f03a35bf39ddaGlenn Kasten uint32_t afSamplingRate; 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // convert the stream type from Java to native value 903eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi // FIXME: code duplication with android_media_AudioTrack_setup() 90424fc2fb1c541e954b83fd31ea9f786a5e9b45501Dima Zavin audio_stream_type_t nativeStreamType; 90529a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten switch (javaStreamType) { 90629a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_VOICE_CALL: 90729a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_SYSTEM: 90829a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_RING: 90929a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_MUSIC: 91029a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_ALARM: 91129a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_NOTIFICATION: 91229a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_BLUETOOTH_SCO: 91329a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten case AUDIO_STREAM_DTMF: 91429a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten nativeStreamType = (audio_stream_type_t) javaStreamType; 91529a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten break; 91629a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten default: 91724fc2fb1c541e954b83fd31ea9f786a5e9b45501Dima Zavin nativeStreamType = AUDIO_STREAM_DEFAULT; 91829a0909c5f777230b9f34ef0703fed3cd4633833Glenn Kasten break; 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9218f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten status_t status = AudioSystem::getOutputSamplingRate(&afSamplingRate, nativeStreamType); 9228f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten if (status != NO_ERROR) { 9238f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten ALOGE("Error %d in AudioSystem::getOutputSamplingRate() for stream type %d " 9248f81d0832bd2eea2e479f38160961fbcf35bd591Glenn Kasten "in AudioTrack JNI", status, nativeStreamType); 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return DEFAULT_OUTPUT_SAMPLE_RATE; 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return afSamplingRate; 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 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// returns the minimum required size for the successful creation of a streaming AudioTrack 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// returns -1 if there was an error querying the hardware. 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thiz, 9365b8fd44365f03601aaba41879ac18e70ce814a0fGlenn Kasten jint sampleRateInHertz, jint channelCount, jint audioFormat) { 937c3308074cd6f06bbb35c1999b5260f938742a9e7Chia-chi Yeh 938659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten size_t frameCount; 939659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten const status_t status = AudioTrack::getMinFrameCount(&frameCount, AUDIO_STREAM_DEFAULT, 940659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten sampleRateInHertz); 941659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten if (status != NO_ERROR) { 942659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten ALOGE("AudioTrack::getMinFrameCount() for sample rate %d failed with status %d", 943659a9712f2072f0bb3fa39de23f252f2f97440b4Glenn Kasten sampleRateInHertz, status); 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 946fe834d30f4f3f51b754d55fecb36f11279733948Glenn Kasten const audio_format_t format = audioFormatToNative(audioFormat); 947ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent if (audio_is_linear_pcm(format)) { 948ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent const size_t bytesPerSample = audio_bytes_per_sample(format); 949ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent return frameCount * channelCount * bytesPerSample; 950ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent } else { 951ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent return frameCount; 952ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent } 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9557070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent// ---------------------------------------------------------------------------- 9563009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kastenstatic jint 9577070b36549d511d6627538c73dfbab23fbae5b43Eric Laurentandroid_media_AudioTrack_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level ) 9587070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent{ 959532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 9607070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent if (lpTrack == NULL ) { 9617070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent jniThrowException(env, "java/lang/IllegalStateException", 9627070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent "Unable to retrieve AudioTrack pointer for setAuxEffectSendLevel()"); 9633009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten return -1; 9647070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent } 9657070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent 9663009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten status_t status = lpTrack->setAuxEffectSendLevel(level); 9673009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten if (status != NO_ERROR) { 9683009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten ALOGE("AudioTrack::setAuxEffectSendLevel() for level %g failed with status %d", 9693009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten level, status); 9703009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten } 9713009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten return (jint) status; 9727070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent} 9737070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent 9747070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent// ---------------------------------------------------------------------------- 9757070b36549d511d6627538c73dfbab23fbae5b43Eric Laurentstatic jint android_media_AudioTrack_attachAuxEffect(JNIEnv *env, jobject thiz, 9767070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent jint effectId) { 977532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); 978532bc1cb7da9fdbf34893fa48b2ae11f54cf6a8eEric Laurent if (lpTrack == NULL) { 9797070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent jniThrowException(env, "java/lang/IllegalStateException", 9807070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent "Unable to retrieve AudioTrack pointer for attachAuxEffect()"); 981bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return (jint)AUDIO_JAVA_ERROR; 9827070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent } 983bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent return nativeToJavaStatus( lpTrack->attachAuxEffect(effectId) ); 9847070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent} 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMethods[] = { 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // name, signature, funcPtr 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_start", "()V", (void *)android_media_AudioTrack_start}, 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_stop", "()V", (void *)android_media_AudioTrack_stop}, 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_pause", "()V", (void *)android_media_AudioTrack_pause}, 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_flush", "()V", (void *)android_media_AudioTrack_flush}, 994a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;IIIII[I)I", 995eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi (void *)android_media_AudioTrack_setup}, 996eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi {"native_finalize", "()V", (void *)android_media_AudioTrack_finalize}, 997eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi {"native_release", "()V", (void *)android_media_AudioTrack_release}, 9987ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi {"native_write_byte", "([BIIIZ)I",(void *)android_media_AudioTrack_write_byte}, 9997ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi {"native_write_native_bytes", 10005d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi "(Ljava/lang/Object;IIIZ)I", 10017ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi (void *)android_media_AudioTrack_write_native_bytes}, 1002eac8438a7dbe42e81f5273e0847a3f5e4247aa5bJean-Michel Trivi {"native_write_short", "([SIII)I", (void *)android_media_AudioTrack_write_short}, 100354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten {"native_write_float", "([FIIIZ)I",(void *)android_media_AudioTrack_write_float}, 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_setVolume", "(FF)V", (void *)android_media_AudioTrack_set_volume}, 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_native_frame_count", 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "()I", (void *)android_media_AudioTrack_get_native_frame_count}, 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_playback_rate", 100888e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent "(I)I", (void *)android_media_AudioTrack_set_playback_rate}, 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_playback_rate", 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "()I", (void *)android_media_AudioTrack_get_playback_rate}, 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_marker_pos","(I)I", (void *)android_media_AudioTrack_set_marker_pos}, 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_marker_pos","()I", (void *)android_media_AudioTrack_get_marker_pos}, 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_pos_update_period", 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "(I)I", (void *)android_media_AudioTrack_set_pos_update_period}, 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_pos_update_period", 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "()I", (void *)android_media_AudioTrack_get_pos_update_period}, 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_position", "(I)I", (void *)android_media_AudioTrack_set_position}, 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_position", "()I", (void *)android_media_AudioTrack_get_position}, 101961dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman {"native_get_latency", "()I", (void *)android_media_AudioTrack_get_latency}, 1020948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten {"native_get_timestamp", "([J)I", (void *)android_media_AudioTrack_get_timestamp}, 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_set_loop", "(III)I", (void *)android_media_AudioTrack_set_loop}, 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_reload_static", "()I", (void *)android_media_AudioTrack_reload}, 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_output_sample_rate", 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "(I)I", (void *)android_media_AudioTrack_get_output_sample_rate}, 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_get_min_buff_size", 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "(III)I", (void *)android_media_AudioTrack_get_min_buff_size}, 10277070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent {"native_setAuxEffectSendLevel", 10283009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten "(F)I", (void *)android_media_AudioTrack_setAuxEffectSendLevel}, 10297070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent {"native_attachAuxEffect", 10307070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent "(I)I", (void *)android_media_AudioTrack_attachAuxEffect}, 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// field names found in android/media/AudioTrack.java 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define JAVA_POSTEVENT_CALLBACK_NAME "postEventFromNative" 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME "mNativeTrackInJavaObj" 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define JAVA_JNIDATA_FIELD_NAME "mJniData" 1038a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi#define JAVA_STREAMTYPE_FIELD_NAME "mStreamType" 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// preconditions: 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// theClass is valid 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool android_media_getIntConstantFromClass(JNIEnv* pEnv, jclass theClass, const char* className, 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* constName, int* constVal) { 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID javaConst = NULL; 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaConst = pEnv->GetStaticFieldID(theClass, constName, "I"); 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (javaConst != NULL) { 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *constVal = pEnv->GetStaticIntField(theClass, javaConst); 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10513762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find %s.%s", className, constName); 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_media_AudioTrack(JNIEnv *env) 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.nativeTrackInJavaObj = NULL; 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.postNativeEventInJava = NULL; 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the AudioTrack class 106446e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom jclass audioTrackClass = env->FindClass(kClassPathName); 106546e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom if (audioTrackClass == NULL) { 10663762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find %s", kClassPathName); 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the postEvent method 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.postNativeEventInJava = env->GetStaticMethodID( 107246e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom audioTrackClass, 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project JAVA_POSTEVENT_CALLBACK_NAME, "(Ljava/lang/Object;IIILjava/lang/Object;)V"); 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (javaAudioTrackFields.postNativeEventInJava == NULL) { 10753762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find AudioTrack.%s", JAVA_POSTEVENT_CALLBACK_NAME); 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the variables fields 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // nativeTrackInJavaObj 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.nativeTrackInJavaObj = env->GetFieldID( 108246e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom audioTrackClass, 1083075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME, "J"); 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (javaAudioTrackFields.nativeTrackInJavaObj == NULL) { 10853762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find AudioTrack.%s", JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME); 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1088a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // jniData 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project javaAudioTrackFields.jniData = env->GetFieldID( 109046e18c11d46a2bc1a46174f963d0ed1224d94cd2Brian Carlstrom audioTrackClass, 1091075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat JAVA_JNIDATA_FIELD_NAME, "J"); 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (javaAudioTrackFields.jniData == NULL) { 10933762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find AudioTrack.%s", JAVA_JNIDATA_FIELD_NAME); 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1096a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // fieldStreamType 1097a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi javaAudioTrackFields.fieldStreamType = env->GetFieldID(audioTrackClass, 1098a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi JAVA_STREAMTYPE_FIELD_NAME, "I"); 1099a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi if (javaAudioTrackFields.fieldStreamType == NULL) { 1100a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi ALOGE("Can't find AudioTrack.%s", JAVA_STREAMTYPE_FIELD_NAME); 1101a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi return -1; 1102a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi } 1103a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 1104a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // Get the AudioAttributes class and fields 1105a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi jclass audioAttrClass = env->FindClass(kAudioAttributesClassPathName); 1106a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi if (audioAttrClass == NULL) { 1107a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi ALOGE("Can't find %s", kAudioAttributesClassPathName); 1108a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi return -1; 1109a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi } 1110a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi jclass audioAttributesClassRef = (jclass)env->NewGlobalRef(audioAttrClass); 1111a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi javaAudioAttrFields.fieldUsage = env->GetFieldID(audioAttributesClassRef, "mUsage", "I"); 1112a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi javaAudioAttrFields.fieldContentType 1113a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi = env->GetFieldID(audioAttributesClassRef, "mContentType", "I"); 1114a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi javaAudioAttrFields.fieldFlags = env->GetFieldID(audioAttributesClassRef, "mFlags", "I"); 1115a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi javaAudioAttrFields.fieldTags = env->GetFieldID(audioAttributesClassRef, "mFormattedTags", 1116a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi "Ljava/lang/String;"); 1117a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi env->DeleteGlobalRef(audioAttributesClassRef); 1118a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi if (javaAudioAttrFields.fieldUsage == NULL || javaAudioAttrFields.fieldContentType == NULL 1119a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi || javaAudioAttrFields.fieldFlags == NULL || javaAudioAttrFields.fieldTags == NULL) { 1120a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi ALOGE("Can't initialize AudioAttributes fields"); 1121a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi return -1; 1122a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi } 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 1129