player.c revision ed462e937cd99e9aaee98613c4e3e0469145d719
1e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer/* 2e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * Copyright 2015 The Android Open Source Project 3e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * 4e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * Licensed under the Apache License, Version 2.0 (the "License"); 5e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * you may not use this file except in compliance with the License. 6e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * You may obtain a copy of the License at 7e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * 8e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * http://www.apache.org/licenses/LICENSE-2.0 9e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * 10e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * Unless required by applicable law or agreed to in writing, software 11e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * distributed under the License is distributed on an "AS IS" BASIS, 12e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * See the License for the specific language governing permissions and 14e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * limitations under the License. 15e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer */ 16e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 17e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <android/log.h> 18e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <assert.h> 19e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <jni.h> 20e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <malloc.h> 21e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <math.h> 22e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <sys/types.h> 23e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 24e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// for native audio 25e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <SLES/OpenSLES.h> 26e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <SLES/OpenSLES_Android.h> 27e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include <SLES/OpenSLES_AndroidConfiguration.h> 28e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 29e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#include "sync_clock.h" 30e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 31e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// logging 32e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#define APPNAME "WALT" 33e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 34e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// engine interfaces 35e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic SLObjectItf engineObject = NULL; 36e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic SLEngineItf engineEngine = NULL; 37e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 38e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// output mix interfaces 39e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic SLObjectItf outputMixObject = NULL; 40e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 41e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// buffer queue player interfaces 42e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic SLObjectItf bqPlayerObject = NULL; 43e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic SLPlayItf bqPlayerPlay = NULL; 44e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue = NULL; 45e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 46e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// recorder interfaces 47e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic SLObjectItf recorderObject = NULL; 48e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic SLRecordItf recorderRecord; 49e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic SLAndroidSimpleBufferQueueItf recorderBufferQueue; 50e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic volatile int bqPlayerRecorderBusy = 0; 51e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 52e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic unsigned int recorder_frames; 53e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic short* recorderBuffer; 54e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic unsigned recorderSize = 0; 55e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 56e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic unsigned int framesPerBuffer; 57e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 58e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#define CHANNELS 1 // 1 for mono, 2 for stereo 59e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 60e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// Each short represents a 16-bit audio sample 61e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic short* beepBuffer = NULL; 62e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic short* silenceBuffer = NULL; 63e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic unsigned int bufferSizeInBytes = 0; 64e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 65e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#define MAXIMUM_AMPLITUDE_VALUE 32767 66e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 67e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// how many times to play the wave table (so we can actually hear it) 68e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer#define BUFFERS_TO_PLAY 10 69e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 70e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic unsigned buffersRemaining = 0; 71e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerstatic short warmedUp = 0; 72e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 73e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 74e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// Timestamps 75e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// te - enqueue time 76e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// tc - callback time 77e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmerint64_t te_play = 0, te_rec = 0, tc_rec = 0; 78e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 79e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer/** 80e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer * Create wave tables for audio out. 81e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer */ 82e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmervoid createWaveTables(){ 83e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer bufferSizeInBytes = framesPerBuffer * sizeof(*beepBuffer); 84e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer silenceBuffer = malloc(bufferSizeInBytes); 85e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer beepBuffer = malloc(bufferSizeInBytes); 86e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 87e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 88e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer __android_log_print(ANDROID_LOG_VERBOSE, 89e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer APPNAME, 90e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer "Creating wave tables, 1 channel. Frames: %i Buffer size (bytes): %i", 91e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer framesPerBuffer, 92e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer bufferSizeInBytes); 93e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 94e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer unsigned int i; 95e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer for (i = 0; i < framesPerBuffer; i++) { 96e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer silenceBuffer[i] = 0; 97e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer beepBuffer[i] = (i & 2 - 1) * MAXIMUM_AMPLITUDE_VALUE; 98e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // This fills a buffer that looks like [min, min, max, max, min, min...] 99e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // which is a square wave at 1/4 frequency of the sampling rate 100e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // for 48kHz sampling this is 12kHz pitch, still well audible. 101e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 102e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 103e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 104e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// this callback handler is called every time a buffer finishes playing 105ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmervoid bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, __attribute__((unused)) void *context) 106e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer{ 107e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer if (bq == NULL) { 108e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer __android_log_print(ANDROID_LOG_ERROR, APPNAME, "buffer queue is null"); 109e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 110e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(bq == bqPlayerBufferQueue); 111e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(NULL == context); 112e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 113e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer if (buffersRemaining > 0) { // continue playing tone 114e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer if(buffersRemaining == BUFFERS_TO_PLAY && warmedUp) { 115e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // Enqueue the first non-silent buffer, save the timestamp 116e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // For cold test Enqueue happens in playTone rather than here. 117e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer te_play = uptimeMicros(); 118e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 119e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer buffersRemaining--; 120e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 121e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, beepBuffer, 122e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer bufferSizeInBytes); 123e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 124e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 125e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } else if (warmedUp) { // stop tone but keep playing silence 126e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, silenceBuffer, 127e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer bufferSizeInBytes); 128e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 129e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void) result; 130e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } else { // stop playing completely 131e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED); 132e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 133e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 134e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 135e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Done playing tone"); 136e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 137e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 138e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 139ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmerjlong Java_org_chromium_latency_walt_AudioTest_playTone(__attribute__((unused)) JNIEnv* env, 140ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) jclass clazz){ 141e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 142e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer int64_t t_start = uptimeMicros(); 143e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer te_play = 0; 144e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 145e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLresult result; 146e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 147e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer if (!warmedUp) { 148e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*bqPlayerBufferQueue)->Clear(bqPlayerBufferQueue); 149e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 150e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 151e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 152e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // Enqueue first buffer 153e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer te_play = uptimeMicros(); 154e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, beepBuffer, 155e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer bufferSizeInBytes); 156e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 157e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void) result; 158e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 159e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); 160e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 161e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void) result; 162e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 163e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer int dt_state = uptimeMicros() - t_start; 164e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "playTone() changed state to playing dt=%d us", dt_state); 165e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // TODO: this block takes lots of time (~13ms on Nexus 7) research this and decide how to measure. 166e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 167e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 168e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Playing tone"); 169e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer buffersRemaining = BUFFERS_TO_PLAY; 170e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 171e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer return (jlong) t_start; 172e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 173e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 174e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 175e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// create the engine and output mix objects 176ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmervoid Java_org_chromium_latency_walt_AudioTest_createEngine(__attribute__((unused)) JNIEnv* env, 177ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) jclass clazz) 178e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer{ 179e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Creating audio engine"); 180e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 181e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLresult result; 182e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 183e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // create engine 184e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 185e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 186e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 187e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 188e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // realize the engine 189e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 190e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 191e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 192e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 193e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // get the engine interface, which is needed in order to create other objects 194e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); 195e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 196e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 197e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 198e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // create output mix, 199e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL); 200e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 201e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 202e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 203e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // realize the output mix 204e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); 205e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 206e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 207e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 208e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 209ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmervoid Java_org_chromium_latency_walt_AudioTest_destroyEngine(__attribute__((unused)) JNIEnv *env, 210ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) jclass clazz) 211e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer{ 212e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer if (bqPlayerObject != NULL) { 213e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (*bqPlayerObject)->Destroy(bqPlayerObject); 214e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer bqPlayerObject = NULL; 215e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 216e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 217e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer if (outputMixObject != NULL) { 218e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (*outputMixObject)->Destroy(outputMixObject); 219e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer outputMixObject = NULL; 220e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 221e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 222e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer if (engineObject != NULL) { 223e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (*engineObject)->Destroy(engineObject); 224e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer engineObject = NULL; 225e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 226e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 227e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 228e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// create buffer queue audio player 229ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmervoid Java_org_chromium_latency_walt_AudioTest_createBufferQueueAudioPlayer( 230ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) JNIEnv* env, 231ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) jclass clazz, 232ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer jint optimalFrameRate, 233ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer jint optimalFramesPerBuffer) 234e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer{ 235e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Creating audio player with frame rate %d and frames per buffer %d", 236e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer optimalFrameRate, optimalFramesPerBuffer); 237e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 238e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer framesPerBuffer = optimalFramesPerBuffer; 239e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer createWaveTables(); 240e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 241e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLresult result; 242e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 243e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // configure the audio source (supply data through a buffer queue in PCM format) 244e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLDataLocator_AndroidSimpleBufferQueue locator_bufferqueue_source; 245e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLDataFormat_PCM format_pcm; 246e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLDataSource audio_source; 247e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 248e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // source location 249e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer locator_bufferqueue_source.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; 250e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer locator_bufferqueue_source.numBuffers = 1; 251e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 252e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // source format 253e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer format_pcm.formatType = SL_DATAFORMAT_PCM; 254e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer format_pcm.numChannels = 1; 255e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 256e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // Note: this shouldn't be called samplesPerSec it should be called *framesPerSec* 257e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // because when channels = 2 then there are 2 samples per frame. 258e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer format_pcm.samplesPerSec = (SLuint32) optimalFrameRate * 1000; 259e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; 260e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer format_pcm.containerSize = 16; 261e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER; 262e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 263e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 264e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer audio_source.pLocator = &locator_bufferqueue_source; 265e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer audio_source.pFormat = &format_pcm; 266e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 267e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // configure the output: An output mix sink 268e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLDataLocator_OutputMix locator_output_mix; 269e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLDataSink audio_sink; 270e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 271e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer locator_output_mix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 272e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer locator_output_mix.outputMix = outputMixObject; 273e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 274e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer audio_sink.pLocator = &locator_output_mix; 275e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer audio_sink.pFormat = NULL; 276e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 277e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // create audio player 278e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // Note: Adding other output interfaces here will result in your audio being routed using the 279e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // normal path NOT the fast path 280e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer const SLInterfaceID interface_ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME }; 281e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer const SLboolean interfaces_required[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE }; 282e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 283e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*engineEngine)->CreateAudioPlayer( 284e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer engineEngine, 285e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer &bqPlayerObject, 286e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer &audio_source, 287e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer &audio_sink, 288e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 2, // Number of interfaces 289e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer interface_ids, 290e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer interfaces_required 291e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer ); 292e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 293e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 294e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 295e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 296e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // realize the player 297e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); 298e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 299e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 300e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 301e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // get the play interface 302e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); 303e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 304e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 305e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 306e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // get the buffer queue interface 307e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, 308e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer &bqPlayerBufferQueue); 309e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 310e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 311e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 312e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // register callback on the buffer queue 313e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL); 314e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 315e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 316e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 317e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 318ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmervoid Java_org_chromium_latency_walt_AudioTest_startWarmTest(__attribute__((unused)) JNIEnv* env, 319ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) jclass clazz) { 320e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLresult result; 321e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 322e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*bqPlayerBufferQueue)->Clear(bqPlayerBufferQueue); 323e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 324e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 325e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 326e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // enqueue some silence 327e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, silenceBuffer, bufferSizeInBytes); 328e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 329e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 330e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 331e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // set the player's state to playing 332e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); 333e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 334e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 335e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 336e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer warmedUp = 1; 337e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 338e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 339ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmervoid Java_org_chromium_latency_walt_AudioTest_stopTests(__attribute__((unused)) JNIEnv *env, 340ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) jclass clazz) { 341e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLresult result; 342e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 343e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED); 344e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 345e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 346e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 347e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer warmedUp = 0; 348e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 349e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 350e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// this callback handler is called every time a buffer finishes recording 351ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmervoid bqRecorderCallback(__attribute__((unused)) SLAndroidSimpleBufferQueueItf bq, 352ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) void *context) 353e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer{ 354e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer tc_rec = uptimeMicros(); 355e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(bq == recorderBufferQueue); 356e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(NULL == context); 357e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 358e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // for streaming recording, here we would call Enqueue to give recorder the next buffer to fill 359e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // but instead, this is a one-time buffer so we stop recording 360e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLresult result; 361e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED); 362e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer if (SL_RESULT_SUCCESS == result) { 363e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer recorderSize = recorder_frames * sizeof(short); 364e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 365e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer bqPlayerRecorderBusy = 0; 366e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 367e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer //// TODO: Use small buffers and re-enqueue each time 368e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, recorderBuffer, 369e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // recorder_frames * sizeof(short)); 370e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // assert(SL_RESULT_SUCCESS == result); 371e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 372e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 373e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// create audio recorder 374ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmerjboolean Java_org_chromium_latency_walt_AudioTest_createAudioRecorder( 375ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) JNIEnv* env, 376ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) jclass clazz, 377ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer jint optimalFrameRate, 378ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer jint framesToRecord) 379e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer{ 380e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLresult result; 381e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 382e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Creating audio recorder with frame rate %d and frames to record %d", 383e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer optimalFrameRate, framesToRecord); 384e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // Allocate buffer 385e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer recorder_frames = framesToRecord; 386e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer recorderBuffer = malloc(sizeof(*recorderBuffer) * recorder_frames); 387e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 388e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // configure audio source 389e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLDataLocator_IODevice loc_dev = { 390e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SL_DATALOCATOR_IODEVICE, 391e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SL_IODEVICE_AUDIOINPUT, 392e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SL_DEFAULTDEVICEID_AUDIOINPUT, 393e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer NULL 394e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer }; 395e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLDataSource audioSrc = {&loc_dev, NULL}; 396e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 397e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // configure audio sink 398e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLDataLocator_AndroidSimpleBufferQueue loc_bq; 399e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; 400e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer loc_bq.numBuffers = 2; 401e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 402e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 403e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // source format 404e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLDataFormat_PCM format_pcm; 405e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer format_pcm.formatType = SL_DATAFORMAT_PCM; 406e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer format_pcm.numChannels = CHANNELS; 407e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // Note: this shouldn't be called samplesPerSec it should be called *framesPerSec* 408e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // because when channels = 2 then there are 2 samples per frame. 409e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer format_pcm.samplesPerSec = (SLuint32) optimalFrameRate * 1000; 410e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; 411e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer format_pcm.containerSize = 16; 412e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER; 413e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 414e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 415e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 416e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLDataSink audioSnk = {&loc_bq, &format_pcm}; 417e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 418e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // create audio recorder 419e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // (requires the RECORD_AUDIO permission) 420e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer const SLInterfaceID id[2] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 421e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SL_IID_ANDROIDCONFIGURATION }; 422e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; 423e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*engineEngine)->CreateAudioRecorder(engineEngine, 424e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer &recorderObject, 425e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer &audioSrc, 426e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer &audioSnk, 427e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer sizeof(id)/sizeof(id[0]), 428e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer id, req); 429e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 430e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // Configure the voice recognition preset which has no 431e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // signal processing for lower latency. 432e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLAndroidConfigurationItf inputConfig; 433e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*recorderObject)->GetInterface(recorderObject, 434e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SL_IID_ANDROIDCONFIGURATION, 435e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer &inputConfig); 436e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer if (SL_RESULT_SUCCESS == result) { 437e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLuint32 presetValue = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION; 438e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (*inputConfig)->SetConfiguration(inputConfig, 439e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SL_ANDROID_KEY_RECORDING_PRESET, 440e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer &presetValue, 441e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer sizeof(SLuint32)); 442e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 443e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 444e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // realize the audio recorder 445e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE); 446e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer if (SL_RESULT_SUCCESS != result) { 447e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer return JNI_FALSE; 448e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 449e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 450e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // get the record interface 451e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD, &recorderRecord); 452e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 453e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 454e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 455e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // get the buffer queue interface 456e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*recorderObject)->GetInterface(recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 457e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer &recorderBufferQueue); 458e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 459e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 460e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 461e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // register callback on the buffer queue 462e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue, bqRecorderCallback, 463e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer NULL); 464e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 465e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 466e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 467e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Audio recorder created, buffer size: %d frames", 468e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer recorder_frames); 469e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 470e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer return JNI_TRUE; 471e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 472e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 473e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 474e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer// set the recording state for the audio recorder 475ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmervoid Java_org_chromium_latency_walt_AudioTest_startRecording(__attribute__((unused)) JNIEnv* env, 476ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) jclass clazz) 477e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer{ 478e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer SLresult result; 479e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 480e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer if( bqPlayerRecorderBusy) { 481e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer return; 482e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 483e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // in case already recording, stop recording and clear buffer queue 484e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED); 485e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 486e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 487e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*recorderBufferQueue)->Clear(recorderBufferQueue); 488e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 489e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 490e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 491e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // the buffer is not valid for playback yet 492e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer recorderSize = 0; 493e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 494e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // enqueue an empty buffer to be filled by the recorder 495e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // (for streaming recording, we would enqueue at least 2 empty buffers to start things off) 496e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer te_rec = uptimeMicros(); // TODO: investigate if it's better to time after SetRecordState 497e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer tc_rec = 0; 498e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, recorderBuffer, 499e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer recorder_frames * sizeof(short)); 500e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, 501e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // which for this code example would indicate a programming error 502e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 503e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 504e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 505e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer // start recording 506e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING); 507e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer assert(SL_RESULT_SUCCESS == result); 508e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (void)result; 509e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer bqPlayerRecorderBusy = 1; 510e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 511e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 512ed462e937cd99e9aaee98613c4e3e0469145d719Andrew LehmerjshortArray Java_org_chromium_latency_walt_AudioTest_getRecordedWave( 513ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer JNIEnv *env, 514ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) jclass cls) 515e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer{ 516e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer jshortArray result; 517e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer result = (*env)->NewShortArray(env, recorder_frames); 518e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer if (result == NULL) { 519e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer return NULL; /* out of memory error thrown */ 520e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer } 521e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer (*env)->SetShortArrayRegion(env, result, 0, recorder_frames, recorderBuffer); 522e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer return result; 523e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 524e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 525ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmerjlong Java_org_chromium_latency_walt_AudioTest_getTcRec(__attribute__((unused)) JNIEnv *env, 526ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) jclass cls) { 527e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer return (jlong) tc_rec; 528e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 529e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 530ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmerjlong Java_org_chromium_latency_walt_AudioTest_getTeRec(__attribute__((unused)) JNIEnv *env, 531ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) jclass cls) { 532e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer return (jlong) te_rec; 533e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 534e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer 535ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmerjlong Java_org_chromium_latency_walt_AudioTest_getTePlay(__attribute__((unused)) JNIEnv *env, 536ed462e937cd99e9aaee98613c4e3e0469145d719Andrew Lehmer __attribute__((unused)) jclass cls) { 537e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer return (jlong) te_play; 538e76dcf96b0c451e46cddfa695de8feeb92533937Andrew Lehmer} 539