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 default:
64 break;
65 }
66 return size;
67 }
68
69 template<>
convertToText(Result returnCode)70 const char *convertToText<Result>(Result returnCode) {
71 switch (returnCode) {
72 case Result::OK: return "OK";
73 case Result::ErrorDisconnected: return "ErrorDisconnected";
74 case Result::ErrorIllegalArgument: return "ErrorIllegalArgument";
75 case Result::ErrorInternal: return "ErrorInternal";
76 case Result::ErrorInvalidState: return "ErrorInvalidState";
77 case Result::ErrorInvalidHandle: return "ErrorInvalidHandle";
78 case Result::ErrorUnimplemented: return "ErrorUnimplemented";
79 case Result::ErrorUnavailable: return "ErrorUnavailable";
80 case Result::ErrorNoFreeHandles: return "ErrorNoFreeHandles";
81 case Result::ErrorNoMemory: return "ErrorNoMemory";
82 case Result::ErrorNull: return "ErrorNull";
83 case Result::ErrorTimeout: return "ErrorTimeout";
84 case Result::ErrorWouldBlock: return "ErrorWouldBlock";
85 case Result::ErrorInvalidFormat: return "ErrorInvalidFormat";
86 case Result::ErrorOutOfRange: return "ErrorOutOfRange";
87 case Result::ErrorNoService: return "ErrorNoService";
88 case Result::ErrorInvalidRate: return "ErrorInvalidRate";
89 case Result::ErrorClosed: return "ErrorClosed";
90 default: return "Unrecognized result";
91 }
92 }
93
94 template<>
convertToText(AudioFormat format)95 const char *convertToText<AudioFormat>(AudioFormat format) {
96 switch (format) {
97 case AudioFormat::Invalid: return "Invalid";
98 case AudioFormat::Unspecified: return "Unspecified";
99 case AudioFormat::I16: return "I16";
100 case AudioFormat::Float: return "Float";
101 default: return "Unrecognized format";
102 }
103 }
104
105 template<>
convertToText(PerformanceMode mode)106 const char *convertToText<PerformanceMode>(PerformanceMode mode) {
107 switch (mode) {
108 case PerformanceMode::LowLatency: return "LowLatency";
109 case PerformanceMode::None: return "None";
110 case PerformanceMode::PowerSaving: return "PowerSaving";
111 default: return "Unrecognized performance mode";
112 }
113 }
114
115 template<>
convertToText(SharingMode mode)116 const char *convertToText<SharingMode>(SharingMode mode) {
117 switch (mode) {
118 case SharingMode::Exclusive: return "Exclusive";
119 case SharingMode::Shared: return "Shared";
120 default: return "Unrecognized sharing mode";
121 }
122 }
123
124 template<>
convertToText(DataCallbackResult result)125 const char *convertToText<DataCallbackResult>(DataCallbackResult result) {
126 switch (result) {
127 case DataCallbackResult::Continue: return "Continue";
128 case DataCallbackResult::Stop: return "Stop";
129 default: return "Unrecognized data callback result";
130 }
131 }
132
133 template<>
convertToText(Direction direction)134 const char *convertToText<Direction>(Direction direction) {
135 switch (direction) {
136 case Direction::Input: return "Input";
137 case Direction::Output: return "Output";
138 default: return "Unrecognized direction";
139 }
140 }
141
142 template<>
convertToText(StreamState state)143 const char *convertToText<StreamState>(StreamState state) {
144 switch (state) {
145 case StreamState::Closed: return "Closed";
146 case StreamState::Closing: return "Closing";
147 case StreamState::Disconnected: return "Disconnected";
148 case StreamState::Flushed: return "Flushed";
149 case StreamState::Flushing: return "Flushing";
150 case StreamState::Open: return "Open";
151 case StreamState::Paused: return "Paused";
152 case StreamState::Pausing: return "Pausing";
153 case StreamState::Started: return "Started";
154 case StreamState::Starting: return "Starting";
155 case StreamState::Stopped: return "Stopped";
156 case StreamState::Stopping: return "Stopping";
157 case StreamState::Uninitialized: return "Uninitialized";
158 case StreamState::Unknown: return "Unknown";
159 default: return "Unrecognized stream state";
160 }
161 }
162
163 template<>
convertToText(AudioApi audioApi)164 const char *convertToText<AudioApi>(AudioApi audioApi) {
165
166 switch (audioApi) {
167 case AudioApi::Unspecified: return "Unspecified";
168 case AudioApi::OpenSLES: return "OpenSLES";
169 case AudioApi::AAudio: return "AAudio";
170 default: return "Unrecognized audio API";
171 }
172 }
173
174 template<>
convertToText(AudioStream * stream)175 const char *convertToText<AudioStream*>(AudioStream* stream) {
176 static std::string streamText;
177 std::stringstream s;
178
179 s<<"StreamID: "<< static_cast<void*>(stream)<<std::endl
180 <<"DeviceId: "<<stream->getDeviceId()<<std::endl
181 <<"Direction: "<<oboe::convertToText(stream->getDirection())<<std::endl
182 <<"API type: "<<oboe::convertToText(stream->getAudioApi())<<std::endl
183 <<"BufferCapacity: "<<stream->getBufferCapacityInFrames()<<std::endl
184 <<"BufferSize: "<<stream->getBufferSizeInFrames()<<std::endl
185 <<"FramesPerBurst: "<< stream->getFramesPerBurst()<<std::endl
186 <<"FramesPerDataCallback: "<<stream->getFramesPerDataCallback()<<std::endl
187 <<"SampleRate: "<<stream->getSampleRate()<<std::endl
188 <<"ChannelCount: "<<stream->getChannelCount()<<std::endl
189 <<"Format: "<<oboe::convertToText(stream->getFormat())<<std::endl
190 <<"SharingMode: "<<oboe::convertToText(stream->getSharingMode())<<std::endl
191 <<"PerformanceMode: "<<oboe::convertToText(stream->getPerformanceMode())
192 <<std::endl
193 <<"CurrentState: "<<oboe::convertToText(stream->getState())<<std::endl
194 <<"XRunCount: "<<stream->getXRunCount()<<std::endl
195 <<"FramesRead: "<<stream->getFramesRead()<<std::endl
196 <<"FramesWritten: "<<stream->getFramesWritten()<<std::endl;
197
198 streamText = s.str();
199 return streamText.c_str();
200 }
201
202 template<>
convertToText(Usage usage)203 const char *convertToText<Usage>(Usage usage) {
204
205 switch (usage) {
206 case Usage::Media: return "Media";
207 case Usage::VoiceCommunication: return "VoiceCommunication";
208 case Usage::VoiceCommunicationSignalling: return "VoiceCommunicationSignalling";
209 case Usage::Alarm: return "Alarm";
210 case Usage::Notification: return "Notification";
211 case Usage::NotificationRingtone: return "NotificationRingtone";
212 case Usage::NotificationEvent: return "NotificationEvent";
213 case Usage::AssistanceAccessibility: return "AssistanceAccessibility";
214 case Usage::AssistanceNavigationGuidance: return "AssistanceNavigationGuidance";
215 case Usage::AssistanceSonification: return "AssistanceSonification";
216 case Usage::Game: return "Game";
217 case Usage::Assistant: return "Assistant";
218 default: return "Unrecognized usage";
219 }
220 }
221
222 template<>
convertToText(ContentType contentType)223 const char *convertToText<ContentType>(ContentType contentType) {
224
225 switch (contentType) {
226 case ContentType::Speech: return "Speech";
227 case ContentType::Music: return "Music";
228 case ContentType::Movie: return "Movie";
229 case ContentType::Sonification: return "Sonification";
230 default: return "Unrecognized content type";
231 }
232 }
233
234 template<>
convertToText(InputPreset inputPreset)235 const char *convertToText<InputPreset>(InputPreset inputPreset) {
236
237 switch (inputPreset) {
238 case InputPreset::Generic: return "Generic";
239 case InputPreset::Camcorder: return "Camcorder";
240 case InputPreset::VoiceRecognition: return "VoiceRecognition";
241 case InputPreset::VoiceCommunication: return "VoiceCommunication";
242 case InputPreset::Unprocessed: return "Unprocessed";
243 case InputPreset::VoicePerformance: return "VoicePerformance";
244 default: return "Unrecognized input preset";
245 }
246 }
247
248 template<>
convertToText(SessionId sessionId)249 const char *convertToText<SessionId>(SessionId sessionId) {
250
251 switch (sessionId) {
252 case SessionId::None: return "None";
253 case SessionId::Allocate: return "Allocate";
254 default: return "Unrecognized session id";
255 }
256 }
257
258 template<>
convertToText(ChannelCount channelCount)259 const char *convertToText<ChannelCount>(ChannelCount channelCount) {
260
261 switch (channelCount) {
262 case ChannelCount::Unspecified: return "Unspecified";
263 case ChannelCount::Mono: return "Mono";
264 case ChannelCount::Stereo: return "Stereo";
265 default: return "Unrecognized channel count";
266 }
267 }
268
getPropertyString(const char * name)269 std::string getPropertyString(const char * name) {
270 std::string result;
271 #ifdef __ANDROID__
272 char valueText[PROP_VALUE_MAX] = {0};
273 if (__system_property_get(name, valueText) != 0) {
274 result = valueText;
275 }
276 #else
277 (void) name;
278 #endif
279 return result;
280 }
281
getPropertyInteger(const char * name,int defaultValue)282 int getPropertyInteger(const char * name, int defaultValue) {
283 int result = defaultValue;
284 #ifdef __ANDROID__
285 char valueText[PROP_VALUE_MAX] = {0};
286 if (__system_property_get(name, valueText) != 0) {
287 result = atoi(valueText);
288 }
289 #else
290 (void) name;
291 #endif
292 return result;
293 }
294
getSdkVersion()295 int getSdkVersion() {
296 static int sCachedSdkVersion = -1;
297 #ifdef __ANDROID__
298 if (sCachedSdkVersion == -1) {
299 sCachedSdkVersion = getPropertyInteger("ro.build.version.sdk", -1);
300 }
301 #endif
302 return sCachedSdkVersion;
303 }
304
305 }// namespace oboe
306