xref: /aosp_15_r20/external/oboe/src/common/Utilities.cpp (revision 05767d913155b055644481607e6fa1e35e2fe72c)
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