123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- /*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include "chre/platform/platform_audio.h"
- #include <cinttypes>
- #include "chre/core/audio_request_manager.h"
- #include "chre/core/event_loop_manager.h"
- #include "chre/platform/fatal_error.h"
- #include "chre/platform/log.h"
- #include "chre/platform/system_time.h"
- namespace chre {
- namespace {
- //! The fixed sampling rate for audio data when running CHRE on Android.
- constexpr uint32_t kAndroidAudioSampleRate = 16000;
- //! The minimum buffer size in samples.
- constexpr uint32_t kAndroidAudioMinBufferSize = kAndroidAudioSampleRate / 10;
- //! The maximum buffer size in samples.
- constexpr uint32_t kAndroidAudioMaxBufferSize = kAndroidAudioSampleRate * 10;
- } // namespace
- void PlatformAudioBase::audioReadCallback(void *cookie) {
- auto *platformAudio = static_cast<PlatformAudio *>(cookie);
- auto& dataEvent = platformAudio->mDataEvent;
- Nanoseconds samplingTime =
- AudioRequestManager::getDurationFromSampleCountAndRate(
- platformAudio->mNumSamples, kAndroidAudioSampleRate);
- dataEvent.timestamp = (SystemTime::getMonotonicTime() - samplingTime)
- .toRawNanoseconds();
- if (dataEvent.format == CHRE_AUDIO_DATA_FORMAT_16_BIT_SIGNED_PCM) {
- uint32_t intervalNumSamples =
- AudioRequestManager::getSampleCountFromRateAndDuration(
- kAndroidAudioSampleRate, platformAudio->mEventDelay);
- // Determine how much new audio data is required to be read from the device.
- // Samples that are already buffered by this implementation may be reused.
- int16_t *audioBuffer = platformAudio->mBuffer.data();
- uint32_t readAmount = platformAudio->mNumSamples;
- if (intervalNumSamples > platformAudio->mNumSamples) {
- uint32_t seekAmount = intervalNumSamples - platformAudio->mNumSamples;
- audioBuffer = &platformAudio->mBuffer.data()[seekAmount];
- readAmount = platformAudio->mNumSamples - seekAmount;
- }
- // Perform a blocking read. A timeout of 1 nanoasecond is passed here to
- // ensure that we read exactly the amount of requested audio frames. The
- // timer ensures that we wait approximately long enough to read the
- // requested number of samples and the timeout ensures that they match
- // exactly.
- int32_t framesRead = AAudioStream_read(
- platformAudio->mStream, audioBuffer, readAmount, 1);
- if (framesRead != static_cast<int32_t>(platformAudio->mNumSamples)) {
- FATAL_ERROR("Failed to read requested number of audio samples");
- } else {
- EventLoopManagerSingleton::get()->getAudioRequestManager()
- .handleAudioDataEvent(&dataEvent);
- }
- } else {
- FATAL_ERROR("Unimplemented data format");
- }
- }
- PlatformAudio::PlatformAudio() {
- if (!mTimer.init()) {
- FATAL_ERROR("Failed to initialize audio timer");
- }
- aaudio_result_t result = AAudio_createStreamBuilder(&mStreamBuilder);
- if (result != AAUDIO_OK) {
- FATAL_ERROR("Failed to create audio stream builder with %" PRId32, result);
- }
- AAudioStreamBuilder_setDirection(mStreamBuilder, AAUDIO_DIRECTION_INPUT);
- AAudioStreamBuilder_setSharingMode(mStreamBuilder,
- AAUDIO_SHARING_MODE_SHARED);
- AAudioStreamBuilder_setSampleRate(mStreamBuilder, kAndroidAudioSampleRate);
- AAudioStreamBuilder_setChannelCount(mStreamBuilder, 1);
- AAudioStreamBuilder_setFormat(mStreamBuilder, AAUDIO_FORMAT_PCM_I16);
- AAudioStreamBuilder_setBufferCapacityInFrames(mStreamBuilder,
- kAndroidAudioMaxBufferSize);
- result = AAudioStreamBuilder_openStream(mStreamBuilder, &mStream);
- if (result != AAUDIO_OK) {
- FATAL_ERROR("Failed to create audio stream with %" PRId32, result);
- }
- int32_t bufferSize = AAudioStream_getBufferCapacityInFrames(mStream);
- LOGD("Created audio stream with %" PRId32 " frames buffer size",
- bufferSize);
- mMinBufferDuration = AudioRequestManager::getDurationFromSampleCountAndRate(
- kAndroidAudioMinBufferSize, kAndroidAudioSampleRate).toRawNanoseconds();
- mMaxBufferDuration = AudioRequestManager::getDurationFromSampleCountAndRate(
- bufferSize, kAndroidAudioSampleRate).toRawNanoseconds();
- result = AAudioStream_requestStart(mStream);
- if (result != AAUDIO_OK) {
- FATAL_ERROR("Failed to start audio stream with %" PRId32, result);
- }
- mBuffer.resize(bufferSize);
- initAudioDataEvent();
- }
- PlatformAudio::~PlatformAudio() {
- AAudioStream_close(mStream);
- AAudioStreamBuilder_delete(mStreamBuilder);
- }
- void PlatformAudio::init() {
- // TODO: Implement this.
- }
- void PlatformAudio::setHandleEnabled(uint32_t handle, bool enabled) {
- // TODO: Implement this.
- }
- bool PlatformAudio::requestAudioDataEvent(uint32_t handle,
- uint32_t numSamples,
- Nanoseconds eventDelay) {
- mNumSamples = numSamples;
- mEventDelay = eventDelay;
- mDataEvent.sampleCount = numSamples;
- return mTimer.set(audioReadCallback, this, eventDelay);
- }
- void PlatformAudio::cancelAudioDataEventRequest(uint32_t handle) {
- mTimer.cancel();
- }
- void PlatformAudio::releaseAudioDataEvent(struct chreAudioDataEvent *event) {
- }
- size_t PlatformAudio::getSourceCount() {
- // Hardcoded at one as the Android platform only surfaces the default mic.
- return 1;
- }
- bool PlatformAudio::getAudioSource(uint32_t handle,
- chreAudioSource *audioSource) const {
- bool success = false;
- if (handle == 0) {
- audioSource->name = "Default Android Audio Input";
- audioSource->sampleRate = kAndroidAudioSampleRate;
- audioSource->minBufferDuration = mMinBufferDuration;
- audioSource->maxBufferDuration = mMaxBufferDuration;
- audioSource->format = mDataEvent.format;
- success = true;
- }
- return success;
- }
- void PlatformAudioBase::initAudioDataEvent() {
- mDataEvent.version = CHRE_AUDIO_DATA_EVENT_VERSION;
- memset(mDataEvent.reserved, 0, sizeof(mDataEvent.reserved));
- mDataEvent.handle = 0;
- mDataEvent.sampleRate = kAndroidAudioSampleRate;
- mDataEvent.format = CHRE_AUDIO_DATA_FORMAT_16_BIT_SIGNED_PCM;
- mDataEvent.samplesS16 = mBuffer.data();
- }
- } // namespace chre
|