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 17965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk#define LOG_TAG "AudioStreamRecord" 18e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk//#define LOG_NDEBUG 0 19e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <utils/Log.h> 20e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 21e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <stdint.h> 223d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk 235ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include <aaudio/AAudio.h> 243d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk#include <audio_utils/primitives.h> 253d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk#include <media/AudioRecord.h> 263d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk#include <utils/String16.h> 27e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 28e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "legacy/AudioStreamLegacy.h" 29e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "legacy/AudioStreamRecord.h" 303d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk#include "utility/AudioClock.h" 31e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "utility/FixedBlockWriter.h" 32e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 33e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkusing namespace android; 345ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio; 35e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 36e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamRecord::AudioStreamRecord() 37e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk : AudioStreamLegacy() 38e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk , mFixedBlockWriter(*this) 39e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 40e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 41e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 42e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamRecord::~AudioStreamRecord() 43e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 445ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk const aaudio_stream_state_t state = getState(); 455ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk bool bad = !(state == AAUDIO_STREAM_STATE_UNINITIALIZED || state == AAUDIO_STREAM_STATE_CLOSED); 46e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ALOGE_IF(bad, "stream not closed, in state %d", state); 47e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 48e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 495ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::open(const AudioStreamBuilder& builder) 50e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 515ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 52e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 53e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk result = AudioStream::open(builder); 545ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 55e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return result; 56e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 57e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 58e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Try to create an AudioRecord 59e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 60a5247769a8afdf03f440fcbe7c71110d46301e6bPhil Burk // TODO Support UNSPECIFIED in AudioRecord. For now, use stereo if unspecified. 615ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) 62e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ? 2 : getSamplesPerFrame(); 63e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(samplesPerFrame); 64e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 653df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk size_t frameCount = (builder.getBufferCapacity() == AAUDIO_UNSPECIFIED) ? 0 663df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk : builder.getBufferCapacity(); 674485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk 68e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 694485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE; 70c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk aaudio_performance_mode_t perfMode = getPerformanceMode(); 71c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk switch (perfMode) { 724485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY: 734485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk flags = (audio_input_flags_t) (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW); 744485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk break; 754485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk 764485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk case AAUDIO_PERFORMANCE_MODE_POWER_SAVING: 774485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk case AAUDIO_PERFORMANCE_MODE_NONE: 784485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk default: 794485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk // No flags. 804485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk break; 814485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk } 824485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk 833d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // Preserve behavior of API 26 843d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk if (getFormat() == AAUDIO_FORMAT_UNSPECIFIED) { 853d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk setFormat(AAUDIO_FORMAT_PCM_FLOAT); 863d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } 873d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk 883d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // Maybe change device format to get a FAST path. 893d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // AudioRecord does not support FAST mode for FLOAT data. 903d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // TODO AudioRecord should allow FLOAT data paths for FAST tracks. 913d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // So IF the user asks for low latency FLOAT 923d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // AND the sampleRate is likely to be compatible with FAST 933d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // THEN request I16 and convert to FLOAT when passing to user. 943d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // Note that hard coding 48000 Hz is not ideal because the sampleRate 953d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // for a FAST path might not be 48000 Hz. 963d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // It normally is but there is a chance that it is not. 973d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // And there is no reliable way to know that in advance. 983d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // Luckily the consequences of a wrong guess are minor. 993d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // We just may not get a FAST track. 1003d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // But we wouldn't have anyway without this hack. 1013d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk constexpr int32_t kMostLikelySampleRateForFast = 48000; 1023d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk if (getFormat() == AAUDIO_FORMAT_PCM_FLOAT 1033d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk && perfMode == AAUDIO_PERFORMANCE_MODE_LOW_LATENCY 1043d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk && (samplesPerFrame <= 2) // FAST only for mono and stereo 1053d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk && (getSampleRate() == kMostLikelySampleRateForFast 1063d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk || getSampleRate() == AAUDIO_UNSPECIFIED)) { 1073d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk setDeviceFormat(AAUDIO_FORMAT_PCM_I16); 1083d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } else { 1093d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk setDeviceFormat(getFormat()); 1103d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } 1113d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk 1124485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk uint32_t notificationFrames = 0; 1134485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk 114e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Setup the callback if there is one. 115e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk AudioRecord::callback_t callback = nullptr; 116e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk void *callbackData = nullptr; 117e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk AudioRecord::transfer_type streamTransferType = AudioRecord::transfer_type::TRANSFER_SYNC; 118e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (builder.getDataCallbackProc() != nullptr) { 119e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk streamTransferType = AudioRecord::transfer_type::TRANSFER_CALLBACK; 120e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk callback = getLegacyCallback(); 121e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk callbackData = this; 1224485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk notificationFrames = builder.getFramesPerDataCallback(); 123e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 124e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mCallbackBufferSize = builder.getFramesPerDataCallback(); 125e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 126ee995399b02c2dc60011f81e5251d24d3a0a79b5Phil Burk // Don't call mAudioRecord->setInputDevice() because it will be overwritten by set()! 127ee995399b02c2dc60011f81e5251d24d3a0a79b5Phil Burk audio_port_handle_t selectedDeviceId = (getDeviceId() == AAUDIO_UNSPECIFIED) 128ee995399b02c2dc60011f81e5251d24d3a0a79b5Phil Burk ? AUDIO_PORT_HANDLE_NONE 129ee995399b02c2dc60011f81e5251d24d3a0a79b5Phil Burk : getDeviceId(); 130ee995399b02c2dc60011f81e5251d24d3a0a79b5Phil Burk 131d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk const audio_content_type_t contentType = 132d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk AAudioConvert_contentTypeToInternal(builder.getContentType()); 133d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk const audio_source_t source = 134d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk AAudioConvert_inputPresetToAudioSource(builder.getInputPreset()); 135d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk 136d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk const audio_attributes_t attributes = { 137d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk .content_type = contentType, 138d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk .usage = AUDIO_USAGE_UNKNOWN, // only used for output 139d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk .source = source, 140ed816010d3e55a5f38c276e7fd3efdc9bb49bd26Phil Burk .flags = AUDIO_FLAG_NONE, // Different than the AUDIO_INPUT_FLAGS 141d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk .tags = "" 142d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk }; 143d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk 1444e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk aaudio_session_id_t requestedSessionId = builder.getSessionId(); 1454e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk audio_session_t sessionId = AAudioConvert_aaudioToAndroidSessionId(requestedSessionId); 1464e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk 1473d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // ----------- open the AudioRecord --------------------- 1483d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // Might retry, but never more than once. 1493d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk for (int i = 0; i < 2; i ++) { 1503d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk audio_format_t requestedInternalFormat = 1513d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk AAudioConvert_aaudioToAndroidDataFormat(getDeviceFormat()); 1523d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk 1533d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk mAudioRecord = new AudioRecord( 1543d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk mOpPackageName // const String16& opPackageName TODO does not compile 1553d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk ); 1563d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk mAudioRecord->set( 1573d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk AUDIO_SOURCE_DEFAULT, // ignored because we pass attributes below 1583d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk getSampleRate(), 1593d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk requestedInternalFormat, 1603d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk channelMask, 1613d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk frameCount, 1623d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk callback, 1633d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk callbackData, 1643d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk notificationFrames, 1653d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk false /*threadCanCallJava*/, 1663d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk sessionId, 1673d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk streamTransferType, 1683d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk flags, 1693d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk AUDIO_UID_INVALID, // DEFAULT uid 1703d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk -1, // DEFAULT pid 1713d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk &attributes, 1723d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk selectedDeviceId 1733d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk ); 1743d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk 1753d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // Did we get a valid track? 1763d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk status_t status = mAudioRecord->initCheck(); 1773d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk if (status != OK) { 1783d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk close(); 1793d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk ALOGE("open(), initCheck() returned %d", status); 1803d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk return AAudioConvert_androidToAAudioResult(status); 1813d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } 1823d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk 1833d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // Check to see if it was worth hacking the deviceFormat. 1843d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk bool gotFastPath = (mAudioRecord->getFlags() & AUDIO_INPUT_FLAG_FAST) 1853d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk == AUDIO_INPUT_FLAG_FAST; 1863d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk if (getFormat() != getDeviceFormat() && !gotFastPath) { 1873d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // We tried to get a FAST path by switching the device format. 1883d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // But it didn't work. So we might as well reopen using the same 1893d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // format for device and for app. 1903d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk ALOGD("%s() used a different device format but no FAST path, reopen", __func__); 1913d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk mAudioRecord.clear(); 1923d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk setDeviceFormat(getFormat()); 1933d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } else { 1943d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk break; // Keep the one we just opened. 1953d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } 196e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 197e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 198a5247769a8afdf03f440fcbe7c71110d46301e6bPhil Burk // Get the actual values from the AudioRecord. 199a5247769a8afdf03f440fcbe7c71110d46301e6bPhil Burk setSamplesPerFrame(mAudioRecord->channelCount()); 200e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 201cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk int32_t actualSampleRate = mAudioRecord->getSampleRate(); 202cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk ALOGW_IF(actualSampleRate != getSampleRate(), 203fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk "open() sampleRate changed from %d to %d", 204cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk getSampleRate(), actualSampleRate); 205cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk setSampleRate(actualSampleRate); 206cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk 207e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // We may need to pass the data through a block size adapter to guarantee constant size. 208e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) { 209e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize; 210e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mFixedBlockWriter.open(callbackSizeBytes); 211e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mBlockAdapter = &mFixedBlockWriter; 212e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } else { 213e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mBlockAdapter = nullptr; 214e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 215e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 2163d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // Allocate format conversion buffer if needed. 2173d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk if (getDeviceFormat() == AAUDIO_FORMAT_PCM_I16 2183d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk && getFormat() == AAUDIO_FORMAT_PCM_FLOAT) { 2193d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk 2203d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk if (builder.getDataCallbackProc() != nullptr) { 2213d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // If we have a callback then we need to convert the data into an internal float 2223d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // array and then pass that entire array to the app. 2233d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk mFormatConversionBufferSizeInFrames = 2243d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk (mCallbackBufferSize != AAUDIO_UNSPECIFIED) 2253d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk ? mCallbackBufferSize : getFramesPerBurst(); 2263d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk int32_t numSamples = mFormatConversionBufferSizeInFrames * getSamplesPerFrame(); 2273d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk mFormatConversionBufferFloat = std::make_unique<float[]>(numSamples); 2283d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } else { 2293d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // If we don't have a callback then we will read into an internal short array 2303d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // and then convert into the app float array in read(). 2313d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk mFormatConversionBufferSizeInFrames = getFramesPerBurst(); 2323d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk int32_t numSamples = mFormatConversionBufferSizeInFrames * getSamplesPerFrame(); 2333d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk mFormatConversionBufferI16 = std::make_unique<int16_t[]>(numSamples); 2343d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } 2353d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk ALOGD("%s() setup I16>FLOAT conversion buffer with %d frames", 2363d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk __func__, mFormatConversionBufferSizeInFrames); 2373d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } 2383d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk 239c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk // Update performance mode based on the actual stream. 240c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk // For example, if the sample rate does not match native then you won't get a FAST track. 241c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk audio_input_flags_t actualFlags = mAudioRecord->getFlags(); 242c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk aaudio_performance_mode_t actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE; 243c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk // FIXME Some platforms do not advertise RAW mode for low latency inputs. 244c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk if ((actualFlags & (AUDIO_INPUT_FLAG_FAST)) 245c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk == (AUDIO_INPUT_FLAG_FAST)) { 246c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY; 247c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk } 248c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk setPerformanceMode(actualPerformanceMode); 249efa5600935ca69d87b0f8fb2fb9be7304f0f326ePhil Burk 250efa5600935ca69d87b0f8fb2fb9be7304f0f326ePhil Burk setSharingMode(AAUDIO_SHARING_MODE_SHARED); // EXCLUSIVE mode not supported in legacy 251efa5600935ca69d87b0f8fb2fb9be7304f0f326ePhil Burk 252c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk // Log warning if we did not get what we asked for. 253c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk ALOGW_IF(actualFlags != flags, 254fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk "open() flags changed from 0x%08X to 0x%08X", 255c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk flags, actualFlags); 256c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk ALOGW_IF(actualPerformanceMode != perfMode, 257fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk "open() perfMode changed from %d to %d", 258c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk perfMode, actualPerformanceMode); 259c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk 2605ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_OPEN); 261fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent setDeviceId(mAudioRecord->getRoutedDeviceId()); 2624e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk 2634e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk aaudio_session_id_t actualSessionId = 2644e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk (requestedSessionId == AAUDIO_SESSION_ID_NONE) 2654e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk ? AAUDIO_SESSION_ID_NONE 2664e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk : (aaudio_session_id_t) mAudioRecord->getSessionId(); 2674e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk setSessionId(actualSessionId); 2684e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk 269fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent mAudioRecord->addAudioDeviceCallback(mDeviceCallback); 270e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2715ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 272e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 273e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2745ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::close() 275e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 276e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO add close() or release() to AudioRecord API then call it from here 2775ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (getState() != AAUDIO_STREAM_STATE_CLOSED) { 278965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk mAudioRecord->removeAudioDeviceCallback(mDeviceCallback); 279e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mAudioRecord.clear(); 2805ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_CLOSED); 281e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 282e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk mFixedBlockWriter.close(); 283965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk return AudioStream::close(); 284e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 285e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 2863d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burkconst void * AudioStreamRecord::maybeConvertDeviceData(const void *audioData, int32_t numFrames) { 2873d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk if (mFormatConversionBufferFloat.get() != nullptr) { 2883d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk LOG_ALWAYS_FATAL_IF(numFrames > mFormatConversionBufferSizeInFrames, 2893d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk "%s() conversion size %d too large for buffer %d", 2903d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk __func__, numFrames, mFormatConversionBufferSizeInFrames); 2913d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk 2923d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk int32_t numSamples = numFrames * getSamplesPerFrame(); 2933d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // Only conversion supported is I16 to FLOAT 2943d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk memcpy_to_float_from_i16( 2953d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk mFormatConversionBufferFloat.get(), 2963d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk (const int16_t *) audioData, 2973d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk numSamples); 2983d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk return mFormatConversionBufferFloat.get(); 2993d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } else { 3003d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk return audioData; 3013d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } 3023d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk} 3033d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk 304e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkvoid AudioStreamRecord::processCallback(int event, void *info) { 305e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk switch (event) { 306e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk case AudioRecord::EVENT_MORE_DATA: 307e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info); 308e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 309e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 310e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk // Stream got rerouted so we disconnect. 311e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk case AudioRecord::EVENT_NEW_IAUDIORECORD: 312e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info); 313e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 314e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 315e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk default: 316e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk break; 317e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk } 318e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk return; 319e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk} 320e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 3215ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestStart() 322e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 323d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk if (mAudioRecord.get() == nullptr) { 3245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 325e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 3260befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk // Get current position so we can detect when the track is recording. 327e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t err = mAudioRecord->getPosition(&mPositionWhenStarting); 328e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 3295ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(err); 330e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 331e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk 3329e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk // Enable callback before starting AudioTrack to avoid shutting 3339e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk // down because of a race condition. 3349e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk mCallbackEnabled.store(true); 335e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk err = mAudioRecord->start(); 336e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 3375ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAudioConvert_androidToAAudioResult(err); 338e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else { 3395ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTING); 340e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 3415ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_OK; 342e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 343e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 3445ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestStop() { 345d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk if (mAudioRecord.get() == nullptr) { 3465ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 347e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 3485ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STOPPING); 349d873a5506149ed47164cf9c11add82eaceba24c3Mikhail Naganov incrementFramesWritten(getFramesRead() - getFramesWritten()); // TODO review 3507328a80ffc83729cc6252c79e0851a31af59c653Phil Burk mTimestampPosition.set(getFramesRead()); 351e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mAudioRecord->stop(); 3529e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk mCallbackEnabled.store(false); 3532b6f128229bdd4a71f2830f554e26465c93c4a7aPhil Burk mFramesWritten.reset32(); // service writes frames, service position reset on flush 3547328a80ffc83729cc6252c79e0851a31af59c653Phil Burk mTimestampPosition.reset32(); 355134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk // Pass false to prevent errorCallback from being called after disconnect 356134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk // when app has already requested a stop(). 357134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk return checkForDisconnectRequest(false); 358e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 359e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 3600befec600314a79c0d142c3edd99f7d1c75e1afePhil Burkaaudio_result_t AudioStreamRecord::updateStateMachine() 361e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 3625ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_result_t result = AAUDIO_OK; 3635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk aaudio_wrapping_frames_t position; 364e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t err; 365e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk switch (getState()) { 366e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO add better state visibility to AudioRecord 3675ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STARTING: 368e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk err = mAudioRecord->getPosition(&position); 369e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 3705ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk result = AAudioConvert_androidToAAudioResult(err); 371e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else if (position != mPositionWhenStarting) { 3725ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STARTED); 373e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 374e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 3755ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk case AAUDIO_STREAM_STATE_STOPPING: 376e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (mAudioRecord->stopped()) { 3775ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk setState(AAUDIO_STREAM_STATE_STOPPED); 378e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 379e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 380e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk default: 381e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 382e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 383e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return result; 384e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 385e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 3865ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::read(void *buffer, 3873316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t numFrames, 3883316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int64_t timeoutNanoseconds) 389e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 3903d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk int32_t bytesPerDeviceFrame = getBytesPerDeviceFrame(); 3913316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk int32_t numBytes; 3923d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // This will detect out of range values for numFrames. 3933d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk aaudio_result_t result = AAudioConvert_framesToBytes(numFrames, bytesPerDeviceFrame, &numBytes); 3945ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk if (result != AAUDIO_OK) { 395e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return result; 396e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 397e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 398fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED) { 399fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent return AAUDIO_ERROR_DISCONNECTED; 400fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent } 401fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent 402e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO add timeout to AudioRecord 403e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk bool blocking = (timeoutNanoseconds > 0); 4043d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk 4053d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk ssize_t bytesActuallyRead = 0; 4063d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk ssize_t totalBytesRead = 0; 4073d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk if (mFormatConversionBufferI16.get() != nullptr) { 4083d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // Convert I16 data to float using an intermediate buffer. 4093d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk float *floatBuffer = (float *) buffer; 4103d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk int32_t framesLeft = numFrames; 4113d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // Perform conversion using multiple read()s if necessary. 4123d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk while (framesLeft > 0) { 4133d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // Read into short internal buffer. 4143d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk int32_t framesToRead = std::min(framesLeft, mFormatConversionBufferSizeInFrames); 4153d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk size_t bytesToRead = framesToRead * bytesPerDeviceFrame; 4163d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk bytesActuallyRead = mAudioRecord->read(mFormatConversionBufferI16.get(), bytesToRead, blocking); 4173d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk if (bytesActuallyRead <= 0) { 4183d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk break; 4193d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } 4203d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk totalBytesRead += bytesActuallyRead; 4213d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk int32_t framesToConvert = bytesActuallyRead / bytesPerDeviceFrame; 4223d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // Convert into app float buffer. 4233d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk size_t numSamples = framesToConvert * getSamplesPerFrame(); 4243d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk memcpy_to_float_from_i16( 4253d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk floatBuffer, 4263d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk mFormatConversionBufferI16.get(), 4273d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk numSamples); 4283d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk floatBuffer += numSamples; 4293d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk framesLeft -= framesToConvert; 4303d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } 4313d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } else { 4323d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk bytesActuallyRead = mAudioRecord->read(buffer, numBytes, blocking); 4333d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk totalBytesRead = bytesActuallyRead; 4343d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } 4353d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk if (bytesActuallyRead == WOULD_BLOCK) { 436e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return 0; 4373d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk } else if (bytesActuallyRead < 0) { 4383d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // In this context, a DEAD_OBJECT is more likely to be a disconnect notification due to 4393d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk // AudioRecord invalidation. 4403d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk if (bytesActuallyRead == DEAD_OBJECT) { 441fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent setState(AAUDIO_STREAM_STATE_DISCONNECTED); 442fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent return AAUDIO_ERROR_DISCONNECTED; 443fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent } 4443d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk return AAudioConvert_androidToAAudioResult(bytesActuallyRead); 445e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 4463d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk int32_t framesRead = (int32_t)(totalBytesRead / bytesPerDeviceFrame); 447d873a5506149ed47164cf9c11add82eaceba24c3Mikhail Naganov incrementFramesRead(framesRead); 4480befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk 4490befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk result = updateStateMachine(); 4500befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk if (result != AAUDIO_OK) { 4510befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk return result; 4520befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk } 4530befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk 4545ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk return (aaudio_result_t) framesRead; 455e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 456e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 4573316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkaaudio_result_t AudioStreamRecord::setBufferSize(int32_t requestedFrames) 458e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 4593316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return getBufferSize(); 460e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 461e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 4623316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getBufferSize() const 463e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 464e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return getBufferCapacity(); // TODO implement in AudioRecord? 465e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 466e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 4673316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getBufferCapacity() const 468e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 4693316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk return static_cast<int32_t>(mAudioRecord->frameCount()); 470e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 471e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 472e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkint32_t AudioStreamRecord::getXRunCount() const 473e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 474068c10f03d16a7f73abf138cc751cf3bde7518dfPhil Burk return 0; // TODO implement when AudioRecord supports it 475e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 476e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 4773316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getFramesPerBurst() const 478e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 479b588402d48c9634fa72e7e13ca6d6f2a0766cb98Phil Burk return static_cast<int32_t>(mAudioRecord->getNotificationPeriodInFrames()); 480e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 481e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 48235e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burkaaudio_result_t AudioStreamRecord::getTimestamp(clockid_t clockId, 48335e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk int64_t *framePosition, 48435e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk int64_t *timeNanoseconds) { 48535e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk ExtendedTimestamp extendedTimestamp; 48635e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk status_t status = mAudioRecord->getTimestamp(&extendedTimestamp); 487c75d97f20843388b9084561635996a01a53d0c0fPhil Burk if (status == WOULD_BLOCK) { 488c75d97f20843388b9084561635996a01a53d0c0fPhil Burk return AAUDIO_ERROR_INVALID_STATE; 489c75d97f20843388b9084561635996a01a53d0c0fPhil Burk } else if (status != NO_ERROR) { 49035e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk return AAudioConvert_androidToAAudioResult(status); 49135e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk } 4925204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk return getBestTimestamp(clockId, framePosition, timeNanoseconds, &extendedTimestamp); 49335e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk} 4940befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk 4950befec600314a79c0d142c3edd99f7d1c75e1afePhil Burkint64_t AudioStreamRecord::getFramesWritten() { 4960befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk aaudio_wrapping_frames_t position; 4970befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk status_t result; 4980befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk switch (getState()) { 4990befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk case AAUDIO_STREAM_STATE_STARTING: 5000befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk case AAUDIO_STREAM_STATE_STARTED: 5010befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk case AAUDIO_STREAM_STATE_STOPPING: 5020befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk result = mAudioRecord->getPosition(&position); 5030befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk if (result == OK) { 5040befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk mFramesWritten.update32(position); 5050befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk } 5060befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk break; 5070befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk default: 5080befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk break; 5090befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk } 5100befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk return AudioStreamLegacy::getFramesWritten(); 5110befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk} 512