blob: ec25935e9ebac1b2075847aa7bc92403ff1d06ec [file] [log] [blame]
Phil Burk0433d8f2018-11-21 16:41:25 -08001/*
2 * Copyright 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
Phil Burk71d97e92019-03-08 12:50:01 -080017#include "common/OboeDebug.h"
Phil Burk0433d8f2018-11-21 16:41:25 -080018#include "OboeStreamCallbackProxy.h"
19
Phil Burk0f94ca12019-12-21 15:13:40 -080020// Linear congruential random number generator.
21static uint32_t s_random16() {
22 static uint32_t seed = 1234;
23 seed = ((seed * 31421) + 6927) & 0x0FFFF;
24 return seed;
Phil Burk0433d8f2018-11-21 16:41:25 -080025}
26
Phil Burk0f94ca12019-12-21 15:13:40 -080027/**
28 * The random number generator is good for burning CPU because the compiler cannot
29 * easily optimize away the computation.
30 * @param workload number of times to execute the loop
31 * @return a white noise value between -1.0 and +1.0
32 */
33static float s_burnCPU(int32_t workload) {
34 uint32_t random = 0;
35 for (int32_t i = 0; i < workload; i++) {
36 for (int32_t j = 0; j < 10; j++) {
37 random = random ^ s_random16();
38 }
39 }
40 return (random - 32768) * (1.0 / 32768);
41}
42
43bool OboeStreamCallbackProxy::mCallbackReturnStop = false;
44
Phil Burk8e038822020-02-25 15:00:59 -080045int64_t OboeStreamCallbackProxy::getNanoseconds(clockid_t clockId) {
46 struct timespec time;
47 int result = clock_gettime(clockId, &time);
48 if (result < 0) {
49 return result;
50 }
51 return (time.tv_sec * 1e9) + time.tv_nsec;
52}
53
Phil Burk0433d8f2018-11-21 16:41:25 -080054oboe::DataCallbackResult OboeStreamCallbackProxy::onAudioReady(
55 oboe::AudioStream *audioStream,
56 void *audioData,
57 int numFrames) {
Phil Burk8e038822020-02-25 15:00:59 -080058 oboe::DataCallbackResult callbackResult = oboe::DataCallbackResult::Stop;
59 int64_t startTimeNanos = getNanoseconds();
60
Phil Burk6fb1d802018-12-21 15:28:07 -080061 mCallbackCount++;
Phil Burk27c72712020-01-27 09:13:19 -080062 mFramesPerCallback = numFrames;
63
Phil Burk6fb1d802018-12-21 15:28:07 -080064 if (mCallbackReturnStop) {
65 return oboe::DataCallbackResult::Stop;
66 }
Phil Burk0f94ca12019-12-21 15:13:40 -080067
Phil Burk0f94ca12019-12-21 15:13:40 -080068 s_burnCPU((int32_t)(mWorkload * kWorkloadScaler * numFrames));
69
Phil Burk0433d8f2018-11-21 16:41:25 -080070 if (mCallback != nullptr) {
Phil Burk8e038822020-02-25 15:00:59 -080071 callbackResult = mCallback->onAudioReady(audioStream, audioData, numFrames);
Phil Burk0433d8f2018-11-21 16:41:25 -080072 }
Phil Burk8e038822020-02-25 15:00:59 -080073
74 // Update CPU load
75 double calculationTime = (double)(getNanoseconds() - startTimeNanos);
76 double inverseRealTime = audioStream->getSampleRate() / (1.0e9 * numFrames);
77 double currentCpuLoad = calculationTime * inverseRealTime; // avoid a divide
78 mCpuLoad = (mCpuLoad * 0.95) + (currentCpuLoad * 0.05); // simple low pass filter
79
80 return callbackResult;
Phil Burk0433d8f2018-11-21 16:41:25 -080081}
82
83void OboeStreamCallbackProxy::onErrorBeforeClose(oboe::AudioStream *audioStream, oboe::Result error) {
Phil Burkc572e882020-01-07 14:26:56 -080084 LOGD("OboeStreamCallbackProxy::%s(%p, %d) called", __func__, audioStream, error);
Phil Burk0433d8f2018-11-21 16:41:25 -080085 if (mCallback != nullptr) {
Phil Burkc572e882020-01-07 14:26:56 -080086 mCallback->onErrorBeforeClose(audioStream, error);
Phil Burk0433d8f2018-11-21 16:41:25 -080087 }
Phil Burkda7f9cc2020-04-24 16:45:19 -070088 // usleep(2000 * 1000); // FIXME - sleep to provoke a race condition
Phil Burkc4556cc2020-04-15 13:50:58 -070089 LOGD("OboeStreamCallbackProxy::%s(%p, %d) returning after sleep", __func__, audioStream, error);
Phil Burk0433d8f2018-11-21 16:41:25 -080090}
91
92void OboeStreamCallbackProxy::onErrorAfterClose(oboe::AudioStream *audioStream, oboe::Result error) {
Phil Burkc572e882020-01-07 14:26:56 -080093
94 LOGD("OboeStreamCallbackProxy::%s(%p, %d) called", __func__, audioStream, error);
Phil Burk0433d8f2018-11-21 16:41:25 -080095 if (mCallback != nullptr) {
Phil Burkc572e882020-01-07 14:26:56 -080096 mCallback->onErrorAfterClose(audioStream, error);
Phil Burk0433d8f2018-11-21 16:41:25 -080097 }
98}