AudioStreamRecord.cpp revision d8bdcabbac30d48ed17fa76c83cb9ee95c290a07
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> 24e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <oboe/OboeAudio.h> 25e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 26e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include "AudioClock.h" 27e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include "AudioStreamRecord.h" 28e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 29e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkusing namespace android; 30e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkusing namespace oboe; 31e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 32e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamRecord::AudioStreamRecord() 33e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk : AudioStream() 34e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 35e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 36e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 37e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamRecord::~AudioStreamRecord() 38e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 39e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk const oboe_stream_state_t state = getState(); 40e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk bool bad = !(state == OBOE_STREAM_STATE_UNINITIALIZED || state == OBOE_STREAM_STATE_CLOSED); 41e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ALOGE_IF(bad, "stream not closed, in state %d", state); 42e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 43e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 44e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkoboe_result_t AudioStreamRecord::open(const AudioStreamBuilder& builder) 45e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 46e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk oboe_result_t result = OBOE_OK; 47e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 48e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk result = AudioStream::open(builder); 49e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (result != OBOE_OK) { 50e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return result; 51e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 52e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 53e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Try to create an AudioRecord 54e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 55e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO Support UNSPECIFIED in AudioTrack. For now, use stereo if unspecified. 56e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk int32_t samplesPerFrame = (getSamplesPerFrame() == OBOE_UNSPECIFIED) 57e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ? 2 : getSamplesPerFrame(); 58e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(samplesPerFrame); 59e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 60d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk AudioRecord::callback_t callback = nullptr; 61e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk audio_input_flags_t flags = (audio_input_flags_t) AUDIO_INPUT_FLAG_NONE; 62e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 63e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO implement an unspecified Android format then use that. 64e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk audio_format_t format = (getFormat() == OBOE_UNSPECIFIED) 65e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ? AUDIO_FORMAT_PCM_FLOAT 66e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk : OboeConvert_oboeToAndroidDataFormat(getFormat()); 67e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 68e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mAudioRecord = new AudioRecord( 69e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk AUDIO_SOURCE_DEFAULT, 70e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk getSampleRate(), 71e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk format, 72e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk channelMask, 73e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 74e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mOpPackageName, // const String16& opPackageName TODO does not compile 75e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 76e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 0, // size_t frameCount = 0, 77e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk callback, 78d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk nullptr, // void* user = nullptr, 79e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 0, // uint32_t notificationFrames = 0, 80e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk AUDIO_SESSION_ALLOCATE, 81e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk AudioRecord::TRANSFER_DEFAULT, 82e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk flags 83e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // int uid = -1, 84e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // pid_t pid = -1, 85d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk // const audio_attributes_t* pAttributes = nullptr 86e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ); 87e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 88e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Did we get a valid track? 89e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t status = mAudioRecord->initCheck(); 90e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (status != OK) { 91e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk close(); 92e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ALOGE("AudioStreamRecord::open(), initCheck() returned %d", status); 93e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return OboeConvert_androidToOboeError(status); 94e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 95e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 96e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Get the actual rate. 97e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk setSampleRate(mAudioRecord->getSampleRate()); 98e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk setSamplesPerFrame(mAudioRecord->channelCount()); 99e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk setFormat(OboeConvert_androidToOboeDataFormat(mAudioRecord->format())); 100e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 101e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk setState(OBOE_STREAM_STATE_OPEN); 102e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 103e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return OBOE_OK; 104e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 105e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 106e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkoboe_result_t AudioStreamRecord::close() 107e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 108e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO add close() or release() to AudioRecord API then call it from here 109e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (getState() != OBOE_STREAM_STATE_CLOSED) { 110e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mAudioRecord.clear(); 111e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk setState(OBOE_STREAM_STATE_CLOSED); 112e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 113e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return OBOE_OK; 114e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 115e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 116e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkoboe_result_t AudioStreamRecord::requestStart() 117e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 118d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk if (mAudioRecord.get() == nullptr) { 119e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return OBOE_ERROR_INVALID_STATE; 120e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 121e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // Get current position so we can detect when the track is playing. 122e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t err = mAudioRecord->getPosition(&mPositionWhenStarting); 123e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 124e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return OboeConvert_androidToOboeError(err); 125e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 126e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk err = mAudioRecord->start(); 127e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 128e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return OboeConvert_androidToOboeError(err); 129e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else { 130e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk setState(OBOE_STREAM_STATE_STARTING); 131e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 132e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return OBOE_OK; 133e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 134e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 135e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkoboe_result_t AudioStreamRecord::requestPause() 136e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 137e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return OBOE_ERROR_UNIMPLEMENTED; 138e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 139e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 140e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkoboe_result_t AudioStreamRecord::requestFlush() { 141e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return OBOE_ERROR_UNIMPLEMENTED; 142e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 143e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 144e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkoboe_result_t AudioStreamRecord::requestStop() { 145d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk if (mAudioRecord.get() == nullptr) { 146e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return OBOE_ERROR_INVALID_STATE; 147e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 148e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk setState(OBOE_STREAM_STATE_STOPPING); 149e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk mAudioRecord->stop(); 150e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return OBOE_OK; 151e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 152e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 153e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkoboe_result_t AudioStreamRecord::updateState() 154e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 155e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk oboe_result_t result = OBOE_OK; 156e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk oboe_wrapping_frames_t position; 157e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk status_t err; 158e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk switch (getState()) { 159e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO add better state visibility to AudioRecord 160e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk case OBOE_STREAM_STATE_STARTING: 161e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk err = mAudioRecord->getPosition(&position); 162e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (err != OK) { 163e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk result = OboeConvert_androidToOboeError(err); 164e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else if (position != mPositionWhenStarting) { 165e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk setState(OBOE_STREAM_STATE_STARTED); 166e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 167e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 168e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk case OBOE_STREAM_STATE_STOPPING: 169e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (mAudioRecord->stopped()) { 170e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk setState(OBOE_STREAM_STATE_STOPPED); 171e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 172e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 173e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk default: 174e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk break; 175e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 176e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return result; 177e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 178e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 179e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkoboe_result_t AudioStreamRecord::read(void *buffer, 180e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk oboe_size_frames_t numFrames, 181e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk oboe_nanoseconds_t timeoutNanoseconds) 182e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 183e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk oboe_size_frames_t bytesPerFrame = getBytesPerFrame(); 184e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk oboe_size_bytes_t numBytes; 185e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk oboe_result_t result = OboeConvert_framesToBytes(numFrames, bytesPerFrame, &numBytes); 186e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (result != OBOE_OK) { 187e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return result; 188e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 189e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 190e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk // TODO add timeout to AudioRecord 191e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk bool blocking = (timeoutNanoseconds > 0); 192e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk ssize_t bytesRead = mAudioRecord->read(buffer, numBytes, blocking); 193e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk if (bytesRead == WOULD_BLOCK) { 194e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return 0; 195e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } else if (bytesRead < 0) { 196e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return OboeConvert_androidToOboeError(bytesRead); 197e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk } 198e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk oboe_size_frames_t framesRead = (oboe_size_frames_t)(bytesRead / bytesPerFrame); 199e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return (oboe_result_t) framesRead; 200e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 201e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 202e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkoboe_result_t AudioStreamRecord::setBufferSize(oboe_size_frames_t requestedFrames, 203e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk oboe_size_frames_t *actualFrames) 204e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 205e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *actualFrames = getBufferCapacity(); 206e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return OBOE_OK; 207e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 208e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 209e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkoboe_size_frames_t AudioStreamRecord::getBufferSize() const 210e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 211e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return getBufferCapacity(); // TODO implement in AudioRecord? 212e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 213e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 214e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkoboe_size_frames_t AudioStreamRecord::getBufferCapacity() const 215e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 216e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return static_cast<oboe_size_frames_t>(mAudioRecord->frameCount()); 217e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 218e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 219e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkint32_t AudioStreamRecord::getXRunCount() const 220e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 221e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return OBOE_ERROR_UNIMPLEMENTED; // TODO implement when AudioRecord supports it 222e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 223e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 224e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkoboe_size_frames_t AudioStreamRecord::getFramesPerBurst() const 225e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{ 226e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk return 192; // TODO add query to AudioRecord.cpp 227e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk} 228e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 229e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk// TODO implement getTimestamp 230e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk 231