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