| /* |
| * Copyright 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <sstream> |
| |
| #ifdef __ANDROID__ |
| #include <sys/system_properties.h> |
| #endif |
| |
| #include <oboe/AudioStream.h> |
| #include "oboe/Definitions.h" |
| #include "oboe/Utilities.h" |
| |
| namespace oboe { |
| |
| constexpr float kScaleI16ToFloat = (1.0f / 32768.0f); |
| |
| void convertFloatToPcm16(const float *source, int16_t *destination, int32_t numSamples) { |
| for (int i = 0; i < numSamples; i++) { |
| float fval = source[i]; |
| fval += 1.0; // to avoid discontinuity at 0.0 caused by truncation |
| fval *= 32768.0f; |
| auto sample = static_cast<int32_t>(fval); |
| // clip to 16-bit range |
| if (sample < 0) sample = 0; |
| else if (sample > 0x0FFFF) sample = 0x0FFFF; |
| sample -= 32768; // center at zero |
| destination[i] = static_cast<int16_t>(sample); |
| } |
| } |
| |
| void convertPcm16ToFloat(const int16_t *source, float *destination, int32_t numSamples) { |
| for (int i = 0; i < numSamples; i++) { |
| destination[i] = source[i] * kScaleI16ToFloat; |
| } |
| } |
| |
| int32_t convertFormatToSizeInBytes(AudioFormat format) { |
| int32_t size = 0; |
| switch (format) { |
| case AudioFormat::I16: |
| size = sizeof(int16_t); |
| break; |
| case AudioFormat::Float: |
| size = sizeof(float); |
| break; |
| default: |
| break; |
| } |
| return size; |
| } |
| |
| template<> |
| const char *convertToText<Result>(Result returnCode) { |
| switch (returnCode) { |
| case Result::OK: return "OK"; |
| case Result::ErrorDisconnected: return "ErrorDisconnected"; |
| case Result::ErrorIllegalArgument: return "ErrorIllegalArgument"; |
| case Result::ErrorInternal: return "ErrorInternal"; |
| case Result::ErrorInvalidState: return "ErrorInvalidState"; |
| case Result::ErrorInvalidHandle: return "ErrorInvalidHandle"; |
| case Result::ErrorUnimplemented: return "ErrorUnimplemented"; |
| case Result::ErrorUnavailable: return "ErrorUnavailable"; |
| case Result::ErrorNoFreeHandles: return "ErrorNoFreeHandles"; |
| case Result::ErrorNoMemory: return "ErrorNoMemory"; |
| case Result::ErrorNull: return "ErrorNull"; |
| case Result::ErrorTimeout: return "ErrorTimeout"; |
| case Result::ErrorWouldBlock: return "ErrorWouldBlock"; |
| case Result::ErrorInvalidFormat: return "ErrorInvalidFormat"; |
| case Result::ErrorOutOfRange: return "ErrorOutOfRange"; |
| case Result::ErrorNoService: return "ErrorNoService"; |
| case Result::ErrorInvalidRate: return "ErrorInvalidRate"; |
| case Result::ErrorClosed: return "ErrorClosed"; |
| default: return "Unrecognized result"; |
| } |
| } |
| |
| template<> |
| const char *convertToText<AudioFormat>(AudioFormat format) { |
| switch (format) { |
| case AudioFormat::Invalid: return "Invalid"; |
| case AudioFormat::Unspecified: return "Unspecified"; |
| case AudioFormat::I16: return "I16"; |
| case AudioFormat::Float: return "Float"; |
| default: return "Unrecognized format"; |
| } |
| } |
| |
| template<> |
| const char *convertToText<PerformanceMode>(PerformanceMode mode) { |
| switch (mode) { |
| case PerformanceMode::LowLatency: return "LowLatency"; |
| case PerformanceMode::None: return "None"; |
| case PerformanceMode::PowerSaving: return "PowerSaving"; |
| default: return "Unrecognized performance mode"; |
| } |
| } |
| |
| template<> |
| const char *convertToText<SharingMode>(SharingMode mode) { |
| switch (mode) { |
| case SharingMode::Exclusive: return "Exclusive"; |
| case SharingMode::Shared: return "Shared"; |
| default: return "Unrecognized sharing mode"; |
| } |
| } |
| |
| template<> |
| const char *convertToText<DataCallbackResult>(DataCallbackResult result) { |
| switch (result) { |
| case DataCallbackResult::Continue: return "Continue"; |
| case DataCallbackResult::Stop: return "Stop"; |
| default: return "Unrecognized data callback result"; |
| } |
| } |
| |
| template<> |
| const char *convertToText<Direction>(Direction direction) { |
| switch (direction) { |
| case Direction::Input: return "Input"; |
| case Direction::Output: return "Output"; |
| default: return "Unrecognized direction"; |
| } |
| } |
| |
| template<> |
| const char *convertToText<StreamState>(StreamState state) { |
| switch (state) { |
| case StreamState::Closed: return "Closed"; |
| case StreamState::Closing: return "Closing"; |
| case StreamState::Disconnected: return "Disconnected"; |
| case StreamState::Flushed: return "Flushed"; |
| case StreamState::Flushing: return "Flushing"; |
| case StreamState::Open: return "Open"; |
| case StreamState::Paused: return "Paused"; |
| case StreamState::Pausing: return "Pausing"; |
| case StreamState::Started: return "Started"; |
| case StreamState::Starting: return "Starting"; |
| case StreamState::Stopped: return "Stopped"; |
| case StreamState::Stopping: return "Stopping"; |
| case StreamState::Uninitialized: return "Uninitialized"; |
| case StreamState::Unknown: return "Unknown"; |
| default: return "Unrecognized stream state"; |
| } |
| } |
| |
| template<> |
| const char *convertToText<AudioApi>(AudioApi audioApi) { |
| |
| switch (audioApi) { |
| case AudioApi::Unspecified: return "Unspecified"; |
| case AudioApi::OpenSLES: return "OpenSLES"; |
| case AudioApi::AAudio: return "AAudio"; |
| default: return "Unrecognized audio API"; |
| } |
| } |
| |
| template<> |
| const char *convertToText<AudioStream*>(AudioStream* stream) { |
| static std::string streamText; |
| std::stringstream s; |
| |
| s<<"StreamID: "<< static_cast<void*>(stream)<<std::endl |
| <<"DeviceId: "<<stream->getDeviceId()<<std::endl |
| <<"Direction: "<<oboe::convertToText(stream->getDirection())<<std::endl |
| <<"API type: "<<oboe::convertToText(stream->getAudioApi())<<std::endl |
| <<"BufferCapacity: "<<stream->getBufferCapacityInFrames()<<std::endl |
| <<"BufferSize: "<<stream->getBufferSizeInFrames()<<std::endl |
| <<"FramesPerBurst: "<< stream->getFramesPerBurst()<<std::endl |
| <<"FramesPerDataCallback: "<<stream->getFramesPerDataCallback()<<std::endl |
| <<"SampleRate: "<<stream->getSampleRate()<<std::endl |
| <<"ChannelCount: "<<stream->getChannelCount()<<std::endl |
| <<"Format: "<<oboe::convertToText(stream->getFormat())<<std::endl |
| <<"SharingMode: "<<oboe::convertToText(stream->getSharingMode())<<std::endl |
| <<"PerformanceMode: "<<oboe::convertToText(stream->getPerformanceMode()) |
| <<std::endl |
| <<"CurrentState: "<<oboe::convertToText(stream->getState())<<std::endl |
| <<"XRunCount: "<<stream->getXRunCount()<<std::endl |
| <<"FramesRead: "<<stream->getFramesRead()<<std::endl |
| <<"FramesWritten: "<<stream->getFramesWritten()<<std::endl; |
| |
| streamText = s.str(); |
| return streamText.c_str(); |
| } |
| |
| template<> |
| const char *convertToText<Usage>(Usage usage) { |
| |
| switch (usage) { |
| case Usage::Media: return "Media"; |
| case Usage::VoiceCommunication: return "VoiceCommunication"; |
| case Usage::VoiceCommunicationSignalling: return "VoiceCommunicationSignalling"; |
| case Usage::Alarm: return "Alarm"; |
| case Usage::Notification: return "Notification"; |
| case Usage::NotificationRingtone: return "NotificationRingtone"; |
| case Usage::NotificationEvent: return "NotificationEvent"; |
| case Usage::AssistanceAccessibility: return "AssistanceAccessibility"; |
| case Usage::AssistanceNavigationGuidance: return "AssistanceNavigationGuidance"; |
| case Usage::AssistanceSonification: return "AssistanceSonification"; |
| case Usage::Game: return "Game"; |
| case Usage::Assistant: return "Assistant"; |
| default: return "Unrecognized usage"; |
| } |
| } |
| |
| template<> |
| const char *convertToText<ContentType>(ContentType contentType) { |
| |
| switch (contentType) { |
| case ContentType::Speech: return "Speech"; |
| case ContentType::Music: return "Music"; |
| case ContentType::Movie: return "Movie"; |
| case ContentType::Sonification: return "Sonification"; |
| default: return "Unrecognized content type"; |
| } |
| } |
| |
| template<> |
| const char *convertToText<InputPreset>(InputPreset inputPreset) { |
| |
| switch (inputPreset) { |
| case InputPreset::Generic: return "Generic"; |
| case InputPreset::Camcorder: return "Camcorder"; |
| case InputPreset::VoiceRecognition: return "VoiceRecognition"; |
| case InputPreset::VoiceCommunication: return "VoiceCommunication"; |
| case InputPreset::Unprocessed: return "Unprocessed"; |
| case InputPreset::VoicePerformance: return "VoicePerformance"; |
| default: return "Unrecognized input preset"; |
| } |
| } |
| |
| template<> |
| const char *convertToText<SessionId>(SessionId sessionId) { |
| |
| switch (sessionId) { |
| case SessionId::None: return "None"; |
| case SessionId::Allocate: return "Allocate"; |
| default: return "Unrecognized session id"; |
| } |
| } |
| |
| template<> |
| const char *convertToText<ChannelCount>(ChannelCount channelCount) { |
| |
| switch (channelCount) { |
| case ChannelCount::Unspecified: return "Unspecified"; |
| case ChannelCount::Mono: return "Mono"; |
| case ChannelCount::Stereo: return "Stereo"; |
| default: return "Unrecognized channel count"; |
| } |
| } |
| |
| std::string getPropertyString(const char * name) { |
| std::string result; |
| #ifdef __ANDROID__ |
| char valueText[PROP_VALUE_MAX] = {0}; |
| if (__system_property_get(name, valueText) != 0) { |
| result = valueText; |
| } |
| #else |
| (void) name; |
| #endif |
| return result; |
| } |
| |
| int getPropertyInteger(const char * name, int defaultValue) { |
| int result = defaultValue; |
| #ifdef __ANDROID__ |
| char valueText[PROP_VALUE_MAX] = {0}; |
| if (__system_property_get(name, valueText) != 0) { |
| result = atoi(valueText); |
| } |
| #else |
| (void) name; |
| #endif |
| return result; |
| } |
| |
| int getSdkVersion() { |
| static int sCachedSdkVersion = -1; |
| #ifdef __ANDROID__ |
| if (sCachedSdkVersion == -1) { |
| sCachedSdkVersion = getPropertyInteger("ro.build.version.sdk", -1); |
| } |
| #endif |
| return sCachedSdkVersion; |
| } |
| |
| }// namespace oboe |