Home | History | Annotate | Download | only in linux
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "chre/platform/platform_audio.h"
     18 
     19 #include <cinttypes>
     20 
     21 #include "chre/core/event_loop_manager.h"
     22 #include "chre/platform/fatal_error.h"
     23 #include "chre/platform/log.h"
     24 #include "chre/platform/system_time.h"
     25 #include "chre/util/dynamic_vector.h"
     26 
     27 namespace chre {
     28 namespace {
     29 
     30 //! The list of audio sources provided by the simulator.
     31 DynamicVector<UniquePtr<AudioSource>> gAudioSources;
     32 
     33 }
     34 
     35 PlatformAudio::PlatformAudio() {}
     36 
     37 PlatformAudio::~PlatformAudio() {}
     38 
     39 void PlatformAudio::init() {
     40   // TODO: Implement this.
     41 }
     42 
     43 void audioSourceCallback(void *cookie) {
     44   auto *audioSource = static_cast<AudioSource *>(cookie);
     45 
     46   auto& dataEvent = audioSource->dataEvent;
     47   Nanoseconds samplingTime =
     48       AudioRequestManager::getDurationFromSampleCountAndRate(
     49         audioSource->numSamples,
     50         static_cast<uint32_t>(audioSource->audioInfo.samplerate));
     51   dataEvent.timestamp = (SystemTime::getMonotonicTime() - samplingTime)
     52       .toRawNanoseconds();
     53   dataEvent.sampleCount = audioSource->numSamples;
     54 
     55   if (dataEvent.format == CHRE_AUDIO_DATA_FORMAT_16_BIT_SIGNED_PCM) {
     56     uint32_t intervalNumSamples =
     57         AudioRequestManager::getSampleCountFromRateAndDuration(
     58           static_cast<uint32_t>(audioSource->audioInfo.samplerate),
     59           audioSource->eventDelay);
     60     if (intervalNumSamples > audioSource->numSamples) {
     61       sf_count_t seekAmount = intervalNumSamples - audioSource->numSamples;
     62       sf_seek(audioSource->audioFile, -seekAmount, SEEK_CUR);
     63     }
     64 
     65     sf_count_t readCount = sf_read_short(
     66         audioSource->audioFile,
     67         const_cast<int16_t *>(dataEvent.samplesS16),
     68         static_cast<sf_count_t>(dataEvent.sampleCount));
     69     if (readCount != dataEvent.sampleCount) {
     70       LOGI("TODO: File done, suspend the source");
     71     } else {
     72       EventLoopManagerSingleton::get()->getAudioRequestManager()
     73           .handleAudioDataEvent(&audioSource->dataEvent);
     74     }
     75   } else {
     76     FATAL_ERROR("Unimplemented data format");
     77   }
     78 }
     79 
     80 void PlatformAudio::setHandleEnabled(uint32_t handle, bool enabled) {
     81   // TODO: Implement this.
     82 }
     83 
     84 bool PlatformAudio::requestAudioDataEvent(uint32_t handle,
     85                                           uint32_t numSamples,
     86                                           Nanoseconds eventDelay) {
     87   LOGD("Request for audio data made for handle %" PRIu32 " with %" PRIu32
     88        " samples and %" PRIu64 " delivery interval", handle, numSamples,
     89        eventDelay.toRawNanoseconds());
     90   auto& source = gAudioSources[handle];
     91   source->numSamples = numSamples;
     92   source->eventDelay = eventDelay;
     93   return source->timer.set(audioSourceCallback, source.get(), eventDelay);
     94 }
     95 
     96 void PlatformAudio::cancelAudioDataEventRequest(uint32_t handle) {
     97   LOGD("Cancelling audio request for handle %" PRIu32, handle);
     98   auto& source = gAudioSources[handle];
     99   source->timer.cancel();
    100 }
    101 
    102 void PlatformAudio::releaseAudioDataEvent(struct chreAudioDataEvent *event) {
    103   // TODO(P1-41459d): Implement this API in terms of libsndfile.
    104 }
    105 
    106 size_t PlatformAudio::getSourceCount() {
    107   return gAudioSources.size();
    108 }
    109 
    110 bool PlatformAudio::getAudioSource(uint32_t handle,
    111                                    chreAudioSource *audioSource) {
    112   bool success = (handle < gAudioSources.size());
    113   if (success) {
    114     const auto& source = gAudioSources[handle];
    115     // TODO(P1-b9ff35): Ensure that name never exceeds 40 bytes in length.
    116     audioSource->name = source->audioFilename.c_str();
    117     audioSource->sampleRate =
    118         static_cast<uint32_t>(source->audioInfo.samplerate);
    119     audioSource->minBufferDuration =
    120         source->minBufferDuration.toRawNanoseconds();
    121     audioSource->maxBufferDuration =
    122         source->maxBufferDuration.toRawNanoseconds();
    123     audioSource->format = source->dataEvent.format;
    124   }
    125 
    126   return success;
    127 }
    128 
    129 void PlatformAudioBase::addAudioSource(UniquePtr<AudioSource>& source) {
    130   LOGI("Adding audio source - filename: %s, min buf size: %" PRIu64 "ms, "
    131        "max buf size: %" PRIu64 "ms", source->audioFilename.c_str(),
    132        Milliseconds(source->minBufferDuration).getMilliseconds(),
    133        Milliseconds(source->maxBufferDuration).getMilliseconds());
    134   auto& audioInfo = source->audioInfo;
    135   source->audioFile = sf_open(source->audioFilename.c_str(), SFM_READ,
    136                               &audioInfo);
    137   auto sampleCount = AudioRequestManager::getSampleCountFromRateAndDuration(
    138       static_cast<uint32_t>(source->audioInfo.samplerate),
    139       source->maxBufferDuration);
    140   if (source->audioFile == nullptr) {
    141     FATAL_ERROR("Failed to open provided audio file %s",
    142                 source->audioFilename.c_str());
    143   } else if ((audioInfo.format & SF_FORMAT_ULAW) == SF_FORMAT_ULAW) {
    144     source->dataEvent.format = CHRE_AUDIO_DATA_FORMAT_8_BIT_U_LAW;
    145     source->dataEvent.samplesULaw8 = static_cast<uint8_t *>(
    146         malloc(sizeof(uint8_t) * sampleCount));
    147   } else if ((audioInfo.format & SF_FORMAT_PCM_16) == SF_FORMAT_PCM_16) {
    148     source->dataEvent.format = CHRE_AUDIO_DATA_FORMAT_16_BIT_SIGNED_PCM;
    149     source->dataEvent.samplesS16 = static_cast<int16_t *>(
    150         malloc(sizeof(uint16_t) * sampleCount));
    151   } else {
    152     FATAL_ERROR("Invalid format 0x%08x", audioInfo.format);
    153   }
    154 
    155   source->dataEvent.version = CHRE_AUDIO_DATA_EVENT_VERSION;
    156   memset(source->dataEvent.reserved, 0, sizeof(source->dataEvent.reserved));
    157   source->dataEvent.handle = static_cast<uint32_t>(gAudioSources.size());
    158   source->dataEvent.sampleRate =
    159       static_cast<uint32_t>(source->audioInfo.samplerate);
    160   gAudioSources.push_back(std::move(source));
    161 }
    162 
    163 }  // namespace chre
    164