• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/audio_util.h"
22 #include "chre/core/event_loop_manager.h"
23 #include "chre/platform/fatal_error.h"
24 #include "chre/platform/log.h"
25 #include "chre/platform/system_time.h"
26 #include "chre/util/dynamic_vector.h"
27 
28 namespace chre {
29 namespace {
30 
31 //! The list of audio sources provided by the simulator.
32 DynamicVector<UniquePtr<AudioSource>> gAudioSources;
33 
34 }  // namespace
35 
PlatformAudio()36 PlatformAudio::PlatformAudio() {}
37 
~PlatformAudio()38 PlatformAudio::~PlatformAudio() {}
39 
init()40 void PlatformAudio::init() {
41   // TODO: Implement this.
42 }
43 
audioSourceCallback(void * cookie)44 void audioSourceCallback(void *cookie) {
45   auto *audioSource = static_cast<AudioSource *>(cookie);
46 
47   auto &dataEvent = audioSource->dataEvent;
48   Nanoseconds samplingTime = AudioUtil::getDurationFromSampleCountAndRate(
49       audioSource->numSamples,
50       static_cast<uint32_t>(audioSource->audioInfo.samplerate));
51   dataEvent.timestamp =
52       (SystemTime::getMonotonicTime() - samplingTime).toRawNanoseconds();
53   dataEvent.sampleCount = audioSource->numSamples;
54 
55   if (dataEvent.format == CHRE_AUDIO_DATA_FORMAT_16_BIT_SIGNED_PCM) {
56     uint32_t intervalNumSamples = AudioUtil::getSampleCountFromRateAndDuration(
57         static_cast<uint32_t>(audioSource->audioInfo.samplerate),
58         audioSource->eventDelay);
59     if (intervalNumSamples > audioSource->numSamples) {
60       sf_count_t seekAmount = intervalNumSamples - audioSource->numSamples;
61       sf_seek(audioSource->audioFile, -seekAmount, SEEK_CUR);
62     }
63 
64     sf_count_t readCount = sf_read_short(
65         audioSource->audioFile, const_cast<int16_t *>(dataEvent.samplesS16),
66         static_cast<sf_count_t>(dataEvent.sampleCount));
67     if (readCount != dataEvent.sampleCount) {
68       LOGI("TODO: File done, suspend the source");
69     } else {
70       EventLoopManagerSingleton::get()
71           ->getAudioRequestManager()
72           .handleAudioDataEvent(&audioSource->dataEvent);
73     }
74   } else {
75     FATAL_ERROR("Unimplemented data format");
76   }
77 }
78 
setHandleEnabled(uint32_t handle,bool enabled)79 void PlatformAudio::setHandleEnabled(uint32_t handle, bool enabled) {
80   // TODO: Implement this.
81 }
82 
requestAudioDataEvent(uint32_t handle,uint32_t numSamples,Nanoseconds eventDelay)83 bool PlatformAudio::requestAudioDataEvent(uint32_t handle, uint32_t numSamples,
84                                           Nanoseconds eventDelay) {
85   LOGD("Request for audio data made for handle %" PRIu32 " with %" PRIu32
86        " samples and %" PRIu64 " delivery interval",
87        handle, numSamples, eventDelay.toRawNanoseconds());
88   auto &source = gAudioSources[handle];
89   source->numSamples = numSamples;
90   source->eventDelay = eventDelay;
91   return source->timer.set(audioSourceCallback, source.get(), eventDelay);
92 }
93 
cancelAudioDataEventRequest(uint32_t handle)94 void PlatformAudio::cancelAudioDataEventRequest(uint32_t handle) {
95   LOGD("Cancelling audio request for handle %" PRIu32, handle);
96   auto &source = gAudioSources[handle];
97   source->timer.cancel();
98 }
99 
releaseAudioDataEvent(struct chreAudioDataEvent * event)100 void PlatformAudio::releaseAudioDataEvent(struct chreAudioDataEvent *event) {
101   // TODO(P1-41459d): Implement this API in terms of libsndfile.
102 }
103 
getSourceCount()104 size_t PlatformAudio::getSourceCount() {
105   return gAudioSources.size();
106 }
107 
getAudioSource(uint32_t handle,chreAudioSource * audioSource) const108 bool PlatformAudio::getAudioSource(uint32_t handle,
109                                    chreAudioSource *audioSource) const {
110   bool success = (handle < gAudioSources.size());
111   if (success) {
112     const auto &source = gAudioSources[handle];
113     // TODO(P1-b9ff35): Ensure that name never exceeds 40 bytes in length.
114     audioSource->name = source->audioFilename.c_str();
115     audioSource->sampleRate =
116         static_cast<uint32_t>(source->audioInfo.samplerate);
117     audioSource->minBufferDuration =
118         source->minBufferDuration.toRawNanoseconds();
119     audioSource->maxBufferDuration =
120         source->maxBufferDuration.toRawNanoseconds();
121     audioSource->format = source->dataEvent.format;
122   }
123 
124   return success;
125 }
126 
addAudioSource(UniquePtr<AudioSource> & source)127 void PlatformAudioBase::addAudioSource(UniquePtr<AudioSource> &source) {
128   LOGI("Adding audio source - filename: %s, min buf size: %" PRIu64
129        "ms, max buf size: %" PRIu64 "ms",
130        source->audioFilename.c_str(),
131        Milliseconds(source->minBufferDuration).getMilliseconds(),
132        Milliseconds(source->maxBufferDuration).getMilliseconds());
133   auto &audioInfo = source->audioInfo;
134   source->audioFile =
135       sf_open(source->audioFilename.c_str(), SFM_READ, &audioInfo);
136   auto sampleCount = AudioUtil::getSampleCountFromRateAndDuration(
137       static_cast<uint32_t>(source->audioInfo.samplerate),
138       source->maxBufferDuration);
139   if (source->audioFile == nullptr) {
140     FATAL_ERROR("Failed to open provided audio file %s",
141                 source->audioFilename.c_str());
142   } else if ((audioInfo.format & SF_FORMAT_ULAW) == SF_FORMAT_ULAW) {
143     source->dataEvent.format = CHRE_AUDIO_DATA_FORMAT_8_BIT_U_LAW;
144     source->dataEvent.samplesULaw8 =
145         static_cast<uint8_t *>(malloc(sizeof(uint8_t) * sampleCount));
146   } else if ((audioInfo.format & SF_FORMAT_PCM_16) == SF_FORMAT_PCM_16) {
147     source->dataEvent.format = CHRE_AUDIO_DATA_FORMAT_16_BIT_SIGNED_PCM;
148     source->dataEvent.samplesS16 =
149         static_cast<int16_t *>(malloc(sizeof(uint16_t) * sampleCount));
150   } else {
151     FATAL_ERROR("Invalid format 0x%08x", audioInfo.format);
152   }
153 
154   source->dataEvent.version = CHRE_AUDIO_DATA_EVENT_VERSION;
155   memset(source->dataEvent.reserved, 0, sizeof(source->dataEvent.reserved));
156   source->dataEvent.handle = static_cast<uint32_t>(gAudioSources.size());
157   source->dataEvent.sampleRate =
158       static_cast<uint32_t>(source->audioInfo.samplerate);
159   gAudioSources.push_back(std::move(source));
160 }
161 
162 }  // namespace chre
163