AudioStreamRecord.cpp revision c42d5f9ba80d827e135f21c7ff995bc752f6477c
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 17e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#define LOG_TAG "AudioStreamRecord" 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; 72c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk aaudio_performance_mode_t perfMode = getPerformanceMode(); 73c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk switch (perfMode) { 744485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY: 754485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk flags = (audio_input_flags_t) (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW); 764485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk break; 774485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk 784485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk case AAUDIO_PERFORMANCE_MODE_POWER_SAVING: 794485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk case AAUDIO_PERFORMANCE_MODE_NONE: 804485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk default: 814485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk // No flags. 824485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk break; 834485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk } 844485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk 854485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk uint32_t notificationFrames = 0; 864485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk 87e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Setup the callback if there is one. 88e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk AudioRecord::callback_t callback = nullptr; 89e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk void *callbackData = nullptr; 90e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk AudioRecord::transfer_type streamTransferType = AudioRecord::transfer_type::TRANSFER_SYNC; 91e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (builder.getDataCallbackProc() != nullptr) { 92e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk streamTransferType = AudioRecord::transfer_type::TRANSFER_CALLBACK; 93e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk callback = getLegacyCallback(); 94e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk callbackData = this; 954485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk notificationFrames = builder.getFramesPerDataCallback(); 96e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 97e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackBufferSize = builder.getFramesPerDataCallback(); 98e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 99e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mAudioRecord = new AudioRecord( 1004485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk AUDIO_SOURCE_VOICE_RECOGNITION, 101e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk getSampleRate(), 102e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk format, 103e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk channelMask, 104e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mOpPackageName, // const String16& opPackageName TODO does not compile 1053df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk frameCount, 106e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk callback, 107e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk callbackData, 1084485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk notificationFrames, 109e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk AUDIO_SESSION_ALLOCATE, 110e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk streamTransferType, 111e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk flags 1123df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk // int uid = -1, 1133df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk // pid_t pid = -1, 1143df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk // const audio_attributes_t* pAttributes = nullptr 1153df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk ); 116e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 117e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Did we get a valid track? 118e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t status = mAudioRecord->initCheck(); 119e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (status != OK) { 120e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk close(); 121e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ALOGE("AudioStreamRecord::open(), initCheck() returned %d", status); 1225ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(status); 123e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 124e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 125e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Get the actual rate. 126e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk setSampleRate(mAudioRecord->getSampleRate()); 127e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk setSamplesPerFrame(mAudioRecord->channelCount()); 1285ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setFormat(AAudioConvert_androidToAAudioDataFormat(mAudioRecord->format())); 129e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 130e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // We may need to pass the data through a block size adapter to guarantee constant size. 131e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) { 132e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize; 133e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mFixedBlockWriter.open(callbackSizeBytes); 134e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mBlockAdapter = &mFixedBlockWriter; 135e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } else { 136e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mBlockAdapter = nullptr; 137e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 138e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 139c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk // Update performance mode based on the actual stream. 140c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk // For example, if the sample rate does not match native then you won't get a FAST track. 141c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk audio_input_flags_t actualFlags = mAudioRecord->getFlags(); 142c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk aaudio_performance_mode_t actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE; 143c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk // FIXME Some platforms do not advertise RAW mode for low latency inputs. 144c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk if ((actualFlags & (AUDIO_INPUT_FLAG_FAST)) 145c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk == (AUDIO_INPUT_FLAG_FAST)) { 146c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY; 147c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk } 148c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk setPerformanceMode(actualPerformanceMode); 149c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk // Log warning if we did not get what we asked for. 150c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk ALOGW_IF(actualFlags != flags, 151c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk "AudioStreamRecord::open() flags changed from 0x%08X to 0x%08X", 152c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk flags, actualFlags); 153c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk ALOGW_IF(actualPerformanceMode != perfMode, 154c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk "AudioStreamRecord::open() perfMode changed from %d to %d", 155c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk perfMode, actualPerformanceMode); 156c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk 1575ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_OPEN); 158e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 1595ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 160e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 161e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 1625ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::close() 163e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 164e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO add close() or release() to AudioRecord API then call it from here 1655ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (getState() != AAUDIO_STREAM_STATE_CLOSED) { 166e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mAudioRecord.clear(); 1675ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_CLOSED); 168e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 169e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mFixedBlockWriter.close(); 1705ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 171e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 172e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 173e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkvoid AudioStreamRecord::processCallback(int event, void *info) { 174e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 175e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk ALOGD("AudioStreamRecord::processCallback(), event %d", event); 176e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk switch (event) { 177e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk case AudioRecord::EVENT_MORE_DATA: 178e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info); 179e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 180e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 181e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Stream got rerouted so we disconnect. 182e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk case AudioRecord::EVENT_NEW_IAUDIORECORD: 183e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info); 184e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 185e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 186e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk default: 187e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 188e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 189e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return; 190e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk} 191e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 1925ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestStart() 193e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 194d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk if (mAudioRecord.get() == nullptr) { 1955ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 196e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 197e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Get current position so we can detect when the track is playing. 198e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t err = mAudioRecord->getPosition(&mPositionWhenStarting); 199e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 2005ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(err); 201e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 202e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 203e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk err = mAudioRecord->start(); 204e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 2055ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(err); 206e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else { 2075ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTING); 208e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 2095ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 210e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 211e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2125ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestPause() 213e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 214068c10f03d16a7f73abf138cc751cf3bde7518dfPhil Burk // This does not make sense for an input stream. 215068c10f03d16a7f73abf138cc751cf3bde7518dfPhil Burk // There is no real difference between pause() and stop(). 2165ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_UNIMPLEMENTED; 217e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 218e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2195ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestFlush() { 220068c10f03d16a7f73abf138cc751cf3bde7518dfPhil Burk // This does not make sense for an input stream. 2215ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_UNIMPLEMENTED; 222e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 223e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestStop() { 225d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk if (mAudioRecord.get() == nullptr) { 2265ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 227e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 2285ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STOPPING); 229d873a5506149ed47164cf9c11add82eaceba24c3Mikhail Naganov incrementFramesWritten(getFramesRead() - getFramesWritten()); // TODO review 230e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mAudioRecord->stop(); 231d873a5506149ed47164cf9c11add82eaceba24c3Mikhail Naganov mFramesRead.reset32(); 2325ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 233e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 234e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 235e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkaaudio_result_t AudioStreamRecord::updateStateWhileWaiting() 236e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 2375ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 2385ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_wrapping_frames_t position; 239e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t err; 240e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk switch (getState()) { 241e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO add better state visibility to AudioRecord 2425ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STARTING: 243e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk err = mAudioRecord->getPosition(&position); 244e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 2455ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAudioConvert_androidToAAudioResult(err); 246e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else if (position != mPositionWhenStarting) { 2475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTED); 248e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 249e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 2505ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STOPPING: 251e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (mAudioRecord->stopped()) { 2525ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STOPPED); 253e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 254e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 255e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk default: 256e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 257e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 258e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return result; 259e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 260e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2615ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::read(void *buffer, 2623316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t numFrames, 2633316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t timeoutNanoseconds) 264e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 2653316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t bytesPerFrame = getBytesPerFrame(); 2663316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t numBytes; 2675ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAudioConvert_framesToBytes(numFrames, bytesPerFrame, &numBytes); 2685ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 269e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return result; 270e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 271e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 272e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO add timeout to AudioRecord 273e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk bool blocking = (timeoutNanoseconds > 0); 274e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ssize_t bytesRead = mAudioRecord->read(buffer, numBytes, blocking); 275e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (bytesRead == WOULD_BLOCK) { 276e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return 0; 277e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else if (bytesRead < 0) { 2785ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(bytesRead); 279e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 2803316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t framesRead = (int32_t)(bytesRead / bytesPerFrame); 281d873a5506149ed47164cf9c11add82eaceba24c3Mikhail Naganov incrementFramesRead(framesRead); 2825ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return (aaudio_result_t) framesRead; 283e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 284e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2853316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkaaudio_result_t AudioStreamRecord::setBufferSize(int32_t requestedFrames) 286e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 2873316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return getBufferSize(); 288e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 289e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2903316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getBufferSize() const 291e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 292e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return getBufferCapacity(); // TODO implement in AudioRecord? 293e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 294e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2953316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getBufferCapacity() const 296e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 2973316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return static_cast<int32_t>(mAudioRecord->frameCount()); 298e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 299e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 300e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkint32_t AudioStreamRecord::getXRunCount() const 301e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 302068c10f03d16a7f73abf138cc751cf3bde7518dfPhil Burk return 0; // TODO implement when AudioRecord supports it 303e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 304e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 3053316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getFramesPerBurst() const 306e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 307b588402d48c9634fa72e7e13ca6d6f2a0766cb98Phil Burk return static_cast<int32_t>(mAudioRecord->getNotificationPeriodInFrames()); 308e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 309e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 31035e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burkaaudio_result_t AudioStreamRecord::getTimestamp(clockid_t clockId, 31135e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk int64_t *framePosition, 31235e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk int64_t *timeNanoseconds) { 31335e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk ExtendedTimestamp extendedTimestamp; 31435e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk status_t status = mAudioRecord->getTimestamp(&extendedTimestamp); 31535e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk if (status != NO_ERROR) { 31635e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk return AAudioConvert_androidToAAudioResult(status); 31735e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk } 3185204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk return getBestTimestamp(clockId, framePosition, timeNanoseconds, &extendedTimestamp); 31935e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk} 320