AudioStreamRecord.cpp revision cf5f6d2825d9a8430a291042ca9c6f68e5b666d0
1e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk/* 2e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Copyright 2016 The Android Open Source Project 3e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * 4e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Licensed under the Apache License, Version 2.0 (the "License"); 5e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * you may not use this file except in compliance with the License. 6e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * You may obtain a copy of the License at 7e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * 8e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * http://www.apache.org/licenses/LICENSE-2.0 9e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * 10e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Unless required by applicable law or agreed to in writing, software 11e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * distributed under the License is distributed on an "AS IS" BASIS, 12e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * See the License for the specific language governing permissions and 14e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * limitations under the License. 15e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk */ 16e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 17cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk#define LOG_TAG "AAudio" 18e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk//#define LOG_NDEBUG 0 19e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <utils/Log.h> 20e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 21e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <stdint.h> 22e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <utils/String16.h> 23e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <media/AudioRecord.h> 245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include <aaudio/AAudio.h> 25e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 26e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include "AudioClock.h" 27e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "legacy/AudioStreamLegacy.h" 28e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "legacy/AudioStreamRecord.h" 29e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "utility/FixedBlockWriter.h" 30e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 31e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkusing namespace android; 325ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio; 33e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 34e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamRecord::AudioStreamRecord() 35e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk : AudioStreamLegacy() 36e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk , mFixedBlockWriter(*this) 37e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 38e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 39e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 40e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamRecord::~AudioStreamRecord() 41e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 425ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const aaudio_stream_state_t state = getState(); 435ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk bool bad = !(state == AAUDIO_STREAM_STATE_UNINITIALIZED || state == AAUDIO_STREAM_STATE_CLOSED); 44e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ALOGE_IF(bad, "stream not closed, in state %d", state); 45e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 46e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::open(const AudioStreamBuilder& builder) 48e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 495ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 50e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 51e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk result = AudioStream::open(builder); 525ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 53e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return result; 54e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 55e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 56e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Try to create an AudioRecord 57e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 58e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO Support UNSPECIFIED in AudioTrack. For now, use stereo if unspecified. 595ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) 60e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ? 2 : getSamplesPerFrame(); 61e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(samplesPerFrame); 62e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 633df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk size_t frameCount = (builder.getBufferCapacity() == AAUDIO_UNSPECIFIED) ? 0 643df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk : builder.getBufferCapacity(); 654485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk 66e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO implement an unspecified Android format then use that. 675ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk audio_format_t format = (getFormat() == AAUDIO_UNSPECIFIED) 68e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ? AUDIO_FORMAT_PCM_FLOAT 695ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk : AAudioConvert_aaudioToAndroidDataFormat(getFormat()); 70e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 714485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE; 724485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk switch(getPerformanceMode()) { 734485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY: 744485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk flags = (audio_input_flags_t) (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW); 754485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk break; 764485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk 774485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk case AAUDIO_PERFORMANCE_MODE_POWER_SAVING: 784485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk case AAUDIO_PERFORMANCE_MODE_NONE: 794485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk default: 804485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk // No flags. 814485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk break; 824485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk } 834485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk 844485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk uint32_t notificationFrames = 0; 854485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk 86e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Setup the callback if there is one. 87e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk AudioRecord::callback_t callback = nullptr; 88e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk void *callbackData = nullptr; 89e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk AudioRecord::transfer_type streamTransferType = AudioRecord::transfer_type::TRANSFER_SYNC; 90e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (builder.getDataCallbackProc() != nullptr) { 91e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk streamTransferType = AudioRecord::transfer_type::TRANSFER_CALLBACK; 92e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk callback = getLegacyCallback(); 93e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk callbackData = this; 944485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk notificationFrames = builder.getFramesPerDataCallback(); 95e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 96e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackBufferSize = builder.getFramesPerDataCallback(); 97e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 98cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk ALOGD("AudioStreamRecord::open(), request notificationFrames = %u, frameCount = %u", 99cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk notificationFrames, (uint)frameCount); 100e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mAudioRecord = new AudioRecord( 1014485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk AUDIO_SOURCE_VOICE_RECOGNITION, 102e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk getSampleRate(), 103e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk format, 104e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk channelMask, 105e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mOpPackageName, // const String16& opPackageName TODO does not compile 1063df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk frameCount, 107e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk callback, 108e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk callbackData, 1094485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk notificationFrames, 110e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk AUDIO_SESSION_ALLOCATE, 111e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk streamTransferType, 112e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk flags 1133df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk // int uid = -1, 1143df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk // pid_t pid = -1, 1153df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk // const audio_attributes_t* pAttributes = nullptr 1163df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk ); 117e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 118e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Did we get a valid track? 119e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t status = mAudioRecord->initCheck(); 120e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (status != OK) { 121e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk close(); 122e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ALOGE("AudioStreamRecord::open(), initCheck() returned %d", status); 1235ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(status); 124e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 125e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 126e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Get the actual rate. 127e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk setSampleRate(mAudioRecord->getSampleRate()); 1285ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setFormat(AAudioConvert_androidToAAudioDataFormat(mAudioRecord->format())); 129e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 130cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk int32_t actualSampleRate = mAudioRecord->getSampleRate(); 131cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk ALOGW_IF(actualSampleRate != getSampleRate(), 132cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk "AudioStreamRecord::open() sampleRate changed from %d to %d", 133cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk getSampleRate(), actualSampleRate); 134cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk setSampleRate(actualSampleRate); 135cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk 136e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // We may need to pass the data through a block size adapter to guarantee constant size. 137e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) { 138e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize; 139e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mFixedBlockWriter.open(callbackSizeBytes); 140e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mBlockAdapter = &mFixedBlockWriter; 141e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } else { 142e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mBlockAdapter = nullptr; 143e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 144e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 1455ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_OPEN); 146e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 1475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 148e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 149e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 1505ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::close() 151e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 152e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO add close() or release() to AudioRecord API then call it from here 1535ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (getState() != AAUDIO_STREAM_STATE_CLOSED) { 154e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mAudioRecord.clear(); 1555ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_CLOSED); 156e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 157e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mFixedBlockWriter.close(); 1585ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 159e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 160e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 161e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkvoid AudioStreamRecord::processCallback(int event, void *info) { 162e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk switch (event) { 163e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk case AudioRecord::EVENT_MORE_DATA: 164e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info); 165e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 166e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 167e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Stream got rerouted so we disconnect. 168e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk case AudioRecord::EVENT_NEW_IAUDIORECORD: 169e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info); 170e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 171e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 172e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk default: 173e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 174e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 175e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return; 176e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk} 177e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 1785ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestStart() 179e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 180d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk if (mAudioRecord.get() == nullptr) { 1815ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 182e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 183e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Get current position so we can detect when the track is playing. 184e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t err = mAudioRecord->getPosition(&mPositionWhenStarting); 185e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 1865ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(err); 187e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 188e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 189e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk err = mAudioRecord->start(); 190e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 1915ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(err); 192e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else { 1935ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTING); 194e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 1955ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 196e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 197e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 1985ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestPause() 199e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 200068c10f03d16a7f73abf138cc751cf3bde7518dfPhil Burk // This does not make sense for an input stream. 201068c10f03d16a7f73abf138cc751cf3bde7518dfPhil Burk // There is no real difference between pause() and stop(). 2025ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_UNIMPLEMENTED; 203e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 204e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2055ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestFlush() { 206068c10f03d16a7f73abf138cc751cf3bde7518dfPhil Burk // This does not make sense for an input stream. 2075ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_UNIMPLEMENTED; 208e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 209e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2105ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestStop() { 211d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk if (mAudioRecord.get() == nullptr) { 2125ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 213e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 2145ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STOPPING); 215d873a5506149ed47164cf9c11add82eaceba24c3Mikhail Naganov incrementFramesWritten(getFramesRead() - getFramesWritten()); // TODO review 216e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mAudioRecord->stop(); 217d873a5506149ed47164cf9c11add82eaceba24c3Mikhail Naganov mFramesRead.reset32(); 2185ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 219e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 220e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 221e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkaaudio_result_t AudioStreamRecord::updateStateWhileWaiting() 222e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 2235ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 2245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_wrapping_frames_t position; 225e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t err; 226e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk switch (getState()) { 227e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO add better state visibility to AudioRecord 2285ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STARTING: 229e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk err = mAudioRecord->getPosition(&position); 230e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 2315ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAudioConvert_androidToAAudioResult(err); 232e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else if (position != mPositionWhenStarting) { 2335ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTED); 234e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 235e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 2365ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STOPPING: 237e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (mAudioRecord->stopped()) { 2385ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STOPPED); 239e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 240e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 241e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk default: 242e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 243e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 244e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return result; 245e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 246e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::read(void *buffer, 2483316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t numFrames, 2493316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t timeoutNanoseconds) 250e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 2513316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t bytesPerFrame = getBytesPerFrame(); 2523316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t numBytes; 2535ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAudioConvert_framesToBytes(numFrames, bytesPerFrame, &numBytes); 2545ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 255e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return result; 256e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 257e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 258e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO add timeout to AudioRecord 259e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk bool blocking = (timeoutNanoseconds > 0); 260e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ssize_t bytesRead = mAudioRecord->read(buffer, numBytes, blocking); 261e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (bytesRead == WOULD_BLOCK) { 262e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return 0; 263e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else if (bytesRead < 0) { 2645ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(bytesRead); 265e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 2663316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t framesRead = (int32_t)(bytesRead / bytesPerFrame); 267d873a5506149ed47164cf9c11add82eaceba24c3Mikhail Naganov incrementFramesRead(framesRead); 2685ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return (aaudio_result_t) framesRead; 269e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 270e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2713316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkaaudio_result_t AudioStreamRecord::setBufferSize(int32_t requestedFrames) 272e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 2733316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return getBufferSize(); 274e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 275e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2763316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getBufferSize() const 277e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 278e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return getBufferCapacity(); // TODO implement in AudioRecord? 279e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 280e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2813316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getBufferCapacity() const 282e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 2833316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return static_cast<int32_t>(mAudioRecord->frameCount()); 284e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 285e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 286e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkint32_t AudioStreamRecord::getXRunCount() const 287e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 288068c10f03d16a7f73abf138cc751cf3bde7518dfPhil Burk return 0; // TODO implement when AudioRecord supports it 289e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 290e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2913316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getFramesPerBurst() const 292e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 293b588402d48c9634fa72e7e13ca6d6f2a0766cb98Phil Burk return static_cast<int32_t>(mAudioRecord->getNotificationPeriodInFrames()); 294e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 295e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 29635e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burkaaudio_result_t AudioStreamRecord::getTimestamp(clockid_t clockId, 29735e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk int64_t *framePosition, 29835e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk int64_t *timeNanoseconds) { 29935e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk ExtendedTimestamp extendedTimestamp; 30035e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk status_t status = mAudioRecord->getTimestamp(&extendedTimestamp); 30135e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk if (status != NO_ERROR) { 30235e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk return AAudioConvert_androidToAAudioResult(status); 30335e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk } 3045204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk return getBestTimestamp(clockId, framePosition, timeNanoseconds, &extendedTimestamp); 30535e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk} 306