1*05767d91SRobert Wu /*
2*05767d91SRobert Wu * Copyright 2016 The Android Open Source Project
3*05767d91SRobert Wu *
4*05767d91SRobert Wu * Licensed under the Apache License, Version 2.0 (the "License");
5*05767d91SRobert Wu * you may not use this file except in compliance with the License.
6*05767d91SRobert Wu * You may obtain a copy of the License at
7*05767d91SRobert Wu *
8*05767d91SRobert Wu * http://www.apache.org/licenses/LICENSE-2.0
9*05767d91SRobert Wu *
10*05767d91SRobert Wu * Unless required by applicable law or agreed to in writing, software
11*05767d91SRobert Wu * distributed under the License is distributed on an "AS IS" BASIS,
12*05767d91SRobert Wu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*05767d91SRobert Wu * See the License for the specific language governing permissions and
14*05767d91SRobert Wu * limitations under the License.
15*05767d91SRobert Wu */
16*05767d91SRobert Wu
17*05767d91SRobert Wu
18*05767d91SRobert Wu #include <stdlib.h>
19*05767d91SRobert Wu #include <unistd.h>
20*05767d91SRobert Wu #include <sstream>
21*05767d91SRobert Wu
22*05767d91SRobert Wu #ifdef __ANDROID__
23*05767d91SRobert Wu #include <sys/system_properties.h>
24*05767d91SRobert Wu #endif
25*05767d91SRobert Wu
26*05767d91SRobert Wu #include <oboe/AudioStream.h>
27*05767d91SRobert Wu #include "oboe/Definitions.h"
28*05767d91SRobert Wu #include "oboe/Utilities.h"
29*05767d91SRobert Wu
30*05767d91SRobert Wu namespace oboe {
31*05767d91SRobert Wu
32*05767d91SRobert Wu constexpr float kScaleI16ToFloat = (1.0f / 32768.0f);
33*05767d91SRobert Wu
convertFloatToPcm16(const float * source,int16_t * destination,int32_t numSamples)34*05767d91SRobert Wu void convertFloatToPcm16(const float *source, int16_t *destination, int32_t numSamples) {
35*05767d91SRobert Wu for (int i = 0; i < numSamples; i++) {
36*05767d91SRobert Wu float fval = source[i];
37*05767d91SRobert Wu fval += 1.0; // to avoid discontinuity at 0.0 caused by truncation
38*05767d91SRobert Wu fval *= 32768.0f;
39*05767d91SRobert Wu auto sample = static_cast<int32_t>(fval);
40*05767d91SRobert Wu // clip to 16-bit range
41*05767d91SRobert Wu if (sample < 0) sample = 0;
42*05767d91SRobert Wu else if (sample > 0x0FFFF) sample = 0x0FFFF;
43*05767d91SRobert Wu sample -= 32768; // center at zero
44*05767d91SRobert Wu destination[i] = static_cast<int16_t>(sample);
45*05767d91SRobert Wu }
46*05767d91SRobert Wu }
47*05767d91SRobert Wu
convertPcm16ToFloat(const int16_t * source,float * destination,int32_t numSamples)48*05767d91SRobert Wu void convertPcm16ToFloat(const int16_t *source, float *destination, int32_t numSamples) {
49*05767d91SRobert Wu for (int i = 0; i < numSamples; i++) {
50*05767d91SRobert Wu destination[i] = source[i] * kScaleI16ToFloat;
51*05767d91SRobert Wu }
52*05767d91SRobert Wu }
53*05767d91SRobert Wu
convertFormatToSizeInBytes(AudioFormat format)54*05767d91SRobert Wu int32_t convertFormatToSizeInBytes(AudioFormat format) {
55*05767d91SRobert Wu int32_t size = 0;
56*05767d91SRobert Wu switch (format) {
57*05767d91SRobert Wu case AudioFormat::I16:
58*05767d91SRobert Wu size = sizeof(int16_t);
59*05767d91SRobert Wu break;
60*05767d91SRobert Wu case AudioFormat::Float:
61*05767d91SRobert Wu size = sizeof(float);
62*05767d91SRobert Wu break;
63*05767d91SRobert Wu case AudioFormat::I24:
64*05767d91SRobert Wu size = 3; // packed 24-bit data
65*05767d91SRobert Wu break;
66*05767d91SRobert Wu case AudioFormat::I32:
67*05767d91SRobert Wu size = sizeof(int32_t);
68*05767d91SRobert Wu break;
69*05767d91SRobert Wu case AudioFormat::IEC61937:
70*05767d91SRobert Wu size = sizeof(int16_t);
71*05767d91SRobert Wu break;
72*05767d91SRobert Wu default:
73*05767d91SRobert Wu break;
74*05767d91SRobert Wu }
75*05767d91SRobert Wu return size;
76*05767d91SRobert Wu }
77*05767d91SRobert Wu
78*05767d91SRobert Wu template<>
convertToText(Result returnCode)79*05767d91SRobert Wu const char *convertToText<Result>(Result returnCode) {
80*05767d91SRobert Wu switch (returnCode) {
81*05767d91SRobert Wu case Result::OK: return "OK";
82*05767d91SRobert Wu case Result::ErrorDisconnected: return "ErrorDisconnected";
83*05767d91SRobert Wu case Result::ErrorIllegalArgument: return "ErrorIllegalArgument";
84*05767d91SRobert Wu case Result::ErrorInternal: return "ErrorInternal";
85*05767d91SRobert Wu case Result::ErrorInvalidState: return "ErrorInvalidState";
86*05767d91SRobert Wu case Result::ErrorInvalidHandle: return "ErrorInvalidHandle";
87*05767d91SRobert Wu case Result::ErrorUnimplemented: return "ErrorUnimplemented";
88*05767d91SRobert Wu case Result::ErrorUnavailable: return "ErrorUnavailable";
89*05767d91SRobert Wu case Result::ErrorNoFreeHandles: return "ErrorNoFreeHandles";
90*05767d91SRobert Wu case Result::ErrorNoMemory: return "ErrorNoMemory";
91*05767d91SRobert Wu case Result::ErrorNull: return "ErrorNull";
92*05767d91SRobert Wu case Result::ErrorTimeout: return "ErrorTimeout";
93*05767d91SRobert Wu case Result::ErrorWouldBlock: return "ErrorWouldBlock";
94*05767d91SRobert Wu case Result::ErrorInvalidFormat: return "ErrorInvalidFormat";
95*05767d91SRobert Wu case Result::ErrorOutOfRange: return "ErrorOutOfRange";
96*05767d91SRobert Wu case Result::ErrorNoService: return "ErrorNoService";
97*05767d91SRobert Wu case Result::ErrorInvalidRate: return "ErrorInvalidRate";
98*05767d91SRobert Wu case Result::ErrorClosed: return "ErrorClosed";
99*05767d91SRobert Wu default: return "Unrecognized result";
100*05767d91SRobert Wu }
101*05767d91SRobert Wu }
102*05767d91SRobert Wu
103*05767d91SRobert Wu template<>
convertToText(AudioFormat format)104*05767d91SRobert Wu const char *convertToText<AudioFormat>(AudioFormat format) {
105*05767d91SRobert Wu switch (format) {
106*05767d91SRobert Wu case AudioFormat::Invalid: return "Invalid";
107*05767d91SRobert Wu case AudioFormat::Unspecified: return "Unspecified";
108*05767d91SRobert Wu case AudioFormat::I16: return "I16";
109*05767d91SRobert Wu case AudioFormat::Float: return "Float";
110*05767d91SRobert Wu case AudioFormat::I24: return "I24";
111*05767d91SRobert Wu case AudioFormat::I32: return "I32";
112*05767d91SRobert Wu case AudioFormat::IEC61937: return "IEC61937";
113*05767d91SRobert Wu default: return "Unrecognized format";
114*05767d91SRobert Wu }
115*05767d91SRobert Wu }
116*05767d91SRobert Wu
117*05767d91SRobert Wu template<>
convertToText(PerformanceMode mode)118*05767d91SRobert Wu const char *convertToText<PerformanceMode>(PerformanceMode mode) {
119*05767d91SRobert Wu switch (mode) {
120*05767d91SRobert Wu case PerformanceMode::LowLatency: return "LowLatency";
121*05767d91SRobert Wu case PerformanceMode::None: return "None";
122*05767d91SRobert Wu case PerformanceMode::PowerSaving: return "PowerSaving";
123*05767d91SRobert Wu default: return "Unrecognized performance mode";
124*05767d91SRobert Wu }
125*05767d91SRobert Wu }
126*05767d91SRobert Wu
127*05767d91SRobert Wu template<>
convertToText(SharingMode mode)128*05767d91SRobert Wu const char *convertToText<SharingMode>(SharingMode mode) {
129*05767d91SRobert Wu switch (mode) {
130*05767d91SRobert Wu case SharingMode::Exclusive: return "Exclusive";
131*05767d91SRobert Wu case SharingMode::Shared: return "Shared";
132*05767d91SRobert Wu default: return "Unrecognized sharing mode";
133*05767d91SRobert Wu }
134*05767d91SRobert Wu }
135*05767d91SRobert Wu
136*05767d91SRobert Wu template<>
convertToText(DataCallbackResult result)137*05767d91SRobert Wu const char *convertToText<DataCallbackResult>(DataCallbackResult result) {
138*05767d91SRobert Wu switch (result) {
139*05767d91SRobert Wu case DataCallbackResult::Continue: return "Continue";
140*05767d91SRobert Wu case DataCallbackResult::Stop: return "Stop";
141*05767d91SRobert Wu default: return "Unrecognized data callback result";
142*05767d91SRobert Wu }
143*05767d91SRobert Wu }
144*05767d91SRobert Wu
145*05767d91SRobert Wu template<>
convertToText(Direction direction)146*05767d91SRobert Wu const char *convertToText<Direction>(Direction direction) {
147*05767d91SRobert Wu switch (direction) {
148*05767d91SRobert Wu case Direction::Input: return "Input";
149*05767d91SRobert Wu case Direction::Output: return "Output";
150*05767d91SRobert Wu default: return "Unrecognized direction";
151*05767d91SRobert Wu }
152*05767d91SRobert Wu }
153*05767d91SRobert Wu
154*05767d91SRobert Wu template<>
convertToText(StreamState state)155*05767d91SRobert Wu const char *convertToText<StreamState>(StreamState state) {
156*05767d91SRobert Wu switch (state) {
157*05767d91SRobert Wu case StreamState::Closed: return "Closed";
158*05767d91SRobert Wu case StreamState::Closing: return "Closing";
159*05767d91SRobert Wu case StreamState::Disconnected: return "Disconnected";
160*05767d91SRobert Wu case StreamState::Flushed: return "Flushed";
161*05767d91SRobert Wu case StreamState::Flushing: return "Flushing";
162*05767d91SRobert Wu case StreamState::Open: return "Open";
163*05767d91SRobert Wu case StreamState::Paused: return "Paused";
164*05767d91SRobert Wu case StreamState::Pausing: return "Pausing";
165*05767d91SRobert Wu case StreamState::Started: return "Started";
166*05767d91SRobert Wu case StreamState::Starting: return "Starting";
167*05767d91SRobert Wu case StreamState::Stopped: return "Stopped";
168*05767d91SRobert Wu case StreamState::Stopping: return "Stopping";
169*05767d91SRobert Wu case StreamState::Uninitialized: return "Uninitialized";
170*05767d91SRobert Wu case StreamState::Unknown: return "Unknown";
171*05767d91SRobert Wu default: return "Unrecognized stream state";
172*05767d91SRobert Wu }
173*05767d91SRobert Wu }
174*05767d91SRobert Wu
175*05767d91SRobert Wu template<>
convertToText(AudioApi audioApi)176*05767d91SRobert Wu const char *convertToText<AudioApi>(AudioApi audioApi) {
177*05767d91SRobert Wu
178*05767d91SRobert Wu switch (audioApi) {
179*05767d91SRobert Wu case AudioApi::Unspecified: return "Unspecified";
180*05767d91SRobert Wu case AudioApi::OpenSLES: return "OpenSLES";
181*05767d91SRobert Wu case AudioApi::AAudio: return "AAudio";
182*05767d91SRobert Wu default: return "Unrecognized audio API";
183*05767d91SRobert Wu }
184*05767d91SRobert Wu }
185*05767d91SRobert Wu
186*05767d91SRobert Wu template<>
convertToText(AudioStream * stream)187*05767d91SRobert Wu const char *convertToText<AudioStream*>(AudioStream* stream) {
188*05767d91SRobert Wu static std::string streamText;
189*05767d91SRobert Wu std::stringstream s;
190*05767d91SRobert Wu
191*05767d91SRobert Wu s<<"StreamID: "<< static_cast<void*>(stream)<<std::endl
192*05767d91SRobert Wu <<"DeviceId: "<<stream->getDeviceId()<<std::endl
193*05767d91SRobert Wu <<"Direction: "<<oboe::convertToText(stream->getDirection())<<std::endl
194*05767d91SRobert Wu <<"API type: "<<oboe::convertToText(stream->getAudioApi())<<std::endl
195*05767d91SRobert Wu <<"BufferCapacity: "<<stream->getBufferCapacityInFrames()<<std::endl
196*05767d91SRobert Wu <<"BufferSize: "<<stream->getBufferSizeInFrames()<<std::endl
197*05767d91SRobert Wu <<"FramesPerBurst: "<< stream->getFramesPerBurst()<<std::endl
198*05767d91SRobert Wu <<"FramesPerDataCallback: "<<stream->getFramesPerDataCallback()<<std::endl
199*05767d91SRobert Wu <<"SampleRate: "<<stream->getSampleRate()<<std::endl
200*05767d91SRobert Wu <<"ChannelCount: "<<stream->getChannelCount()<<std::endl
201*05767d91SRobert Wu <<"Format: "<<oboe::convertToText(stream->getFormat())<<std::endl
202*05767d91SRobert Wu <<"SharingMode: "<<oboe::convertToText(stream->getSharingMode())<<std::endl
203*05767d91SRobert Wu <<"PerformanceMode: "<<oboe::convertToText(stream->getPerformanceMode())
204*05767d91SRobert Wu <<std::endl
205*05767d91SRobert Wu <<"CurrentState: "<<oboe::convertToText(stream->getState())<<std::endl
206*05767d91SRobert Wu <<"XRunCount: "<<stream->getXRunCount()<<std::endl
207*05767d91SRobert Wu <<"FramesRead: "<<stream->getFramesRead()<<std::endl
208*05767d91SRobert Wu <<"FramesWritten: "<<stream->getFramesWritten()<<std::endl;
209*05767d91SRobert Wu
210*05767d91SRobert Wu streamText = s.str();
211*05767d91SRobert Wu return streamText.c_str();
212*05767d91SRobert Wu }
213*05767d91SRobert Wu
214*05767d91SRobert Wu template<>
convertToText(Usage usage)215*05767d91SRobert Wu const char *convertToText<Usage>(Usage usage) {
216*05767d91SRobert Wu
217*05767d91SRobert Wu switch (usage) {
218*05767d91SRobert Wu case Usage::Media: return "Media";
219*05767d91SRobert Wu case Usage::VoiceCommunication: return "VoiceCommunication";
220*05767d91SRobert Wu case Usage::VoiceCommunicationSignalling: return "VoiceCommunicationSignalling";
221*05767d91SRobert Wu case Usage::Alarm: return "Alarm";
222*05767d91SRobert Wu case Usage::Notification: return "Notification";
223*05767d91SRobert Wu case Usage::NotificationRingtone: return "NotificationRingtone";
224*05767d91SRobert Wu case Usage::NotificationEvent: return "NotificationEvent";
225*05767d91SRobert Wu case Usage::AssistanceAccessibility: return "AssistanceAccessibility";
226*05767d91SRobert Wu case Usage::AssistanceNavigationGuidance: return "AssistanceNavigationGuidance";
227*05767d91SRobert Wu case Usage::AssistanceSonification: return "AssistanceSonification";
228*05767d91SRobert Wu case Usage::Game: return "Game";
229*05767d91SRobert Wu case Usage::Assistant: return "Assistant";
230*05767d91SRobert Wu default: return "Unrecognized usage";
231*05767d91SRobert Wu }
232*05767d91SRobert Wu }
233*05767d91SRobert Wu
234*05767d91SRobert Wu template<>
convertToText(ContentType contentType)235*05767d91SRobert Wu const char *convertToText<ContentType>(ContentType contentType) {
236*05767d91SRobert Wu
237*05767d91SRobert Wu switch (contentType) {
238*05767d91SRobert Wu case ContentType::Speech: return "Speech";
239*05767d91SRobert Wu case ContentType::Music: return "Music";
240*05767d91SRobert Wu case ContentType::Movie: return "Movie";
241*05767d91SRobert Wu case ContentType::Sonification: return "Sonification";
242*05767d91SRobert Wu default: return "Unrecognized content type";
243*05767d91SRobert Wu }
244*05767d91SRobert Wu }
245*05767d91SRobert Wu
246*05767d91SRobert Wu template<>
convertToText(InputPreset inputPreset)247*05767d91SRobert Wu const char *convertToText<InputPreset>(InputPreset inputPreset) {
248*05767d91SRobert Wu
249*05767d91SRobert Wu switch (inputPreset) {
250*05767d91SRobert Wu case InputPreset::Generic: return "Generic";
251*05767d91SRobert Wu case InputPreset::Camcorder: return "Camcorder";
252*05767d91SRobert Wu case InputPreset::VoiceRecognition: return "VoiceRecognition";
253*05767d91SRobert Wu case InputPreset::VoiceCommunication: return "VoiceCommunication";
254*05767d91SRobert Wu case InputPreset::Unprocessed: return "Unprocessed";
255*05767d91SRobert Wu case InputPreset::VoicePerformance: return "VoicePerformance";
256*05767d91SRobert Wu default: return "Unrecognized input preset";
257*05767d91SRobert Wu }
258*05767d91SRobert Wu }
259*05767d91SRobert Wu
260*05767d91SRobert Wu template<>
convertToText(SessionId sessionId)261*05767d91SRobert Wu const char *convertToText<SessionId>(SessionId sessionId) {
262*05767d91SRobert Wu
263*05767d91SRobert Wu switch (sessionId) {
264*05767d91SRobert Wu case SessionId::None: return "None";
265*05767d91SRobert Wu case SessionId::Allocate: return "Allocate";
266*05767d91SRobert Wu default: return "Unrecognized session id";
267*05767d91SRobert Wu }
268*05767d91SRobert Wu }
269*05767d91SRobert Wu
270*05767d91SRobert Wu template<>
convertToText(ChannelCount channelCount)271*05767d91SRobert Wu const char *convertToText<ChannelCount>(ChannelCount channelCount) {
272*05767d91SRobert Wu
273*05767d91SRobert Wu switch (channelCount) {
274*05767d91SRobert Wu case ChannelCount::Unspecified: return "Unspecified";
275*05767d91SRobert Wu case ChannelCount::Mono: return "Mono";
276*05767d91SRobert Wu case ChannelCount::Stereo: return "Stereo";
277*05767d91SRobert Wu default: return "Unrecognized channel count";
278*05767d91SRobert Wu }
279*05767d91SRobert Wu }
280*05767d91SRobert Wu
281*05767d91SRobert Wu template<>
convertToText(SampleRateConversionQuality sampleRateConversionQuality)282*05767d91SRobert Wu const char *convertToText<SampleRateConversionQuality>(SampleRateConversionQuality sampleRateConversionQuality) {
283*05767d91SRobert Wu
284*05767d91SRobert Wu switch (sampleRateConversionQuality) {
285*05767d91SRobert Wu case SampleRateConversionQuality::None: return "None";
286*05767d91SRobert Wu case SampleRateConversionQuality::Fastest: return "Fastest";
287*05767d91SRobert Wu case SampleRateConversionQuality::Low: return "Low";
288*05767d91SRobert Wu case SampleRateConversionQuality::Medium: return "Medium";
289*05767d91SRobert Wu case SampleRateConversionQuality::High: return "High";
290*05767d91SRobert Wu case SampleRateConversionQuality::Best: return "Best";
291*05767d91SRobert Wu default: return "Unrecognized sample rate conversion quality";
292*05767d91SRobert Wu }
293*05767d91SRobert Wu }
294*05767d91SRobert Wu
getPropertyString(const char * name)295*05767d91SRobert Wu std::string getPropertyString(const char * name) {
296*05767d91SRobert Wu std::string result;
297*05767d91SRobert Wu #ifdef __ANDROID__
298*05767d91SRobert Wu char valueText[PROP_VALUE_MAX] = {0};
299*05767d91SRobert Wu if (__system_property_get(name, valueText) != 0) {
300*05767d91SRobert Wu result = valueText;
301*05767d91SRobert Wu }
302*05767d91SRobert Wu #else
303*05767d91SRobert Wu (void) name;
304*05767d91SRobert Wu #endif
305*05767d91SRobert Wu return result;
306*05767d91SRobert Wu }
307*05767d91SRobert Wu
getPropertyInteger(const char * name,int defaultValue)308*05767d91SRobert Wu int getPropertyInteger(const char * name, int defaultValue) {
309*05767d91SRobert Wu int result = defaultValue;
310*05767d91SRobert Wu #ifdef __ANDROID__
311*05767d91SRobert Wu char valueText[PROP_VALUE_MAX] = {0};
312*05767d91SRobert Wu if (__system_property_get(name, valueText) != 0) {
313*05767d91SRobert Wu result = atoi(valueText);
314*05767d91SRobert Wu }
315*05767d91SRobert Wu #else
316*05767d91SRobert Wu (void) name;
317*05767d91SRobert Wu #endif
318*05767d91SRobert Wu return result;
319*05767d91SRobert Wu }
320*05767d91SRobert Wu
getSdkVersion()321*05767d91SRobert Wu int getSdkVersion() {
322*05767d91SRobert Wu static int sCachedSdkVersion = -1;
323*05767d91SRobert Wu #ifdef __ANDROID__
324*05767d91SRobert Wu if (sCachedSdkVersion == -1) {
325*05767d91SRobert Wu sCachedSdkVersion = getPropertyInteger("ro.build.version.sdk", -1);
326*05767d91SRobert Wu }
327*05767d91SRobert Wu #endif
328*05767d91SRobert Wu return sCachedSdkVersion;
329*05767d91SRobert Wu }
330*05767d91SRobert Wu
isAtLeastPreReleaseCodename(const std::string & codename)331*05767d91SRobert Wu bool isAtLeastPreReleaseCodename(const std::string& codename) {
332*05767d91SRobert Wu std::string buildCodename = getPropertyString("ro.build.version.codename");
333*05767d91SRobert Wu // Special case "REL", which means the build is not a pre-release build.
334*05767d91SRobert Wu if ("REL" == buildCodename) {
335*05767d91SRobert Wu return false;
336*05767d91SRobert Wu }
337*05767d91SRobert Wu
338*05767d91SRobert Wu // Otherwise lexically compare them. Return true if the build codename is equal to or
339*05767d91SRobert Wu // greater than the requested codename.
340*05767d91SRobert Wu return buildCodename.compare(codename) >= 0;
341*05767d91SRobert Wu }
342*05767d91SRobert Wu
getChannelCountFromChannelMask(ChannelMask channelMask)343*05767d91SRobert Wu int getChannelCountFromChannelMask(ChannelMask channelMask) {
344*05767d91SRobert Wu return __builtin_popcount(static_cast<uint32_t>(channelMask));
345*05767d91SRobert Wu }
346*05767d91SRobert Wu
347*05767d91SRobert Wu }// namespace oboe
348