1 /*
2 * Copyright 2016 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
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <sstream>
21
22 #ifdef __ANDROID__
23 #include <sys/system_properties.h>
24 #endif
25
26 #include <oboe/AudioStream.h>
27 #include "oboe/Definitions.h"
28 #include "oboe/Utilities.h"
29
30 namespace oboe {
31
32 constexpr float kScaleI16ToFloat = (1.0f / 32768.0f);
33
convertFloatToPcm16(const float * source,int16_t * destination,int32_t numSamples)34 void convertFloatToPcm16(const float *source, int16_t *destination, int32_t numSamples) {
35 for (int i = 0; i < numSamples; i++) {
36 float fval = source[i];
37 fval += 1.0; // to avoid discontinuity at 0.0 caused by truncation
38 fval *= 32768.0f;
39 auto sample = static_cast<int32_t>(fval);
40 // clip to 16-bit range
41 if (sample < 0) sample = 0;
42 else if (sample > 0x0FFFF) sample = 0x0FFFF;
43 sample -= 32768; // center at zero
44 destination[i] = static_cast<int16_t>(sample);
45 }
46 }
47
convertPcm16ToFloat(const int16_t * source,float * destination,int32_t numSamples)48 void convertPcm16ToFloat(const int16_t *source, float *destination, int32_t numSamples) {
49 for (int i = 0; i < numSamples; i++) {
50 destination[i] = source[i] * kScaleI16ToFloat;
51 }
52 }
53
convertFormatToSizeInBytes(AudioFormat format)54 int32_t convertFormatToSizeInBytes(AudioFormat format) {
55 int32_t size = 0;
56 switch (format) {
57 case AudioFormat::I16:
58 size = sizeof(int16_t);
59 break;
60 case AudioFormat::Float:
61 size = sizeof(float);
62 break;
63 case AudioFormat::I24:
64 size = 3; // packed 24-bit data
65 break;
66 case AudioFormat::I32:
67 size = sizeof(int32_t);
68 break;
69 default:
70 break;
71 }
72 return size;
73 }
74
75 template<>
convertToText(Result returnCode)76 const char *convertToText<Result>(Result returnCode) {
77 switch (returnCode) {
78 case Result::OK: return "OK";
79 case Result::ErrorDisconnected: return "ErrorDisconnected";
80 case Result::ErrorIllegalArgument: return "ErrorIllegalArgument";
81 case Result::ErrorInternal: return "ErrorInternal";
82 case Result::ErrorInvalidState: return "ErrorInvalidState";
83 case Result::ErrorInvalidHandle: return "ErrorInvalidHandle";
84 case Result::ErrorUnimplemented: return "ErrorUnimplemented";
85 case Result::ErrorUnavailable: return "ErrorUnavailable";
86 case Result::ErrorNoFreeHandles: return "ErrorNoFreeHandles";
87 case Result::ErrorNoMemory: return "ErrorNoMemory";
88 case Result::ErrorNull: return "ErrorNull";
89 case Result::ErrorTimeout: return "ErrorTimeout";
90 case Result::ErrorWouldBlock: return "ErrorWouldBlock";
91 case Result::ErrorInvalidFormat: return "ErrorInvalidFormat";
92 case Result::ErrorOutOfRange: return "ErrorOutOfRange";
93 case Result::ErrorNoService: return "ErrorNoService";
94 case Result::ErrorInvalidRate: return "ErrorInvalidRate";
95 case Result::ErrorClosed: return "ErrorClosed";
96 default: return "Unrecognized result";
97 }
98 }
99
100 template<>
convertToText(AudioFormat format)101 const char *convertToText<AudioFormat>(AudioFormat format) {
102 switch (format) {
103 case AudioFormat::Invalid: return "Invalid";
104 case AudioFormat::Unspecified: return "Unspecified";
105 case AudioFormat::I16: return "I16";
106 case AudioFormat::Float: return "Float";
107 case AudioFormat::I24: return "I24";
108 case AudioFormat::I32: return "I32";
109 default: return "Unrecognized format";
110 }
111 }
112
113 template<>
convertToText(PerformanceMode mode)114 const char *convertToText<PerformanceMode>(PerformanceMode mode) {
115 switch (mode) {
116 case PerformanceMode::LowLatency: return "LowLatency";
117 case PerformanceMode::None: return "None";
118 case PerformanceMode::PowerSaving: return "PowerSaving";
119 default: return "Unrecognized performance mode";
120 }
121 }
122
123 template<>
convertToText(SharingMode mode)124 const char *convertToText<SharingMode>(SharingMode mode) {
125 switch (mode) {
126 case SharingMode::Exclusive: return "Exclusive";
127 case SharingMode::Shared: return "Shared";
128 default: return "Unrecognized sharing mode";
129 }
130 }
131
132 template<>
convertToText(DataCallbackResult result)133 const char *convertToText<DataCallbackResult>(DataCallbackResult result) {
134 switch (result) {
135 case DataCallbackResult::Continue: return "Continue";
136 case DataCallbackResult::Stop: return "Stop";
137 default: return "Unrecognized data callback result";
138 }
139 }
140
141 template<>
convertToText(Direction direction)142 const char *convertToText<Direction>(Direction direction) {
143 switch (direction) {
144 case Direction::Input: return "Input";
145 case Direction::Output: return "Output";
146 default: return "Unrecognized direction";
147 }
148 }
149
150 template<>
convertToText(StreamState state)151 const char *convertToText<StreamState>(StreamState state) {
152 switch (state) {
153 case StreamState::Closed: return "Closed";
154 case StreamState::Closing: return "Closing";
155 case StreamState::Disconnected: return "Disconnected";
156 case StreamState::Flushed: return "Flushed";
157 case StreamState::Flushing: return "Flushing";
158 case StreamState::Open: return "Open";
159 case StreamState::Paused: return "Paused";
160 case StreamState::Pausing: return "Pausing";
161 case StreamState::Started: return "Started";
162 case StreamState::Starting: return "Starting";
163 case StreamState::Stopped: return "Stopped";
164 case StreamState::Stopping: return "Stopping";
165 case StreamState::Uninitialized: return "Uninitialized";
166 case StreamState::Unknown: return "Unknown";
167 default: return "Unrecognized stream state";
168 }
169 }
170
171 template<>
convertToText(AudioApi audioApi)172 const char *convertToText<AudioApi>(AudioApi audioApi) {
173
174 switch (audioApi) {
175 case AudioApi::Unspecified: return "Unspecified";
176 case AudioApi::OpenSLES: return "OpenSLES";
177 case AudioApi::AAudio: return "AAudio";
178 default: return "Unrecognized audio API";
179 }
180 }
181
182 template<>
convertToText(AudioStream * stream)183 const char *convertToText<AudioStream*>(AudioStream* stream) {
184 static std::string streamText;
185 std::stringstream s;
186
187 s<<"StreamID: "<< static_cast<void*>(stream)<<std::endl
188 <<"DeviceId: "<<stream->getDeviceId()<<std::endl
189 <<"Direction: "<<oboe::convertToText(stream->getDirection())<<std::endl
190 <<"API type: "<<oboe::convertToText(stream->getAudioApi())<<std::endl
191 <<"BufferCapacity: "<<stream->getBufferCapacityInFrames()<<std::endl
192 <<"BufferSize: "<<stream->getBufferSizeInFrames()<<std::endl
193 <<"FramesPerBurst: "<< stream->getFramesPerBurst()<<std::endl
194 <<"FramesPerDataCallback: "<<stream->getFramesPerDataCallback()<<std::endl
195 <<"SampleRate: "<<stream->getSampleRate()<<std::endl
196 <<"ChannelCount: "<<stream->getChannelCount()<<std::endl
197 <<"Format: "<<oboe::convertToText(stream->getFormat())<<std::endl
198 <<"SharingMode: "<<oboe::convertToText(stream->getSharingMode())<<std::endl
199 <<"PerformanceMode: "<<oboe::convertToText(stream->getPerformanceMode())
200 <<std::endl
201 <<"CurrentState: "<<oboe::convertToText(stream->getState())<<std::endl
202 <<"XRunCount: "<<stream->getXRunCount()<<std::endl
203 <<"FramesRead: "<<stream->getFramesRead()<<std::endl
204 <<"FramesWritten: "<<stream->getFramesWritten()<<std::endl;
205
206 streamText = s.str();
207 return streamText.c_str();
208 }
209
210 template<>
convertToText(Usage usage)211 const char *convertToText<Usage>(Usage usage) {
212
213 switch (usage) {
214 case Usage::Media: return "Media";
215 case Usage::VoiceCommunication: return "VoiceCommunication";
216 case Usage::VoiceCommunicationSignalling: return "VoiceCommunicationSignalling";
217 case Usage::Alarm: return "Alarm";
218 case Usage::Notification: return "Notification";
219 case Usage::NotificationRingtone: return "NotificationRingtone";
220 case Usage::NotificationEvent: return "NotificationEvent";
221 case Usage::AssistanceAccessibility: return "AssistanceAccessibility";
222 case Usage::AssistanceNavigationGuidance: return "AssistanceNavigationGuidance";
223 case Usage::AssistanceSonification: return "AssistanceSonification";
224 case Usage::Game: return "Game";
225 case Usage::Assistant: return "Assistant";
226 default: return "Unrecognized usage";
227 }
228 }
229
230 template<>
convertToText(ContentType contentType)231 const char *convertToText<ContentType>(ContentType contentType) {
232
233 switch (contentType) {
234 case ContentType::Speech: return "Speech";
235 case ContentType::Music: return "Music";
236 case ContentType::Movie: return "Movie";
237 case ContentType::Sonification: return "Sonification";
238 default: return "Unrecognized content type";
239 }
240 }
241
242 template<>
convertToText(InputPreset inputPreset)243 const char *convertToText<InputPreset>(InputPreset inputPreset) {
244
245 switch (inputPreset) {
246 case InputPreset::Generic: return "Generic";
247 case InputPreset::Camcorder: return "Camcorder";
248 case InputPreset::VoiceRecognition: return "VoiceRecognition";
249 case InputPreset::VoiceCommunication: return "VoiceCommunication";
250 case InputPreset::Unprocessed: return "Unprocessed";
251 case InputPreset::VoicePerformance: return "VoicePerformance";
252 default: return "Unrecognized input preset";
253 }
254 }
255
256 template<>
convertToText(SessionId sessionId)257 const char *convertToText<SessionId>(SessionId sessionId) {
258
259 switch (sessionId) {
260 case SessionId::None: return "None";
261 case SessionId::Allocate: return "Allocate";
262 default: return "Unrecognized session id";
263 }
264 }
265
266 template<>
convertToText(ChannelCount channelCount)267 const char *convertToText<ChannelCount>(ChannelCount channelCount) {
268
269 switch (channelCount) {
270 case ChannelCount::Unspecified: return "Unspecified";
271 case ChannelCount::Mono: return "Mono";
272 case ChannelCount::Stereo: return "Stereo";
273 default: return "Unrecognized channel count";
274 }
275 }
276
getPropertyString(const char * name)277 std::string getPropertyString(const char * name) {
278 std::string result;
279 #ifdef __ANDROID__
280 char valueText[PROP_VALUE_MAX] = {0};
281 if (__system_property_get(name, valueText) != 0) {
282 result = valueText;
283 }
284 #else
285 (void) name;
286 #endif
287 return result;
288 }
289
getPropertyInteger(const char * name,int defaultValue)290 int getPropertyInteger(const char * name, int defaultValue) {
291 int result = defaultValue;
292 #ifdef __ANDROID__
293 char valueText[PROP_VALUE_MAX] = {0};
294 if (__system_property_get(name, valueText) != 0) {
295 result = atoi(valueText);
296 }
297 #else
298 (void) name;
299 #endif
300 return result;
301 }
302
getSdkVersion()303 int getSdkVersion() {
304 static int sCachedSdkVersion = -1;
305 #ifdef __ANDROID__
306 if (sCachedSdkVersion == -1) {
307 sCachedSdkVersion = getPropertyInteger("ro.build.version.sdk", -1);
308 }
309 #endif
310 return sCachedSdkVersion;
311 }
312
getChannelCountFromChannelMask(ChannelMask channelMask)313 int getChannelCountFromChannelMask(ChannelMask channelMask) {
314 return __builtin_popcount(static_cast<uint32_t>(channelMask));
315 }
316
317 }// namespace oboe
318