blob: 14f823495c3dd09bc0c50207b713f937d8dcc246 [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}