From b6cc2e110bd16aed555b42ba71734a1ad977536f Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Mon, 2 Oct 2023 10:23:24 +0200 Subject: [PATCH 01/26] added .idea to gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index bd63e09b0..1adfe452d 100644 --- a/.gitignore +++ b/.gitignore @@ -57,4 +57,7 @@ CMakeSettings.json # VSCode .vscode* +# idea +.idea* + # Common build directories of users and VSCode From 2217003caa9556591d96e5a79879da51711e62b7 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Mon, 2 Oct 2023 10:45:24 +0200 Subject: [PATCH 02/26] restored workflows directory --- .github/workflows/MSBuild.yml | 96 ++++++++++++++++++ .github/workflows/autotools.yml | 20 ++++ .github/workflows/cmake.yml | 128 ++++++++++++++++++++++++ .github/workflows/compare_def_files.yml | 17 ++++ .github/workflows/whitelint.yml | 17 ++++ 5 files changed, 278 insertions(+) create mode 100644 .github/workflows/MSBuild.yml create mode 100644 .github/workflows/autotools.yml create mode 100644 .github/workflows/cmake.yml create mode 100644 .github/workflows/compare_def_files.yml create mode 100644 .github/workflows/whitelint.yml diff --git a/.github/workflows/MSBuild.yml b/.github/workflows/MSBuild.yml new file mode 100644 index 000000000..ea90dba46 --- /dev/null +++ b/.github/workflows/MSBuild.yml @@ -0,0 +1,96 @@ +name: MSBuild MSVC Project File CI + +on: [push, pull_request] + +env: + # Path to the solution file relative to the root of the project. + SOLUTION_FILE_PATH: ./msvc/portaudio.sln + VCPROJ_FILE_PATH: ./msvc/portaudio.vcproj + VCXPROJ_FILE_PATH: ./msvc/portaudio.vcxproj + VCXPROJ_FILTERS_FILE_PATH: ./msvc/portaudio.vcxproj.filters + VCXPROJ_USER_FILE_PATH: ./msvc/portaudio.vcxproj.user + DEF_FILE_PATH: ./msvc/portaudio.def + +jobs: + build: + runs-on: windows-latest + strategy: + matrix: + BUILD_CONFIGURATION: [Release] + BUILD_PLATFORM: [Win32, x64] + + steps: + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v1 + + - uses: actions/checkout@v2 + + - name: Upgrade VC Project File + # We maintain our vcproj file in an old format to maintain backwards compatibility + # This step upgrades the project to the latest version of MSVC + # see https://docs.microsoft.com/en-us/visualstudio/ide/reference/upgrade-devenv-exe?view=vs-2019 + # pipe to file to ensure that it terminates https://stackoverflow.com/questions/48896010/occasionally-occurring-msbuild-error-msb3428/48918105#48918105 + # discussion of using vswhere.exe here: https://stackoverflow.com/questions/65287456/how-to-upgrade-a-visual-studio-project-from-within-a-github-action/65311868#65311868 + run: | + $devenv = & vswhere.exe '-property' productPath + Write-Output "$devenv" + & $devenv "${{env.VCPROJ_FILE_PATH}}" /Upgrade /NoSplash | Out-Null + Write-Output "devenv launched" + while (!(Test-Path "${{env.VCXPROJ_FILE_PATH}}")) { Start-Sleep -Seconds 10 } + Write-Output "vcxproj found" + while (!(Test-Path "${{env.VCXPROJ_FILTERS_FILE_PATH}}")) { Start-Sleep -Seconds 10 } + Write-Output "vcxproj.filters found" + Start-Sleep -Seconds 10 + Write-Output "done." + + - name: Remove ASIO Files and Enable PA_USE_DS=1 + # Process the project files to remove ASIO-related sources and includes (since we can not access the ASIO SDK in a public build) + run: | + # Process .vcxproj file: remove source files + $xdoc = new-object System.Xml.XmlDocument + $vcxprojFile = resolve-path("${{env.VCXPROJ_FILE_PATH}}") + $xdoc.load($vcxprojFile) + $namespace = New-Object -TypeName "Xml.XmlNamespaceManager" -ArgumentList $xdoc.NameTable + $namespace.AddNamespace("vs", $xdoc.DocumentElement.NamespaceURI) + $nodes = $xdoc.SelectNodes("//vs:ClCompile[contains(@Include, '..\src\hostapi\asio')]", $namespace) + Write-Output "deleting ASIO related compilation nodes from .vcxproj:" + Write-Output $nodes + ForEach($node in $nodes) { + $parent = $node.ParentNode + $parent.RemoveChild($node) + } + # Enable DirectSound host API + $nodes = $xdoc.SelectNodes("//vs:PreprocessorDefinitions[contains(., 'PA_USE_DS=0')]", $namespace) + ForEach($node in $nodes) { + $text = $node.InnerText + $node.InnerText = $text -replace 'PA_USE_DS=0', 'PA_USE_DS=1' + } + $xdoc.save($vcxprojFile) + # Process .vcxproj.filters file: remove source files and includes + $vcxprojFiltersFile = resolve-path("${{env.VCXPROJ_FILTERS_FILE_PATH}}") + $xdoc.load($vcxprojFiltersFile) + $namespace = New-Object -TypeName "Xml.XmlNamespaceManager" -ArgumentList $xdoc.NameTable + $namespace.AddNamespace("vs", $xdoc.DocumentElement.NamespaceURI) + $nodes = $xdoc.SelectNodes("//vs:ClCompile[contains(@Include, '..\src\hostapi\asio')]", $namespace) + Write-Output "deleting ASIO related compilation nodes from .vcxproj.filters:" + Write-Output $nodes + ForEach($node in $nodes) { + $parent = $node.ParentNode + $parent.RemoveChild($node) + } + $nodes = $xdoc.SelectNodes("//vs:ClInclude[contains(@Include, 'pa_asio.h')]", $namespace) + Write-Output "deleting ASIO related include nodes from .vcxproj.filters:" + Write-Output $nodes + ForEach($node in $nodes) { + $parent = $node.ParentNode + $parent.RemoveChild($node) + } + $xdoc.save($vcxprojFiltersFile) + # Process .def file: remove PaAsio_ symbols + Set-Content -Path "${{env.DEF_FILE_PATH}}" -Value (Get-Content -Path "${{env.DEF_FILE_PATH}}" | Select-String -Pattern 'PaAsio_' -NotMatch) + + - name: Build + working-directory: ${{env.GITHUB_WORKSPACE}} + # Add additional options to the MSBuild command line here (like platform or verbosity level). + # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference + run: msbuild /m /p:Configuration=${{matrix.BUILD_CONFIGURATION}} /p:Platform=${{matrix.BUILD_PLATFORM}} ${{env.VCXPROJ_FILE_PATH}} diff --git a/.github/workflows/autotools.yml b/.github/workflows/autotools.yml new file mode 100644 index 000000000..4d6fb6cb9 --- /dev/null +++ b/.github/workflows/autotools.yml @@ -0,0 +1,20 @@ +name: autotools build + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build-autotools: + + runs-on: ubuntu-latest + name: Ubuntu + + steps: + - uses: actions/checkout@v2 + - name: configure + run: ./configure + - name: make + run: make diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml new file mode 100644 index 000000000..a25eaabf7 --- /dev/null +++ b/.github/workflows/cmake.yml @@ -0,0 +1,128 @@ +name: CMake build + +on: [push, pull_request] + +jobs: + build: + strategy: + fail-fast: false + matrix: + include: + - name: Ubuntu GCC + os: ubuntu-latest + install_dir: ~/portaudio + vcpkg_triplet: x64-linux + cmake_generator: "Unix Makefiles" + cmake_options: + -DPA_USE_OSS=ON + -DCMAKE_TOOLCHAIN_FILE=vcpkg/scripts/buildsystems/vcpkg.cmake + - name: Ubuntu MinGW + os: ubuntu-latest + install_dir: ~/portaudio + asio_sdk_cache_path: asiosdk.zip + dependencies_extras: mingw-w64 + # FIXME: linking JACK fails with vcpkg. Switch the CMake toolchain file to use vcpkg. The + # toolchain file in this repository is not needed when using a MinGW triplet with vcpkg. + vcpkg_triplet: x64-mingw-static + cmake_generator: "Unix Makefiles" + cmake_options: + -DPA_USE_ASIO=ON + -DASIO_SDK_ZIP_PATH=asiosdk.zip + -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/i686-w64-mingw32.cmake + - name: Windows MSVC + os: windows-latest + install_dir: C:\portaudio + vcpkg_triplet: x64-windows + cmake_generator: "Visual Studio 17 2022" + # ASIO_SDK_ZIP_PATH needs to be quoted or CMake will save the download to + # asiosdk instead of asiosdk.zip. + asio_sdk_cache_path: "asiosdk.zip" + # Somehow CMake fails to find the toolchain file if a relative path is used on Windows. + cmake_options: + -DPA_USE_ASIO=ON + -DASIO_SDK_ZIP_PATH="asiosdk.zip" + -DCMAKE_TOOLCHAIN_FILE=D:\a\portaudio\portaudio\vcpkg\scripts\buildsystems\vcpkg.cmake + - name: Windows MinGW + os: windows-latest + install_dir: C:\portaudio + vcpkg_triplet: x64-mingw-static + cmake_generator: "MinGW Makefiles" + # ASIO_SDK_ZIP_PATH needs to be quoted or CMake will save the download to + # asiosdk instead of asiosdk.zip. + asio_sdk_cache_path: "asiosdk.zip" + # Somehow CMake fails to find the toolchain file if a relative path is used on Windows. + cmake_options: + -DPA_USE_ASIO=ON + -DASIO_SDK_ZIP_PATH="asiosdk.zip" + -DCMAKE_TOOLCHAIN_FILE=D:\a\portaudio\portaudio\vcpkg\scripts\buildsystems\vcpkg.cmake + - name: macOS Clang + os: macOS-latest + install_dir: ~/portaudio + vcpkg_triplet: x64-osx + cmake_generator: "Unix Makefiles" + cmake_options: + -DCMAKE_FRAMEWORK=OFF + -DCMAKE_TOOLCHAIN_FILE=vcpkg/scripts/buildsystems/vcpkg.cmake + - name: macOS Clang framework + os: macOS-latest + install_dir: ~/portaudio + vcpkg_triplet: x64-osx + cmake_generator: "Unix Makefiles" + cmake_options: + -DCMAKE_FRAMEWORK=ON + -DCMAKE_TOOLCHAIN_FILE=vcpkg/scripts/buildsystems/vcpkg.cmake + + runs-on: ${{ matrix.os }} + name: ${{ matrix.name }} + env: + cmake_build_type: RelWithDebInfo + steps: + - name: checkout Git repository + uses: actions/checkout@v2 + - name: "[Ubuntu] install dependencies" + run: | + sudo apt-get update + sudo apt-get install libasound2-dev ${{ matrix.dependencies_extras }} + if: matrix.os == 'ubuntu-latest' + - name: "[macOS] install dependencies" + # https://github.com/PortAudio/portaudio/issues/767 + run: brew install pkg-config + if: matrix.os == 'macOS-latest' + - name: "[Windows/MinGW] set up ASIO SDK cache" + uses: actions/cache@v2 + if: matrix.asio_sdk_cache_path != null + with: + path: ${{ matrix.asio_sdk_cache_path }} + key: ${{ hashFiles('.github/asiosdk-version.txt') }} + - name: Setup vcpkg + uses: lukka/run-vcpkg@v7 + if: ${{ matrix.vcpkg_triplet }} != null + with: + vcpkgTriplet: ${{ matrix.vcpkg_triplet }} + appendedCacheKey: ${{ hashFiles( '**/vcpkg.json' ) }} + additionalCachedPaths: build/vcpkg_installed + vcpkgGitCommitId: f30786c9c4c901f21a13e2d524349e39cc359a90 + # Required when using vcpkg.json manifest in repository + setupOnly: true + - name: configure + run: cmake + -G "${{ matrix.cmake_generator }}" + ${{ matrix.cmake_options }} + -DCMAKE_INSTALL_PREFIX=${{ matrix.install_dir }} + -DCMAKE_BUILD_TYPE=${{ env.cmake_build_type }} + -DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_triplet }} + -DPA_USE_SKELETON=ON + -DPA_BUILD_TESTS=ON + -DPA_BUILD_EXAMPLES=ON + -DPA_WARNINGS_ARE_ERRORS=ON + -S . + -B build + - name: build + run: cmake --build build --config ${{ env.cmake_build_type }} --parallel 2 + - name: install + run: cmake --install build --config ${{ env.cmake_build_type }} + - name: "Upload GitHub Actions artifacts" + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.name }} PortAudio build + path: ${{ matrix.install_dir }} diff --git a/.github/workflows/compare_def_files.yml b/.github/workflows/compare_def_files.yml new file mode 100644 index 000000000..b2b342411 --- /dev/null +++ b/.github/workflows/compare_def_files.yml @@ -0,0 +1,17 @@ +name: Check that PortAudio .def files are in sync + +on: [push, pull_request] + +jobs: + run-pa-compare-def-files-py: + + runs-on: ubuntu-latest + name: Ubuntu + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.x' + - name: Run the pa_compare_def_files.py script + run: python ./pa_compare_def_files.py diff --git a/.github/workflows/whitelint.yml b/.github/workflows/whitelint.yml new file mode 100644 index 000000000..41cf8ff8b --- /dev/null +++ b/.github/workflows/whitelint.yml @@ -0,0 +1,17 @@ +name: Check for valid whitespace usage in PortAudio source files + +on: [push, pull_request] + +jobs: + run-pa-whitelint-dot-py: + + runs-on: ubuntu-latest + name: Ubuntu + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.x' + - name: Run the pa_whitelint.py script + run: python ./pa_whitelint.py From b9e7f419a90f6d39c3743e62bcbb07d138481e0f Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Mon, 2 Oct 2023 11:41:36 +0200 Subject: [PATCH 03/26] Minor fixes to FindOboe.cmake --- cmake/modules/FindOboe.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/modules/FindOboe.cmake b/cmake/modules/FindOboe.cmake index 23fd02308..9e27ee01e 100644 --- a/cmake/modules/FindOboe.cmake +++ b/cmake/modules/FindOboe.cmake @@ -22,7 +22,8 @@ endif() if(NOT OBOE_DIRECTORY) message(AUTHOR_WARNING - "If you're trying to use Oboe as a Host API, please specify the directory where you cloned its repository. For further information, please read src/hostapi/oboe/README.md" + "If you're trying to use Oboe as a Host API, please specify the directory where you + cloned its repository. For further information, please read src/hostapi/oboe/README.md" ) set(OBOE_FOUND FALSE) else() @@ -53,8 +54,7 @@ else() find_library(LOG_LIBRARY log) #used by pa_oboe.cpp and pa_oboe.h as a logging tool set(OBOE_LINK_LIBRARIES ${OBOE_LIBRARIES} ${LOG_LIBRARY}) - - + include(FindPackageHandleStandardArgs) find_package_handle_standard_args( Oboe @@ -71,4 +71,4 @@ else() target_include_directories(Oboe::oboe INTERFACE "${OBOE_INCLUDE_DIR}") endif() endif() -endif() \ No newline at end of file +endif() From 42a02b4f42b43bb76c1bffb3d3f81af44e12b8ef Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Mon, 2 Oct 2023 11:52:36 +0200 Subject: [PATCH 04/26] Enhanced prebuilt libraries compatibility in FindOboe.cmake --- cmake/modules/FindOboe.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/modules/FindOboe.cmake b/cmake/modules/FindOboe.cmake index 9e27ee01e..ea66ec394 100644 --- a/cmake/modules/FindOboe.cmake +++ b/cmake/modules/FindOboe.cmake @@ -31,10 +31,10 @@ else() set(OBOE_INCLUDE_DIR ${OBOE_DIRECTORY}/include) endif() - if(NOT DEFINED OBOE_LIBRARIES) + if(NOT DEFINED OBOE_LIBRARY_DIRS) set(OBOE_LIBRARY_DIRS ${OBOE_DIRECTORY}/build/${ANDROID_ABI}) - set(OBOE_LIBRARIES ${OBOE_LIBRARY_DIRS}/liboboe.so) endif() + set(OBOE_LIBRARIES ${OBOE_LIBRARY_DIRS}/liboboe.so) find_package(PkgConfig QUIET) if(PkgConfig_FOUND) @@ -54,7 +54,7 @@ else() find_library(LOG_LIBRARY log) #used by pa_oboe.cpp and pa_oboe.h as a logging tool set(OBOE_LINK_LIBRARIES ${OBOE_LIBRARIES} ${LOG_LIBRARY}) - + include(FindPackageHandleStandardArgs) find_package_handle_standard_args( Oboe From 26b11aa8f7dd885067c67977e1beead245a8d2a6 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Mon, 2 Oct 2023 11:53:50 +0200 Subject: [PATCH 05/26] Minor changes to Pa_Oboe/Readme and pa_oboe.cpp --- src/hostapi/oboe/README.md | 7 +++---- src/hostapi/oboe/pa_oboe.cpp | 12 +++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/hostapi/oboe/README.md b/src/hostapi/oboe/README.md index db64c90bc..c4de74088 100644 --- a/src/hostapi/oboe/README.md +++ b/src/hostapi/oboe/README.md @@ -8,13 +8,12 @@ Building: To build portaudio with Oboe, there are some necessary steps: 1) An android NDK is needed to crosscompile it. I used the version 25.1.8937393, which I found at https://developer.android.com/ndk/downloads. 2) Clone the Oboe repository - just follow the steps detailed here: https://github.com/google/oboe/blob/main/docs/GettingStarted.md. - Make sure to correctly link the NDK path in the Oboe build. If you instead prefer to use the prebuilt libraries, you can just clone the include directory. + Make sure to correctly link the NDK path in the Oboe build. If you instead prefer to use the prebuilt libraries, you can skip this step. 3) Set the CMake variable OBOE_DIRECTORY (used in cmake/modules/FindOboe.cmake) to the path of the cloned Oboe repository, and build the Oboe libraries (you can use "build_all_android.sh"). If you instead used the prebuilt libraries, do the following: - set OBOE_DIRECTORY to TRUE; - - set OBOE_INCLUDE_DIR to the include directory you cloned in step 2; - - set OBOE_LIBRARIES to path_to_Oboe_libraries_folder/${ANDROID_ABI}/your_path_to_prebuilt_libraries_of_the_chosen_ABI; + - set OBOE_LIBRARY_DIRS path_to_Oboe_libraries_folder/${ANDROID_ABI}), the code will search the prebuilt library of the chosen ABI in that folder. 4) Build PaOboe (you can use "build_all_PaOboe.sh"). 5) Don't forget to add liboboe.so and libportaudio.so in your jniLibs folder. @@ -31,4 +30,4 @@ I'm positive that automatic format selection is possible, but simply using PaUt ### Buffer sizes: -Portaudio often tries to get approximately low buffer sizes, and if you need specific sizes for your buffer you should manually modify it (or make a simple function that can set it). For your convenience, there is a *FIXME* as a bookmark. \ No newline at end of file +Portaudio often tries to get approximately low buffer sizes, and if you need specific sizes for your buffer you should manually modify it (or make a simple function that can set it). For your convenience, there is a *FIXME* as a bookmark. \ No newline at end of file diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index c96fdbc5f..5878ca25e 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -1337,9 +1337,9 @@ static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *hostApi, m_androidOutputUsage != Usage::NotificationRingtone && m_androidOutputUsage != Usage::VoiceCommunication && m_androidOutputUsage != Usage::VoiceCommunicationSignalling && - m_androidOutputUsage != Usage::Alarm - // See if more are needed. - ) { + m_androidOutputUsage != Usage::Alarm && + m_androidOutputUsage != Usage::Game + ) { m_outcome = paIncompatibleHostApiSpecificStreamInfo; return m_outcome; } @@ -1442,6 +1442,8 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *hostApi, PaSampleFormat m_inputSampleFormat, m_outputSampleFormat; PaSampleFormat m_hostInputSampleFormat, m_hostOutputSampleFormat; + + //FIXME: add a function that lets the user choose usage and preset Usage m_androidOutputUsage = Usage::VoiceCommunication; InputPreset m_androidInputPreset = InputPreset::Generic; @@ -1476,8 +1478,8 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *hostApi, m_androidInputPreset != InputPreset::Camcorder && m_androidInputPreset != InputPreset::VoiceRecognition && m_androidInputPreset != InputPreset::VoiceCommunication - // Should I add compatibility with VoicePerformance? - ) + m_androidInputPreset != InputPreset::VoicePerformance + ) return paIncompatibleHostApiSpecificStreamInfo; } /* FIXME: Replace "paInt16" with whatever format you prefer - From 8265a71f1a77350c33506429666eaee3047261ab Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Mon, 2 Oct 2023 12:09:14 +0200 Subject: [PATCH 06/26] Removed auto latency tuning in favor of simpler impleentation in pa_oboe.cpp --- src/hostapi/oboe/pa_oboe.cpp | 74 ++---------------------------------- 1 file changed, 3 insertions(+), 71 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index 5878ca25e..fd763bd40 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -161,10 +161,9 @@ using namespace oboe; //Useful global variables int32_t g_inputDeviceId = kUnspecified; int32_t g_outputDeviceId = kUnspecified; -PerformanceMode g_inputPerfMode = PerformanceMode::None; -bool g_inputPerfModeUser = false; -PerformanceMode g_outputPerfMode = PerformanceMode::None; -bool g_outputPerfModeUser = false; + +PerformanceMode g_inputPerfMode = PerformanceMode::LowLatency; +PerformanceMode g_outputPerfMode = PerformanceMode::LowLatency; /** * Stream structure, useful to store relevant information. It's needed by Portaudio. @@ -254,10 +253,6 @@ class OboeEngine : public AudioStreamCallback { //device selection implementation int32_t getSelectedDevice(oboe::Direction direction); - - //auto performance mode selection - void performanceModeAutoSelection(Direction direction); - double assertLatency(Direction direction); }; @@ -320,8 +315,6 @@ bool OboeEngine::tryStream(Direction direction, int32_t sampleRate, int32_t chan return m_outcome; } - performanceModeAutoSelection(direction); - if (sampleRate != kUnspecified) { m_outcome = (sampleRate == m_builder.getSampleRate()); if(!m_outcome) { @@ -880,65 +873,6 @@ int32_t OboeEngine::getSelectedDevice(Direction direction) { } -/** - * \brief Function used to automatically select the performance mode, based on the latency value LOW_LATENCY_MS, if no - * choice was made via PaOboe_SetPerformanceMode. It uses OboeEngine::assertLatency to make this decision. - * @param direction the Oboe::Direction of the stream we want to select the mode of. - */ -void OboeEngine::performanceModeAutoSelection(Direction direction){ - double m_result = assertLatency(direction); - - if(direction == Direction::Input) { - if (m_result >= 0 && !g_inputPerfModeUser) { - if (m_result <= LOW_LATENCY_MS) - g_inputPerfMode = PerformanceMode::LowLatency; - else - g_inputPerfMode = PerformanceMode::PowerSaving; - } - } else { - if (m_result >= 0 && !g_outputPerfModeUser) { - if (m_result <= LOW_LATENCY_MS) - g_outputPerfMode = PerformanceMode::LowLatency; - else - g_outputPerfMode = PerformanceMode::PowerSaving; - } - } -} - - -/** - * \brief Asserts if the device supports latency tutning, then calculates the latency of an AudioStream. - * @param direction the direction of the AudioStream we want to check. - * @return the measured latency, or -1.0 if any error occurs. - */ -double OboeEngine::assertLatency(Direction direction){ - if(__ANDROID_API__<31) { - LOGI("[OboeEngine::assertLatency]\t Latency Tuning is not supported for Android API level < 31"); - return -1.0; - } - if(direction == Direction::Input){ - ResultWithValue m_result = inputStream->calculateLatencyMillis(); - if (m_result) { - return m_result.value(); - } else { - LOGE("[OboeEngine::assertLatency]\t Error calculating input latency: %s", - oboe::convertToText(m_result.error())); - return -1.0; - } - } else { - ResultWithValue m_result = outputStream->calculateLatencyMillis(); - if (m_result) { - return m_result.value(); - } else { - LOGE("[OboeEngine::assertLatency]\t Error calculating output latency: %s", - oboe::convertToText(m_result.error())); - return -1.0; - } - } - -} - - /*----------------------------- PaSkeleton functions implementations -----------------------------*/ /** @@ -1957,10 +1891,8 @@ void PaOboe_SetSelectedDevice(Direction direction, int32_t deviceID) { void PaOboe_SetPerformanceMode(oboe::Direction direction, oboe::PerformanceMode performanceMode){ if(direction == Direction::Input) { g_inputPerfMode = performanceMode; - g_inputPerfModeUser = true; } else { g_outputPerfMode = performanceMode; - g_outputPerfModeUser = true; } } From e19c30d6d5382d5dff2cffd802d4e8433dbc6840 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Mon, 2 Oct 2023 12:35:46 +0200 Subject: [PATCH 07/26] Set paFloat32 as default format in pa_oboe.cpp --- src/hostapi/oboe/pa_oboe.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index fd763bd40..1f9b63e99 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -299,14 +299,14 @@ bool OboeEngine::tryStream(Direction direction, int32_t sampleRate, int32_t chan m_builder.setDeviceId(getSelectedDevice(direction)) // Arbitrary format usually broadly supported. Later, we'll open streams with correct formats. - ->setFormat(AudioFormat::I16) + ->setFormat(AudioFormat::Float) ->setDirection(direction) ->setSampleRate(sampleRate) ->setChannelCount(channelCount); if (direction == Direction::Input) { - m_result = m_builder.openStream(inputStream); + m_result = m_builder->openStream(inputStream); } else { - m_result = m_builder.openStream(outputStream); + m_result = m_builder->openStream(outputStream); } if (m_result != Result::OK) { @@ -1225,8 +1225,8 @@ static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *hostApi, m_androidRecordingPreset != InputPreset::Camcorder && m_androidRecordingPreset != InputPreset::VoiceRecognition && m_androidRecordingPreset != InputPreset::VoiceCommunication - // Should I add compatibility with VoicePerformance? - ) { + m_androidRecordingPreset != InputPreset::VoicePerformance + ) { m_outcome = paIncompatibleHostApiSpecificStreamInfo; return m_outcome; } @@ -1416,14 +1416,14 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *hostApi, ) return paIncompatibleHostApiSpecificStreamInfo; } - /* FIXME: Replace "paInt16" with whatever format you prefer - + /* FIXME: Replace "paFloat32" with whatever format you prefer - * PaUtil_SelectClosestAvailableFormat is a bit faulty when working with multiple options */ m_hostInputSampleFormat = PaUtil_SelectClosestAvailableFormat( - paInt16, m_inputSampleFormat); + paFloat32, m_inputSampleFormat); m_oboeStream->inputFormat = m_hostInputSampleFormat; } else { m_inputChannelCount = 0; - m_inputSampleFormat = m_hostInputSampleFormat = paInt16; /* Surpress 'uninitialised var' warnings. */ + m_inputSampleFormat = m_hostInputSampleFormat = paFloat32; /* Surpress 'uninitialised var' warnings. */ m_oboeStream->inputFormat = m_hostInputSampleFormat; } @@ -1456,15 +1456,15 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *hostApi, ) return paIncompatibleHostApiSpecificStreamInfo; } - /* FIXME: Replace "paInt16" with whatever format you prefer - + /* FIXME: Replace "paFloat32" with whatever format you prefer - PaUtil_SelectClosestAvailableFormat is a bit faulty when working with multiple options */ m_hostOutputSampleFormat = PaUtil_SelectClosestAvailableFormat( - paInt16, m_outputSampleFormat); + paFloat32, m_outputSampleFormat); m_oboeStream->outputFormat = m_hostOutputSampleFormat; } else { m_outputChannelCount = 0; - m_outputSampleFormat = m_hostOutputSampleFormat = paInt16; + m_outputSampleFormat = m_hostOutputSampleFormat = paFloat32; m_oboeStream->outputFormat = m_hostOutputSampleFormat; } From 4112fcbfbcf890ab033ffded5d59a9a126b01b94 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Wed, 4 Oct 2023 10:06:19 +0200 Subject: [PATCH 08/26] Renamed most of the variables according to best coding practices. --- include/pa_oboe.h | 2 +- src/hostapi/oboe/pa_oboe.cpp | 1547 +++++++++++++++++----------------- 2 files changed, 767 insertions(+), 782 deletions(-) diff --git a/include/pa_oboe.h b/include/pa_oboe.h index 761a7b937..d345617d7 100644 --- a/include/pa_oboe.h +++ b/include/pa_oboe.h @@ -104,7 +104,7 @@ void PaOboe_SetNativeBufferSize(unsigned long bufferSize); * buffer size when doing this, and use the sample rate defined in AudioManager's * android.media.property.OUTPUT_SAMPLE_RATE. */ -void PaOboe_SetNumberOfBuffers(unsigned buffers); +void PaOboe_SetNumberOfBuffers(unsigned numberOfBuffers); #ifdef __cplusplus } diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index 1f9b63e99..fd70931a3 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -153,8 +153,8 @@ static signed long GetStreamWriteAvailable(PaStream *stream); static unsigned long GetApproximateLowBufferSize(); // Commonly used parameters initialized. -static unsigned long nativeBufferSize = 0; -static unsigned numberOfBuffers = 2; +static unsigned long g_nativeBufferSize = 0; +static unsigned g_numberOfBuffers = 2; using namespace oboe; @@ -165,6 +165,8 @@ int32_t g_outputDeviceId = kUnspecified; PerformanceMode g_inputPerfMode = PerformanceMode::LowLatency; PerformanceMode g_outputPerfMode = PerformanceMode::LowLatency; +class OboeEngine; + /** * Stream structure, useful to store relevant information. It's needed by Portaudio. */ @@ -194,9 +196,15 @@ typedef struct OboeStream { void **inputBuffers; int currentInputBuffer; - long engineAddress; unsigned long framesPerHostCallback; unsigned bytesPerFrame; + + OboeEngine *getEngineAddress() { return oboeEngineAddress; } + + void setEngineAddress(OboeEngine *i_oboeEngine) { oboeEngineAddress = i_oboeEngine; } + +private: + OboeEngine *oboeEngineAddress; } OboeStream; @@ -211,42 +219,49 @@ class OboeEngine : public AudioStreamCallback { //Stream-managing functions bool tryStream(Direction direction, int32_t sampleRate, int32_t channelCount); - PaError openStream(Direction direction, int32_t sampleRate, + + PaError openStream(OboeStream *oboeStream, Direction direction, int32_t sampleRate, Usage outputUsage, InputPreset inputPreset); - bool startStream(); - bool stopStream(); + + bool startStream(OboeStream *oboeStream); + + bool stopStream(OboeStream *oboeStream); + bool restartStream(int direction); - bool closeStream(); - bool abortStream(); + + bool closeStream(OboeStream *oboeStream); + + bool abortStream(OboeStream *oboeStream); //Callback function for non-blocking streams and some callback utils DataCallbackResult onAudioReady(AudioStream *audioStream, void *audioData, int32_t numFrames) override; + void onErrorAfterClose(AudioStream *audioStream, oboe::Result error) override; + void resetCallbackCounters(); //Blocking read/write functions bool writeStream(const void *buffer, int32_t framesToWrite); + bool readStream(void *buffer, int32_t framesToRead); //Engine utils - OboeStream* initializeOboeStream(); - void setEngineAddress(long address); + OboeStream *allocateOboeStream(); private: - //The only instance of OboeStream that will be used - OboeStream *oboeStream; + OboeStream *m_oboeStreamHolder; //The only instances of output and input streams that will be used, and their builders - std::shared_ptr outputStream; - AudioStreamBuilder outputBuilder; - std::shared_ptr inputStream; - AudioStreamBuilder inputBuilder; + std::shared_ptr m_outputStream; + AudioStreamBuilder m_outputBuilder; + std::shared_ptr m_inputStream; + AudioStreamBuilder m_inputBuilder; //callback utils - unsigned long framesProcessed{}; - PaStreamCallbackTimeInfo timeInfo{}; - struct timespec timeSpec{}; + unsigned long m_framesProcessed{}; + PaStreamCallbackTimeInfo m_timeInfo{}; + struct timespec m_timeSpec{}; //Conversion utils static AudioFormat PaToOboeFormat(PaSampleFormat paFormat); @@ -277,7 +292,7 @@ typedef struct PaOboeHostApiRepresentation { * \brief Initializes an instance of the engine. */ OboeEngine::OboeEngine() { - oboeStream = nullptr; + m_oboeStreamHolder = allocateOboeStream(); } @@ -292,52 +307,52 @@ OboeEngine::OboeEngine() { * @return true if the requested sample rate / channel count is supported by the device, false if * they aren't, or if tryStream couldn't open a stream. */ -bool OboeEngine::tryStream(Direction direction, int32_t sampleRate, int32_t channelCount) { - AudioStreamBuilder m_builder; - Result m_result; - bool m_outcome = false; +bool OboeEngine::tryStream(Direction i_direction, int32_t i_sampleRate, int32_t i_channelCount) { + AudioStreamBuilder builder; + Result result; + bool outcome = false; - m_builder.setDeviceId(getSelectedDevice(direction)) - // Arbitrary format usually broadly supported. Later, we'll open streams with correct formats. + builder.setDeviceId(getSelectedDevice(i_direction)) + // Arbitrary format usually broadly supported. Later, we'll open streams with correct formats. ->setFormat(AudioFormat::Float) - ->setDirection(direction) - ->setSampleRate(sampleRate) - ->setChannelCount(channelCount); - if (direction == Direction::Input) { - m_result = m_builder->openStream(inputStream); + ->setDirection(i_direction) + ->setSampleRate(i_sampleRate) + ->setChannelCount(i_channelCount); + if (i_direction == Direction::Input) { + result = builder->openStream(m_inputStream); } else { - m_result = m_builder->openStream(outputStream); + result = builder->openStream(m_outputStream); } - if (m_result != Result::OK) { + if (result != Result::OK) { LOGE("[OboeEngine::TryStream]\t Couldn't open the stream in TryStream. Error: %s", - convertToText(m_result)); - return m_outcome; + convertToText(result)); + return outcome; } - if (sampleRate != kUnspecified) { - m_outcome = (sampleRate == m_builder.getSampleRate()); - if(!m_outcome) { + if (i_sampleRate != kUnspecified) { + outcome = (i_sampleRate == builder.getSampleRate()); + if (!outcome) { LOGW("[OboeEngine::TryStream]\t Tried sampleRate = %d, built sampleRate = %d", - sampleRate, m_builder.getSampleRate()); + i_sampleRate, builder.getSampleRate()); } - } else if (channelCount != kUnspecified) { - m_outcome = (channelCount == m_builder.getChannelCount()); - if(!m_outcome) { + } else if (i_channelCount != kUnspecified) { + outcome = (i_channelCount == builder.getChannelCount()); + if (!outcome) { LOGW("[OboeEngine::TryStream]\t Tried channelCount = %d, built channelCount = %d", - channelCount, m_builder.getChannelCount()); + channelCount, builder.getChannelCount()); } } else { LOGE("[OboeEngine::TryStream]\t Logical failure. This message should NEVER occur."); - m_outcome = false; + outcome = false; } - if (direction == Direction::Input) - inputStream->close(); + if (i_direction == Direction::Input) + m_inputStream->close(); else - outputStream->close(); + m_outputStream->close(); - return m_outcome; + return outcome; } @@ -356,103 +371,101 @@ bool OboeEngine::tryStream(Direction direction, int32_t sampleRate, int32_t chan * @return paNoError if everything goes as expected, paUnanticipatedHostError if Oboe fails to open * a stream, and paInsufficientMemory if the memory allocation of the buffers fails. */ -PaError OboeEngine::openStream(Direction direction, int32_t sampleRate, - Usage androidOutputUsage, InputPreset androidInputPreset) { - PaError m_error = paNoError; - Result m_result; - - if (direction == Direction::Input) { - inputBuilder.setChannelCount(oboeStream->bufferProcessor.inputChannelCount) - ->setFormat(PaToOboeFormat(oboeStream->inputFormat)) - ->setSampleRate(sampleRate) +PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, int32_t i_sampleRate, + Usage i_androidOutputUsage, InputPreset i_androidInputPreset) { + PaError error = paNoError; + Result result; + + if (i_direction == Direction::Input) { + m_inputBuilder.setChannelCount(i_oboeStream->bufferProcessor.inputChannelCount) + ->setFormat(PaToOboeFormat(i_oboeStream->inputFormat)) + ->setSampleRate(i_sampleRate) ->setDirection(Direction::Input) ->setDeviceId(getSelectedDevice(Direction::Input)) ->setPerformanceMode(g_inputPerfMode) - ->setInputPreset(androidInputPreset) - ->setFramesPerCallback(oboeStream->framesPerHostCallback); + ->setInputPreset(i_androidInputPreset) + ->setFramesPerCallback(i_oboeStream->framesPerHostCallback); - if (!(oboeStream->isBlocking)) { + if (!(i_oboeStream->isBlocking)) { resetCallbackCounters(); - inputBuilder.setDataCallback(this) + m_inputBuilder.setDataCallback(this) ->setErrorCallback(this); } - m_result = inputBuilder.openStream(inputStream); + result = m_inputBuilder.openStream(m_inputStream); - if (m_result != Result::OK) { + if (result != Result::OK) { LOGE("[OboeEngine::OpenStream]\t Oboe couldn't open the input stream: %s", - convertToText(m_result)); - m_error = paUnanticipatedHostError; - return m_error; + convertToText(result)); + return paUnanticipatedHostError; } - inputStream->setBufferSizeInFrames(inputStream->getFramesPerBurst() * numberOfBuffers); - oboeStream->inputBuffers = - (void **) PaUtil_AllocateZeroInitializedMemory(numberOfBuffers * sizeof(int32_t *)); + m_inputStream->setBufferSizeInFrames(m_inputStream->getFramesPerBurst() * g_numberOfBuffers); + i_oboeStream->inputBuffers = + (void **) PaUtil_AllocateZeroInitializedMemory(g_numberOfBuffers * sizeof(int32_t * )); - for (int i = 0; i < numberOfBuffers; ++i) { - oboeStream->inputBuffers[i] = (void *) PaUtil_AllocateZeroInitializedMemory( - oboeStream->framesPerHostCallback * - oboeStream->bytesPerFrame * - oboeStream->bufferProcessor.inputChannelCount); + for (int i = 0; i < g_numberOfBuffers; ++i) { + i_oboeStream->inputBuffers[i] = (void *) PaUtil_AllocateZeroInitializedMemory( + i_oboeStream->framesPerHostCallback * + i_oboeStream->bytesPerFrame * + i_oboeStream->bufferProcessor.inputChannelCount); - if (!oboeStream->inputBuffers[i]) { + if (!i_oboeStream->inputBuffers[i]) { for (int j = 0; j < i; ++j) - PaUtil_FreeMemory(oboeStream->inputBuffers[j]); - PaUtil_FreeMemory(oboeStream->inputBuffers); - inputStream->close(); - m_error = paInsufficientMemory; + PaUtil_FreeMemory(i_oboeStream->inputBuffers[j]); + PaUtil_FreeMemory(i_oboeStream->inputBuffers); + m_inputStream->close(); + error = paInsufficientMemory; break; } } - oboeStream->currentInputBuffer = 0; + i_oboeStream->currentInputBuffer = 0; } else { - outputBuilder.setChannelCount(oboeStream->bufferProcessor.outputChannelCount) - ->setFormat(PaToOboeFormat(oboeStream->outputFormat)) - ->setSampleRate(sampleRate) + m_outputBuilder.setChannelCount(i_oboeStream->bufferProcessor.outputChannelCount) + ->setFormat(PaToOboeFormat(i_oboeStream->outputFormat)) + ->setSampleRate(i_sampleRate) ->setDirection(Direction::Output) ->setDeviceId(getSelectedDevice(Direction::Output)) ->setPerformanceMode(g_outputPerfMode) - ->setUsage(androidOutputUsage) - ->setFramesPerCallback(oboeStream->framesPerHostCallback); + ->setUsage(i_androidOutputUsage) + ->setFramesPerCallback(i_oboeStream->framesPerHostCallback); - if (!(oboeStream->isBlocking)) { + if (!(i_oboeStream->isBlocking)) { resetCallbackCounters(); - outputBuilder.setDataCallback(this) + m_outputBuilder.setDataCallback(this) ->setErrorCallback(this); } - m_result = outputBuilder.openStream(outputStream); - if (m_result != Result::OK) { + result = m_outputBuilder.openStream(m_outputStream); + if (result != Result::OK) { LOGE("[OboeEngine::OpenStream]\t Oboe couldn't open the output stream: %s", - convertToText(m_result)); - m_error = paUnanticipatedHostError; - return m_error; + convertToText(result)); + return paUnanticipatedHostError; } - outputStream->setBufferSizeInFrames(outputStream->getFramesPerBurst() * numberOfBuffers); - oboeStream->outputBuffers = - (void **) PaUtil_AllocateZeroInitializedMemory(numberOfBuffers * sizeof(int32_t *)); + m_outputStream->setBufferSizeInFrames(m_outputStream->getFramesPerBurst() * g_numberOfBuffers); + i_oboeStream->outputBuffers = + (void **) PaUtil_AllocateZeroInitializedMemory(g_numberOfBuffers * sizeof(int32_t * )); - for (int i = 0; i < numberOfBuffers; ++i) { - oboeStream->outputBuffers[i] = (void *) PaUtil_AllocateZeroInitializedMemory( - oboeStream->framesPerHostCallback * - oboeStream->bytesPerFrame * - oboeStream->bufferProcessor.outputChannelCount); + for (int i = 0; i < g_numberOfBuffers; ++i) { + i_oboeStream->outputBuffers[i] = (void *) PaUtil_AllocateZeroInitializedMemory( + i_oboeStream->framesPerHostCallback * + i_oboeStream->bytesPerFrame * + i_oboeStream->bufferProcessor.outputChannelCount); - if (!oboeStream->outputBuffers[i]) { + if (!i_oboeStream->outputBuffers[i]) { for (int j = 0; j < i; ++j) - PaUtil_FreeMemory(oboeStream->outputBuffers[j]); - PaUtil_FreeMemory(oboeStream->outputBuffers); - outputStream->close(); - m_error = paInsufficientMemory; + PaUtil_FreeMemory(i_oboeStream->outputBuffers[j]); + PaUtil_FreeMemory(i_oboeStream->outputBuffers); + m_outputStream->close(); + error = paInsufficientMemory; break; } } - oboeStream->currentOutputBuffer = 0; + i_oboeStream->currentOutputBuffer = 0; } - return m_error; + return error; } @@ -461,23 +474,23 @@ PaError OboeEngine::openStream(Direction direction, int32_t sampleRate, * and requested to be started. * @return true if the streams we wanted to start are started successfully, false otherwise. */ -bool OboeEngine::startStream() { - Result m_outputResult = Result::OK, m_inputResult = Result::OK; +bool OboeEngine::startStream(OboeStream *i_oboeStream) { + Result outputResult = Result::OK, inputResult = Result::OK; - if (oboeStream->hasInput) { - m_inputResult = inputStream->requestStart(); - if (m_inputResult != Result::OK) + if (i_oboeStream->hasInput) { + inputResult = m_inputStream->requestStart(); + if (inputResult != Result::OK) LOGE("[OboeEngine::startStream]\t Oboe couldn't start the input stream: %s", - convertToText(m_inputResult)); + convertToText(inputResult)); } - if (oboeStream->hasOutput) { - m_outputResult = outputStream->requestStart(); - if (m_outputResult != Result::OK) + if (i_oboeStream->hasOutput) { + outputResult = m_outputStream->requestStart(); + if (outputResult != Result::OK) LOGE("[OboeEngine::startStream]\t Oboe couldn't start the output stream: %s", - convertToText(m_outputResult)); + convertToText(outputResult)); } - return (m_outputResult == Result::OK && m_inputResult == Result::OK); + return (outputResult == Result::OK && inputResult == Result::OK); } @@ -486,23 +499,23 @@ bool OboeEngine::startStream() { * and requested to be stopped. * @return true if the streams we wanted to stop are stopped successfully, false otherwise. */ -bool OboeEngine::stopStream() { - Result m_outputResult = Result::OK, m_inputResult = Result::OK; +bool OboeEngine::stopStream(OboeStream *i_oboeStream) { + Result outputResult = Result::OK, inputResult = Result::OK; - if (oboeStream->hasInput) { - m_inputResult = inputStream->requestStop(); - if (m_inputResult != Result::OK) + if (i_oboeStream->hasInput) { + inputResult = m_inputStream->requestStop(); + if (inputResult != Result::OK) LOGE("[OboeEngine::stopStream]\t Oboe couldn't stop the input stream: %s", - convertToText(m_inputResult)); + convertToText(inputResult)); } - if (oboeStream->hasOutput) { - m_outputResult = outputStream->requestStop(); - if (m_outputResult != Result::OK) + if (i_oboeStream->hasOutput) { + outputResult = m_outputStream->requestStop(); + if (outputResult != Result::OK) LOGE("[OboeEngine::stopStream]\t Oboe couldn't stop the output stream: %s", - convertToText(m_outputResult)); + convertToText(outputResult)); } - return (m_outputResult == Result::OK && m_inputResult == Result::OK); + return (outputResult == Result::OK && inputResult == Result::OK); } @@ -511,67 +524,67 @@ bool OboeEngine::stopStream() { * audio devices change while a stream is started. * @return true if the stream is restarted successfully, false otherwise. */ -bool OboeEngine::restartStream(int direction) { - bool m_outcome = true; - Result m_result; +bool OboeEngine::restartStream(int i_direction) { + bool outcome = true; + Result result; - switch (direction) { + switch (i_direction) { case 1: //output-only //stopping and closing - m_result = outputStream->stop(); - if (m_result != Result::OK) + result = m_outputStream->stop(); + if (result != Result::OK) LOGW("[OboeEngine::restartStream]\t Oboe couldn't stop the output stream: %s", - convertToText(m_result)); - m_result = outputStream->close(); - if (m_result != Result::OK) + convertToText(result)); + result = m_outputStream->close(); + if (result != Result::OK) LOGW("[OboeEngine::restartStream]\t Oboe couldn't close the output stream: %s", - convertToText(m_result)); + convertToText(result)); //reopening and restarting - m_result = outputBuilder.openStream(outputStream); - if (m_result != Result::OK) + result = outputBuilder.openStream(m_outputStream); + if (result != Result::OK) LOGE("[OboeEngine::restartStream]\t Oboe couldn't reopen the output stream: %s", - convertToText(m_result)); - m_result = outputStream->start(); - if (m_result != Result::OK) { + convertToText(result)); + result = m_outputStream->start(); + if (result != Result::OK) { LOGE("[OboeEngine::restartStream]\t Oboe couldn't restart the output stream: %s", - convertToText(m_result)); - m_outcome = false; + convertToText(result)); + outcome = false; } break; case 2: //input-only //stopping and closing - m_result = inputStream->stop(); - if (m_result != Result::OK) + result = m_inputStream->stop(); + if (result != Result::OK) LOGW("[OboeEngine::restartStream]\t Oboe couldn't stop the input stream: %s", - convertToText(m_result)); - m_result = inputStream->close(); - if (m_result != Result::OK) + convertToText(result)); + result = m_inputStream->close(); + if (result != Result::OK) LOGW("[OboeEngine::restartStream]\t Oboe couldn't close the input stream: %s", - convertToText(m_result)); + convertToText(result)); //reopening and restarting - m_result = inputBuilder.openStream(inputStream); - if (m_result != Result::OK) + result = inputBuilder.openStream(m_inputStream); + if (result != Result::OK) LOGE("[OboeEngine::restartStream]\t Oboe couldn't reopen the input stream: %s", - convertToText(m_result)); - m_result = inputStream->start(); - if (m_result != Result::OK) { + convertToText(result)); + result = m_inputStream->start(); + if (result != Result::OK) { LOGE("[OboeEngine::restartStream]\t Oboe couldn't restart the input stream: %s", - convertToText(m_result)); - m_outcome = false; + convertToText(result)); + outcome = false; } break; default: - // unspecified direction or both directions, abort streams + // unspecified direction or both directions: restart both streams LOGW("[OboeEngine::restartStream]\t Unspecified direction, restarting both streams"); - m_outcome = (restartStream(1) && restartStream(2)); + outcome = (restartStream(1) && restartStream(2)); break; } - return m_outcome; + return outcome; } @@ -580,30 +593,33 @@ bool OboeEngine::restartStream(int direction) { * and closed if active. * @return true if the stream is closed successfully, otherwise returns false. */ -bool OboeEngine::closeStream() { - Result m_outputResult = Result::OK, m_inputResult = Result::OK; +bool OboeEngine::closeStream(OboeStream *i_oboeStream) { + Result outputResult = Result::OK, inputResult = Result::OK; + bool hasOutput = true, hasInput = true; - if(oboeStream == nullptr){ - LOGE("[OboeEngine::closeStream]\t Tried to close a NULL stream. Exiting closeStream."); - return false; + if (i_oboeStream == nullptr) { + LOGW("[OboeEngine::closeStream]\t i_oboeStream is a nullptr. Terminating both oboe streams."); + } else { + hasInput = i_oboeStream->hasInput; + hasOutput = i_oboeStream->hasOutput; } - if (oboeStream->hasOutput) { - m_outputResult = outputStream->close(); - if (m_outputResult == Result::ErrorClosed) { - m_outputResult = Result::OK; + if (hasOutput) { + outputResult = m_outputStream->close(); + if (outputResult == Result::ErrorClosed) { + outputResult = Result::OK; LOGW("[OboeEngine::closeStream]\t Tried to close output stream, but was already closed."); } } - if (oboeStream->hasInput) { - m_inputResult = inputStream->close(); - if (m_inputResult == Result::ErrorClosed) { - m_inputResult = Result::OK; + if (hasInput) { + inputResult = m_inputStream->close(); + if (inputResult == Result::ErrorClosed) { + inputResult = Result::OK; LOGW("[OboeEngine::closeStream]\t Tried to close input stream, but was already closed."); } } - return (m_outputResult == Result::OK && m_inputResult == Result::OK); + return (outputResult == Result::OK && inputResult == Result::OK); } @@ -611,36 +627,39 @@ bool OboeEngine::closeStream() { * \brief Stops oboeStream - both input and output audiostreams are checked and forcefully stopped. * @return true if the output stream and the input stream are stopped successfully, false otherwise. */ -bool OboeEngine::abortStream() { - Result m_outputResult = Result::OK, m_inputResult = Result::OK; +bool OboeEngine::abortStream(OboeStream *i_oboeStream) { + Result outputResult = Result::OK, inputResult = Result::OK; + bool hasOutput = true, hasInput = true; - if(oboeStream == nullptr){ - LOGE("[OboeEngine::abortStream]\t Tried to abort a NULL stream. Exiting abortStream."); - return false; + if (i_oboeStream == nullptr) { + LOGW("[OboeEngine::closeStream]\t i_oboeStream is a nullptr. Aborting both oboe streams."); + } else { + hasInput = i_oboeStream->hasInput; + hasOutput = i_oboeStream->hasOutput; } - if (oboeStream->hasInput) { - m_inputResult = inputStream->stop(); - if (m_inputResult != Result::OK) + if (hasInput) { + inputResult = m_inputStream->stop(); + if (inputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the input stream to stop: %s", - convertToText(m_inputResult)); - m_inputResult = inputStream->close(); + convertToText(inputResult)); + inputResult = m_inputStream->close(); if (m_inputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the input stream to close: %s", - convertToText(m_inputResult)); + convertToText(inputResult)); } - if (oboeStream->hasOutput) { - m_outputResult = outputStream->stop(); + if (hasOutput) { + outputResult = m_outputStream->stop(); if (m_outputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the output stream to stop: %s", convertToText(m_outputResult)); - m_outputResult = outputStream->close(); - if (m_outputResult != Result::OK) + outputResult = m_outputStream->close(); + if (outputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the output stream to close: %s", - convertToText(m_outputResult)); + convertToText(outputResult)); } - return (m_outputResult == Result::OK && m_inputResult == Result::OK); + return (outputResult == Result::OK && inputResult == Result::OK); } @@ -648,84 +667,86 @@ bool OboeEngine::abortStream() { * \brief Oboe's callback routine. FIXME: implement onErrorAfterClose correctly */ DataCallbackResult -OboeEngine::onAudioReady(AudioStream *audioStream, void *audioData, int32_t numFrames) { - - clock_gettime(CLOCK_REALTIME, &timeSpec); - timeInfo.currentTime = (PaTime) (timeSpec.tv_sec + (timeSpec.tv_nsec / 1000000000.0)); - timeInfo.outputBufferDacTime = (PaTime) (oboeStream->framesPerHostCallback +OboeEngine::onAudioReady(AudioStream *i_audioStream, void *i_audioData, int32_t i_numFrames) { + + clock_gettime(CLOCK_REALTIME, &m_timeSpec); + m_timeInfo.currentTime = (PaTime)(m_timeSpec.tv_sec + (m_timeSpec.tv_nsec / 1000000000.0)); + m_timeInfo.outputBufferDacTime = (PaTime)(m_oboeStreamHolder->framesPerHostCallback + / + m_oboeStreamHolder->streamRepresentation.streamInfo.sampleRate + + m_timeInfo.currentTime); + m_timeInfo.inputBufferAdcTime = (PaTime)(m_oboeStreamHolder->framesPerHostCallback / - oboeStream->streamRepresentation.streamInfo.sampleRate - + timeInfo.currentTime); - timeInfo.inputBufferAdcTime = (PaTime) (oboeStream->framesPerHostCallback - / - oboeStream->streamRepresentation.streamInfo.sampleRate - + timeInfo.currentTime); + m_oboeStreamHolder->streamRepresentation.streamInfo.sampleRate + + m_timeInfo.currentTime); /* check if StopStream or AbortStream was called */ - if (oboeStream->doStop) { - oboeStream->callbackResult = paComplete; - } else if (oboeStream->doAbort) { - oboeStream->callbackResult = paAbort; + if (m_oboeStreamHolder->doStop) { + m_oboeStreamHolder->callbackResult = paComplete; + } else if (m_oboeStreamHolder->doAbort) { + m_oboeStreamHolder->callbackResult = paAbort; } - PaUtil_BeginCpuLoadMeasurement(&oboeStream->cpuLoadMeasurer); - PaUtil_BeginBufferProcessing(&oboeStream->bufferProcessor, - &timeInfo, oboeStream->cbFlags); + PaUtil_BeginCpuLoadMeasurement(&m_oboeStreamHolder->cpuLoadMeasurer); + PaUtil_BeginBufferProcessing(&m_oboeStreamHolder->bufferProcessor, + &m_timeInfo, m_oboeStreamHolder->cbFlags); - if (oboeStream->hasOutput) { - oboeStream->outputBuffers[oboeStream->currentOutputBuffer] = audioData; - PaUtil_SetOutputFrameCount(&oboeStream->bufferProcessor, numFrames); - PaUtil_SetInterleavedOutputChannels(&oboeStream->bufferProcessor, 0, - (void *) ((PaInt16 **) oboeStream->outputBuffers)[oboeStream->currentOutputBuffer], + if (m_oboeStreamHolder->hasOutput) { + m_oboeStreamHolder->outputBuffers[m_oboeStreamHolder->currentOutputBuffer] = i_audioData; + PaUtil_SetOutputFrameCount(&m_oboeStreamHolder->bufferProcessor, i_numFrames); + PaUtil_SetInterleavedOutputChannels(&m_oboeStreamHolder->bufferProcessor, 0, + (void *) ((PaInt16 **) m_oboeStreamHolder->outputBuffers)[ + m_oboeStreamHolder->currentOutputBuffer], 0); } - if (oboeStream->hasInput) { - audioData = oboeStream->inputBuffers[oboeStream->currentInputBuffer]; - PaUtil_SetInputFrameCount(&oboeStream->bufferProcessor, 0); - PaUtil_SetInterleavedInputChannels(&oboeStream->bufferProcessor, 0, - (void *) ((PaInt16 **) oboeStream->inputBuffers)[oboeStream->currentInputBuffer], + if (m_oboeStreamHolder->hasInput) { + i_audioData = m_oboeStreamHolder->inputBuffers[m_oboeStreamHolder->currentInputBuffer]; + PaUtil_SetInputFrameCount(&m_oboeStreamHolder->bufferProcessor, 0); + PaUtil_SetInterleavedInputChannels(&m_oboeStreamHolder->bufferProcessor, 0, + (void *) ((PaInt16 **) m_oboeStreamHolder->inputBuffers)[ + m_oboeStreamHolder->currentInputBuffer], 0); } - /* continue processing user buffers if cbresult is pacontinue or if cbresult is pacomplete and userbuffers aren't empty yet */ - if (oboeStream->callbackResult == paContinue - || (oboeStream->callbackResult == paComplete - && !PaUtil_IsBufferProcessorOutputEmpty(&oboeStream->bufferProcessor))) { - framesProcessed = PaUtil_EndBufferProcessing(&oboeStream->bufferProcessor, - &oboeStream->callbackResult); + /* continue processing user buffers if cbresult is paContinue or if cbresult is paComplete and userBuffers aren't empty yet */ + if (m_oboeStreamHolder->callbackResult == paContinue + || (m_oboeStreamHolder->callbackResult == paComplete + && !PaUtil_IsBufferProcessorOutputEmpty(&m_oboeStreamHolder->bufferProcessor))) { + m_framesProcessed = PaUtil_EndBufferProcessing(&oboeStream->bufferProcessor, + &oboeStream->callbackResult); } /* enqueue a buffer only when there are frames to be processed, * this will be 0 when paComplete + empty buffers or paAbort */ - if (framesProcessed > 0) { - if (oboeStream->hasOutput) { - oboeStream->currentOutputBuffer = - (oboeStream->currentOutputBuffer + 1) % numberOfBuffers; + if (m_framesProcessed > 0) { + if (m_oboeStreamHolder->hasOutput) { + m_oboeStreamHolder->currentOutputBuffer = + (m_oboeStreamHolder->currentOutputBuffer + 1) % g_numberOfBuffers; } - if (oboeStream->hasInput) { - oboeStream->currentInputBuffer = (oboeStream->currentInputBuffer + 1) % numberOfBuffers; + if (m_oboeStreamHolder->hasInput) { + m_oboeStreamHolder->currentInputBuffer = (m_oboeStreamHolder->currentInputBuffer + 1) % g_numberOfBuffers; } } - PaUtil_EndCpuLoadMeasurement(&oboeStream->cpuLoadMeasurer, framesProcessed); + PaUtil_EndCpuLoadMeasurement(&m_oboeStreamHolder->cpuLoadMeasurer, m_framesProcessed); /* StopStream was called */ - if (framesProcessed == 0 && oboeStream->doStop) { - oboeStream->oboeCallbackResult = DataCallbackResult::Stop; + if (m_framesProcessed == 0 && m_oboeStreamHolder->doStop) { + m_oboeStreamHolder->oboeCallbackResult = DataCallbackResult::Stop; } /* if AbortStream or StopStream weren't called, stop from the cb */ - else if (framesProcessed == 0 && !(oboeStream->doAbort || oboeStream->doStop)) { - oboeStream->isActive = false; - oboeStream->isStopped = true; - if (oboeStream->streamRepresentation.streamFinishedCallback != nullptr) - oboeStream->streamRepresentation.streamFinishedCallback( - oboeStream->streamRepresentation.userData); - //oboeStream->oboeCallbackResult = DataCallbackResult::Stop; TODO: Resume this test (onAudioReady) + else if (m_framesProcessed == 0 && !(m_oboeStreamHolder->doAbort || m_oboeStreamHolder->doStop)) { + m_oboeStreamHolder->isActive = false; + m_oboeStreamHolder->isStopped = true; + if (m_oboeStreamHolder->streamRepresentation.streamFinishedCallback != nullptr) + m_oboeStreamHolder->streamRepresentation.streamFinishedCallback( + m_oboeStreamHolder->streamRepresentation.userData); + m_oboeStreamHolder->oboeCallbackResult = DataCallbackResult::Stop; //TODO: Resume this test (onAudioReady) } - return oboeStream->oboeCallbackResult; + return m_oboeStreamHolder->oboeCallbackResult; } @@ -733,14 +754,13 @@ OboeEngine::onAudioReady(AudioStream *audioStream, void *audioData, int32_t numF * \brief If the data callback ends without returning DataCallbackResult::Stop, this routine tells * what error occurred. */ -void OboeEngine::onErrorAfterClose(AudioStream *audioStream, Result error) { - if (error == oboe::Result::ErrorDisconnected) { +void OboeEngine::onErrorAfterClose(AudioStream *i_audioStream, Result i_error) { + if (i_error == oboe::Result::ErrorDisconnected) { LOGW("[OboeEngine::onErrorAfterClose]\t ErrorDisconnected - Restarting stream(s)"); if (!restartStream(0)) LOGE("[OboeEngine::onErrorAfterClose]\t Couldn't restart stream(s)"); - } - else - LOGE("[OboeEngine::onErrorAfterClose]\t Error was %s", oboe::convertToText(error)); + } else + LOGE("[OboeEngine::onErrorAfterClose]\t Error was %s", oboe::convertToText(i_error)); } @@ -748,8 +768,8 @@ void OboeEngine::onErrorAfterClose(AudioStream *audioStream, Result error) { * \brief Resets callback counters (called at the start of each iteration of onAudioReady */ void OboeEngine::resetCallbackCounters() { - framesProcessed = 0; - timeInfo = {0, 0, 0}; + m_framesProcessed = 0; + m_timeInfo = {0, 0, 0}; } @@ -761,22 +781,22 @@ void OboeEngine::resetCallbackCounters() { * different from ErrorDisconnected. In case of ErrorDisconnected, the function returns * true if the stream is successfully restarted, and false otherwise. */ -bool OboeEngine::writeStream(const void *buffer, int32_t framesToWrite) { - bool m_outcome = true; +bool OboeEngine::writeStream(const void *i_buffer, int32_t i_framesToWrite) { + bool outcome = true; - ResultWithValue m_result = outputStream->write(buffer, framesToWrite, TIMEOUT_NS); + ResultWithValue result = m_outputStream->write(i_buffer, i_framesToWrite, TIMEOUT_NS); // If the stream is interrupted because the device suddenly changes, restart the stream. - if (m_result.error() == Result::ErrorDisconnected) { + if (result.error() == Result::ErrorDisconnected) { if (OboeEngine::restartStream(1)) return true; } - if (!m_result) { - LOGE("[OboeEngine::writeStream]\t Error writing stream: %s", convertToText(m_result.error())); - m_outcome = false; + if (!result) { + LOGE("[OboeEngine::writeStream]\t Error writing stream: %s", convertToText(result.error())); + outcome = false; } - return m_outcome; + return outcome; } @@ -788,22 +808,22 @@ bool OboeEngine::writeStream(const void *buffer, int32_t framesToWrite) { * different from ErrorDisconnected. In case of ErrorDisconnected, the function returns * true if the stream is successfully restarted, and false otherwise. */ -bool OboeEngine::readStream(void *buffer, int32_t framesToRead) { - bool m_outcome = true; +bool OboeEngine::readStream(void *i_buffer, int32_t i_framesToRead) { + bool outcome = true; - ResultWithValue m_result = inputStream->read(buffer, framesToRead, TIMEOUT_NS); + ResultWithValue result = m_inputStream->read(i_buffer, i_framesToRead, TIMEOUT_NS); // If the stream is interrupted because the device suddenly changes, restart the stream. - if (m_result.error() == Result::ErrorDisconnected) { + if (result.error() == Result::ErrorDisconnected) { if (OboeEngine::restartStream(2)) return true; } - if (!m_result) { - LOGE("[OboeEngine::readStream]\t Error reading stream: %s", convertToText(m_result.error())); - m_outcome = false; + if (!result) { + LOGE("[OboeEngine::readStream]\t Error reading stream: %s", convertToText(result.error())); + outcome = false; } - return m_outcome; + return outcome; } @@ -811,51 +831,43 @@ bool OboeEngine::readStream(void *buffer, int32_t framesToRead) { * \brief Allocates the memory of oboeStream. * @return the address of the oboeStream. */ -OboeStream* OboeEngine::initializeOboeStream() { - oboeStream = (OboeStream *) PaUtil_AllocateZeroInitializedMemory(sizeof(OboeStream)); +OboeStream *OboeEngine::allocateOboeStream() { + OboeStream *oboeStream = (OboeStream *) PaUtil_AllocateZeroInitializedMemory(sizeof(OboeStream)); + oboeStream->setEngineAddress(this); return oboeStream; } -/** - * \brief Sets the engineAddress parameter of oboeStream, useful for recalling the engine whenever - * it's needed. - * @param address the address of the only instance of OboeEngine. - */ -void OboeEngine::setEngineAddress(long address) { - oboeStream->engineAddress = address; -} - /** * \brief Converts PaSampleFormat values into Oboe::AudioFormat values. * @param paFormat the PaSampleFormat we want to convert. * @return the converted AudioFormat. */ -AudioFormat OboeEngine::PaToOboeFormat(PaSampleFormat paFormat) { - AudioFormat m_oboeFormat; - switch (paFormat) { +AudioFormat OboeEngine::PaToOboeFormat(PaSampleFormat i_paFormat) { + AudioFormat oboeFormat; + switch (i_paFormat) { case paFloat32: - m_oboeFormat = AudioFormat::Float; + oboeFormat = AudioFormat::Float; LOGI("[OboeEngine::PaToOboeFormat]\t REQUESTED OBOE FORMAT: FLOAT"); break; case paInt16: - m_oboeFormat = AudioFormat::I16; + oboeFormat = AudioFormat::I16; LOGI("[OboeEngine::PaToOboeFormat]\t REQUESTED OBOE FORMAT: I16"); break; case paInt32: - m_oboeFormat = AudioFormat::I32; + oboeFormat = AudioFormat::I32; LOGI("[OboeEngine::PaToOboeFormat]\t REQUESTED OBOE FORMAT: I32"); break; case paInt24: - m_oboeFormat = AudioFormat::I24; + oboeFormat = AudioFormat::I24; LOGI("[OboeEngine::PaToOboeFormat]\t REQUESTED OBOE FORMAT: I24"); break; default: - m_oboeFormat = AudioFormat::Unspecified; - LOGW("[OboeEngine::PaToOboeFormat]\t Setting AudioFormat to Unspecified, because Oboe does not support the requested format."); + oboeFormat = AudioFormat::Unspecified; + LOGW("[OboeEngine::PaToOboeFormat]\t Setting AudioFormat to Unspecified, Oboe does not support the requested format."); break; } - return m_oboeFormat; + return oboeFormat; } @@ -865,8 +877,8 @@ AudioFormat OboeEngine::PaToOboeFormat(PaSampleFormat paFormat) { * @param direction the Oboe::Direction for which we want to know the device Id. * @return the device Id of the appropriate direction. */ -int32_t OboeEngine::getSelectedDevice(Direction direction) { - if (direction == Direction::Input) +int32_t OboeEngine::getSelectedDevice(Direction i_direction) { + if (i_direction == Direction::Input) return g_inputDeviceId; else return g_outputDeviceId; @@ -879,17 +891,16 @@ int32_t OboeEngine::getSelectedDevice(Direction direction) { * \brief Checks if the requested sample rate is supported by the output device using * OboeEngine::tryStream. * This function is used by PaOboe_Initialize, IsFormatSupported, and OpenStream. - * @param oboeHostApi points towards a OboeHostApiRepresentation (see struct defined at the top of - * this file); + * @param oboeHostApi points towards a OboeHostApiRepresentation (see struct defined at the top of this file); * @param sampleRate is the sample rate we want to check. * @return PaNoError regardless of the outcome of the check, but warns in the Logs if the sample * rate was changed by Oboe. */ -PaError IsOutputSampleRateSupported(PaOboeHostApiRepresentation *oboeHostApi, double sampleRate) { - if (!(oboeHostApi->oboeEngine->tryStream(Direction::Output, - sampleRate, - kUnspecified))) - LOGW("[PaOboe - IsOutputSampleRateSupported]\t Sample Rate was changed by Oboe. The device might not support high frequencies."); +PaError IsOutputSampleRateSupported(PaOboeHostApiRepresentation *i_oboeHostApi, double i_sampleRate) { + if (!(i_oboeHostApi->oboeEngine->tryStream(Direction::Output, + i_sampleRate, + kUnspecified))) + LOGW("[PaOboe - IsOutputSampleRateSupported]\t Sample Rate was changed by Oboe."); /* Since Oboe manages the sample rate in a smart way, we can avoid blocking the process if the sample rate we requested wasn't supported. */ @@ -907,11 +918,11 @@ PaError IsOutputSampleRateSupported(PaOboeHostApiRepresentation *oboeHostApi, do * @return PaNoError regardless of the outcome of the check, but warns in the Logs if the sample * rate was changed by Oboe. */ -PaError IsInputSampleRateSupported(PaOboeHostApiRepresentation *oboeHostApi, double sampleRate) { - if (!(oboeHostApi->oboeEngine->tryStream(Direction::Input, - sampleRate, - kUnspecified))) - LOGW("[PaOboe - IsInputSampleRateSupported]\t Sample Rate was changed by Oboe. The device might not support high frequencies."); +PaError IsInputSampleRateSupported(PaOboeHostApiRepresentation *i_oboeHostApi, double i_sampleRate) { + if (!(i_oboeHostApi->oboeEngine->tryStream(Direction::Input, + i_sampleRate, + kUnspecified))) + LOGW("[PaOboe - IsInputSampleRateSupported]\t Sample Rate was changed by Oboe."); /* Since Oboe manages the sample rate in a smart way, we can avoid blocking the process if the sample rate we requested wasn't supported. */ @@ -928,17 +939,15 @@ PaError IsInputSampleRateSupported(PaOboeHostApiRepresentation *oboeHostApi, dou * @return PaNoError regardless of the outcome of the check, but warns in the Logs if the channel * count was changed by Oboe. */ -static PaError IsOutputChannelCountSupported( - PaOboeHostApiRepresentation *oboeHostApi, - int32_t numOfChannels) { - if (numOfChannels > 2 || numOfChannels == 0) { +static PaError IsOutputChannelCountSupported(PaOboeHostApiRepresentation *i_oboeHostApi, int32_t i_numOfChannels) { + if (i_numOfChannels > 2 || i_numOfChannels == 0) { LOGE("[PaOboe - IsOutputChannelCountSupported]\t Invalid channel count."); return paInvalidChannelCount; } - if (!(oboeHostApi->oboeEngine->tryStream(Direction::Output, - kUnspecified, - numOfChannels))) + if (!(i_oboeHostApi->oboeEngine->tryStream(Direction::Output, + kUnspecified, + i_numOfChannels))) LOGW("[PaOboe - IsOutputChannelCountSupported]\t Channel Count was changed by Oboe. The device might not support stereo audio."); /* Since Oboe manages the channel count in a smart way, we can avoid blocking the process if @@ -956,17 +965,15 @@ static PaError IsOutputChannelCountSupported( * @return PaNoError regardless of the outcome of the check, but warns in the Logs if the channel * count was changed by Oboe. */ -static PaError IsInputChannelCountSupported( - PaOboeHostApiRepresentation *oboeHostApi, - int32_t numOfChannels) { - if (numOfChannels > 2 || numOfChannels == 0) { +static PaError IsInputChannelCountSupported(PaOboeHostApiRepresentation *i_oboeHostApi, int32_t i_numOfChannels) { + if (i_numOfChannels > 2 || i_numOfChannels == 0) { LOGE("[PaOboe - IsInputChannelCountSupported]\t Invalid channel count."); return paInvalidChannelCount; } - if (!(oboeHostApi->oboeEngine->tryStream(Direction::Input, - kUnspecified, - numOfChannels))) + if (!(i_oboeHostApi->oboeEngine->tryStream(Direction::Input, + kUnspecified, + i_numOfChannels))) LOGW("[PaOboe - IsInputChannelCountSupported]\t Channel Count was changed by Oboe. The device might not support stereo audio."); /* Since Oboe manages the channel count in a smart way, we can avoid blocking the process if @@ -983,136 +990,133 @@ static PaError IsInputChannelCountSupported( * @param hostApiIndex is a PaHostApiIndex, the type used to enumerate the host APIs at runtime. * @return paNoError if no errors occur, or paInsufficientMemory if memory allocation fails; */ -PaError PaOboe_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex) { - PaError m_result = paNoError; - int m_deviceCount; - PaOboeHostApiRepresentation *m_oboeHostApi; - PaDeviceInfo *m_deviceInfoArray; - char *m_deviceName; - - m_oboeHostApi = (PaOboeHostApiRepresentation *) PaUtil_AllocateZeroInitializedMemory( +PaError PaOboe_Initialize(PaUtilHostApiRepresentation **i_hostApi, PaHostApiIndex i_hostApiIndex) { + PaError result = paNoError; + int deviceCount; + PaOboeHostApiRepresentation *oboeHostApi; + PaDeviceInfo *deviceInfoArray; + char *deviceName; + + oboeHostApi = (PaOboeHostApiRepresentation *) PaUtil_AllocateZeroInitializedMemory( sizeof(PaOboeHostApiRepresentation)); - if (!m_oboeHostApi) { - m_result = paInsufficientMemory; + if (!oboeHostApi) { + result = paInsufficientMemory; goto error; } - m_oboeHostApi->oboeEngine = new OboeEngine(); + oboeHostApi->oboeEngine = new OboeEngine(); - m_oboeHostApi->allocations = PaUtil_CreateAllocationGroup(); - if (!m_oboeHostApi->allocations) { - m_result = paInsufficientMemory; + oboeHostApi->allocations = PaUtil_CreateAllocationGroup(); + if (!oboeHostApi->allocations) { + result = paInsufficientMemory; goto error; } - *hostApi = &m_oboeHostApi->inheritedHostApiRep; + *i_hostApi = &oboeHostApi->inheritedHostApiRep; // Initialization of infos. - (*hostApi)->info.structVersion = 1; - (*hostApi)->info.type = paInDevelopment; - (*hostApi)->info.name = "android Oboe"; - (*hostApi)->info.defaultOutputDevice = 0; - (*hostApi)->info.defaultInputDevice = 0; - (*hostApi)->info.deviceCount = 0; - - - m_deviceCount = 1; - (*hostApi)->deviceInfos = (PaDeviceInfo **) PaUtil_GroupAllocateZeroInitializedMemory( - m_oboeHostApi->allocations, sizeof(PaDeviceInfo *) * m_deviceCount); - - if (!(*hostApi)->deviceInfos) { - m_result = paInsufficientMemory; + (*i_hostApi)->info.structVersion = 1; + (*i_hostApi)->info.type = paInDevelopment; + (*i_hostApi)->info.name = "android Oboe"; + (*i_hostApi)->info.defaultOutputDevice = 0; + (*i_hostApi)->info.defaultInputDevice = 0; + (*i_hostApi)->info.deviceCount = 0; + + deviceCount = 1; + (*i_hostApi)->deviceInfos = (PaDeviceInfo **) PaUtil_GroupAllocateZeroInitializedMemory( + oboeHostApi->allocations, sizeof(PaDeviceInfo * ) * deviceCount); + + if (!(*i_hostApi)->deviceInfos) { + result = paInsufficientMemory; goto error; } /* allocate all device info structs in a contiguous block */ - m_deviceInfoArray = (PaDeviceInfo *) PaUtil_GroupAllocateZeroInitializedMemory( - m_oboeHostApi->allocations, sizeof(PaDeviceInfo) * m_deviceCount); - if (!m_deviceInfoArray) { - m_result = paInsufficientMemory; + deviceInfoArray = (PaDeviceInfo *) PaUtil_GroupAllocateZeroInitializedMemory( + oboeHostApi->allocations, sizeof(PaDeviceInfo) * deviceCount); + if (!deviceInfoArray) { + result = paInsufficientMemory; goto error; } - for (int i = 0; i < m_deviceCount; ++i) { - PaDeviceInfo *m_deviceInfo = &m_deviceInfoArray[i]; - m_deviceInfo->structVersion = 2; - m_deviceInfo->hostApi = hostApiIndex; + for (int i = 0; i < deviceCount; ++i) { + PaDeviceInfo *deviceInfo = &deviceInfoArray[i]; + deviceInfo->structVersion = 2; + deviceInfo->hostApi = hostApiIndex; - /* OboeEngine will handle manual device selection through the use of - PaOboe_SetSelectedDevice via a JNI interface that can be implemented. + /* OboeEngine will handle manual device selection through the use of PaOboe_SetSelectedDevice. Portaudio doesn't need to know about this, so we just use a default device. */ - - m_deviceInfo->name = "default"; + deviceInfo->name = "default"; /* Try channels in order of preference - Stereo > Mono. */ - const int32_t m_channelsToTry[] = {2, 1}; - const int32_t m_channelsToTryLength = 2; + const int32_t channelsToTry[] = {2, 1}; + const int32_t channelsToTryLength = 2; - m_deviceInfo->maxOutputChannels = 0; - m_deviceInfo->maxInputChannels = 0; + deviceInfo->maxOutputChannels = 0; + deviceInfo->maxInputChannels = 0; - for (i = 0; i < m_channelsToTryLength; ++i) { - if (IsOutputChannelCountSupported(m_oboeHostApi, m_channelsToTry[i]) == paNoError) { - m_deviceInfo->maxOutputChannels = m_channelsToTry[i]; + for (i = 0; i < channelsToTryLength; ++i) { + if (IsOutputChannelCountSupported(oboeHostApi, channelsToTry[i]) == paNoError) { + deviceInfo->maxOutputChannels = channelsToTry[i]; break; } } - for (i = 0; i < m_channelsToTryLength; ++i) { - if (IsInputChannelCountSupported(m_oboeHostApi, m_channelsToTry[i]) == paNoError) { - m_deviceInfo->maxInputChannels = m_channelsToTry[i]; + for (i = 0; i < channelsToTryLength; ++i) { + if (IsInputChannelCountSupported(oboeHostApi, channelsToTry[i]) == paNoError) { + deviceInfo->maxInputChannels = channelsToTry[i]; break; } } /* check sample rates in order of preference */ - const int32_t m_sampleRates[] = {48000, 44100, 32000, 24000, 16000}; - const int32_t m_numberOfSampleRates = 5; + const int32_t sampleRates[] = {48000, 44100, 32000, 24000, 16000}; + const int32_t numberOfSampleRates = 5; - m_deviceInfo->defaultSampleRate = m_sampleRates[0]; + deviceInfo->defaultSampleRate = sampleRates[0]; - for (i = 0; i < m_numberOfSampleRates; ++i) { + for (i = 0; i < numberOfSampleRates; ++i) { if (IsOutputSampleRateSupported( - m_oboeHostApi, m_sampleRates[i]) == paNoError && + oboeHostApi, sampleRates[i]) == paNoError && IsInputSampleRateSupported( - m_oboeHostApi, m_sampleRates[i]) == paNoError) { - m_deviceInfo->defaultSampleRate = m_sampleRates[i]; + oboeHostApi, sampleRates[i]) == paNoError) { + deviceInfo->defaultSampleRate = sampleRates[i]; break; } } - if (m_deviceInfo->defaultSampleRate == 0) + if (deviceInfo->defaultSampleRate == 0) goto error; - /* If the user has set nativeBufferSize by querying the optimal buffer size via java, + /* If the user has set g_nativeBufferSize by querying the optimal buffer size via java, use the user-defined value since that will offer the lowest possible latency. */ - if (nativeBufferSize != 0) { - m_deviceInfo->defaultLowInputLatency = - (double) nativeBufferSize / m_deviceInfo->defaultSampleRate; - m_deviceInfo->defaultLowOutputLatency = - (double) nativeBufferSize / m_deviceInfo->defaultSampleRate; - m_deviceInfo->defaultHighInputLatency = - (double) nativeBufferSize * 4 / m_deviceInfo->defaultSampleRate; - m_deviceInfo->defaultHighOutputLatency = - (double) nativeBufferSize * 4 / m_deviceInfo->defaultSampleRate; + if (g_nativeBufferSize != 0) { + deviceInfo->defaultLowInputLatency = + (double) g_nativeBufferSize / deviceInfo->defaultSampleRate; + deviceInfo->defaultLowOutputLatency = + (double) g_nativeBufferSize / deviceInfo->defaultSampleRate; + deviceInfo->defaultHighInputLatency = + (double) g_nativeBufferSize * 4 / deviceInfo->defaultSampleRate; + deviceInfo->defaultHighOutputLatency = + (double) g_nativeBufferSize * 4 / deviceInfo->defaultSampleRate; } else { - m_deviceInfo->defaultLowInputLatency = - (double) GetApproximateLowBufferSize() / m_deviceInfo->defaultSampleRate; - m_deviceInfo->defaultLowOutputLatency = - (double) GetApproximateLowBufferSize() / m_deviceInfo->defaultSampleRate; - m_deviceInfo->defaultHighInputLatency = - (double) GetApproximateLowBufferSize() * 4 / m_deviceInfo->defaultSampleRate; - m_deviceInfo->defaultHighOutputLatency = - (double) GetApproximateLowBufferSize() * 4 / m_deviceInfo->defaultSampleRate; + deviceInfo->defaultLowInputLatency = + (double) GetApproximateLowBufferSize() / deviceInfo->defaultSampleRate; + deviceInfo->defaultLowOutputLatency = + (double) GetApproximateLowBufferSize() / deviceInfo->defaultSampleRate; + deviceInfo->defaultHighInputLatency = + (double) GetApproximateLowBufferSize() * 4 / deviceInfo->defaultSampleRate; + deviceInfo->defaultHighOutputLatency = + (double) GetApproximateLowBufferSize() * 4 / deviceInfo->defaultSampleRate; } - (*hostApi)->deviceInfos[i] = m_deviceInfo; - ++(*hostApi)->info.deviceCount; + (*i_hostApi)->deviceInfos[i] = deviceInfo; + ++(*i_hostApi)->info.deviceCount; } - (*hostApi)->Terminate = Terminate; - (*hostApi)->OpenStream = OpenStream; - (*hostApi)->IsFormatSupported = IsFormatSupported; + (*i_hostApi)->Terminate = Terminate; + (*i_hostApi)->OpenStream = OpenStream; + (*i_hostApi)->IsFormatSupported = IsFormatSupported; - PaUtil_InitializeStreamInterface(&m_oboeHostApi->callbackStreamInterface, + PaUtil_InitializeStreamInterface(&oboeHostApi->callbackStreamInterface, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, @@ -1121,7 +1125,7 @@ PaError PaOboe_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable); - PaUtil_InitializeStreamInterface(&m_oboeHostApi->blockingStreamInterface, + PaUtil_InitializeStreamInterface(&oboeHostApi->blockingStreamInterface, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, @@ -1129,23 +1133,23 @@ PaError PaOboe_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable); - if (m_result == paNoError) + if (result == paNoError) LOGV("[PaOboe - Initialize]\t Oboe host API successfully initialized"); else - LOGE("[PaOboe - Initialize]\t An unusual error occurred. Error code: %d", m_result); - return m_result; + LOGE("[PaOboe - Initialize]\t An unusual error occurred. Error code: %d", result); + return result; error: - if (m_oboeHostApi) { - if (m_oboeHostApi->allocations) { - PaUtil_FreeAllAllocations(m_oboeHostApi->allocations); - PaUtil_DestroyAllocationGroup(m_oboeHostApi->allocations); + if (oboeHostApi) { + if (oboeHostApi->allocations) { + PaUtil_FreeAllAllocations(oboeHostApi->allocations); + PaUtil_DestroyAllocationGroup(oboeHostApi->allocations); } - PaUtil_FreeMemory(m_oboeHostApi); + PaUtil_FreeMemory(boeHostApi); } - LOGE("[PaOboe - Initialize]\t Initialization failed. Error code: %d", m_result); - return m_result; + LOGE("[PaOboe - Initialize]\t Initialization failed. Error code: %d", result); + return result; } @@ -1154,21 +1158,21 @@ PaError PaOboe_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex * @param hostApi points towards a *HostApiRepresentation, which is a structure representing the * interface to a host API (see struct in "pa_hostapi.h"). */ -static void Terminate(struct PaUtilHostApiRepresentation *hostApi) { - auto *m_oboeHostApi = (PaOboeHostApiRepresentation *) hostApi; +static void Terminate(struct PaUtilHostApiRepresentation *i_hostApi) { + auto *oboeHostApi = (PaOboeHostApiRepresentation *) i_hostApi; - if (!(m_oboeHostApi->oboeEngine->closeStream())) + if (!(oboeHostApi->oboeEngine->closeStream(nullptr))) LOGW("[PaOboe - Terminate]\t Couldn't close the streams correctly - see OboeEngine::CloseStream logs."); - if(m_oboeHostApi->oboeEngine != nullptr) - delete m_oboeHostApi->oboeEngine; + if (oboeHostApi->oboeEngine != nullptr) + delete oboeHostApi->oboeEngine; - if (m_oboeHostApi->allocations) { - PaUtil_FreeAllAllocations(m_oboeHostApi->allocations); - PaUtil_DestroyAllocationGroup(m_oboeHostApi->allocations); + if (oboeHostApi->allocations) { + PaUtil_FreeAllAllocations(oboeHostApi->allocations); + PaUtil_DestroyAllocationGroup(oboeHostApi->allocations); } - PaUtil_FreeMemory(m_oboeHostApi); + PaUtil_FreeMemory(oboeHostApi); } @@ -1182,116 +1186,103 @@ static void Terminate(struct PaUtilHostApiRepresentation *hostApi) { * @return paNoError (== paFormatIsSupported) if no errors occur, otherwise returns an appropriate * PaError message. */ -static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *hostApi, - const PaStreamParameters *inputParameters, - const PaStreamParameters *outputParameters, - double sampleRate) { - PaError m_outcome; - int m_inputChannelCount, m_outputChannelCount; - PaSampleFormat m_inputSampleFormat, m_outputSampleFormat; - auto *m_oboeHostApi = (PaOboeHostApiRepresentation *) hostApi; - - if (inputParameters) { - m_inputChannelCount = inputParameters->channelCount; - m_inputSampleFormat = inputParameters->sampleFormat; +static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *i_hostApi, + const PaStreamParameters *i_inputParameters, + const PaStreamParameters *i_outputParameters, + double i_sampleRate) { + int inputChannelCount, outputChannelCount; + PaSampleFormat inputSampleFormat, outputSampleFormat; + auto *oboeHostApi = (PaOboeHostApiRepresentation *) i_hostApi; + + if (i_inputParameters) { + inputChannelCount = i_inputParameters->channelCount; + inputSampleFormat = i_inputParameters->sampleFormat; /* all standard sample formats are supported by the buffer adapter, this implementation doesn't support any custom sample formats */ - if (m_inputSampleFormat & paCustomFormat) { - m_outcome = paSampleFormatNotSupported; - return m_outcome; + if (inputSampleFormat & paCustomFormat) { + return paSampleFormatNotSupported; } /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ - if (inputParameters->device == paUseHostApiSpecificDeviceSpecification) { - m_outcome = paInvalidDevice; - return m_outcome; + if (i_inputParameters->device == paUseHostApiSpecificDeviceSpecification) { + return paInvalidDevice; } /* check that input device can support inputChannelCount */ - if (m_inputChannelCount > - hostApi->deviceInfos[inputParameters->device]->maxInputChannels) { - m_outcome = paInvalidChannelCount; - return m_outcome; + if (inputChannelCount > + i_hostApi->deviceInfos[i_inputParameters->device]->maxInputChannels) { + return paInvalidChannelCount; } /* validate inputStreamInfo */ - if (inputParameters->hostApiSpecificStreamInfo) { + if (i_inputParameters->hostApiSpecificStreamInfo) { // Only has an effect on ANDROID_API>=28. - InputPreset m_androidRecordingPreset = - ((PaOboeStreamInfo *) outputParameters->hostApiSpecificStreamInfo)->androidInputPreset; - if (m_androidRecordingPreset != InputPreset::Generic && - m_androidRecordingPreset != InputPreset::Camcorder && - m_androidRecordingPreset != InputPreset::VoiceRecognition && - m_androidRecordingPreset != InputPreset::VoiceCommunication - m_androidRecordingPreset != InputPreset::VoicePerformance - ) { - m_outcome = paIncompatibleHostApiSpecificStreamInfo; - return m_outcome; + InputPreset androidRecordingPreset = + ((PaOboeStreamInfo *) i_inputParameters->hostApiSpecificStreamInfo)->androidInputPreset; + if (androidRecordingPreset != InputPreset::Generic && + androidRecordingPreset != InputPreset::Camcorder && + androidRecordingPreset != InputPreset::VoiceRecognition && + androidRecordingPreset != InputPreset::VoiceCommunication + androidRecordingPreset != InputPreset::VoicePerformance) { + return paIncompatibleHostApiSpecificStreamInfo; } } } else { - m_inputChannelCount = 0; + inputChannelCount = 0; } - if (outputParameters) { - m_outputChannelCount = outputParameters->channelCount; - m_outputSampleFormat = outputParameters->sampleFormat; + if (i_outputParameters) { + outputChannelCount = i_outputParameters->channelCount; + outputSampleFormat = i_outputParameters->sampleFormat; /* all standard sample formats are supported by the buffer adapter, this implementation doesn't support any custom sample formats */ - if (m_outputSampleFormat & paCustomFormat) { - m_outcome = paSampleFormatNotSupported; - return m_outcome; + if (outputSampleFormat & paCustomFormat) { + return paSampleFormatNotSupported; } /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ - if (outputParameters->device == paUseHostApiSpecificDeviceSpecification) { - m_outcome = paInvalidDevice; - return m_outcome; + if (i_outputParameters->device == paUseHostApiSpecificDeviceSpecification) { + return paInvalidDevice; } /* check that output device can support outputChannelCount */ - if (m_outputChannelCount > - hostApi->deviceInfos[outputParameters->device]->maxOutputChannels) { - m_outcome = paInvalidChannelCount; - return m_outcome; + if (outputChannelCount > + i_hostApi->deviceInfos[i_outputParameters->device]->maxOutputChannels) { + return paInvalidChannelCount; } /* validate outputStreamInfo */ - if (outputParameters->hostApiSpecificStreamInfo) { + if (i_outputParameters->hostApiSpecificStreamInfo) { // Only has an effect on ANDROID_API>=28. - Usage m_androidOutputUsage = - ((PaOboeStreamInfo *) outputParameters->hostApiSpecificStreamInfo)->androidOutputUsage; - if (m_androidOutputUsage != Usage::Media && - m_androidOutputUsage != Usage::Notification && - m_androidOutputUsage != Usage::NotificationEvent && - m_androidOutputUsage != Usage::NotificationRingtone && - m_androidOutputUsage != Usage::VoiceCommunication && - m_androidOutputUsage != Usage::VoiceCommunicationSignalling && - m_androidOutputUsage != Usage::Alarm && - m_androidOutputUsage != Usage::Game - ) { - m_outcome = paIncompatibleHostApiSpecificStreamInfo; - return m_outcome; + Usage androidOutputUsage = + ((PaOboeStreamInfo *) i_outputParameters->hostApiSpecificStreamInfo)->androidOutputUsage; + if (androidOutputUsage != Usage::Media && + androidOutputUsage != Usage::Notification && + androidOutputUsage != Usage::NotificationEvent && + androidOutputUsage != Usage::NotificationRingtone && + androidOutputUsage != Usage::VoiceCommunication && + androidOutputUsage != Usage::VoiceCommunicationSignalling && + androidOutputUsage != Usage::Alarm && + androidOutputUsage != Usage::Game) { + return paIncompatibleHostApiSpecificStreamInfo; } } } else { - m_outputChannelCount = 0; + outputChannelCount = 0; } - if (m_outputChannelCount > 0) { - if (IsOutputSampleRateSupported(m_oboeHostApi, sampleRate) != paNoError) { - m_outcome = paInvalidSampleRate; - return m_outcome; + if (outputChannelCount > 0) { + if (IsOutputSampleRateSupported(oboeHostApi, i_sampleRate) != paNoError) { + return paInvalidSampleRate; } } - if (m_inputChannelCount > 0) { - if (IsInputSampleRateSupported(m_oboeHostApi, sampleRate) != paNoError) { - m_outcome = paInvalidSampleRate; - return m_outcome; + if (inputChannelCount > 0) { + if (IsInputSampleRateSupported(oboeHostApi, i_sampleRate) != paNoError) { + return paInvalidSampleRate; } } @@ -1310,14 +1301,14 @@ static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *hostApi, * the correct amount of memory. * @return the value returned by OboeEngine::openStream. */ -static PaError InitializeOutputStream(PaOboeHostApiRepresentation *oboeHostApi, - Usage androidOutputUsage, double sampleRate) { - - return oboeHostApi->oboeEngine->openStream(Direction::Output, - sampleRate, - androidOutputUsage, - Generic //Won't be used, so we put the default value. - ); +static PaError InitializeOutputStream(PaOboeHostApiRepresentation *i_oboeHostApi, + Usage i_androidOutputUsage, double i_sampleRate) { + + return i_oboeHostApi->oboeEngine->openStream(i_oboeStream, + Direction::Output, + sampleRate, + androidOutputUsage, + Generic); //Input preset won't be used, so we put the default value. } @@ -1332,14 +1323,14 @@ static PaError InitializeOutputStream(PaOboeHostApiRepresentation *oboeHostApi, * the correct amount of memory. * @return the value returned by OboeEngine::openStream. */ -static PaError InitializeInputStream(PaOboeHostApiRepresentation *oboeHostApi, - InputPreset androidInputPreset, double sampleRate) { - - return oboeHostApi->oboeEngine->openStream(Direction::Input, - sampleRate, - Usage::Media, //Won't be used, so we put the default value. - androidInputPreset - ); +static PaError InitializeInputStream(OboeStream i_oboeStream, PaOboeHostApiRepresentation *i_oboeHostApi, + InputPreset i_androidInputPreset, double i_sampleRate) { + + return i_oboeHostApi->oboeEngine->openStream(i_oboeStream, + Direction::Input, + i_sampleRate, + Usage::Media, //Usage won't be used, so we put the default value. + i_androidInputPreset); } @@ -1360,203 +1351,200 @@ static PaError InitializeInputStream(PaOboeHostApiRepresentation *oboeHostApi, * manipulation or checks. * @return paNoError if no errors occur, or other error codes accordingly with what goes wrong. */ -static PaError OpenStream(struct PaUtilHostApiRepresentation *hostApi, - PaStream **s, - const PaStreamParameters *inputParameters, - const PaStreamParameters *outputParameters, - double sampleRate, - unsigned long framesPerBuffer, - PaStreamFlags streamFlags, - PaStreamCallback *streamCallback, - void *userData) { - PaError m_error = paNoError; - auto m_oboeHostApi = (PaOboeHostApiRepresentation *) hostApi; - unsigned long m_framesPerHostBuffer; /* these may not be equivalent for all implementations */ - int m_inputChannelCount, m_outputChannelCount; - PaSampleFormat m_inputSampleFormat, m_outputSampleFormat; - PaSampleFormat m_hostInputSampleFormat, m_hostOutputSampleFormat; - - - //FIXME: add a function that lets the user choose usage and preset - Usage m_androidOutputUsage = Usage::VoiceCommunication; - InputPreset m_androidInputPreset = InputPreset::Generic; - - OboeStream *m_oboeStream = m_oboeHostApi->oboeEngine->initializeOboeStream(); - - if (!m_oboeStream) { - m_error = paInsufficientMemory; +static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, + PaStream **i_paStream, + const PaStreamParameters *i_inputParameters, + const PaStreamParameters *i_outputParameters, + double i_sampleRate, + unsigned long i_framesPerBuffer, + PaStreamFlags i_streamFlags, + PaStreamCallback *i_streamCallback, + void *i_userData) { + PaError error = paNoError; + auto oboeHostApi = (PaOboeHostApiRepresentation *) i_hostApi; + unsigned long framesPerHostBuffer; /* these may not be equivalent for all implementations */ + int inputChannelCount, outputChannelCount; + PaSampleFormat inputSampleFormat, outputSampleFormat; + PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat; + + + //TODO: add a function that lets the user choose usage and preset + Usage androidOutputUsage = Usage::VoiceCommunication; + InputPreset androidInputPreset = InputPreset::Generic; + + OboeStream *oboeStream = oboeHostApi->oboeEngine->allocateOboeStream(); + + if (!oboeStream) { + error = paInsufficientMemory; goto error; } LOGI("[PaOboe - OpenStream]\t OpenStream called."); - if (inputParameters) { - m_inputChannelCount = inputParameters->channelCount; - m_inputSampleFormat = inputParameters->sampleFormat; + if (i_inputParameters) { + inputChannelCount = i_inputParameters->channelCount; + inputSampleFormat = i_inputParameters->sampleFormat; - /* Oboe supports alternate device specification with API>=28, but for now we reject the use of - paUseHostApiSpecificDeviceSpecification and stick with the default.*/ - if (inputParameters->device == paUseHostApiSpecificDeviceSpecification) + /* Oboe supports alternate device specification with API>=28, but here we reject the use of + paUseHostApiSpecificDeviceSpecification and stick with the default. Devices can be set via + PaOboe_SetSelectedDevice. */ + if (i_inputParameters->device == paUseHostApiSpecificDeviceSpecification) return paInvalidDevice; /* check that input device can support inputChannelCount */ - if (m_inputChannelCount > hostApi->deviceInfos[inputParameters->device]->maxInputChannels) + if (inputChannelCount > i_hostApi->deviceInfos[i_inputParameters->device]->maxInputChannels) return paInvalidChannelCount; /* validate inputStreamInfo */ - if (inputParameters->hostApiSpecificStreamInfo) { + if (i_inputParameters->hostApiSpecificStreamInfo) { // Only has an effect on ANDROID_API>=28. - m_androidInputPreset = - ((PaOboeStreamInfo *) outputParameters->hostApiSpecificStreamInfo)->androidInputPreset; - if (m_androidInputPreset != InputPreset::Generic && - m_androidInputPreset != InputPreset::Camcorder && - m_androidInputPreset != InputPreset::VoiceRecognition && - m_androidInputPreset != InputPreset::VoiceCommunication - m_androidInputPreset != InputPreset::VoicePerformance - ) + androidInputPreset = + ((PaOboeStreamInfo *) i_outputParameters->hostApiSpecificStreamInfo)->androidInputPreset; + if (androidInputPreset != InputPreset::Generic && + androidInputPreset != InputPreset::Camcorder && + androidInputPreset != InputPreset::VoiceRecognition && + androidInputPreset != InputPreset::VoiceCommunication + androidInputPreset != InputPreset::VoicePerformance) return paIncompatibleHostApiSpecificStreamInfo; } /* FIXME: Replace "paFloat32" with whatever format you prefer - * PaUtil_SelectClosestAvailableFormat is a bit faulty when working with multiple options */ - m_hostInputSampleFormat = PaUtil_SelectClosestAvailableFormat( - paFloat32, m_inputSampleFormat); - m_oboeStream->inputFormat = m_hostInputSampleFormat; + hostInputSampleFormat = PaUtil_SelectClosestAvailableFormat( + paFloat32, inputSampleFormat); + oboeStream->inputFormat = hostInputSampleFormat; } else { - m_inputChannelCount = 0; - m_inputSampleFormat = m_hostInputSampleFormat = paFloat32; /* Surpress 'uninitialised var' warnings. */ - m_oboeStream->inputFormat = m_hostInputSampleFormat; + inputChannelCount = 0; + inputSampleFormat = hostInputSampleFormat = paFloat32; /* Surpress 'uninitialised var' warnings. */ + oboeStream->inputFormat = hostInputSampleFormat; } - if (outputParameters) { - m_outputChannelCount = outputParameters->channelCount; - m_outputSampleFormat = outputParameters->sampleFormat; + if (i_outputParameters) { + outputChannelCount = i_outputParameters->channelCount; + outputSampleFormat = i_outputParameters->sampleFormat; - /* Oboe supports alternate device specification with API>=28, but for now we reject the use of - paUseHostApiSpecificDeviceSpecification and stick with the default.*/ - if (outputParameters->device == paUseHostApiSpecificDeviceSpecification) + /* Oboe supports alternate device specification with API>=28, but here we reject the use of + paUseHostApiSpecificDeviceSpecification and stick with the default. Devices can be set via + PaOboe_SetSelectedDevice. */ + if (i_outputParameters->device == paUseHostApiSpecificDeviceSpecification) return paInvalidDevice; /* check that output device can support outputChannelCount */ - if (m_outputChannelCount > - hostApi->deviceInfos[outputParameters->device]->maxOutputChannels) + if (outputChannelCount > + i_hostApi->deviceInfos[i_outputParameters->device]->maxOutputChannels) return paInvalidChannelCount; /* validate outputStreamInfo */ - if (outputParameters->hostApiSpecificStreamInfo) { - m_androidOutputUsage = - ((PaOboeStreamInfo *) outputParameters->hostApiSpecificStreamInfo)->androidOutputUsage; - if (m_androidOutputUsage != Usage::Media && - m_androidOutputUsage != Usage::Notification && - m_androidOutputUsage != Usage::NotificationEvent && - m_androidOutputUsage != Usage::NotificationRingtone && - m_androidOutputUsage != Usage::VoiceCommunication && - m_androidOutputUsage != Usage::VoiceCommunicationSignalling && - m_androidOutputUsage != Usage::Alarm - // See if more are needed. - ) + if (i_outputParameters->hostApiSpecificStreamInfo) { + androidOutputUsage = + ((PaOboeStreamInfo *) i_outputParameters->hostApiSpecificStreamInfo)->androidOutputUsage; + if (androidOutputUsage != Usage::Media && + androidOutputUsage != Usage::Notification && + androidOutputUsage != Usage::NotificationEvent && + androidOutputUsage != Usage::NotificationRingtone && + androidOutputUsage != Usage::VoiceCommunication && + androidOutputUsage != Usage::VoiceCommunicationSignalling && + androidOutputUsage != Usage::Alarm && + androidOutputUsage != Usage::Game) return paIncompatibleHostApiSpecificStreamInfo; } /* FIXME: Replace "paFloat32" with whatever format you prefer - PaUtil_SelectClosestAvailableFormat is a bit faulty when working with multiple options */ - m_hostOutputSampleFormat = PaUtil_SelectClosestAvailableFormat( + hostOutputSampleFormat = PaUtil_SelectClosestAvailableFormat( paFloat32, m_outputSampleFormat); - m_oboeStream->outputFormat = m_hostOutputSampleFormat; + oboeStream->outputFormat = hostOutputSampleFormat; } else { - m_outputChannelCount = 0; - m_outputSampleFormat = m_hostOutputSampleFormat = paFloat32; - m_oboeStream->outputFormat = m_hostOutputSampleFormat; + outputChannelCount = 0; + outputSampleFormat = hostOutputSampleFormat = paFloat32; + oboeStream->outputFormat = hostOutputSampleFormat; } /* validate platform specific flags */ - if ((streamFlags & paPlatformSpecificFlags) != 0) + if ((i_streamFlags & paPlatformSpecificFlags) != 0) return paInvalidFlag; /* unexpected platform specific flag */ - if (framesPerBuffer == paFramesPerBufferUnspecified) { - if (outputParameters) { - m_framesPerHostBuffer = - (unsigned long) (outputParameters->suggestedLatency * sampleRate); + if (i_framesPerBuffer == paFramesPerBufferUnspecified) { + if (i_outputParameters) { + framesPerHostBuffer = + (unsigned long) (i_outputParameters->suggestedLatency * i_sampleRate); } else { - m_framesPerHostBuffer = - (unsigned long) (inputParameters->suggestedLatency * sampleRate); + framesPerHostBuffer = + (unsigned long) (i_inputParameters->suggestedLatency * i_sampleRate); } } else { - m_framesPerHostBuffer = framesPerBuffer; + framesPerHostBuffer = i_framesPerBuffer; } - m_oboeHostApi->oboeEngine->setEngineAddress( - reinterpret_cast(m_oboeHostApi->oboeEngine)); - - if (streamCallback) { - PaUtil_InitializeStreamRepresentation(&(m_oboeStream->streamRepresentation), - &m_oboeHostApi->callbackStreamInterface, - streamCallback, userData); + if (i_streamCallback) { + PaUtil_InitializeStreamRepresentation(&(oboeStream->streamRepresentation), + &oboeHostApi->callbackStreamInterface, + i_streamCallback, i_userData); } else { - PaUtil_InitializeStreamRepresentation(&(m_oboeStream->streamRepresentation), - &m_oboeHostApi->blockingStreamInterface, - streamCallback, userData); + PaUtil_InitializeStreamRepresentation(&(oboeStream->streamRepresentation), + &oboeHostApi->blockingStreamInterface, + i_streamCallback, i_userData); } - PaUtil_InitializeCpuLoadMeasurer(&(m_oboeStream->cpuLoadMeasurer), sampleRate); - - m_error = PaUtil_InitializeBufferProcessor(&(m_oboeStream->bufferProcessor), - m_inputChannelCount, - m_inputSampleFormat, - m_hostInputSampleFormat, - m_outputChannelCount, - m_outputSampleFormat, - m_hostOutputSampleFormat, - sampleRate, streamFlags, - framesPerBuffer, - m_framesPerHostBuffer, - paUtilFixedHostBufferSize, - streamCallback, userData); - if (m_error != paNoError) + PaUtil_InitializeCpuLoadMeasurer(&(oboeStream->cpuLoadMeasurer), i_sampleRate); + + error = PaUtil_InitializeBufferProcessor(&(oboeStream->bufferProcessor), + inputChannelCount, + inputSampleFormat, + hostInputSampleFormat, + outputChannelCount, + outputSampleFormat, + hostOutputSampleFormat, + i_sampleRate, i_streamFlags, + i_framesPerBuffer, + framesPerHostBuffer, + paUtilFixedHostBufferSize, + i_streamCallback, i_userData); + if (error != paNoError) goto error; - m_oboeStream->streamRepresentation.streamInfo.sampleRate = sampleRate; - m_oboeStream->isBlocking = (streamCallback == nullptr); - m_oboeStream->framesPerHostCallback = m_framesPerHostBuffer; - m_oboeStream->bytesPerFrame = sizeof(int16_t); - m_oboeStream->cbFlags = 0; - m_oboeStream->isStopped = true; - m_oboeStream->isActive = false; + oboeStream->streamRepresentation.streamInfo.sampleRate = i_sampleRate; + oboeStream->isBlocking = (i_streamCallback == nullptr); + oboeStream->framesPerHostCallback = framesPerHostBuffer; + oboeStream->bytesPerFrame = sizeof(int16_t); + oboeStream->cbFlags = 0; + oboeStream->isStopped = true; + oboeStream->isActive = false; - if (!(m_oboeStream->isBlocking)) {} + if (!(oboeStream->isBlocking)) {} // PaUnixThreading_Initialize(); TODO: see if threading works with this version of PortAudio - if (m_inputChannelCount > 0) { - m_oboeStream->hasInput = true; - m_oboeStream->streamRepresentation.streamInfo.inputLatency = + if (inputChannelCount > 0) { + oboeStream->hasInput = true; + oboeStream->streamRepresentation.streamInfo.inputLatency = ((PaTime) PaUtil_GetBufferProcessorInputLatencyFrames( - &(m_oboeStream->bufferProcessor)) + - m_oboeStream->framesPerHostCallback) / sampleRate; - ENSURE(InitializeInputStream(m_oboeHostApi, - m_androidInputPreset, sampleRate), + &(oboeStream->bufferProcessor)) + + oboeStream->framesPerHostCallback) / i_sampleRate; + ENSURE(InitializeInputStream(oboeStream, oboeHostApi, + androidInputPreset, i_sampleRate), "Initializing inputstream failed") - } else { m_oboeStream->hasInput = false; } + } else { oboeStream->hasInput = false; } - if (m_outputChannelCount > 0) { - m_oboeStream->hasOutput = true; - m_oboeStream->streamRepresentation.streamInfo.outputLatency = + if (outputChannelCount > 0) { + oboeStream->hasOutput = true; + oboeStream->streamRepresentation.streamInfo.outputLatency = ((PaTime) PaUtil_GetBufferProcessorOutputLatencyFrames( - &m_oboeStream->bufferProcessor) - + m_oboeStream->framesPerHostCallback) / sampleRate; - ENSURE(InitializeOutputStream(m_oboeHostApi, - m_androidOutputUsage, sampleRate), + &oboeStream->bufferProcessor) + + oboeStream->framesPerHostCallback) / i_sampleRate; + ENSURE(InitializeOutputStream(oboeHostApi, + androidOutputUsage, i_sampleRate), "Initializing outputstream failed"); - } else { m_oboeStream->hasOutput = false; } + } else { oboeStream->hasOutput = false; } - *s = (PaStream *) m_oboeStream; - return m_error; + *i_paStream = (PaStream *) oboeStream; + return error; error: - if (m_oboeStream) - PaUtil_FreeMemory(m_oboeStream); + if (oboeStream) + PaUtil_FreeMemory(oboeStream); - LOGE("[PaOboe - OpenStream]\t Error opening stream(s). Error code: %d", m_error); + LOGE("[PaOboe - OpenStream]\t Error opening stream(s). Error code: %d", error); - return m_error; + return error; } @@ -1568,29 +1556,29 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *hostApi, * portaudio, which holds the information of our OboeStream. * @return paNoError, but warns in the logs if OboeEngine::closeStream failed. */ -static PaError CloseStream(PaStream *s) { - auto *m_stream = (OboeStream *) s; - auto *m_oboeEngine = reinterpret_cast(m_stream->engineAddress); +static PaError CloseStream(PaStream *i_paStream) { + auto *oboeStream = (OboeStream *) i_paStream; + auto *oboeEngine = oboeStream->getEngineAddress(); - if (!(m_oboeEngine->closeStream())) - LOGW("[PaOboe - CloseStream]\t Couldn't close the stream(s) correctly - see OboeEngine::CloseStream logs."); + if (!(oboeEngine->closeStream(oboeStream))) + LOGW("[PaOboe - CloseStream]\t Some errors have occurred in closing oboe streams - see OboeEngine::CloseStream logs."); - PaUtil_TerminateBufferProcessor(&m_stream->bufferProcessor); - PaUtil_TerminateStreamRepresentation(&m_stream->streamRepresentation); + PaUtil_TerminateBufferProcessor(&oboeStream->bufferProcessor); + PaUtil_TerminateStreamRepresentation(&oboeStream->streamRepresentation); - for (int i = 0; i < numberOfBuffers; ++i) { - if (m_stream->hasOutput) - PaUtil_FreeMemory(m_stream->outputBuffers[i]); - if (m_stream->hasInput) - PaUtil_FreeMemory(m_stream->inputBuffers[i]); + for (int i = 0; i < g_numberOfBuffers; ++i) { + if (oboeStream->hasOutput) + PaUtil_FreeMemory(oboeStream->outputBuffers[i]); + if (oboeStream->hasInput) + PaUtil_FreeMemory(oboeStream->inputBuffers[i]); } - if (m_stream->hasOutput) - PaUtil_FreeMemory(m_stream->outputBuffers); - if (m_stream->hasInput) - PaUtil_FreeMemory(m_stream->inputBuffers); + if (oboeStream->hasOutput) + PaUtil_FreeMemory(oboeStream->outputBuffers); + if (oboeStream->hasInput) + PaUtil_FreeMemory(oboeStream->inputBuffers); - PaUtil_FreeMemory(m_stream); + PaUtil_FreeMemory(oboeStream); return paNoError; } @@ -1602,53 +1590,52 @@ static PaError CloseStream(PaStream *s) { * portaudio, which holds the information of our OboeStream. * @return paNoError if no errors occur, paUnanticipatedHostError if OboeEngine::startStream fails. */ -static PaError StartStream(PaStream *s) { - auto *m_stream = (OboeStream *) s; - auto *m_oboeEngine = reinterpret_cast(m_stream->engineAddress); +static PaError StartStream(PaStream *i_paStream) { + auto *oboeStream = (OboeStream *) i_paStream; + auto *oboeEngine = oboeStream->getEngineAddress(); - PaUtil_ResetBufferProcessor(&m_stream->bufferProcessor); + PaUtil_ResetBufferProcessor(&oboeStream->bufferProcessor); - //Checking if the stream(s) are already active. TODO: check if it's working as expected (extensive testing needed, no problem spotted with situational tests) - if (m_stream->isActive) { + //Checking if the stream(s) are already active. + //TODO: check if it's working as expected (extensive testing needed, no problem spotted with situational tests) + if (oboeStream->isActive) { LOGW("[PaOboe - StartStream]\t Stream was already active, stopping..."); - StopStream(s); + StopStream(i_paStream); LOGW("[PaOboe - StartStream]\t Restarting..."); - StartStream(s); + StartStream(i_paStream); } - m_stream->currentOutputBuffer = 0; - m_stream->currentInputBuffer = 0; + oboeStream->currentOutputBuffer = 0; + oboeStream->currentInputBuffer = 0; /* Initialize buffers */ - for (int i = 0; i < numberOfBuffers; ++i) { - if (m_stream->hasOutput) { - memset(m_stream->outputBuffers[m_stream->currentOutputBuffer], 0, - m_stream->framesPerHostCallback * m_stream->bytesPerFrame * - m_stream->bufferProcessor.outputChannelCount - ); - m_stream->currentOutputBuffer = (m_stream->currentOutputBuffer + 1) % numberOfBuffers; + for (int i = 0; i < g_numberOfBuffers; ++i) { + if (oboeStream->hasOutput) { + memset(oboeStream->outputBuffers[oboeStream->currentOutputBuffer], 0, + oboeStream->framesPerHostCallback * oboeStream->bytesPerFrame * + oboeStream->bufferProcessor.outputChannelCount); + oboeStream->currentOutputBuffer = (oboeStream->currentOutputBuffer + 1) % g_numberOfBuffers; } - if (m_stream->hasInput) { - memset(m_stream->inputBuffers[m_stream->currentInputBuffer], 0, - m_stream->framesPerHostCallback * m_stream->bytesPerFrame * - m_stream->bufferProcessor.inputChannelCount - ); - m_stream->currentInputBuffer = (m_stream->currentInputBuffer + 1) % numberOfBuffers; + if (oboeStream->hasInput) { + memset(oboeStream->inputBuffers[oboeStream->currentInputBuffer], 0, + oboeStream->framesPerHostCallback * oboeStream->bytesPerFrame * + oboeStream->bufferProcessor.inputChannelCount); + oboeStream->currentInputBuffer = (oboeStream->currentInputBuffer + 1) % g_numberOfBuffers; } } /* Start the processing thread.*/ - if (!m_stream->isBlocking) { - m_stream->callbackResult = paContinue; - m_stream->oboeCallbackResult = DataCallbackResult::Continue; + if (!oboeStream->isBlocking) { + oboeStream->callbackResult = paContinue; + oboeStream->oboeCallbackResult = DataCallbackResult::Continue; } - m_stream->isStopped = false; - m_stream->isActive = true; - m_stream->doStop = false; - m_stream->doAbort = false; + oboeStream->isStopped = false; + oboeStream->isActive = true; + oboeStream->doStop = false; + oboeStream->doAbort = false; - if (!(m_oboeEngine->startStream())) + if (!(oboeEngine->startStream(oboeStream))) return paUnanticipatedHostError; else return paNoError; @@ -1662,30 +1649,30 @@ static PaError StartStream(PaStream *s) { * portaudio, which holds the information of our OboeStream. * @return paNoError if no errors occur, paUnanticipatedHostError if OboeStream::stopStream fails. */ -static PaError StopStream(PaStream *s) { - PaError m_error = paNoError; - auto *m_stream = (OboeStream *) s; - auto *m_oboeEngine = reinterpret_cast(m_stream->engineAddress); +static PaError StopStream(PaStream *i_paStream) { + PaError error = paNoError; + auto *oboeStream = (OboeStream *) i_paStream; + auto *oboeEngine = oboeStream->getEngineAddress(); - if (m_stream->isStopped) { + if (oboeStream->isStopped) { LOGW("[PaOboe - StopStream]\t Stream was already stopped."); } else { - if (!(m_stream->isBlocking)) { - m_stream->doStop = true; + if (!(oboeStream->isBlocking)) { + oboeStream->doStop = true; } - if (!(m_oboeEngine->stopStream())) { + if (!(oboeEngine->stopStream(oboeStream))) { LOGE("[PaOboe - StopStream]\t Couldn't stop the stream(s) correctly - see OboeEngine::StopStream logs."); - m_error = paUnanticipatedHostError; + error = paUnanticipatedHostError; } - m_stream->isActive = false; - m_stream->isStopped = true; - if (m_stream->streamRepresentation.streamFinishedCallback != nullptr) - m_stream->streamRepresentation.streamFinishedCallback( - m_stream->streamRepresentation.userData); + oboeStream->isActive = false; + oboeStream->isStopped = true; + if (oboeStream->streamRepresentation.streamFinishedCallback != nullptr) + oboeStream->streamRepresentation.streamFinishedCallback( + oboeStream->streamRepresentation.userData); } - return m_error; + return error; } @@ -1696,29 +1683,29 @@ static PaError StopStream(PaStream *s) { * portaudio, which holds the information of our OboeStream. * @return paNoError if no errors occur, paUnanticipatedHostError if OboeStream::abortStream fails. */ -static PaError AbortStream(PaStream *s) { - PaError m_error = paNoError; - auto *m_stream = (OboeStream *) s; - auto *m_oboeEngine = reinterpret_cast(m_stream->engineAddress); +static PaError AbortStream(PaStream *i_paStream) { + PaError error = paNoError; + auto *oboeStream = (OboeStream *) i_paStream; + auto *oboeEngine = oboeStream->getEngineAddress(); LOGI("[PaOboe - AbortStream]\t Aborting stream."); - if (!m_stream->isBlocking) { - m_stream->doAbort = true; + if (!oboeStream->isBlocking) { + oboeStream->doAbort = true; } /* stop immediately so enqueue has no effect */ - if (!(m_oboeEngine->abortStream())) { + if (!(oboeEngine->abortStream(oboeStream))) { LOGE("[PaOboe - AbortStream]\t Couldn't abort the stream - see OboeEngine::abortStream logs."); - m_error = paUnanticipatedHostError; + error = paUnanticipatedHostError; } - m_stream->isActive = false; - m_stream->isStopped = true; - if (m_stream->streamRepresentation.streamFinishedCallback != nullptr) - m_stream->streamRepresentation.streamFinishedCallback( - m_stream->streamRepresentation.userData); + oboeStream->isActive = false; + oboeStream->isStopped = true; + if (oboeStream->streamRepresentation.streamFinishedCallback != nullptr) + oboeStream->streamRepresentation.streamFinishedCallback( + oboeStream->streamRepresentation.userData); - return m_error; + return error; } @@ -1730,26 +1717,25 @@ static PaError AbortStream(PaStream *s) { * @param frames is the total number of frames to read. * @return paInternalError if OboeEngine::readStream fails, paNoError otherwise. */ -static PaError ReadStream(PaStream *s, void *buffer, unsigned long frames) { - auto *m_stream = (OboeStream *) s; - auto *m_oboeEngine = reinterpret_cast(m_stream->engineAddress); - void *m_userBuffer = buffer; - unsigned m_framesToRead; - PaError m_error = paNoError; - - while (frames > 0) { - m_framesToRead = PA_MIN(m_stream->framesPerHostCallback, frames); - - if (!(m_oboeEngine->readStream(m_userBuffer, - m_framesToRead * - m_stream->bufferProcessor.inputChannelCount))) - m_error = paInternalError; - - m_stream->currentInputBuffer = (m_stream->currentInputBuffer + 1) % numberOfBuffers; - frames -= m_framesToRead; +static PaError ReadStream(PaStream *i_paStream, void *i_buffer, unsigned long i_frames) { + auto *oboeStream = (OboeStream *) i_paStream; + auto *oboeEngine = oboeStream->getEngineAddress(); + void *userBuffer = i_buffer; + unsigned framesToRead; + PaError error = paNoError; + + while (i_frames > 0) { + framesToRead = PA_MIN(oboeStream->framesPerHostCallback, i_frames); + + if (!(oboeEngine->readStream(userBuffer, framesToRead * + oboeStream->bufferProcessor.inputChannelCount))) + error = paInternalError; + + oboeStream->currentInputBuffer = (oboeStream->currentInputBuffer + 1) % g_numberOfBuffers; + i_frames -= framesToRead; } - return m_error; + return error; } @@ -1761,26 +1747,25 @@ static PaError ReadStream(PaStream *s, void *buffer, unsigned long frames) { * @param frames is the total number of frames to write. * @return paInternalError if OboeEngine::writeStream fails, paNoError otherwise. */ -static PaError WriteStream(PaStream *s, const void *buffer, unsigned long frames) { - auto *m_stream = (OboeStream *) s; - auto *m_oboeEngine = reinterpret_cast(m_stream->engineAddress); - const void *m_userBuffer = buffer; - unsigned m_framesToWrite; - PaError m_error = paNoError; - - while (frames > 0) { - m_framesToWrite = PA_MIN(m_stream->framesPerHostCallback, frames); - - if (!(m_oboeEngine->writeStream(m_userBuffer, - m_framesToWrite * - m_stream->bufferProcessor.outputChannelCount))) - m_error = paInternalError; - - m_stream->currentOutputBuffer = (m_stream->currentOutputBuffer + 1) % numberOfBuffers; - frames -= m_framesToWrite; +static PaError WriteStream(PaStream *i_paStream, const void *i_buffer, unsigned long i_frames) { + auto *oboeStream = (OboeStream *) i_paStream; + auto *oboeEngine = oboeStream->getEngineAddress(); + const void *userBuffer = i_buffer; + unsigned framesToWrite; + PaError error = paNoError; + + while (i_frames > 0) { + framesToWrite = PA_MIN(stream->framesPerHostCallback, i_frames); + + if (!(oboeEngine->writeStream(userBuffer, framesToWrite * + oboeStream->bufferProcessor.outputChannelCount))) + error = paInternalError; + + oboeStream->currentOutputBuffer = (oboeStream->currentOutputBuffer + 1) % g_numberOfBuffers; + i_frames -= framesToWrite; } - return m_error; + return error; } @@ -1792,9 +1777,9 @@ static PaError WriteStream(PaStream *s, const void *buffer, unsigned long frames * portaudio, which holds the information of our OboeStream. * @return the minimum number of frames that can be read without waiting. */ -static signed long GetStreamReadAvailable(PaStream *s) { - auto *m_stream = (OboeStream *) s; - return m_stream->framesPerHostCallback * (numberOfBuffers - m_stream->currentInputBuffer); +static signed long GetStreamReadAvailable(PaStream *i_paStream) { + auto *oboeStream = (OboeStream *) i_paStream; + return oboeStream->framesPerHostCallback * (g_numberOfBuffers - oboeStream->currentInputBuffer); } @@ -1804,9 +1789,9 @@ static signed long GetStreamReadAvailable(PaStream *s) { * portaudio, which holds the information of our OboeStream. * @return the minimum number of frames that can be written without waiting. */ -static signed long GetStreamWriteAvailable(PaStream *s) { - auto *m_stream = (OboeStream *) s; - return m_stream->framesPerHostCallback * (numberOfBuffers - m_stream->currentOutputBuffer); +static signed long GetStreamWriteAvailable(PaStream *i_paStream) { + auto *oboeStream = (OboeStream *) i_paStream; + return oboeStream->framesPerHostCallback * (g_numberOfBuffers - oboeStream->currentOutputBuffer); } @@ -1816,9 +1801,9 @@ static signed long GetStreamWriteAvailable(PaStream *s) { * portaudio, which holds the information of our OboeStream. * @return one (1) when the stream is stopped, or zero (0) when the stream is running. */ -static PaError IsStreamStopped(PaStream *s) { - auto *m_stream = (OboeStream *) s; - return m_stream->isStopped; +static PaError IsStreamStopped(PaStream *i_paStream) { + auto *oboeStream = (OboeStream *) i_paStream; + return oboeStream->isStopped; } @@ -1828,9 +1813,9 @@ static PaError IsStreamStopped(PaStream *s) { * portaudio, which holds the information of our OboeStream. * @return one (1) when the stream is active (ie playing or recording audio), or zero (0) otherwise. */ -static PaError IsStreamActive(PaStream *s) { - auto *m_stream = (OboeStream *) s; - return m_stream->isActive; +static PaError IsStreamActive(PaStream *i_paStream) { + auto *oboeStream = (OboeStream *) i_paStream; + return oboeStream->isActive; } @@ -1840,7 +1825,7 @@ static PaError IsStreamActive(PaStream *s) { * portaudio, which holds the information of our OboeStream. * @return The stream's current time in seconds, or 0 if an error occurred. */ -static PaTime GetStreamTime(PaStream *s) { +static PaTime GetStreamTime(PaStream *i_paStream) { return PaUtil_GetTime(); } @@ -1856,9 +1841,9 @@ static PaTime GetStreamTime(PaStream *s) { * A value of 0.0 will always be returned for a blocking read/write stream, or if an error * occurs. */ -static double GetStreamCpuLoad(PaStream *s) { - auto *m_stream = (OboeStream *) s; - return PaUtil_GetCpuLoad(&m_stream->cpuLoadMeasurer); +static double GetStreamCpuLoad(PaStream *i_paStream) { + auto *oboeStream = (OboeStream *) i_paStream; + return PaUtil_GetCpuLoad(&oboeStream->cpuLoadMeasurer); } @@ -1879,29 +1864,29 @@ static unsigned long GetApproximateLowBufferSize() { /*----------------------------- Implementation of PaOboe.h functions -----------------------------*/ -void PaOboe_SetSelectedDevice(Direction direction, int32_t deviceID) { +void PaOboe_SetSelectedDevice(Direction i_direction, int32_t i_deviceID) { LOGI("[PaOboe - SetSelectedDevice] Selecting device..."); - if (direction == Direction::Input) - g_inputDeviceId = deviceID; + if (i_direction == Direction::Input) + g_inputDeviceId = i_deviceID; else - g_outputDeviceId = deviceID; + g_outputDeviceId = i_deviceID; } -void PaOboe_SetPerformanceMode(oboe::Direction direction, oboe::PerformanceMode performanceMode){ - if(direction == Direction::Input) { - g_inputPerfMode = performanceMode; +void PaOboe_SetPerformanceMode(oboe::Direction i_direction, oboe::PerformanceMode i_performanceMode) { + if (i_direction == Direction::Input) { + g_inputPerfMode = i_performanceMode; } else { - g_outputPerfMode = performanceMode; + g_outputPerfMode = i_performanceMode; } } -void PaOboe_SetNativeBufferSize(unsigned long bufferSize) { - nativeBufferSize = bufferSize; +void PaOboe_SetNativeBufferSize(unsigned long i_bufferSize) { + g_nativeBufferSize = i_bufferSize; } -void PaOboe_SetNumberOfBuffers(unsigned buffers) { - numberOfBuffers = buffers; +void PaOboe_SetNumberOfBuffers(unsigned i_numberOfBuffers) { + g_numberOfBuffers = i_numberOfBuffers; } From 49d8122494a2a01ab1a24d58b920ffaa4feb33dc Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Wed, 4 Oct 2023 12:04:52 +0200 Subject: [PATCH 09/26] Added separate callback class to fix the single-stream issue. --- include/pa_oboe.h | 1 + src/hostapi/oboe/pa_oboe.cpp | 293 ++++++++++++++++++----------------- 2 files changed, 153 insertions(+), 141 deletions(-) diff --git a/include/pa_oboe.h b/include/pa_oboe.h index d345617d7..900a1f19f 100644 --- a/include/pa_oboe.h +++ b/include/pa_oboe.h @@ -50,6 +50,7 @@ * @brief Android Oboe-specific PortAudio API extension header file. */ +#include "portaudio.h" #include "oboe/Oboe.h" #ifdef __cplusplus diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index fd70931a3..3f0de18d1 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -166,6 +166,7 @@ PerformanceMode g_inputPerfMode = PerformanceMode::LowLatency; PerformanceMode g_outputPerfMode = PerformanceMode::LowLatency; class OboeEngine; +class OboeCallback; /** * Stream structure, useful to store relevant information. It's needed by Portaudio. @@ -190,6 +191,7 @@ typedef struct OboeStream { PaSampleFormat inputFormat; PaSampleFormat outputFormat; + OboeCallback *oboeCallback; // Buffers are managed by the callback function in Oboe. void **outputBuffers; int currentOutputBuffer; @@ -207,9 +209,33 @@ typedef struct OboeStream { OboeEngine *oboeEngineAddress; } OboeStream; +/** + * Callback class for OboeStream. Will be used for non-blocking streams. + */ +class OboeCallback: public AudioStreamCallback { +public: + OboeCallback(){ m_oboeStreamHolder = (OboeStream *) PaUtil_AllocateZeroInitializedMemory(sizeof(OboeStream)); } + //Callback function for non-blocking streams + DataCallbackResult onAudioReady(AudioStream *audioStream, void *audioData, + int32_t numFrames) override; + + void onErrorAfterClose(AudioStream *audioStream, oboe::Result error) override; + + void setStreamHolder(OboeStream* oboeStream){ m_oboeStreamHolder = oboeStream; } + + void resetCallbackCounters(); + +private: + //callback utils + OboeStream *m_oboeStreamHolder; + unsigned long m_framesProcessed{}; + PaStreamCallbackTimeInfo m_timeInfo{}; + struct timespec m_timeSpec{}; +}; + /** - * Stream engine of the host API - Oboe. We allocate only one instance of the engine, and + * Stream engine of the host API - Oboe. We allocate only one instance of the engine per PaOboe_Initialize call, and * we call its functions when we want to operate directly on Oboe. More infos on each functions are * provided right before their implementations. */ @@ -233,14 +259,6 @@ class OboeEngine : public AudioStreamCallback { bool abortStream(OboeStream *oboeStream); - //Callback function for non-blocking streams and some callback utils - DataCallbackResult onAudioReady(AudioStream *audioStream, void *audioData, - int32_t numFrames) override; - - void onErrorAfterClose(AudioStream *audioStream, oboe::Result error) override; - - void resetCallbackCounters(); - //Blocking read/write functions bool writeStream(const void *buffer, int32_t framesToWrite); @@ -250,19 +268,12 @@ class OboeEngine : public AudioStreamCallback { OboeStream *allocateOboeStream(); private: - OboeStream *m_oboeStreamHolder; - //The only instances of output and input streams that will be used, and their builders std::shared_ptr m_outputStream; AudioStreamBuilder m_outputBuilder; std::shared_ptr m_inputStream; AudioStreamBuilder m_inputBuilder; - //callback utils - unsigned long m_framesProcessed{}; - PaStreamCallbackTimeInfo m_timeInfo{}; - struct timespec m_timeSpec{}; - //Conversion utils static AudioFormat PaToOboeFormat(PaSampleFormat paFormat); @@ -291,14 +302,12 @@ typedef struct PaOboeHostApiRepresentation { /** * \brief Initializes an instance of the engine. */ -OboeEngine::OboeEngine() { - m_oboeStreamHolder = allocateOboeStream(); -} +OboeEngine::OboeEngine() {} /** - * \brief Tries to open a stream with the direction @direction, sample rate @sampleRate and/or - * channel count @channelCount. It then checks if the stream was in fact opened with the + * \brief Tries to open a stream with the direction i_direction, sample rate i_sampleRate and/or + * channel count i_channelCount. It then checks if the stream was in fact opened with the * desired settings, and then closes the stream. It's used to see if the requested * parameters are supported by the devices that are going to be used. * @param direction the Direction of the stream; @@ -357,7 +366,7 @@ bool OboeEngine::tryStream(Direction i_direction, int32_t i_sampleRate, int32_t /** - * \brief Opens an audio stream of oboeStream with a specific direction, sample rate and, + * \brief Opens an audio stream with a specific direction, sample rate and, * depending on the direction of the stream, sets its usage (if * direction == Ditrction::Output) or its preset (if direction == Direction::Input). * Moreover, this function checks if the stream is blocking, and sets its callback @@ -376,6 +385,12 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, PaError error = paNoError; Result result; + if(!(i_oboeStream->isBlocking)){ + i_oboeStream->oboeCallback = new OboeCallback(); + i_oboeStream->oboeCallback->setStreamHolder(i_oboeStream); + i_oboeStream->oboeCallback->resetCallbackCounters(); + } + if (i_direction == Direction::Input) { m_inputBuilder.setChannelCount(i_oboeStream->bufferProcessor.inputChannelCount) ->setFormat(PaToOboeFormat(i_oboeStream->inputFormat)) @@ -387,9 +402,8 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, ->setFramesPerCallback(i_oboeStream->framesPerHostCallback); if (!(i_oboeStream->isBlocking)) { - resetCallbackCounters(); - m_inputBuilder.setDataCallback(this) - ->setErrorCallback(this); + m_inputBuilder.setDataCallback(i_oboeStream->oboeCallback) + ->setErrorCallback(i_oboeStream->oboeCallback); } result = m_inputBuilder.openStream(m_inputStream); @@ -431,9 +445,8 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, ->setFramesPerCallback(i_oboeStream->framesPerHostCallback); if (!(i_oboeStream->isBlocking)) { - resetCallbackCounters(); - m_outputBuilder.setDataCallback(this) - ->setErrorCallback(this); + m_outputBuilder.setDataCallback(i_oboeStream->oboeCallback) + ->setErrorCallback(i_oboeStream->oboeCallback); } result = m_outputBuilder.openStream(m_outputStream); @@ -663,116 +676,6 @@ bool OboeEngine::abortStream(OboeStream *i_oboeStream) { } -/** - * \brief Oboe's callback routine. FIXME: implement onErrorAfterClose correctly - */ -DataCallbackResult -OboeEngine::onAudioReady(AudioStream *i_audioStream, void *i_audioData, int32_t i_numFrames) { - - clock_gettime(CLOCK_REALTIME, &m_timeSpec); - m_timeInfo.currentTime = (PaTime)(m_timeSpec.tv_sec + (m_timeSpec.tv_nsec / 1000000000.0)); - m_timeInfo.outputBufferDacTime = (PaTime)(m_oboeStreamHolder->framesPerHostCallback - / - m_oboeStreamHolder->streamRepresentation.streamInfo.sampleRate - + m_timeInfo.currentTime); - m_timeInfo.inputBufferAdcTime = (PaTime)(m_oboeStreamHolder->framesPerHostCallback - / - m_oboeStreamHolder->streamRepresentation.streamInfo.sampleRate - + m_timeInfo.currentTime); - - /* check if StopStream or AbortStream was called */ - if (m_oboeStreamHolder->doStop) { - m_oboeStreamHolder->callbackResult = paComplete; - } else if (m_oboeStreamHolder->doAbort) { - m_oboeStreamHolder->callbackResult = paAbort; - } - - PaUtil_BeginCpuLoadMeasurement(&m_oboeStreamHolder->cpuLoadMeasurer); - PaUtil_BeginBufferProcessing(&m_oboeStreamHolder->bufferProcessor, - &m_timeInfo, m_oboeStreamHolder->cbFlags); - - if (m_oboeStreamHolder->hasOutput) { - m_oboeStreamHolder->outputBuffers[m_oboeStreamHolder->currentOutputBuffer] = i_audioData; - PaUtil_SetOutputFrameCount(&m_oboeStreamHolder->bufferProcessor, i_numFrames); - PaUtil_SetInterleavedOutputChannels(&m_oboeStreamHolder->bufferProcessor, 0, - (void *) ((PaInt16 **) m_oboeStreamHolder->outputBuffers)[ - m_oboeStreamHolder->currentOutputBuffer], - 0); - } - if (m_oboeStreamHolder->hasInput) { - i_audioData = m_oboeStreamHolder->inputBuffers[m_oboeStreamHolder->currentInputBuffer]; - PaUtil_SetInputFrameCount(&m_oboeStreamHolder->bufferProcessor, 0); - PaUtil_SetInterleavedInputChannels(&m_oboeStreamHolder->bufferProcessor, 0, - (void *) ((PaInt16 **) m_oboeStreamHolder->inputBuffers)[ - m_oboeStreamHolder->currentInputBuffer], - 0); - } - - /* continue processing user buffers if cbresult is paContinue or if cbresult is paComplete and userBuffers aren't empty yet */ - if (m_oboeStreamHolder->callbackResult == paContinue - || (m_oboeStreamHolder->callbackResult == paComplete - && !PaUtil_IsBufferProcessorOutputEmpty(&m_oboeStreamHolder->bufferProcessor))) { - m_framesProcessed = PaUtil_EndBufferProcessing(&oboeStream->bufferProcessor, - &oboeStream->callbackResult); - } - - /* enqueue a buffer only when there are frames to be processed, - * this will be 0 when paComplete + empty buffers or paAbort - */ - if (m_framesProcessed > 0) { - if (m_oboeStreamHolder->hasOutput) { - m_oboeStreamHolder->currentOutputBuffer = - (m_oboeStreamHolder->currentOutputBuffer + 1) % g_numberOfBuffers; - } - if (m_oboeStreamHolder->hasInput) { - m_oboeStreamHolder->currentInputBuffer = (m_oboeStreamHolder->currentInputBuffer + 1) % g_numberOfBuffers; - } - } - - PaUtil_EndCpuLoadMeasurement(&m_oboeStreamHolder->cpuLoadMeasurer, m_framesProcessed); - - /* StopStream was called */ - if (m_framesProcessed == 0 && m_oboeStreamHolder->doStop) { - m_oboeStreamHolder->oboeCallbackResult = DataCallbackResult::Stop; - } - - /* if AbortStream or StopStream weren't called, stop from the cb */ - else if (m_framesProcessed == 0 && !(m_oboeStreamHolder->doAbort || m_oboeStreamHolder->doStop)) { - m_oboeStreamHolder->isActive = false; - m_oboeStreamHolder->isStopped = true; - if (m_oboeStreamHolder->streamRepresentation.streamFinishedCallback != nullptr) - m_oboeStreamHolder->streamRepresentation.streamFinishedCallback( - m_oboeStreamHolder->streamRepresentation.userData); - m_oboeStreamHolder->oboeCallbackResult = DataCallbackResult::Stop; //TODO: Resume this test (onAudioReady) - } - - return m_oboeStreamHolder->oboeCallbackResult; -} - - -/** - * \brief If the data callback ends without returning DataCallbackResult::Stop, this routine tells - * what error occurred. - */ -void OboeEngine::onErrorAfterClose(AudioStream *i_audioStream, Result i_error) { - if (i_error == oboe::Result::ErrorDisconnected) { - LOGW("[OboeEngine::onErrorAfterClose]\t ErrorDisconnected - Restarting stream(s)"); - if (!restartStream(0)) - LOGE("[OboeEngine::onErrorAfterClose]\t Couldn't restart stream(s)"); - } else - LOGE("[OboeEngine::onErrorAfterClose]\t Error was %s", oboe::convertToText(i_error)); -} - - -/** - * \brief Resets callback counters (called at the start of each iteration of onAudioReady - */ -void OboeEngine::resetCallbackCounters() { - m_framesProcessed = 0; - m_timeInfo = {0, 0, 0}; -} - - /** * \brief Writes frames on the output stream of oboeStream. Used by blocking streams. * @param buffer The buffer that we want to write on the output stream; @@ -884,6 +787,117 @@ int32_t OboeEngine::getSelectedDevice(Direction i_direction) { return g_outputDeviceId; } +/*----------------------------- OboeCallback functions implementations -----------------------------*/ +/** + * \brief Oboe's callback routine. + */ +DataCallbackResult +OboeCallback::onAudioReady(AudioStream *i_audioStream, void *i_audioData, int32_t i_numFrames) { + + clock_gettime(CLOCK_REALTIME, &m_timeSpec); + m_timeInfo.currentTime = (PaTime)(m_timeSpec.tv_sec + (m_timeSpec.tv_nsec / 1000000000.0)); + m_timeInfo.outputBufferDacTime = (PaTime)(m_oboeStreamHolder->framesPerHostCallback + / + m_oboeStreamHolder->streamRepresentation.streamInfo.sampleRate + + m_timeInfo.currentTime); + m_timeInfo.inputBufferAdcTime = (PaTime)(m_oboeStreamHolder->framesPerHostCallback + / + m_oboeStreamHolder->streamRepresentation.streamInfo.sampleRate + + m_timeInfo.currentTime); + + /* check if StopStream or AbortStream was called */ + if (m_oboeStreamHolder->doStop) { + m_oboeStreamHolder->callbackResult = paComplete; + } else if (m_oboeStreamHolder->doAbort) { + m_oboeStreamHolder->callbackResult = paAbort; + } + + PaUtil_BeginCpuLoadMeasurement(&m_oboeStreamHolder->cpuLoadMeasurer); + PaUtil_BeginBufferProcessing(&m_oboeStreamHolder->bufferProcessor, + &m_timeInfo, m_oboeStreamHolder->cbFlags); + + if (m_oboeStreamHolder->hasOutput) { + m_oboeStreamHolder->outputBuffers[m_oboeStreamHolder->currentOutputBuffer] = i_audioData; + PaUtil_SetOutputFrameCount(&m_oboeStreamHolder->bufferProcessor, i_numFrames); + PaUtil_SetInterleavedOutputChannels(&m_oboeStreamHolder->bufferProcessor, 0, + (void *) ((PaInt16 **) m_oboeStreamHolder->outputBuffers)[ + m_oboeStreamHolder->currentOutputBuffer], + 0); + } + if (m_oboeStreamHolder->hasInput) { + i_audioData = m_oboeStreamHolder->inputBuffers[m_oboeStreamHolder->currentInputBuffer]; + PaUtil_SetInputFrameCount(&m_oboeStreamHolder->bufferProcessor, 0); + PaUtil_SetInterleavedInputChannels(&m_oboeStreamHolder->bufferProcessor, 0, + (void *) ((PaInt16 **) m_oboeStreamHolder->inputBuffers)[ + m_oboeStreamHolder->currentInputBuffer], + 0); + } + + /* continue processing user buffers if cbresult is paContinue or if cbresult is paComplete and userBuffers aren't empty yet */ + if (m_oboeStreamHolder->callbackResult == paContinue + || (m_oboeStreamHolder->callbackResult == paComplete + && !PaUtil_IsBufferProcessorOutputEmpty(&m_oboeStreamHolder->bufferProcessor))) { + m_framesProcessed = PaUtil_EndBufferProcessing(&oboeStream->bufferProcessor, + &oboeStream->callbackResult); + } + + /* enqueue a buffer only when there are frames to be processed, + * this will be 0 when paComplete + empty buffers or paAbort + */ + if (m_framesProcessed > 0) { + if (m_oboeStreamHolder->hasOutput) { + m_oboeStreamHolder->currentOutputBuffer = + (m_oboeStreamHolder->currentOutputBuffer + 1) % g_numberOfBuffers; + } + if (m_oboeStreamHolder->hasInput) { + m_oboeStreamHolder->currentInputBuffer = (m_oboeStreamHolder->currentInputBuffer + 1) % g_numberOfBuffers; + } + } + + PaUtil_EndCpuLoadMeasurement(&m_oboeStreamHolder->cpuLoadMeasurer, m_framesProcessed); + + /* StopStream was called */ + if (m_framesProcessed == 0 && m_oboeStreamHolder->doStop) { + m_oboeStreamHolder->oboeCallbackResult = DataCallbackResult::Stop; + } + + /* if AbortStream or StopStream weren't called, stop from the cb */ + else if (m_framesProcessed == 0 && !(m_oboeStreamHolder->doAbort || m_oboeStreamHolder->doStop)) { + m_oboeStreamHolder->isActive = false; + m_oboeStreamHolder->isStopped = true; + if (m_oboeStreamHolder->streamRepresentation.streamFinishedCallback != nullptr) + m_oboeStreamHolder->streamRepresentation.streamFinishedCallback( + m_oboeStreamHolder->streamRepresentation.userData); + m_oboeStreamHolder->oboeCallbackResult = DataCallbackResult::Stop; //TODO: Resume this test (onAudioReady) + } + + return m_oboeStreamHolder->oboeCallbackResult; +} + + +/** + * \brief If the data callback ends without returning DataCallbackResult::Stop, this routine tells + * what error occurred. + */ +void OboeCallback::onErrorAfterClose(AudioStream *i_audioStream, Result i_error) { + if (i_error == oboe::Result::ErrorDisconnected) { + OboeEngine* oboeEngine = m_oboeStreamHolder->getEngineAddress(); + LOGW("[OboeEngine::onErrorAfterClose]\t ErrorDisconnected - Restarting stream(s)"); + if (!oboeEngine->restartStream(0)) + LOGE("[OboeEngine::onErrorAfterClose]\t Couldn't restart stream(s)"); + } else + LOGE("[OboeEngine::onErrorAfterClose]\t Error was %s", oboe::convertToText(i_error)); +} + + +/** + * \brief Resets callback counters (called at the start of each iteration of onAudioReady + */ +void OboeCallback::resetCallbackCounters() { + m_framesProcessed = 0; + m_timeInfo = {0, 0, 0}; +} + /*----------------------------- PaSkeleton functions implementations -----------------------------*/ @@ -1367,8 +1381,6 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, PaSampleFormat inputSampleFormat, outputSampleFormat; PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat; - - //TODO: add a function that lets the user choose usage and preset Usage androidOutputUsage = Usage::VoiceCommunication; InputPreset androidInputPreset = InputPreset::Generic; @@ -1624,7 +1636,6 @@ static PaError StartStream(PaStream *i_paStream) { } } - /* Start the processing thread.*/ if (!oboeStream->isBlocking) { oboeStream->callbackResult = paContinue; oboeStream->oboeCallbackResult = DataCallbackResult::Continue; From 8035e7ea79317d0c2eaec68bdf3c3e88f370d124 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Wed, 4 Oct 2023 12:51:09 +0200 Subject: [PATCH 10/26] Modified OboeEngine accordingly --- src/hostapi/oboe/pa_oboe.cpp | 140 +++++++++++++++++------------------ 1 file changed, 69 insertions(+), 71 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index 3f0de18d1..853b7c8e5 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -205,6 +205,12 @@ typedef struct OboeStream { void setEngineAddress(OboeEngine *i_oboeEngine) { oboeEngineAddress = i_oboeEngine; } + //The only instances of output and input streams that will be used, and their builders + std::shared_ptr outputStream; + AudioStreamBuilder outputBuilder; + std::shared_ptr inputStream; + AudioStreamBuilder inputBuilder; + private: OboeEngine *oboeEngineAddress; } OboeStream; @@ -235,11 +241,11 @@ class OboeCallback: public AudioStreamCallback { /** - * Stream engine of the host API - Oboe. We allocate only one instance of the engine per PaOboe_Initialize call, and - * we call its functions when we want to operate directly on Oboe. More infos on each functions are - * provided right before their implementations. + * Stream engine of the host API - Oboe. We allocate only one instance of the engine per OboeStream, and + * we call its functions when we want to operate directly on Oboe. More infos on each function are + * provided right before its implementation. */ -class OboeEngine : public AudioStreamCallback { +class OboeEngine { public: OboeEngine(); @@ -253,26 +259,23 @@ class OboeEngine : public AudioStreamCallback { bool stopStream(OboeStream *oboeStream); - bool restartStream(int direction); + bool restartStream(OboeStream *oboeStream, int direction); bool closeStream(OboeStream *oboeStream); bool abortStream(OboeStream *oboeStream); //Blocking read/write functions - bool writeStream(const void *buffer, int32_t framesToWrite); + bool writeStream(OboeStream *oboeStream, const void *buffer, int32_t framesToWrite); - bool readStream(void *buffer, int32_t framesToRead); + bool readStream(OboeStream *oboeStream, void *buffer, int32_t framesToRead); //Engine utils OboeStream *allocateOboeStream(); private: - //The only instances of output and input streams that will be used, and their builders - std::shared_ptr m_outputStream; - AudioStreamBuilder m_outputBuilder; - std::shared_ptr m_inputStream; - AudioStreamBuilder m_inputBuilder; + std::shared_ptr m_testStream; + AudioStreamBuilder m_testBuilder; //Conversion utils static AudioFormat PaToOboeFormat(PaSampleFormat paFormat); @@ -300,7 +303,7 @@ typedef struct PaOboeHostApiRepresentation { /** - * \brief Initializes an instance of the engine. + * \brief Constructor. */ OboeEngine::OboeEngine() {} @@ -317,21 +320,16 @@ OboeEngine::OboeEngine() {} * they aren't, or if tryStream couldn't open a stream. */ bool OboeEngine::tryStream(Direction i_direction, int32_t i_sampleRate, int32_t i_channelCount) { - AudioStreamBuilder builder; Result result; bool outcome = false; - builder.setDeviceId(getSelectedDevice(i_direction)) - // Arbitrary format usually broadly supported. Later, we'll open streams with correct formats. + m_testBuilder.setDeviceId(getSelectedDevice(i_direction)) + // Arbitrary format usually broadly supported. Later, we'll open streams with correct formats. ->setFormat(AudioFormat::Float) ->setDirection(i_direction) ->setSampleRate(i_sampleRate) - ->setChannelCount(i_channelCount); - if (i_direction == Direction::Input) { - result = builder->openStream(m_inputStream); - } else { - result = builder->openStream(m_outputStream); - } + ->setChannelCount(i_channelCount) + ->openStream(m_testStream); if (result != Result::OK) { LOGE("[OboeEngine::TryStream]\t Couldn't open the stream in TryStream. Error: %s", @@ -340,26 +338,23 @@ bool OboeEngine::tryStream(Direction i_direction, int32_t i_sampleRate, int32_t } if (i_sampleRate != kUnspecified) { - outcome = (i_sampleRate == builder.getSampleRate()); + outcome = (i_sampleRate == m_testBuilder.getSampleRate()); if (!outcome) { LOGW("[OboeEngine::TryStream]\t Tried sampleRate = %d, built sampleRate = %d", - i_sampleRate, builder.getSampleRate()); + i_sampleRate, m_testBuilder.getSampleRate()); } } else if (i_channelCount != kUnspecified) { - outcome = (i_channelCount == builder.getChannelCount()); + outcome = (i_channelCount == m_testBuilder.getChannelCount()); if (!outcome) { LOGW("[OboeEngine::TryStream]\t Tried channelCount = %d, built channelCount = %d", - channelCount, builder.getChannelCount()); + i_channelCount, m_testBuilder.getChannelCount()); } } else { LOGE("[OboeEngine::TryStream]\t Logical failure. This message should NEVER occur."); outcome = false; } - if (i_direction == Direction::Input) - m_inputStream->close(); - else - m_outputStream->close(); + m_testStream->close(); return outcome; } @@ -371,6 +366,7 @@ bool OboeEngine::tryStream(Direction i_direction, int32_t i_sampleRate, int32_t * direction == Ditrction::Output) or its preset (if direction == Direction::Input). * Moreover, this function checks if the stream is blocking, and sets its callback * function if not. + * @param oboeStream The stream we want to open * @param direction The Oboe::Direction of the stream we want to open; * @param sampleRate The sample rate of the stream we want to open; * @param androidOutputUsage The Oboe::Usage of the output stream we want to open @@ -392,7 +388,7 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, } if (i_direction == Direction::Input) { - m_inputBuilder.setChannelCount(i_oboeStream->bufferProcessor.inputChannelCount) + i_oboeStream->inputBuilder.setChannelCount(i_oboeStream->bufferProcessor.inputChannelCount) ->setFormat(PaToOboeFormat(i_oboeStream->inputFormat)) ->setSampleRate(i_sampleRate) ->setDirection(Direction::Input) @@ -406,7 +402,7 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, ->setErrorCallback(i_oboeStream->oboeCallback); } - result = m_inputBuilder.openStream(m_inputStream); + result = i_oboeStream->inputBuilder.openStream(i_oboeStream->inputStream); if (result != Result::OK) { LOGE("[OboeEngine::OpenStream]\t Oboe couldn't open the input stream: %s", @@ -414,7 +410,8 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, return paUnanticipatedHostError; } - m_inputStream->setBufferSizeInFrames(m_inputStream->getFramesPerBurst() * g_numberOfBuffers); + i_oboeStream->inputStream->setBufferSizeInFrames(i_oboeStream->inputStream->getFramesPerBurst() * + g_numberOfBuffers); i_oboeStream->inputBuffers = (void **) PaUtil_AllocateZeroInitializedMemory(g_numberOfBuffers * sizeof(int32_t * )); @@ -428,14 +425,14 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, for (int j = 0; j < i; ++j) PaUtil_FreeMemory(i_oboeStream->inputBuffers[j]); PaUtil_FreeMemory(i_oboeStream->inputBuffers); - m_inputStream->close(); + i_oboeStream->inputStream->close(); error = paInsufficientMemory; break; } } i_oboeStream->currentInputBuffer = 0; } else { - m_outputBuilder.setChannelCount(i_oboeStream->bufferProcessor.outputChannelCount) + i_oboeStream->outputBuilder.setChannelCount(i_oboeStream->bufferProcessor.outputChannelCount) ->setFormat(PaToOboeFormat(i_oboeStream->outputFormat)) ->setSampleRate(i_sampleRate) ->setDirection(Direction::Output) @@ -445,18 +442,19 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, ->setFramesPerCallback(i_oboeStream->framesPerHostCallback); if (!(i_oboeStream->isBlocking)) { - m_outputBuilder.setDataCallback(i_oboeStream->oboeCallback) + i_oboeStream->outputBuilder.setDataCallback(i_oboeStream->oboeCallback) ->setErrorCallback(i_oboeStream->oboeCallback); } - result = m_outputBuilder.openStream(m_outputStream); + result = i_oboeStream->outputBuilder.openStream(m_outputStream); if (result != Result::OK) { LOGE("[OboeEngine::OpenStream]\t Oboe couldn't open the output stream: %s", convertToText(result)); return paUnanticipatedHostError; } - m_outputStream->setBufferSizeInFrames(m_outputStream->getFramesPerBurst() * g_numberOfBuffers); + i_oboeStream->outputStream->setBufferSizeInFrames(i_oboeStream->outputStream->getFramesPerBurst() * + g_numberOfBuffers); i_oboeStream->outputBuffers = (void **) PaUtil_AllocateZeroInitializedMemory(g_numberOfBuffers * sizeof(int32_t * )); @@ -470,7 +468,7 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, for (int j = 0; j < i; ++j) PaUtil_FreeMemory(i_oboeStream->outputBuffers[j]); PaUtil_FreeMemory(i_oboeStream->outputBuffers); - m_outputStream->close(); + i_oboeStream->outputStream->close(); error = paInsufficientMemory; break; } @@ -491,13 +489,13 @@ bool OboeEngine::startStream(OboeStream *i_oboeStream) { Result outputResult = Result::OK, inputResult = Result::OK; if (i_oboeStream->hasInput) { - inputResult = m_inputStream->requestStart(); + inputResult = i_oboeStream->inputStream->requestStart(); if (inputResult != Result::OK) LOGE("[OboeEngine::startStream]\t Oboe couldn't start the input stream: %s", convertToText(inputResult)); } if (i_oboeStream->hasOutput) { - outputResult = m_outputStream->requestStart(); + outputResult = i_oboeStream->outputStream->requestStart(); if (outputResult != Result::OK) LOGE("[OboeEngine::startStream]\t Oboe couldn't start the output stream: %s", convertToText(outputResult)); @@ -516,13 +514,13 @@ bool OboeEngine::stopStream(OboeStream *i_oboeStream) { Result outputResult = Result::OK, inputResult = Result::OK; if (i_oboeStream->hasInput) { - inputResult = m_inputStream->requestStop(); + inputResult = i_oboeStream->inputStream->requestStop(); if (inputResult != Result::OK) LOGE("[OboeEngine::stopStream]\t Oboe couldn't stop the input stream: %s", convertToText(inputResult)); } if (i_oboeStream->hasOutput) { - outputResult = m_outputStream->requestStop(); + outputResult = i_oboeStream->outputStream->requestStop(); if (outputResult != Result::OK) LOGE("[OboeEngine::stopStream]\t Oboe couldn't stop the output stream: %s", convertToText(outputResult)); @@ -537,28 +535,28 @@ bool OboeEngine::stopStream(OboeStream *i_oboeStream) { * audio devices change while a stream is started. * @return true if the stream is restarted successfully, false otherwise. */ -bool OboeEngine::restartStream(int i_direction) { +bool OboeEngine::restartStream(OboeStream* i_oboeStream, int i_direction) { bool outcome = true; Result result; switch (i_direction) { case 1: //output-only //stopping and closing - result = m_outputStream->stop(); + result = i_oboeStream->outputStream->stop(); if (result != Result::OK) LOGW("[OboeEngine::restartStream]\t Oboe couldn't stop the output stream: %s", convertToText(result)); - result = m_outputStream->close(); + result = i_oboeStream->outputStream->close(); if (result != Result::OK) LOGW("[OboeEngine::restartStream]\t Oboe couldn't close the output stream: %s", convertToText(result)); //reopening and restarting - result = outputBuilder.openStream(m_outputStream); + result = i_oboeStream->outputBuilder.openStream(i_oboeStream->outputStream); if (result != Result::OK) LOGE("[OboeEngine::restartStream]\t Oboe couldn't reopen the output stream: %s", convertToText(result)); - result = m_outputStream->start(); + result = i_oboeStream->outputStream->start(); if (result != Result::OK) { LOGE("[OboeEngine::restartStream]\t Oboe couldn't restart the output stream: %s", convertToText(result)); @@ -568,21 +566,21 @@ bool OboeEngine::restartStream(int i_direction) { case 2: //input-only //stopping and closing - result = m_inputStream->stop(); + result = i_oboeStream->inputStream->stop(); if (result != Result::OK) LOGW("[OboeEngine::restartStream]\t Oboe couldn't stop the input stream: %s", convertToText(result)); - result = m_inputStream->close(); + result = i_oboeStream->inputStream->close(); if (result != Result::OK) LOGW("[OboeEngine::restartStream]\t Oboe couldn't close the input stream: %s", convertToText(result)); //reopening and restarting - result = inputBuilder.openStream(m_inputStream); + result = inputBuilder.openStream(i_oboeStream->inputStream); if (result != Result::OK) LOGE("[OboeEngine::restartStream]\t Oboe couldn't reopen the input stream: %s", convertToText(result)); - result = m_inputStream->start(); + result = i_oboeStream->inputStream->start(); if (result != Result::OK) { LOGE("[OboeEngine::restartStream]\t Oboe couldn't restart the input stream: %s", convertToText(result)); @@ -593,7 +591,7 @@ bool OboeEngine::restartStream(int i_direction) { default: // unspecified direction or both directions: restart both streams LOGW("[OboeEngine::restartStream]\t Unspecified direction, restarting both streams"); - outcome = (restartStream(1) && restartStream(2)); + outcome = (restartStream(i_oboeStream, 1) && restartStream(i_oboeStream, 2)); break; } @@ -618,14 +616,14 @@ bool OboeEngine::closeStream(OboeStream *i_oboeStream) { } if (hasOutput) { - outputResult = m_outputStream->close(); + outputResult = i_oboeStream->outputStream->close(); if (outputResult == Result::ErrorClosed) { outputResult = Result::OK; LOGW("[OboeEngine::closeStream]\t Tried to close output stream, but was already closed."); } } if (hasInput) { - inputResult = m_inputStream->close(); + inputResult = i_oboeStream->inputStream->close(); if (inputResult == Result::ErrorClosed) { inputResult = Result::OK; LOGW("[OboeEngine::closeStream]\t Tried to close input stream, but was already closed."); @@ -652,21 +650,21 @@ bool OboeEngine::abortStream(OboeStream *i_oboeStream) { } if (hasInput) { - inputResult = m_inputStream->stop(); + inputResult = i_oboeStream->inputStream->stop(); if (inputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the input stream to stop: %s", convertToText(inputResult)); - inputResult = m_inputStream->close(); - if (m_inputResult != Result::OK) + inputResult = i_oboeStream->inputStream->close(); + if (i_oboeStream->inputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the input stream to close: %s", convertToText(inputResult)); } if (hasOutput) { - outputResult = m_outputStream->stop(); - if (m_outputResult != Result::OK) + outputResult = i_oboeStream->outputStream->stop(); + if (i_oboeStream->outputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the output stream to stop: %s", - convertToText(m_outputResult)); - outputResult = m_outputStream->close(); + convertToText(outputResult)); + outputResult = i_oboeStream->outputStream->close(); if (outputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the output stream to close: %s", convertToText(outputResult)); @@ -684,14 +682,14 @@ bool OboeEngine::abortStream(OboeStream *i_oboeStream) { * different from ErrorDisconnected. In case of ErrorDisconnected, the function returns * true if the stream is successfully restarted, and false otherwise. */ -bool OboeEngine::writeStream(const void *i_buffer, int32_t i_framesToWrite) { +bool OboeEngine::writeStream(OboeStream *i_oboeStream, const void *i_buffer, int32_t i_framesToWrite) { bool outcome = true; - ResultWithValue result = m_outputStream->write(i_buffer, i_framesToWrite, TIMEOUT_NS); + ResultWithValue result = i_oboeStream->outputStream->write(i_buffer, i_framesToWrite, TIMEOUT_NS); // If the stream is interrupted because the device suddenly changes, restart the stream. if (result.error() == Result::ErrorDisconnected) { - if (OboeEngine::restartStream(1)) + if (restartStream(i_oboeStream, 1)) return true; } @@ -711,14 +709,14 @@ bool OboeEngine::writeStream(const void *i_buffer, int32_t i_framesToWrite) { * different from ErrorDisconnected. In case of ErrorDisconnected, the function returns * true if the stream is successfully restarted, and false otherwise. */ -bool OboeEngine::readStream(void *i_buffer, int32_t i_framesToRead) { +bool OboeEngine::readStream(OboeStream *i_oboeStream, void *i_buffer, int32_t i_framesToRead) { bool outcome = true; - ResultWithValue result = m_inputStream->read(i_buffer, i_framesToRead, TIMEOUT_NS); + ResultWithValue result = i_oboeStream->inputStream->read(i_buffer, i_framesToRead, TIMEOUT_NS); // If the stream is interrupted because the device suddenly changes, restart the stream. if (result.error() == Result::ErrorDisconnected) { - if (OboeEngine::restartStream(2)) + if (restartStream(i_oboeStream, 2)) return true; } @@ -837,8 +835,8 @@ OboeCallback::onAudioReady(AudioStream *i_audioStream, void *i_audioData, int32_ if (m_oboeStreamHolder->callbackResult == paContinue || (m_oboeStreamHolder->callbackResult == paComplete && !PaUtil_IsBufferProcessorOutputEmpty(&m_oboeStreamHolder->bufferProcessor))) { - m_framesProcessed = PaUtil_EndBufferProcessing(&oboeStream->bufferProcessor, - &oboeStream->callbackResult); + m_framesProcessed = PaUtil_EndBufferProcessing(&m_oboeStreamHolder->bufferProcessor, + &m_oboeStreamHolder->callbackResult); } /* enqueue a buffer only when there are frames to be processed, @@ -883,7 +881,7 @@ void OboeCallback::onErrorAfterClose(AudioStream *i_audioStream, Result i_error) if (i_error == oboe::Result::ErrorDisconnected) { OboeEngine* oboeEngine = m_oboeStreamHolder->getEngineAddress(); LOGW("[OboeEngine::onErrorAfterClose]\t ErrorDisconnected - Restarting stream(s)"); - if (!oboeEngine->restartStream(0)) + if (!oboeEngine->restartStream(m_oboeStreamHolder, 0)) LOGE("[OboeEngine::onErrorAfterClose]\t Couldn't restart stream(s)"); } else LOGE("[OboeEngine::onErrorAfterClose]\t Error was %s", oboe::convertToText(i_error)); From 494600d34e32a3a30372ee8c0233b150c7232f14 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Wed, 4 Oct 2023 16:04:03 +0200 Subject: [PATCH 11/26] Adjusted the code in the rest of pa_oboe.cpp --- src/hostapi/oboe/pa_oboe.cpp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index 853b7c8e5..0929033fa 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -880,11 +880,11 @@ OboeCallback::onAudioReady(AudioStream *i_audioStream, void *i_audioData, int32_ void OboeCallback::onErrorAfterClose(AudioStream *i_audioStream, Result i_error) { if (i_error == oboe::Result::ErrorDisconnected) { OboeEngine* oboeEngine = m_oboeStreamHolder->getEngineAddress(); - LOGW("[OboeEngine::onErrorAfterClose]\t ErrorDisconnected - Restarting stream(s)"); + LOGW("[OboeCallback::onErrorAfterClose]\t ErrorDisconnected - Restarting stream(s)"); if (!oboeEngine->restartStream(m_oboeStreamHolder, 0)) - LOGE("[OboeEngine::onErrorAfterClose]\t Couldn't restart stream(s)"); + LOGE("[OboeCallback::onErrorAfterClose]\t Couldn't restart stream(s)"); } else - LOGE("[OboeEngine::onErrorAfterClose]\t Error was %s", oboe::convertToText(i_error)); + LOGE("[OboeCallback::onErrorAfterClose]\t Error was %s", oboe::convertToText(i_error)); } @@ -1086,10 +1086,8 @@ PaError PaOboe_Initialize(PaUtilHostApiRepresentation **i_hostApi, PaHostApiInde deviceInfo->defaultSampleRate = sampleRates[0]; for (i = 0; i < numberOfSampleRates; ++i) { - if (IsOutputSampleRateSupported( - oboeHostApi, sampleRates[i]) == paNoError && - IsInputSampleRateSupported( - oboeHostApi, sampleRates[i]) == paNoError) { + if (IsOutputSampleRateSupported(oboeHostApi, sampleRates[i]) == paNoError && + IsInputSampleRateSupported(oboeHostApi, sampleRates[i]) == paNoError) { deviceInfo->defaultSampleRate = sampleRates[i]; break; } @@ -1224,7 +1222,7 @@ static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *i_hostApi, /* check that input device can support inputChannelCount */ if (inputChannelCount > - i_hostApi->deviceInfos[i_inputParameters->device]->maxInputChannels) { + i_hostApi->deviceInfos[i_inputParameters->device]->maxInputChannels) { return paInvalidChannelCount; } @@ -1262,8 +1260,7 @@ static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *i_hostApi, } /* check that output device can support outputChannelCount */ - if (outputChannelCount > - i_hostApi->deviceInfos[i_outputParameters->device]->maxOutputChannels) { + if (outputChannelCount > i_hostApi->deviceInfos[i_outputParameters->device]->maxOutputChannels) { return paInvalidChannelCount; } @@ -1304,6 +1301,7 @@ static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *i_hostApi, /** * \brief Calls OboeEngine::openStream to open the outputStream and a Generic input preset. + * @param oboeStream is the OboeStream we want to initialize in the output direction. * @param oboeHostApi points towards a OboeHostApiRepresentation (see struct defined at the top of * this file); * @param androidOutputUsage is an attribute that expresses why we are opening the output stream. @@ -1313,7 +1311,7 @@ static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *i_hostApi, * the correct amount of memory. * @return the value returned by OboeEngine::openStream. */ -static PaError InitializeOutputStream(PaOboeHostApiRepresentation *i_oboeHostApi, +static PaError InitializeOutputStream(OboeStream i_oboeStream, PaOboeHostApiRepresentation *i_oboeHostApi, Usage i_androidOutputUsage, double i_sampleRate) { return i_oboeHostApi->oboeEngine->openStream(i_oboeStream, @@ -1326,6 +1324,7 @@ static PaError InitializeOutputStream(PaOboeHostApiRepresentation *i_oboeHostApi /** * \brief Calls OboeEngine::openStream to open the outputStream and a Generic input preset. + * @param oboeStream is the OboeStream we want to initialize in the input direction. * @param oboeHostApi points towards a OboeHostApiRepresentation (see struct defined at the top of * this file); * @param androidInputPreset is an attribute that defines the audio source. This information @@ -1350,7 +1349,7 @@ static PaError InitializeInputStream(OboeStream i_oboeStream, PaOboeHostApiRepre * \brief Opens the portaudio audio stream - while initializing our OboeStream. * @param hostApi points towards a *HostApiRepresentation, which is a structure representing the * interface to a host API (see struct in "pa_hostapi.h"); - * @param s points to a pointer to a PaStream, which is an audio stream structure used and built + * @param paStream points to a pointer to a PaStream, which is an audio stream structure used and built * by portaudio, which will hold the information of our OboeStream; * @param inputParameters points towards the parameters given to the input stream; * @param outputParameters points towards the parameters given to the output stream; @@ -1540,7 +1539,7 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, ((PaTime) PaUtil_GetBufferProcessorOutputLatencyFrames( &oboeStream->bufferProcessor) + oboeStream->framesPerHostCallback) / i_sampleRate; - ENSURE(InitializeOutputStream(oboeHostApi, + ENSURE(InitializeOutputStream(oboeStream, oboeHostApi, androidOutputUsage, i_sampleRate), "Initializing outputstream failed"); } else { oboeStream->hasOutput = false; } @@ -1562,7 +1561,7 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, * \brief Calls OboeEngine::closeStream, and then frees the memory that was allocated to sustain * the stream(s). When CloseStream() is called, the multi-api layer ensures that the stream * has already been stopped or aborted. - * @param s points to to a PaStream, which is an audio stream structure used and built by + * @param paStream points to to a PaStream, which is an audio stream structure used and built by * portaudio, which holds the information of our OboeStream. * @return paNoError, but warns in the logs if OboeEngine::closeStream failed. */ @@ -1736,7 +1735,7 @@ static PaError ReadStream(PaStream *i_paStream, void *i_buffer, unsigned long i_ while (i_frames > 0) { framesToRead = PA_MIN(oboeStream->framesPerHostCallback, i_frames); - if (!(oboeEngine->readStream(userBuffer, framesToRead * + if (!(oboeEngine->readStream(oboeStream, userBuffer, framesToRead * oboeStream->bufferProcessor.inputChannelCount))) error = paInternalError; @@ -1766,7 +1765,7 @@ static PaError WriteStream(PaStream *i_paStream, const void *i_buffer, unsigned while (i_frames > 0) { framesToWrite = PA_MIN(stream->framesPerHostCallback, i_frames); - if (!(oboeEngine->writeStream(userBuffer, framesToWrite * + if (!(oboeEngine->writeStream(oboeStream, userBuffer, framesToWrite * oboeStream->bufferProcessor.outputChannelCount))) error = paInternalError; From f389437633bf5b092ff4c218cea702ccff92f162 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Wed, 4 Oct 2023 16:17:09 +0200 Subject: [PATCH 12/26] Removed stop and close phases of OboeEngine::restartStream --- src/hostapi/oboe/pa_oboe.cpp | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index 0929033fa..d0d2c3d78 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -541,17 +541,6 @@ bool OboeEngine::restartStream(OboeStream* i_oboeStream, int i_direction) { switch (i_direction) { case 1: //output-only - //stopping and closing - result = i_oboeStream->outputStream->stop(); - if (result != Result::OK) - LOGW("[OboeEngine::restartStream]\t Oboe couldn't stop the output stream: %s", - convertToText(result)); - result = i_oboeStream->outputStream->close(); - if (result != Result::OK) - LOGW("[OboeEngine::restartStream]\t Oboe couldn't close the output stream: %s", - convertToText(result)); - - //reopening and restarting result = i_oboeStream->outputBuilder.openStream(i_oboeStream->outputStream); if (result != Result::OK) LOGE("[OboeEngine::restartStream]\t Oboe couldn't reopen the output stream: %s", @@ -565,17 +554,6 @@ bool OboeEngine::restartStream(OboeStream* i_oboeStream, int i_direction) { break; case 2: //input-only - //stopping and closing - result = i_oboeStream->inputStream->stop(); - if (result != Result::OK) - LOGW("[OboeEngine::restartStream]\t Oboe couldn't stop the input stream: %s", - convertToText(result)); - result = i_oboeStream->inputStream->close(); - if (result != Result::OK) - LOGW("[OboeEngine::restartStream]\t Oboe couldn't close the input stream: %s", - convertToText(result)); - - //reopening and restarting result = inputBuilder.openStream(i_oboeStream->inputStream); if (result != Result::OK) LOGE("[OboeEngine::restartStream]\t Oboe couldn't reopen the input stream: %s", From e62621461de76f7946af457f6528388ce94e6858 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Thu, 5 Oct 2023 09:42:01 +0200 Subject: [PATCH 13/26] Updated functions' description --- src/hostapi/oboe/pa_oboe.cpp | 43 ++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index d0d2c3d78..f500f5995 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -81,7 +81,6 @@ #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,MODULE_NAME, __VA_ARGS__) #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,MODULE_NAME, __VA_ARGS__) -// Copied from @{pa_opensles.c}. #define ENSURE(expr, errorText) \ do \ { \ @@ -212,7 +211,7 @@ typedef struct OboeStream { AudioStreamBuilder inputBuilder; private: - OboeEngine *oboeEngineAddress; + OboeEngine *oboeEngineAddress = nullptr; } OboeStream; /** @@ -242,7 +241,7 @@ class OboeCallback: public AudioStreamCallback { /** * Stream engine of the host API - Oboe. We allocate only one instance of the engine per OboeStream, and - * we call its functions when we want to operate directly on Oboe. More infos on each function are + * we call its functions when we want to operate directly on Oboe. More information on each function is * provided right before its implementation. */ class OboeEngine { @@ -363,7 +362,7 @@ bool OboeEngine::tryStream(Direction i_direction, int32_t i_sampleRate, int32_t /** * \brief Opens an audio stream with a specific direction, sample rate and, * depending on the direction of the stream, sets its usage (if - * direction == Ditrction::Output) or its preset (if direction == Direction::Input). + * direction == Direction::Output) or its preset (if direction == Direction::Input). * Moreover, this function checks if the stream is blocking, and sets its callback * function if not. * @param oboeStream The stream we want to open @@ -481,8 +480,9 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, /** - * \brief Starts oboeStream - both input and output audiostreams are checked + * \brief Starts oboeStream - both input and output AudioStreams of the OboeStream are checked * and requested to be started. + * @param oboeStream The stream we want to start. * @return true if the streams we wanted to start are started successfully, false otherwise. */ bool OboeEngine::startStream(OboeStream *i_oboeStream) { @@ -506,8 +506,9 @@ bool OboeEngine::startStream(OboeStream *i_oboeStream) { /** - * \brief Stops oboeStream - both input and output audiostreams are checked + * \brief Stops oboeStream - both input and output AudioStreams of the OboeStream are checked * and requested to be stopped. + * @param oboeStream The stream we want to stop. * @return true if the streams we wanted to stop are stopped successfully, false otherwise. */ bool OboeEngine::stopStream(OboeStream *i_oboeStream) { @@ -531,8 +532,11 @@ bool OboeEngine::stopStream(OboeStream *i_oboeStream) { /** - * \brief Called when it's needed to restart the oboeStream's audio stream(s), mainly when the - * audio devices change while a stream is started. + * \brief Called when it's needed to restart the OboeStream's audio stream(s) when the audio device(s) change + * while a stream is started. Oboe will stop and close said streams in that case, + * so this function just reopens and restarts them. + * @param oboeStream The stream we want to restart. + * @param direction The direction(s) of the stream that have to be restarted (1 for output, 2 for input, 0 for both). * @return true if the stream is restarted successfully, false otherwise. */ bool OboeEngine::restartStream(OboeStream* i_oboeStream, int i_direction) { @@ -578,8 +582,9 @@ bool OboeEngine::restartStream(OboeStream* i_oboeStream, int i_direction) { /** - * \brief Closes oboeStream - both input and output audiostreams are checked + * \brief Closes oboeStream - both input and output AudioStreams of the OboeStream are checked * and closed if active. + * @param oboeStream The stream we want to close. * @return true if the stream is closed successfully, otherwise returns false. */ bool OboeEngine::closeStream(OboeStream *i_oboeStream) { @@ -613,7 +618,8 @@ bool OboeEngine::closeStream(OboeStream *i_oboeStream) { /** - * \brief Stops oboeStream - both input and output audiostreams are checked and forcefully stopped. + * \brief Stops oboeStream - both input and output AudioStreams of the OboeStream are checked and forcefully stopped. + * @param oboeStream The stream we want to abort. * @return true if the output stream and the input stream are stopped successfully, false otherwise. */ bool OboeEngine::abortStream(OboeStream *i_oboeStream) { @@ -654,6 +660,7 @@ bool OboeEngine::abortStream(OboeStream *i_oboeStream) { /** * \brief Writes frames on the output stream of oboeStream. Used by blocking streams. + * @param oboeStream The stream we want to write onto. * @param buffer The buffer that we want to write on the output stream; * @param framesToWrite The number of frames that we want to write. * @return true if the buffer is written correctly, false if the write function returns an error @@ -681,6 +688,7 @@ bool OboeEngine::writeStream(OboeStream *i_oboeStream, const void *i_buffer, int /** * \brief Reads frames from the input stream of oboeStream. Used by blocking streams. + * @param oboeStream The stream we want to read from. * @param buffer The buffer that we want to read from the input stream; * @param framesToWrite The number of frames that we want to read. * @return true if the buffer is read correctly, false if the read function returns an error @@ -707,7 +715,7 @@ bool OboeEngine::readStream(OboeStream *i_oboeStream, void *i_buffer, int32_t i_ /** - * \brief Allocates the memory of oboeStream. + * \brief Allocates the memory of an OboeStream, and sets its address in it. * @return the address of the oboeStream. */ OboeStream *OboeEngine::allocateOboeStream() { @@ -809,7 +817,8 @@ OboeCallback::onAudioReady(AudioStream *i_audioStream, void *i_audioData, int32_ 0); } - /* continue processing user buffers if cbresult is paContinue or if cbresult is paComplete and userBuffers aren't empty yet */ + /* continue processing user buffers if callback result is paContinue or + * if it is paComplete and userBuffers aren't empty yet */ if (m_oboeStreamHolder->callbackResult == paContinue || (m_oboeStreamHolder->callbackResult == paComplete && !PaUtil_IsBufferProcessorOutputEmpty(&m_oboeStreamHolder->bufferProcessor))) { @@ -1003,7 +1012,7 @@ PaError PaOboe_Initialize(PaUtilHostApiRepresentation **i_hostApi, PaHostApiInde } *i_hostApi = &oboeHostApi->inheritedHostApiRep; - // Initialization of infos. + // Info initialization. (*i_hostApi)->info.structVersion = 1; (*i_hostApi)->info.type = paInDevelopment; (*i_hostApi)->info.name = "android Oboe"; @@ -1134,7 +1143,7 @@ PaError PaOboe_Initialize(PaUtilHostApiRepresentation **i_hostApi, PaHostApiInde PaUtil_DestroyAllocationGroup(oboeHostApi->allocations); } - PaUtil_FreeMemory(boeHostApi); + PaUtil_FreeMemory(oboeeHostApi); } LOGE("[PaOboe - Initialize]\t Initialization failed. Error code: %d", result); return result; @@ -1401,7 +1410,7 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, oboeStream->inputFormat = hostInputSampleFormat; } else { inputChannelCount = 0; - inputSampleFormat = hostInputSampleFormat = paFloat32; /* Surpress 'uninitialised var' warnings. */ + inputSampleFormat = hostInputSampleFormat = paFloat32; /* Suppress 'uninitialised var' warnings. */ oboeStream->inputFormat = hostInputSampleFormat; } @@ -1508,7 +1517,7 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, oboeStream->framesPerHostCallback) / i_sampleRate; ENSURE(InitializeInputStream(oboeStream, oboeHostApi, androidInputPreset, i_sampleRate), - "Initializing inputstream failed") + "Initializing input stream failed") } else { oboeStream->hasInput = false; } if (outputChannelCount > 0) { @@ -1519,7 +1528,7 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, + oboeStream->framesPerHostCallback) / i_sampleRate; ENSURE(InitializeOutputStream(oboeStream, oboeHostApi, androidOutputUsage, i_sampleRate), - "Initializing outputstream failed"); + "Initializing output stream failed"); } else { oboeStream->hasOutput = false; } *i_paStream = (PaStream *) oboeStream; From 62cfeb6c3c275185aa76639f4029a6b8d9820aa3 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Thu, 5 Oct 2023 09:56:52 +0200 Subject: [PATCH 14/26] minor description corrections --- src/hostapi/oboe/pa_oboe.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index f500f5995..d417238ad 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -715,7 +715,7 @@ bool OboeEngine::readStream(OboeStream *i_oboeStream, void *i_buffer, int32_t i_ /** - * \brief Allocates the memory of an OboeStream, and sets its address in it. + * \brief Allocates the memory of an OboeStream, and sets its EngineAddress to this. * @return the address of the oboeStream. */ OboeStream *OboeEngine::allocateOboeStream() { @@ -1159,7 +1159,7 @@ static void Terminate(struct PaUtilHostApiRepresentation *i_hostApi) { auto *oboeHostApi = (PaOboeHostApiRepresentation *) i_hostApi; if (!(oboeHostApi->oboeEngine->closeStream(nullptr))) - LOGW("[PaOboe - Terminate]\t Couldn't close the streams correctly - see OboeEngine::CloseStream logs."); + LOGI("[PaOboe - Terminate]\t The streams were probably already closed - see OboeEngine::CloseStream logs."); if (oboeHostApi->oboeEngine != nullptr) delete oboeHostApi->oboeEngine; From ae5c61c20ee18656df030d2b446078d129b2b01c Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Thu, 5 Oct 2023 10:14:56 +0200 Subject: [PATCH 15/26] fixed all compiling errors generated by typos --- include/portaudio.h | 2 +- src/hostapi/oboe/pa_oboe.cpp | 38 ++++++++++++++++++------------------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/portaudio.h b/include/portaudio.h index bfee195f7..2b4e3ba75 100644 --- a/include/portaudio.h +++ b/include/portaudio.h @@ -291,7 +291,7 @@ typedef enum PaHostApiTypeId paWASAPI=13, paAudioScienceHPI=14, paAudioIO=15, - paPulseAudio=16 + paPulseAudio=16, paOboe=17 } PaHostApiTypeId; diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index d417238ad..c69edafd3 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -84,13 +84,13 @@ #define ENSURE(expr, errorText) \ do \ { \ - PaError m_err; \ - if (UNLIKELY((m_err = (expr)) < paNoError)) \ + PaError err; \ + if (UNLIKELY((err = (expr)) < paNoError)) \ { \ PaUtil_DebugPrint(("Expression '" #expr "' failed in '" __FILE__ "', line: " PA_STRINGIZE( \ __LINE__ ) "\n")); \ - PaUtil_SetLastHostErrorInfo(paInDevelopment, m_err, errorText); \ - m_error = m_err; \ + PaUtil_SetLastHostErrorInfo(paInDevelopment, err, errorText); \ + error = err; \ goto error; \ } \ } while (0); @@ -397,7 +397,7 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, ->setFramesPerCallback(i_oboeStream->framesPerHostCallback); if (!(i_oboeStream->isBlocking)) { - m_inputBuilder.setDataCallback(i_oboeStream->oboeCallback) + i_oboeStream->inputBuilder.setDataCallback(i_oboeStream->oboeCallback) ->setErrorCallback(i_oboeStream->oboeCallback); } @@ -445,7 +445,7 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, ->setErrorCallback(i_oboeStream->oboeCallback); } - result = i_oboeStream->outputBuilder.openStream(m_outputStream); + result = i_oboeStream->outputBuilder.openStream(i_oboeStream->outputStream); if (result != Result::OK) { LOGE("[OboeEngine::OpenStream]\t Oboe couldn't open the output stream: %s", convertToText(result)); @@ -558,7 +558,7 @@ bool OboeEngine::restartStream(OboeStream* i_oboeStream, int i_direction) { break; case 2: //input-only - result = inputBuilder.openStream(i_oboeStream->inputStream); + result = i_oboeStream->inputBuilder.openStream(i_oboeStream->inputStream); if (result != Result::OK) LOGE("[OboeEngine::restartStream]\t Oboe couldn't reopen the input stream: %s", convertToText(result)); @@ -639,13 +639,13 @@ bool OboeEngine::abortStream(OboeStream *i_oboeStream) { LOGE("[OboeEngine::abortStream]\t Couldn't force the input stream to stop: %s", convertToText(inputResult)); inputResult = i_oboeStream->inputStream->close(); - if (i_oboeStream->inputResult != Result::OK) + if (inputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the input stream to close: %s", convertToText(inputResult)); } if (hasOutput) { outputResult = i_oboeStream->outputStream->stop(); - if (i_oboeStream->outputResult != Result::OK) + if (outputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the output stream to stop: %s", convertToText(outputResult)); outputResult = i_oboeStream->outputStream->close(); @@ -1040,7 +1040,7 @@ PaError PaOboe_Initialize(PaUtilHostApiRepresentation **i_hostApi, PaHostApiInde for (int i = 0; i < deviceCount; ++i) { PaDeviceInfo *deviceInfo = &deviceInfoArray[i]; deviceInfo->structVersion = 2; - deviceInfo->hostApi = hostApiIndex; + deviceInfo->hostApi = i_hostApiIndex; /* OboeEngine will handle manual device selection through the use of PaOboe_SetSelectedDevice. Portaudio doesn't need to know about this, so we just use a default device. */ @@ -1143,7 +1143,7 @@ PaError PaOboe_Initialize(PaUtilHostApiRepresentation **i_hostApi, PaHostApiInde PaUtil_DestroyAllocationGroup(oboeHostApi->allocations); } - PaUtil_FreeMemory(oboeeHostApi); + PaUtil_FreeMemory(oboeHostApi); } LOGE("[PaOboe - Initialize]\t Initialization failed. Error code: %d", result); return result; @@ -1221,7 +1221,7 @@ static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *i_hostApi, if (androidRecordingPreset != InputPreset::Generic && androidRecordingPreset != InputPreset::Camcorder && androidRecordingPreset != InputPreset::VoiceRecognition && - androidRecordingPreset != InputPreset::VoiceCommunication + androidRecordingPreset != InputPreset::VoiceCommunication && androidRecordingPreset != InputPreset::VoicePerformance) { return paIncompatibleHostApiSpecificStreamInfo; } @@ -1298,13 +1298,13 @@ static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *i_hostApi, * the correct amount of memory. * @return the value returned by OboeEngine::openStream. */ -static PaError InitializeOutputStream(OboeStream i_oboeStream, PaOboeHostApiRepresentation *i_oboeHostApi, +static PaError InitializeOutputStream(OboeStream* i_oboeStream, PaOboeHostApiRepresentation *i_oboeHostApi, Usage i_androidOutputUsage, double i_sampleRate) { return i_oboeHostApi->oboeEngine->openStream(i_oboeStream, Direction::Output, - sampleRate, - androidOutputUsage, + i_sampleRate, + i_androidOutputUsage, Generic); //Input preset won't be used, so we put the default value. } @@ -1321,7 +1321,7 @@ static PaError InitializeOutputStream(OboeStream i_oboeStream, PaOboeHostApiRepr * the correct amount of memory. * @return the value returned by OboeEngine::openStream. */ -static PaError InitializeInputStream(OboeStream i_oboeStream, PaOboeHostApiRepresentation *i_oboeHostApi, +static PaError InitializeInputStream(OboeStream* i_oboeStream, PaOboeHostApiRepresentation *i_oboeHostApi, InputPreset i_androidInputPreset, double i_sampleRate) { return i_oboeHostApi->oboeEngine->openStream(i_oboeStream, @@ -1399,7 +1399,7 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, if (androidInputPreset != InputPreset::Generic && androidInputPreset != InputPreset::Camcorder && androidInputPreset != InputPreset::VoiceRecognition && - androidInputPreset != InputPreset::VoiceCommunication + androidInputPreset != InputPreset::VoiceCommunication && androidInputPreset != InputPreset::VoicePerformance) return paIncompatibleHostApiSpecificStreamInfo; } @@ -1447,7 +1447,7 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, PaUtil_SelectClosestAvailableFormat is a bit faulty when working with multiple options */ hostOutputSampleFormat = PaUtil_SelectClosestAvailableFormat( - paFloat32, m_outputSampleFormat); + paFloat32, outputSampleFormat); oboeStream->outputFormat = hostOutputSampleFormat; } else { outputChannelCount = 0; @@ -1750,7 +1750,7 @@ static PaError WriteStream(PaStream *i_paStream, const void *i_buffer, unsigned PaError error = paNoError; while (i_frames > 0) { - framesToWrite = PA_MIN(stream->framesPerHostCallback, i_frames); + framesToWrite = PA_MIN(oboeStream->framesPerHostCallback, i_frames); if (!(oboeEngine->writeStream(oboeStream, userBuffer, framesToWrite * oboeStream->bufferProcessor.outputChannelCount))) From 9d03a735517e0d77f6560e7e5077b9c0b358953c Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Thu, 5 Oct 2023 16:09:29 +0200 Subject: [PATCH 16/26] Added OboeMediator class in place of OboeCallback, that mediates PortAudio C stream struct and the C++ OboeEngine class --- src/hostapi/oboe/pa_oboe.cpp | 267 +++++++++++++++++++---------------- 1 file changed, 143 insertions(+), 124 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index c69edafd3..a716c4340 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -165,7 +165,7 @@ PerformanceMode g_inputPerfMode = PerformanceMode::LowLatency; PerformanceMode g_outputPerfMode = PerformanceMode::LowLatency; class OboeEngine; -class OboeCallback; +class OboeMediator; /** * Stream structure, useful to store relevant information. It's needed by Portaudio. @@ -190,7 +190,6 @@ typedef struct OboeStream { PaSampleFormat inputFormat; PaSampleFormat outputFormat; - OboeCallback *oboeCallback; // Buffers are managed by the callback function in Oboe. void **outputBuffers; int currentOutputBuffer; @@ -200,39 +199,43 @@ typedef struct OboeStream { unsigned long framesPerHostCallback; unsigned bytesPerFrame; - OboeEngine *getEngineAddress() { return oboeEngineAddress; } - - void setEngineAddress(OboeEngine *i_oboeEngine) { oboeEngineAddress = i_oboeEngine; } - - //The only instances of output and input streams that will be used, and their builders - std::shared_ptr outputStream; - AudioStreamBuilder outputBuilder; - std::shared_ptr inputStream; - AudioStreamBuilder inputBuilder; - -private: - OboeEngine *oboeEngineAddress = nullptr; + OboeMediator* oboeMediator; } OboeStream; -/** - * Callback class for OboeStream. Will be used for non-blocking streams. - */ -class OboeCallback: public AudioStreamCallback { + +class OboeMediator: public AudioStreamCallback{ public: - OboeCallback(){ m_oboeStreamHolder = (OboeStream *) PaUtil_AllocateZeroInitializedMemory(sizeof(OboeStream)); } + OboeMediator(OboeStream* i_oboeStream) { + m_oboeCallbackStream = i_oboeStream; + } + //Callback function for non-blocking streams DataCallbackResult onAudioReady(AudioStream *audioStream, void *audioData, int32_t numFrames) override; - + //Callback utils void onErrorAfterClose(AudioStream *audioStream, oboe::Result error) override; + void resetCallbackCounters(); + void setOutputCallback() { m_outputBuilder.setDataCallback(this)->setErrorCallback(this); } + void setInputCallback() { m_inputBuilder.setDataCallback(this)->setErrorCallback(this); } - void setStreamHolder(OboeStream* oboeStream){ m_oboeStreamHolder = oboeStream; } + //getter and setter of m_oboeEngine and m_oboeCallbackStream + OboeEngine *getEngine() { return m_oboeEngine; } + void setEngine(OboeEngine *i_oboeEngine) { m_oboeEngine = i_oboeEngine; } - void resetCallbackCounters(); + OboeStream *getStreamAddress() { return m_oboeCallbackStream; } + void setCallbackStream(OboeStream *i_oboeStream) { m_oboeCallbackStream = i_oboeStream; } + + //The only instances of output and input streams that will be used, and their builders + std::shared_ptr m_outputStream; + AudioStreamBuilder m_outputBuilder; + std::shared_ptr m_inputStream; + AudioStreamBuilder m_inputBuilder; private: + OboeEngine *m_oboeEngine; + //callback utils - OboeStream *m_oboeStreamHolder; + OboeStream *m_oboeCallbackStream; unsigned long m_framesProcessed{}; PaStreamCallbackTimeInfo m_timeInfo{}; struct timespec m_timeSpec{}; @@ -270,12 +273,14 @@ class OboeEngine { bool readStream(OboeStream *oboeStream, void *buffer, int32_t framesToRead); //Engine utils - OboeStream *allocateOboeStream(); + void constructOboeStream(OboeStream* oboeStream); private: std::shared_ptr m_testStream; AudioStreamBuilder m_testBuilder; + OboeMediator* m_terminableMediator; + //Conversion utils static AudioFormat PaToOboeFormat(PaSampleFormat paFormat); @@ -379,15 +384,14 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, Usage i_androidOutputUsage, InputPreset i_androidInputPreset) { PaError error = paNoError; Result result; + OboeMediator* mediator = i_oboeStream->oboeMediator; if(!(i_oboeStream->isBlocking)){ - i_oboeStream->oboeCallback = new OboeCallback(); - i_oboeStream->oboeCallback->setStreamHolder(i_oboeStream); - i_oboeStream->oboeCallback->resetCallbackCounters(); + mediator->resetCallbackCounters(); } if (i_direction == Direction::Input) { - i_oboeStream->inputBuilder.setChannelCount(i_oboeStream->bufferProcessor.inputChannelCount) + mediator->m_inputBuilder.setChannelCount(i_oboeStream->bufferProcessor.inputChannelCount) ->setFormat(PaToOboeFormat(i_oboeStream->inputFormat)) ->setSampleRate(i_sampleRate) ->setDirection(Direction::Input) @@ -397,11 +401,10 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, ->setFramesPerCallback(i_oboeStream->framesPerHostCallback); if (!(i_oboeStream->isBlocking)) { - i_oboeStream->inputBuilder.setDataCallback(i_oboeStream->oboeCallback) - ->setErrorCallback(i_oboeStream->oboeCallback); + mediator->setInputCallback(); } - result = i_oboeStream->inputBuilder.openStream(i_oboeStream->inputStream); + result = mediator->m_inputBuilder.openStream(mediator->m_inputStream); if (result != Result::OK) { LOGE("[OboeEngine::OpenStream]\t Oboe couldn't open the input stream: %s", @@ -409,7 +412,7 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, return paUnanticipatedHostError; } - i_oboeStream->inputStream->setBufferSizeInFrames(i_oboeStream->inputStream->getFramesPerBurst() * + mediator->m_inputStream->setBufferSizeInFrames(mediator->m_inputStream->getFramesPerBurst() * g_numberOfBuffers); i_oboeStream->inputBuffers = (void **) PaUtil_AllocateZeroInitializedMemory(g_numberOfBuffers * sizeof(int32_t * )); @@ -424,14 +427,14 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, for (int j = 0; j < i; ++j) PaUtil_FreeMemory(i_oboeStream->inputBuffers[j]); PaUtil_FreeMemory(i_oboeStream->inputBuffers); - i_oboeStream->inputStream->close(); + mediator->m_inputStream->close(); error = paInsufficientMemory; break; } } i_oboeStream->currentInputBuffer = 0; } else { - i_oboeStream->outputBuilder.setChannelCount(i_oboeStream->bufferProcessor.outputChannelCount) + mediator->m_outputBuilder.setChannelCount(i_oboeStream->bufferProcessor.outputChannelCount) ->setFormat(PaToOboeFormat(i_oboeStream->outputFormat)) ->setSampleRate(i_sampleRate) ->setDirection(Direction::Output) @@ -441,18 +444,17 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, ->setFramesPerCallback(i_oboeStream->framesPerHostCallback); if (!(i_oboeStream->isBlocking)) { - i_oboeStream->outputBuilder.setDataCallback(i_oboeStream->oboeCallback) - ->setErrorCallback(i_oboeStream->oboeCallback); + mediator->setOutputCallback(); } - result = i_oboeStream->outputBuilder.openStream(i_oboeStream->outputStream); + result = mediator->m_outputBuilder.openStream(mediator->m_outputStream); if (result != Result::OK) { LOGE("[OboeEngine::OpenStream]\t Oboe couldn't open the output stream: %s", convertToText(result)); return paUnanticipatedHostError; } - i_oboeStream->outputStream->setBufferSizeInFrames(i_oboeStream->outputStream->getFramesPerBurst() * + mediator->m_outputStream->setBufferSizeInFrames(mediator->m_outputStream->getFramesPerBurst() * g_numberOfBuffers); i_oboeStream->outputBuffers = (void **) PaUtil_AllocateZeroInitializedMemory(g_numberOfBuffers * sizeof(int32_t * )); @@ -467,7 +469,7 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, for (int j = 0; j < i; ++j) PaUtil_FreeMemory(i_oboeStream->outputBuffers[j]); PaUtil_FreeMemory(i_oboeStream->outputBuffers); - i_oboeStream->outputStream->close(); + mediator->m_outputStream->close(); error = paInsufficientMemory; break; } @@ -487,15 +489,16 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, */ bool OboeEngine::startStream(OboeStream *i_oboeStream) { Result outputResult = Result::OK, inputResult = Result::OK; + OboeMediator* mediator = i_oboeStream->oboeMediator; if (i_oboeStream->hasInput) { - inputResult = i_oboeStream->inputStream->requestStart(); + inputResult = mediator->m_inputStream->requestStart(); if (inputResult != Result::OK) LOGE("[OboeEngine::startStream]\t Oboe couldn't start the input stream: %s", convertToText(inputResult)); } if (i_oboeStream->hasOutput) { - outputResult = i_oboeStream->outputStream->requestStart(); + outputResult = mediator->m_outputStream->requestStart(); if (outputResult != Result::OK) LOGE("[OboeEngine::startStream]\t Oboe couldn't start the output stream: %s", convertToText(outputResult)); @@ -513,15 +516,16 @@ bool OboeEngine::startStream(OboeStream *i_oboeStream) { */ bool OboeEngine::stopStream(OboeStream *i_oboeStream) { Result outputResult = Result::OK, inputResult = Result::OK; + OboeMediator* mediator = i_oboeStream->oboeMediator; if (i_oboeStream->hasInput) { - inputResult = i_oboeStream->inputStream->requestStop(); + inputResult = mediator->m_inputStream->requestStop(); if (inputResult != Result::OK) LOGE("[OboeEngine::stopStream]\t Oboe couldn't stop the input stream: %s", convertToText(inputResult)); } if (i_oboeStream->hasOutput) { - outputResult = i_oboeStream->outputStream->requestStop(); + outputResult = mediator->m_outputStream->requestStop(); if (outputResult != Result::OK) LOGE("[OboeEngine::stopStream]\t Oboe couldn't stop the output stream: %s", convertToText(outputResult)); @@ -536,20 +540,21 @@ bool OboeEngine::stopStream(OboeStream *i_oboeStream) { * while a stream is started. Oboe will stop and close said streams in that case, * so this function just reopens and restarts them. * @param oboeStream The stream we want to restart. - * @param direction The direction(s) of the stream that have to be restarted (1 for output, 2 for input, 0 for both). + * @param direction The direction(s) of the stream that have to be restarted (1 for output, 2 for input, 3 for both). * @return true if the stream is restarted successfully, false otherwise. */ bool OboeEngine::restartStream(OboeStream* i_oboeStream, int i_direction) { bool outcome = true; Result result; + OboeMediator* mediator = i_oboeStream->oboeMediator; switch (i_direction) { case 1: //output-only - result = i_oboeStream->outputBuilder.openStream(i_oboeStream->outputStream); + result = mediator->m_outputBuilder.openStream(mediator->m_outputStream); if (result != Result::OK) LOGE("[OboeEngine::restartStream]\t Oboe couldn't reopen the output stream: %s", convertToText(result)); - result = i_oboeStream->outputStream->start(); + result = mediator->m_outputStream->start(); if (result != Result::OK) { LOGE("[OboeEngine::restartStream]\t Oboe couldn't restart the output stream: %s", convertToText(result)); @@ -558,11 +563,11 @@ bool OboeEngine::restartStream(OboeStream* i_oboeStream, int i_direction) { break; case 2: //input-only - result = i_oboeStream->inputBuilder.openStream(i_oboeStream->inputStream); + result = mediator->m_inputBuilder.openStream(mediator->m_inputStream); if (result != Result::OK) LOGE("[OboeEngine::restartStream]\t Oboe couldn't reopen the input stream: %s", convertToText(result)); - result = i_oboeStream->inputStream->start(); + result = mediator->m_inputStream->start(); if (result != Result::OK) { LOGE("[OboeEngine::restartStream]\t Oboe couldn't restart the input stream: %s", convertToText(result)); @@ -590,23 +595,26 @@ bool OboeEngine::restartStream(OboeStream* i_oboeStream, int i_direction) { bool OboeEngine::closeStream(OboeStream *i_oboeStream) { Result outputResult = Result::OK, inputResult = Result::OK; bool hasOutput = true, hasInput = true; + OboeMediator* mediator; if (i_oboeStream == nullptr) { - LOGW("[OboeEngine::closeStream]\t i_oboeStream is a nullptr. Terminating both oboe streams."); + LOGW("[OboeEngine::closeStream]\t i_oboeStream is a nullptr. Aborting both oboe streams of the terminable mediator"); + mediator = m_terminableMediator; } else { + mediator = i_oboeStream->oboeMediator; hasInput = i_oboeStream->hasInput; hasOutput = i_oboeStream->hasOutput; } if (hasOutput) { - outputResult = i_oboeStream->outputStream->close(); + outputResult = mediator->m_outputStream->close(); if (outputResult == Result::ErrorClosed) { outputResult = Result::OK; LOGW("[OboeEngine::closeStream]\t Tried to close output stream, but was already closed."); } } if (hasInput) { - inputResult = i_oboeStream->inputStream->close(); + inputResult = mediator->m_inputStream->close(); if (inputResult == Result::ErrorClosed) { inputResult = Result::OK; LOGW("[OboeEngine::closeStream]\t Tried to close input stream, but was already closed."); @@ -625,30 +633,33 @@ bool OboeEngine::closeStream(OboeStream *i_oboeStream) { bool OboeEngine::abortStream(OboeStream *i_oboeStream) { Result outputResult = Result::OK, inputResult = Result::OK; bool hasOutput = true, hasInput = true; + OboeMediator* mediator; if (i_oboeStream == nullptr) { - LOGW("[OboeEngine::closeStream]\t i_oboeStream is a nullptr. Aborting both oboe streams."); + LOGW("[OboeEngine::abortStream]\t i_oboeStream is a nullptr. Aborting both oboe streams of the terminable mediator"); + mediator = m_terminableMediator; } else { + mediator = i_oboeStream->oboeMediator; hasInput = i_oboeStream->hasInput; hasOutput = i_oboeStream->hasOutput; } if (hasInput) { - inputResult = i_oboeStream->inputStream->stop(); + inputResult = mediator->m_inputStream->stop(); if (inputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the input stream to stop: %s", convertToText(inputResult)); - inputResult = i_oboeStream->inputStream->close(); + inputResult = mediator->m_inputStream->close(); if (inputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the input stream to close: %s", convertToText(inputResult)); } if (hasOutput) { - outputResult = i_oboeStream->outputStream->stop(); + outputResult = mediator->m_outputStream->stop(); if (outputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the output stream to stop: %s", convertToText(outputResult)); - outputResult = i_oboeStream->outputStream->close(); + outputResult = mediator->m_outputStream->close(); if (outputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the output stream to close: %s", convertToText(outputResult)); @@ -669,8 +680,9 @@ bool OboeEngine::abortStream(OboeStream *i_oboeStream) { */ bool OboeEngine::writeStream(OboeStream *i_oboeStream, const void *i_buffer, int32_t i_framesToWrite) { bool outcome = true; + OboeMediator* mediator = i_oboeStream->oboeMediator; - ResultWithValue result = i_oboeStream->outputStream->write(i_buffer, i_framesToWrite, TIMEOUT_NS); + ResultWithValue result = mediator->m_outputStream->write(i_buffer, i_framesToWrite, TIMEOUT_NS); // If the stream is interrupted because the device suddenly changes, restart the stream. if (result.error() == Result::ErrorDisconnected) { @@ -697,8 +709,9 @@ bool OboeEngine::writeStream(OboeStream *i_oboeStream, const void *i_buffer, int */ bool OboeEngine::readStream(OboeStream *i_oboeStream, void *i_buffer, int32_t i_framesToRead) { bool outcome = true; + OboeMediator* mediator = i_oboeStream->oboeMediator; - ResultWithValue result = i_oboeStream->inputStream->read(i_buffer, i_framesToRead, TIMEOUT_NS); + ResultWithValue result = mediator->m_inputStream->read(i_buffer, i_framesToRead, TIMEOUT_NS); // If the stream is interrupted because the device suddenly changes, restart the stream. if (result.error() == Result::ErrorDisconnected) { @@ -718,10 +731,10 @@ bool OboeEngine::readStream(OboeStream *i_oboeStream, void *i_buffer, int32_t i_ * \brief Allocates the memory of an OboeStream, and sets its EngineAddress to this. * @return the address of the oboeStream. */ -OboeStream *OboeEngine::allocateOboeStream() { - OboeStream *oboeStream = (OboeStream *) PaUtil_AllocateZeroInitializedMemory(sizeof(OboeStream)); - oboeStream->setEngineAddress(this); - return oboeStream; +void OboeEngine::constructOboeStream(OboeStream* i_oboeStream) { + i_oboeStream = (OboeStream *) PaUtil_AllocateZeroInitializedMemory(sizeof(OboeStream)); + m_terminableMediator = i_oboeStream->oboeMediator = new OboeMediator(i_oboeStream); + i_oboeStream->oboeMediator->setEngine(this); } @@ -771,114 +784,119 @@ int32_t OboeEngine::getSelectedDevice(Direction i_direction) { return g_outputDeviceId; } -/*----------------------------- OboeCallback functions implementations -----------------------------*/ +/*----------------------------- OboeMediator functions implementations -----------------------------*/ /** * \brief Oboe's callback routine. */ DataCallbackResult -OboeCallback::onAudioReady(AudioStream *i_audioStream, void *i_audioData, int32_t i_numFrames) { +OboeMediator::onAudioReady(AudioStream *i_audioStream, void *i_audioData, int32_t i_numFrames) { clock_gettime(CLOCK_REALTIME, &m_timeSpec); m_timeInfo.currentTime = (PaTime)(m_timeSpec.tv_sec + (m_timeSpec.tv_nsec / 1000000000.0)); - m_timeInfo.outputBufferDacTime = (PaTime)(m_oboeStreamHolder->framesPerHostCallback + m_timeInfo.outputBufferDacTime = (PaTime)(m_oboeCallbackStream->framesPerHostCallback / - m_oboeStreamHolder->streamRepresentation.streamInfo.sampleRate + m_oboeCallbackStream->streamRepresentation.streamInfo.sampleRate + m_timeInfo.currentTime); - m_timeInfo.inputBufferAdcTime = (PaTime)(m_oboeStreamHolder->framesPerHostCallback + m_timeInfo.inputBufferAdcTime = (PaTime)(m_oboeCallbackStream->framesPerHostCallback / - m_oboeStreamHolder->streamRepresentation.streamInfo.sampleRate + m_oboeCallbackStream->streamRepresentation.streamInfo.sampleRate + m_timeInfo.currentTime); /* check if StopStream or AbortStream was called */ - if (m_oboeStreamHolder->doStop) { - m_oboeStreamHolder->callbackResult = paComplete; - } else if (m_oboeStreamHolder->doAbort) { - m_oboeStreamHolder->callbackResult = paAbort; + if (m_oboeCallbackStream->doStop) { + m_oboeCallbackStream->callbackResult = paComplete; + } else if (m_oboeCallbackStream->doAbort) { + m_oboeCallbackStream->callbackResult = paAbort; } - PaUtil_BeginCpuLoadMeasurement(&m_oboeStreamHolder->cpuLoadMeasurer); - PaUtil_BeginBufferProcessing(&m_oboeStreamHolder->bufferProcessor, - &m_timeInfo, m_oboeStreamHolder->cbFlags); + PaUtil_BeginCpuLoadMeasurement(&m_oboeCallbackStream->cpuLoadMeasurer); + PaUtil_BeginBufferProcessing(&m_oboeCallbackStream->bufferProcessor, + &m_timeInfo, m_oboeCallbackStream->cbFlags); - if (m_oboeStreamHolder->hasOutput) { - m_oboeStreamHolder->outputBuffers[m_oboeStreamHolder->currentOutputBuffer] = i_audioData; - PaUtil_SetOutputFrameCount(&m_oboeStreamHolder->bufferProcessor, i_numFrames); - PaUtil_SetInterleavedOutputChannels(&m_oboeStreamHolder->bufferProcessor, 0, - (void *) ((PaInt16 **) m_oboeStreamHolder->outputBuffers)[ - m_oboeStreamHolder->currentOutputBuffer], + if (m_oboeCallbackStream->hasOutput) { + m_oboeCallbackStream->outputBuffers[m_oboeCallbackStream->currentOutputBuffer] = i_audioData; + PaUtil_SetOutputFrameCount(&m_oboeCallbackStream->bufferProcessor, i_numFrames); + PaUtil_SetInterleavedOutputChannels(&m_oboeCallbackStream->bufferProcessor, 0, + (void *) ((PaInt16 **) m_oboeCallbackStream->outputBuffers)[ + m_oboeCallbackStream->currentOutputBuffer], 0); } - if (m_oboeStreamHolder->hasInput) { - i_audioData = m_oboeStreamHolder->inputBuffers[m_oboeStreamHolder->currentInputBuffer]; - PaUtil_SetInputFrameCount(&m_oboeStreamHolder->bufferProcessor, 0); - PaUtil_SetInterleavedInputChannels(&m_oboeStreamHolder->bufferProcessor, 0, - (void *) ((PaInt16 **) m_oboeStreamHolder->inputBuffers)[ - m_oboeStreamHolder->currentInputBuffer], + if (m_oboeCallbackStream->hasInput) { + i_audioData = m_oboeCallbackStream->inputBuffers[m_oboeCallbackStream->currentInputBuffer]; + PaUtil_SetInputFrameCount(&m_oboeCallbackStream->bufferProcessor, 0); + PaUtil_SetInterleavedInputChannels(&m_oboeCallbackStream->bufferProcessor, 0, + (void *) ((PaInt16 **) m_oboeCallbackStream->inputBuffers)[ + m_oboeCallbackStream->currentInputBuffer], 0); } /* continue processing user buffers if callback result is paContinue or * if it is paComplete and userBuffers aren't empty yet */ - if (m_oboeStreamHolder->callbackResult == paContinue - || (m_oboeStreamHolder->callbackResult == paComplete - && !PaUtil_IsBufferProcessorOutputEmpty(&m_oboeStreamHolder->bufferProcessor))) { - m_framesProcessed = PaUtil_EndBufferProcessing(&m_oboeStreamHolder->bufferProcessor, - &m_oboeStreamHolder->callbackResult); + if (m_oboeCallbackStream->callbackResult == paContinue + || (m_oboeCallbackStream->callbackResult == paComplete + && !PaUtil_IsBufferProcessorOutputEmpty(&m_oboeCallbackStream->bufferProcessor))) { + m_framesProcessed = PaUtil_EndBufferProcessing(&m_oboeCallbackStream->bufferProcessor, + &m_oboeCallbackStream->callbackResult); } /* enqueue a buffer only when there are frames to be processed, * this will be 0 when paComplete + empty buffers or paAbort */ if (m_framesProcessed > 0) { - if (m_oboeStreamHolder->hasOutput) { - m_oboeStreamHolder->currentOutputBuffer = - (m_oboeStreamHolder->currentOutputBuffer + 1) % g_numberOfBuffers; + if (m_oboeCallbackStream->hasOutput) { + m_oboeCallbackStream->currentOutputBuffer = + (m_oboeCallbackStream->currentOutputBuffer + 1) % g_numberOfBuffers; } - if (m_oboeStreamHolder->hasInput) { - m_oboeStreamHolder->currentInputBuffer = (m_oboeStreamHolder->currentInputBuffer + 1) % g_numberOfBuffers; + if (m_oboeCallbackStream->hasInput) { + m_oboeCallbackStream->currentInputBuffer = (m_oboeCallbackStream->currentInputBuffer + 1) % g_numberOfBuffers; } } - PaUtil_EndCpuLoadMeasurement(&m_oboeStreamHolder->cpuLoadMeasurer, m_framesProcessed); + PaUtil_EndCpuLoadMeasurement(&m_oboeCallbackStream->cpuLoadMeasurer, m_framesProcessed); /* StopStream was called */ - if (m_framesProcessed == 0 && m_oboeStreamHolder->doStop) { - m_oboeStreamHolder->oboeCallbackResult = DataCallbackResult::Stop; + if (m_framesProcessed == 0 && m_oboeCallbackStream->doStop) { + m_oboeCallbackStream->oboeCallbackResult = DataCallbackResult::Stop; } /* if AbortStream or StopStream weren't called, stop from the cb */ - else if (m_framesProcessed == 0 && !(m_oboeStreamHolder->doAbort || m_oboeStreamHolder->doStop)) { - m_oboeStreamHolder->isActive = false; - m_oboeStreamHolder->isStopped = true; - if (m_oboeStreamHolder->streamRepresentation.streamFinishedCallback != nullptr) - m_oboeStreamHolder->streamRepresentation.streamFinishedCallback( - m_oboeStreamHolder->streamRepresentation.userData); - m_oboeStreamHolder->oboeCallbackResult = DataCallbackResult::Stop; //TODO: Resume this test (onAudioReady) + else if (m_framesProcessed == 0 && !(m_oboeCallbackStream->doAbort || m_oboeCallbackStream->doStop)) { + m_oboeCallbackStream->isActive = false; + m_oboeCallbackStream->isStopped = true; + if (m_oboeCallbackStream->streamRepresentation.streamFinishedCallback != nullptr) + m_oboeCallbackStream->streamRepresentation.streamFinishedCallback( + m_oboeCallbackStream->streamRepresentation.userData); + m_oboeCallbackStream->oboeCallbackResult = DataCallbackResult::Stop; //TODO: Resume this test (onAudioReady) } - return m_oboeStreamHolder->oboeCallbackResult; + return m_oboeCallbackStream->oboeCallbackResult; } /** * \brief If the data callback ends without returning DataCallbackResult::Stop, this routine tells - * what error occurred. + * what error occurred, and tries to restart the stream if the error was ErrorDisconnected. */ -void OboeCallback::onErrorAfterClose(AudioStream *i_audioStream, Result i_error) { +void OboeMediator::onErrorAfterClose(AudioStream *i_audioStream, Result i_error) { if (i_error == oboe::Result::ErrorDisconnected) { - OboeEngine* oboeEngine = m_oboeStreamHolder->getEngineAddress(); - LOGW("[OboeCallback::onErrorAfterClose]\t ErrorDisconnected - Restarting stream(s)"); - if (!oboeEngine->restartStream(m_oboeStreamHolder, 0)) - LOGE("[OboeCallback::onErrorAfterClose]\t Couldn't restart stream(s)"); + OboeEngine* oboeEngine = getEngine(); + LOGW("[OboeMediator::onErrorAfterClose]\t ErrorDisconnected - Restarting stream(s)"); + int i = 0; + if(m_oboeCallbackStream->hasOutput) + i++; + if(m_oboeCallbackStream->hasInput) + i+=2; + if (!oboeEngine->restartStream(m_oboeCallbackStream, i)) + LOGE("[OboeMediator::onErrorAfterClose]\t Couldn't restart stream(s)"); } else - LOGE("[OboeCallback::onErrorAfterClose]\t Error was %s", oboe::convertToText(i_error)); + LOGE("[OboeMediator::onErrorAfterClose]\t Error was %s", oboe::convertToText(i_error)); } /** - * \brief Resets callback counters (called at the start of each iteration of onAudioReady + * \brief Resets callback counters (called at the start of each iteration of onAudioReady). */ -void OboeCallback::resetCallbackCounters() { +void OboeMediator::resetCallbackCounters() { m_framesProcessed = 0; m_timeInfo = {0, 0, 0}; } @@ -1368,7 +1386,8 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, Usage androidOutputUsage = Usage::VoiceCommunication; InputPreset androidInputPreset = InputPreset::Generic; - OboeStream *oboeStream = oboeHostApi->oboeEngine->allocateOboeStream(); + OboeStream* oboeStream; + oboeHostApi->oboeEngine->constructOboeStream(oboeStream); if (!oboeStream) { error = paInsufficientMemory; @@ -1554,7 +1573,7 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, */ static PaError CloseStream(PaStream *i_paStream) { auto *oboeStream = (OboeStream *) i_paStream; - auto *oboeEngine = oboeStream->getEngineAddress(); + auto *oboeEngine = oboeStream->oboeMediator->getEngine(); if (!(oboeEngine->closeStream(oboeStream))) LOGW("[PaOboe - CloseStream]\t Some errors have occurred in closing oboe streams - see OboeEngine::CloseStream logs."); @@ -1588,7 +1607,7 @@ static PaError CloseStream(PaStream *i_paStream) { */ static PaError StartStream(PaStream *i_paStream) { auto *oboeStream = (OboeStream *) i_paStream; - auto *oboeEngine = oboeStream->getEngineAddress(); + auto *oboeEngine = oboeStream->oboeMediator->getEngine(); PaUtil_ResetBufferProcessor(&oboeStream->bufferProcessor); @@ -1647,7 +1666,7 @@ static PaError StartStream(PaStream *i_paStream) { static PaError StopStream(PaStream *i_paStream) { PaError error = paNoError; auto *oboeStream = (OboeStream *) i_paStream; - auto *oboeEngine = oboeStream->getEngineAddress(); + auto *oboeEngine = oboeStream->oboeMediator->getEngine(); if (oboeStream->isStopped) { LOGW("[PaOboe - StopStream]\t Stream was already stopped."); @@ -1681,7 +1700,7 @@ static PaError StopStream(PaStream *i_paStream) { static PaError AbortStream(PaStream *i_paStream) { PaError error = paNoError; auto *oboeStream = (OboeStream *) i_paStream; - auto *oboeEngine = oboeStream->getEngineAddress(); + auto *oboeEngine = oboeStream->oboeMediator->getEngine(); LOGI("[PaOboe - AbortStream]\t Aborting stream."); if (!oboeStream->isBlocking) { @@ -1714,7 +1733,7 @@ static PaError AbortStream(PaStream *i_paStream) { */ static PaError ReadStream(PaStream *i_paStream, void *i_buffer, unsigned long i_frames) { auto *oboeStream = (OboeStream *) i_paStream; - auto *oboeEngine = oboeStream->getEngineAddress(); + auto *oboeEngine = oboeStream->oboeMediator->getEngine(); void *userBuffer = i_buffer; unsigned framesToRead; PaError error = paNoError; @@ -1744,7 +1763,7 @@ static PaError ReadStream(PaStream *i_paStream, void *i_buffer, unsigned long i_ */ static PaError WriteStream(PaStream *i_paStream, const void *i_buffer, unsigned long i_frames) { auto *oboeStream = (OboeStream *) i_paStream; - auto *oboeEngine = oboeStream->getEngineAddress(); + auto *oboeEngine = oboeStream->oboeMediator->getEngine(); const void *userBuffer = i_buffer; unsigned framesToWrite; PaError error = paNoError; From 5098235f37a3bd4eb3b4809fcae460ff27c34ae4 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Fri, 6 Oct 2023 10:07:35 +0200 Subject: [PATCH 17/26] Fixed allocation problem, working PaOboe implementation --- src/hostapi/oboe/pa_oboe.cpp | 44 ++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index a716c4340..2fd0dc564 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -384,6 +384,12 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, Usage i_androidOutputUsage, InputPreset i_androidInputPreset) { PaError error = paNoError; Result result; + + if (i_oboeStream == nullptr) { + LOGE("[OboeEngine::openStream]\t i_oboeStream is a nullptr."); + return paInternalError; + } + OboeMediator* mediator = i_oboeStream->oboeMediator; if(!(i_oboeStream->isBlocking)){ @@ -594,26 +600,22 @@ bool OboeEngine::restartStream(OboeStream* i_oboeStream, int i_direction) { */ bool OboeEngine::closeStream(OboeStream *i_oboeStream) { Result outputResult = Result::OK, inputResult = Result::OK; - bool hasOutput = true, hasInput = true; - OboeMediator* mediator; if (i_oboeStream == nullptr) { - LOGW("[OboeEngine::closeStream]\t i_oboeStream is a nullptr. Aborting both oboe streams of the terminable mediator"); - mediator = m_terminableMediator; - } else { - mediator = i_oboeStream->oboeMediator; - hasInput = i_oboeStream->hasInput; - hasOutput = i_oboeStream->hasOutput; + LOGE("[OboeEngine::closeStream]\t i_oboeStream is a nullptr."); + return false; } - if (hasOutput) { + OboeMediator* mediator = i_oboeStream->oboeMediator; + + if (i_oboeStream->hasOutput) { outputResult = mediator->m_outputStream->close(); if (outputResult == Result::ErrorClosed) { outputResult = Result::OK; LOGW("[OboeEngine::closeStream]\t Tried to close output stream, but was already closed."); } } - if (hasInput) { + if (i_oboeStream->hasInput) { inputResult = mediator->m_inputStream->close(); if (inputResult == Result::ErrorClosed) { inputResult = Result::OK; @@ -632,19 +634,15 @@ bool OboeEngine::closeStream(OboeStream *i_oboeStream) { */ bool OboeEngine::abortStream(OboeStream *i_oboeStream) { Result outputResult = Result::OK, inputResult = Result::OK; - bool hasOutput = true, hasInput = true; - OboeMediator* mediator; if (i_oboeStream == nullptr) { - LOGW("[OboeEngine::abortStream]\t i_oboeStream is a nullptr. Aborting both oboe streams of the terminable mediator"); - mediator = m_terminableMediator; - } else { - mediator = i_oboeStream->oboeMediator; - hasInput = i_oboeStream->hasInput; - hasOutput = i_oboeStream->hasOutput; + LOGE("[OboeEngine::abortStream]\t i_oboeStream is a nullptr."); + return false; } - if (hasInput) { + OboeMediator* mediator = i_oboeStream->oboeMediator; + + if (i_oboeStream->hasInput) { inputResult = mediator->m_inputStream->stop(); if (inputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the input stream to stop: %s", @@ -654,7 +652,7 @@ bool OboeEngine::abortStream(OboeStream *i_oboeStream) { LOGE("[OboeEngine::abortStream]\t Couldn't force the input stream to close: %s", convertToText(inputResult)); } - if (hasOutput) { + if (i_oboeStream->hasOutput) { outputResult = mediator->m_outputStream->stop(); if (outputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the output stream to stop: %s", @@ -732,7 +730,6 @@ bool OboeEngine::readStream(OboeStream *i_oboeStream, void *i_buffer, int32_t i_ * @return the address of the oboeStream. */ void OboeEngine::constructOboeStream(OboeStream* i_oboeStream) { - i_oboeStream = (OboeStream *) PaUtil_AllocateZeroInitializedMemory(sizeof(OboeStream)); m_terminableMediator = i_oboeStream->oboeMediator = new OboeMediator(i_oboeStream); i_oboeStream->oboeMediator->setEngine(this); } @@ -1176,9 +1173,6 @@ PaError PaOboe_Initialize(PaUtilHostApiRepresentation **i_hostApi, PaHostApiInde static void Terminate(struct PaUtilHostApiRepresentation *i_hostApi) { auto *oboeHostApi = (PaOboeHostApiRepresentation *) i_hostApi; - if (!(oboeHostApi->oboeEngine->closeStream(nullptr))) - LOGI("[PaOboe - Terminate]\t The streams were probably already closed - see OboeEngine::CloseStream logs."); - if (oboeHostApi->oboeEngine != nullptr) delete oboeHostApi->oboeEngine; @@ -1386,7 +1380,7 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, Usage androidOutputUsage = Usage::VoiceCommunication; InputPreset androidInputPreset = InputPreset::Generic; - OboeStream* oboeStream; + OboeStream* oboeStream = (OboeStream *) PaUtil_AllocateZeroInitializedMemory(sizeof(OboeStream));; oboeHostApi->oboeEngine->constructOboeStream(oboeStream); if (!oboeStream) { From d8b1b8e3a8582f136ca50b0b09a514749a18b753 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Mon, 9 Oct 2023 10:29:19 +0200 Subject: [PATCH 18/26] fixed README.md indenting --- src/hostapi/oboe/README.md | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/hostapi/oboe/README.md b/src/hostapi/oboe/README.md index c4de74088..14d6b6b73 100644 --- a/src/hostapi/oboe/README.md +++ b/src/hostapi/oboe/README.md @@ -6,28 +6,37 @@ headers in your project. Building: ---- To build portaudio with Oboe, there are some necessary steps: -1) An android NDK is needed to crosscompile it. I used the version 25.1.8937393, which I found at https://developer.android.com/ndk/downloads. -2) Clone the Oboe repository - just follow the steps detailed here: https://github.com/google/oboe/blob/main/docs/GettingStarted.md. - Make sure to correctly link the NDK path in the Oboe build. If you instead prefer to use the prebuilt libraries, you can skip this step. -3) Set the CMake variable OBOE_DIRECTORY (used in cmake/modules/FindOboe.cmake) to the path of the cloned Oboe repository, and build the Oboe libraries (you can use "build_all_android.sh"). +1) An android NDK is needed to crosscompile it. I used the version 25.1.8937393, which I found at + https://developer.android.com/ndk/downloads. +2) Clone the Oboe repository - just follow the steps detailed here: + https://github.com/google/oboe/blob/main/docs/GettingStarted.md. + Make sure to correctly link the NDK path in the Oboe build. If you instead prefer to use the + prebuilt libraries, you can skip this step. +3) Set the CMake variable OBOE_DIRECTORY (used in cmake/modules/FindOboe.cmake) to the path of the + cloned Oboe repository, and build the Oboe libraries (you can use "build_all_android.sh"). If you instead used the prebuilt libraries, do the following: - set OBOE_DIRECTORY to TRUE; - - set OBOE_LIBRARY_DIRS path_to_Oboe_libraries_folder/${ANDROID_ABI}), the code will search the prebuilt library of the chosen ABI in that folder. + - set OBOE_LIBRARY_DIRS path_to_Oboe_libraries_folder/${ANDROID_ABI}), the code will search the + prebuilt library of the chosen ABI in that folder. 4) Build PaOboe (you can use "build_all_PaOboe.sh"). 5) Don't forget to add liboboe.so and libportaudio.so in your jniLibs folder. TODOs: ---- -- Testing. This implementation is being tested for VoIP calls that use blocking streams - for everything else, lots of tests are needed. +- Testing. This implementation is being tested for VoIP calls that use blocking streams - for + everything else, lots of tests are needed. Misc ---- ### Audio Format: -If you need to select a specific audio format, you'll have to manually set it in PaOboe_OpenStream by modifying the format selection marked with a *FIXME*. -I'm positive that automatic format selection is possible, but simply using PaUtil_SelectClosestAvailableFormat got me nowhere. +If you need to select a specific audio format, you'll have to manually set it in PaOboe_OpenStream +by modifying the format selection marked with a *FIXME*. I'm positive that automatic format selection +is possible, but simply using PaUtil_SelectClosestAvailableFormat got me nowhere. ### Buffer sizes: -Portaudio often tries to get approximately low buffer sizes, and if you need specific sizes for your buffer you should manually modify it (or make a simple function that can set it). For your convenience, there is a *FIXME* as a bookmark. \ No newline at end of file +Portaudio often tries to get approximately low buffer sizes, and if you need specific sizes for your +buffer you should manually modify it (or make a simple function that can set it). For your convenience, +there is a *FIXME* as a bookmark. \ No newline at end of file From 72abf68c14e21702844bbbe7a296fe2c3ba2bd73 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Mon, 9 Oct 2023 10:30:28 +0200 Subject: [PATCH 19/26] Removed .idea folder from repo --- .idea/.gitignore | 3 --- .idea/misc.xml | 5 ----- .idea/modules.xml | 8 -------- .idea/portaudio.iml | 9 --------- .idea/vcs.xml | 6 ------ 5 files changed, 31 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/portaudio.iml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d33521a..000000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 6e8667213..000000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index f2d867481..000000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/portaudio.iml b/.idea/portaudio.iml deleted file mode 100644 index d6ebd4805..000000000 --- a/.idea/portaudio.iml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1ddfb..000000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 912e951edf07c8a0bbc1dab38ae261ea55bebab3 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Mon, 9 Oct 2023 10:46:33 +0200 Subject: [PATCH 20/26] replaced 'g_' with 'paOboe_' in non-static global variables --- src/hostapi/oboe/pa_oboe.cpp | 568 +++++++++++++++++------------------ 1 file changed, 284 insertions(+), 284 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index 2fd0dc564..ca1571a59 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -152,17 +152,17 @@ static signed long GetStreamWriteAvailable(PaStream *stream); static unsigned long GetApproximateLowBufferSize(); // Commonly used parameters initialized. -static unsigned long g_nativeBufferSize = 0; -static unsigned g_numberOfBuffers = 2; +static unsigned long paOboe_nativeBufferSize = 0; +static unsigned paOboe_numberOfBuffers = 2; using namespace oboe; //Useful global variables -int32_t g_inputDeviceId = kUnspecified; -int32_t g_outputDeviceId = kUnspecified; +int32_t paOboe_inputDeviceId = kUnspecified; +int32_t paOboe_outputDeviceId = kUnspecified; -PerformanceMode g_inputPerfMode = PerformanceMode::LowLatency; -PerformanceMode g_outputPerfMode = PerformanceMode::LowLatency; +PerformanceMode paOboe_inputPerfMode = PerformanceMode::LowLatency; +PerformanceMode paOboe_outputPerfMode = PerformanceMode::LowLatency; class OboeEngine; class OboeMediator; @@ -205,8 +205,8 @@ typedef struct OboeStream { class OboeMediator: public AudioStreamCallback{ public: - OboeMediator(OboeStream* i_oboeStream) { - m_oboeCallbackStream = i_oboeStream; + OboeMediator(OboeStream* oboeStream) { + m_oboeCallbackStream = oboeStream; } //Callback function for non-blocking streams @@ -220,10 +220,10 @@ class OboeMediator: public AudioStreamCallback{ //getter and setter of m_oboeEngine and m_oboeCallbackStream OboeEngine *getEngine() { return m_oboeEngine; } - void setEngine(OboeEngine *i_oboeEngine) { m_oboeEngine = i_oboeEngine; } + void setEngine(OboeEngine *oboeEngine) { m_oboeEngine = oboeEngine; } OboeStream *getStreamAddress() { return m_oboeCallbackStream; } - void setCallbackStream(OboeStream *i_oboeStream) { m_oboeCallbackStream = i_oboeStream; } + void setCallbackStream(OboeStream *oboeStream) { m_oboeCallbackStream = oboeStream; } //The only instances of output and input streams that will be used, and their builders std::shared_ptr m_outputStream; @@ -313,8 +313,8 @@ OboeEngine::OboeEngine() {} /** - * \brief Tries to open a stream with the direction i_direction, sample rate i_sampleRate and/or - * channel count i_channelCount. It then checks if the stream was in fact opened with the + * \brief Tries to open a stream with the direction direction, sample rate sampleRate and/or + * channel count channelCount. It then checks if the stream was in fact opened with the * desired settings, and then closes the stream. It's used to see if the requested * parameters are supported by the devices that are going to be used. * @param direction the Direction of the stream; @@ -323,16 +323,16 @@ OboeEngine::OboeEngine() {} * @return true if the requested sample rate / channel count is supported by the device, false if * they aren't, or if tryStream couldn't open a stream. */ -bool OboeEngine::tryStream(Direction i_direction, int32_t i_sampleRate, int32_t i_channelCount) { +bool OboeEngine::tryStream(Direction direction, int32_t sampleRate, int32_t channelCount) { Result result; bool outcome = false; - m_testBuilder.setDeviceId(getSelectedDevice(i_direction)) + m_testBuilder.setDeviceId(getSelectedDevice(direction)) // Arbitrary format usually broadly supported. Later, we'll open streams with correct formats. ->setFormat(AudioFormat::Float) - ->setDirection(i_direction) - ->setSampleRate(i_sampleRate) - ->setChannelCount(i_channelCount) + ->setDirection(direction) + ->setSampleRate(sampleRate) + ->setChannelCount(channelCount) ->openStream(m_testStream); if (result != Result::OK) { @@ -341,17 +341,17 @@ bool OboeEngine::tryStream(Direction i_direction, int32_t i_sampleRate, int32_t return outcome; } - if (i_sampleRate != kUnspecified) { - outcome = (i_sampleRate == m_testBuilder.getSampleRate()); + if (sampleRate != kUnspecified) { + outcome = (sampleRate == m_testBuilder.getSampleRate()); if (!outcome) { LOGW("[OboeEngine::TryStream]\t Tried sampleRate = %d, built sampleRate = %d", - i_sampleRate, m_testBuilder.getSampleRate()); + sampleRate, m_testBuilder.getSampleRate()); } - } else if (i_channelCount != kUnspecified) { - outcome = (i_channelCount == m_testBuilder.getChannelCount()); + } else if (channelCount != kUnspecified) { + outcome = (channelCount == m_testBuilder.getChannelCount()); if (!outcome) { LOGW("[OboeEngine::TryStream]\t Tried channelCount = %d, built channelCount = %d", - i_channelCount, m_testBuilder.getChannelCount()); + channelCount, m_testBuilder.getChannelCount()); } } else { LOGE("[OboeEngine::TryStream]\t Logical failure. This message should NEVER occur."); @@ -380,33 +380,33 @@ bool OboeEngine::tryStream(Direction i_direction, int32_t i_sampleRate, int32_t * @return paNoError if everything goes as expected, paUnanticipatedHostError if Oboe fails to open * a stream, and paInsufficientMemory if the memory allocation of the buffers fails. */ -PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, int32_t i_sampleRate, - Usage i_androidOutputUsage, InputPreset i_androidInputPreset) { +PaError OboeEngine::openStream(OboeStream *oboeStream, Direction direction, int32_t sampleRate, + Usage androidOutputUsage, InputPreset androidInputPreset) { PaError error = paNoError; Result result; - if (i_oboeStream == nullptr) { - LOGE("[OboeEngine::openStream]\t i_oboeStream is a nullptr."); + if (oboeStream == nullptr) { + LOGE("[OboeEngine::openStream]\t oboeStream is a nullptr."); return paInternalError; } - OboeMediator* mediator = i_oboeStream->oboeMediator; + OboeMediator* mediator = oboeStream->oboeMediator; - if(!(i_oboeStream->isBlocking)){ + if(!(oboeStream->isBlocking)){ mediator->resetCallbackCounters(); } - if (i_direction == Direction::Input) { - mediator->m_inputBuilder.setChannelCount(i_oboeStream->bufferProcessor.inputChannelCount) - ->setFormat(PaToOboeFormat(i_oboeStream->inputFormat)) - ->setSampleRate(i_sampleRate) + if (direction == Direction::Input) { + mediator->m_inputBuilder.setChannelCount(oboeStream->bufferProcessor.inputChannelCount) + ->setFormat(PaToOboeFormat(oboeStream->inputFormat)) + ->setSampleRate(sampleRate) ->setDirection(Direction::Input) ->setDeviceId(getSelectedDevice(Direction::Input)) - ->setPerformanceMode(g_inputPerfMode) - ->setInputPreset(i_androidInputPreset) - ->setFramesPerCallback(i_oboeStream->framesPerHostCallback); + ->setPerformanceMode(paOboe_inputPerfMode) + ->setInputPreset(androidInputPreset) + ->setFramesPerCallback(oboeStream->framesPerHostCallback); - if (!(i_oboeStream->isBlocking)) { + if (!(oboeStream->isBlocking)) { mediator->setInputCallback(); } @@ -419,37 +419,37 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, } mediator->m_inputStream->setBufferSizeInFrames(mediator->m_inputStream->getFramesPerBurst() * - g_numberOfBuffers); - i_oboeStream->inputBuffers = - (void **) PaUtil_AllocateZeroInitializedMemory(g_numberOfBuffers * sizeof(int32_t * )); + paOboe_numberOfBuffers); + oboeStream->inputBuffers = + (void **) PaUtil_AllocateZeroInitializedMemory(paOboe_numberOfBuffers * sizeof(int32_t * )); - for (int i = 0; i < g_numberOfBuffers; ++i) { - i_oboeStream->inputBuffers[i] = (void *) PaUtil_AllocateZeroInitializedMemory( - i_oboeStream->framesPerHostCallback * - i_oboeStream->bytesPerFrame * - i_oboeStream->bufferProcessor.inputChannelCount); + for (int i = 0; i < paOboe_numberOfBuffers; ++i) { + oboeStream->inputBuffers[i] = (void *) PaUtil_AllocateZeroInitializedMemory( + oboeStream->framesPerHostCallback * + oboeStream->bytesPerFrame * + oboeStream->bufferProcessor.inputChannelCount); - if (!i_oboeStream->inputBuffers[i]) { + if (!oboeStream->inputBuffers[i]) { for (int j = 0; j < i; ++j) - PaUtil_FreeMemory(i_oboeStream->inputBuffers[j]); - PaUtil_FreeMemory(i_oboeStream->inputBuffers); + PaUtil_FreeMemory(oboeStream->inputBuffers[j]); + PaUtil_FreeMemory(oboeStream->inputBuffers); mediator->m_inputStream->close(); error = paInsufficientMemory; break; } } - i_oboeStream->currentInputBuffer = 0; + oboeStream->currentInputBuffer = 0; } else { - mediator->m_outputBuilder.setChannelCount(i_oboeStream->bufferProcessor.outputChannelCount) - ->setFormat(PaToOboeFormat(i_oboeStream->outputFormat)) - ->setSampleRate(i_sampleRate) + mediator->m_outputBuilder.setChannelCount(oboeStream->bufferProcessor.outputChannelCount) + ->setFormat(PaToOboeFormat(oboeStream->outputFormat)) + ->setSampleRate(sampleRate) ->setDirection(Direction::Output) ->setDeviceId(getSelectedDevice(Direction::Output)) - ->setPerformanceMode(g_outputPerfMode) - ->setUsage(i_androidOutputUsage) - ->setFramesPerCallback(i_oboeStream->framesPerHostCallback); + ->setPerformanceMode(paOboe_outputPerfMode) + ->setUsage(androidOutputUsage) + ->setFramesPerCallback(oboeStream->framesPerHostCallback); - if (!(i_oboeStream->isBlocking)) { + if (!(oboeStream->isBlocking)) { mediator->setOutputCallback(); } @@ -461,26 +461,26 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, } mediator->m_outputStream->setBufferSizeInFrames(mediator->m_outputStream->getFramesPerBurst() * - g_numberOfBuffers); - i_oboeStream->outputBuffers = - (void **) PaUtil_AllocateZeroInitializedMemory(g_numberOfBuffers * sizeof(int32_t * )); + paOboe_numberOfBuffers); + oboeStream->outputBuffers = + (void **) PaUtil_AllocateZeroInitializedMemory(paOboe_numberOfBuffers * sizeof(int32_t * )); - for (int i = 0; i < g_numberOfBuffers; ++i) { - i_oboeStream->outputBuffers[i] = (void *) PaUtil_AllocateZeroInitializedMemory( - i_oboeStream->framesPerHostCallback * - i_oboeStream->bytesPerFrame * - i_oboeStream->bufferProcessor.outputChannelCount); + for (int i = 0; i < paOboe_numberOfBuffers; ++i) { + oboeStream->outputBuffers[i] = (void *) PaUtil_AllocateZeroInitializedMemory( + oboeStream->framesPerHostCallback * + oboeStream->bytesPerFrame * + oboeStream->bufferProcessor.outputChannelCount); - if (!i_oboeStream->outputBuffers[i]) { + if (!oboeStream->outputBuffers[i]) { for (int j = 0; j < i; ++j) - PaUtil_FreeMemory(i_oboeStream->outputBuffers[j]); - PaUtil_FreeMemory(i_oboeStream->outputBuffers); + PaUtil_FreeMemory(oboeStream->outputBuffers[j]); + PaUtil_FreeMemory(oboeStream->outputBuffers); mediator->m_outputStream->close(); error = paInsufficientMemory; break; } } - i_oboeStream->currentOutputBuffer = 0; + oboeStream->currentOutputBuffer = 0; } return error; @@ -493,17 +493,17 @@ PaError OboeEngine::openStream(OboeStream *i_oboeStream, Direction i_direction, * @param oboeStream The stream we want to start. * @return true if the streams we wanted to start are started successfully, false otherwise. */ -bool OboeEngine::startStream(OboeStream *i_oboeStream) { +bool OboeEngine::startStream(OboeStream *oboeStream) { Result outputResult = Result::OK, inputResult = Result::OK; - OboeMediator* mediator = i_oboeStream->oboeMediator; + OboeMediator* mediator = oboeStream->oboeMediator; - if (i_oboeStream->hasInput) { + if (oboeStream->hasInput) { inputResult = mediator->m_inputStream->requestStart(); if (inputResult != Result::OK) LOGE("[OboeEngine::startStream]\t Oboe couldn't start the input stream: %s", convertToText(inputResult)); } - if (i_oboeStream->hasOutput) { + if (oboeStream->hasOutput) { outputResult = mediator->m_outputStream->requestStart(); if (outputResult != Result::OK) LOGE("[OboeEngine::startStream]\t Oboe couldn't start the output stream: %s", @@ -520,17 +520,17 @@ bool OboeEngine::startStream(OboeStream *i_oboeStream) { * @param oboeStream The stream we want to stop. * @return true if the streams we wanted to stop are stopped successfully, false otherwise. */ -bool OboeEngine::stopStream(OboeStream *i_oboeStream) { +bool OboeEngine::stopStream(OboeStream *oboeStream) { Result outputResult = Result::OK, inputResult = Result::OK; - OboeMediator* mediator = i_oboeStream->oboeMediator; + OboeMediator* mediator = oboeStream->oboeMediator; - if (i_oboeStream->hasInput) { + if (oboeStream->hasInput) { inputResult = mediator->m_inputStream->requestStop(); if (inputResult != Result::OK) LOGE("[OboeEngine::stopStream]\t Oboe couldn't stop the input stream: %s", convertToText(inputResult)); } - if (i_oboeStream->hasOutput) { + if (oboeStream->hasOutput) { outputResult = mediator->m_outputStream->requestStop(); if (outputResult != Result::OK) LOGE("[OboeEngine::stopStream]\t Oboe couldn't stop the output stream: %s", @@ -549,12 +549,12 @@ bool OboeEngine::stopStream(OboeStream *i_oboeStream) { * @param direction The direction(s) of the stream that have to be restarted (1 for output, 2 for input, 3 for both). * @return true if the stream is restarted successfully, false otherwise. */ -bool OboeEngine::restartStream(OboeStream* i_oboeStream, int i_direction) { +bool OboeEngine::restartStream(OboeStream* oboeStream, int direction) { bool outcome = true; Result result; - OboeMediator* mediator = i_oboeStream->oboeMediator; + OboeMediator* mediator = oboeStream->oboeMediator; - switch (i_direction) { + switch (direction) { case 1: //output-only result = mediator->m_outputBuilder.openStream(mediator->m_outputStream); if (result != Result::OK) @@ -584,7 +584,7 @@ bool OboeEngine::restartStream(OboeStream* i_oboeStream, int i_direction) { default: // unspecified direction or both directions: restart both streams LOGW("[OboeEngine::restartStream]\t Unspecified direction, restarting both streams"); - outcome = (restartStream(i_oboeStream, 1) && restartStream(i_oboeStream, 2)); + outcome = (restartStream(oboeStream, 1) && restartStream(oboeStream, 2)); break; } @@ -598,24 +598,24 @@ bool OboeEngine::restartStream(OboeStream* i_oboeStream, int i_direction) { * @param oboeStream The stream we want to close. * @return true if the stream is closed successfully, otherwise returns false. */ -bool OboeEngine::closeStream(OboeStream *i_oboeStream) { +bool OboeEngine::closeStream(OboeStream *oboeStream) { Result outputResult = Result::OK, inputResult = Result::OK; - if (i_oboeStream == nullptr) { - LOGE("[OboeEngine::closeStream]\t i_oboeStream is a nullptr."); + if (oboeStream == nullptr) { + LOGE("[OboeEngine::closeStream]\t oboeStream is a nullptr."); return false; } - OboeMediator* mediator = i_oboeStream->oboeMediator; + OboeMediator* mediator = oboeStream->oboeMediator; - if (i_oboeStream->hasOutput) { + if (oboeStream->hasOutput) { outputResult = mediator->m_outputStream->close(); if (outputResult == Result::ErrorClosed) { outputResult = Result::OK; LOGW("[OboeEngine::closeStream]\t Tried to close output stream, but was already closed."); } } - if (i_oboeStream->hasInput) { + if (oboeStream->hasInput) { inputResult = mediator->m_inputStream->close(); if (inputResult == Result::ErrorClosed) { inputResult = Result::OK; @@ -632,17 +632,17 @@ bool OboeEngine::closeStream(OboeStream *i_oboeStream) { * @param oboeStream The stream we want to abort. * @return true if the output stream and the input stream are stopped successfully, false otherwise. */ -bool OboeEngine::abortStream(OboeStream *i_oboeStream) { +bool OboeEngine::abortStream(OboeStream *oboeStream) { Result outputResult = Result::OK, inputResult = Result::OK; - if (i_oboeStream == nullptr) { - LOGE("[OboeEngine::abortStream]\t i_oboeStream is a nullptr."); + if (oboeStream == nullptr) { + LOGE("[OboeEngine::abortStream]\t oboeStream is a nullptr."); return false; } - OboeMediator* mediator = i_oboeStream->oboeMediator; + OboeMediator* mediator = oboeStream->oboeMediator; - if (i_oboeStream->hasInput) { + if (oboeStream->hasInput) { inputResult = mediator->m_inputStream->stop(); if (inputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the input stream to stop: %s", @@ -652,7 +652,7 @@ bool OboeEngine::abortStream(OboeStream *i_oboeStream) { LOGE("[OboeEngine::abortStream]\t Couldn't force the input stream to close: %s", convertToText(inputResult)); } - if (i_oboeStream->hasOutput) { + if (oboeStream->hasOutput) { outputResult = mediator->m_outputStream->stop(); if (outputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the output stream to stop: %s", @@ -676,15 +676,15 @@ bool OboeEngine::abortStream(OboeStream *i_oboeStream) { * different from ErrorDisconnected. In case of ErrorDisconnected, the function returns * true if the stream is successfully restarted, and false otherwise. */ -bool OboeEngine::writeStream(OboeStream *i_oboeStream, const void *i_buffer, int32_t i_framesToWrite) { +bool OboeEngine::writeStream(OboeStream *oboeStream, const void buffer, int32_t framesToWrite) { bool outcome = true; - OboeMediator* mediator = i_oboeStream->oboeMediator; + OboeMediator* mediator = oboeStream->oboeMediator; - ResultWithValue result = mediator->m_outputStream->write(i_buffer, i_framesToWrite, TIMEOUT_NS); + ResultWithValue result = mediator->m_outputStream->write(buffer, framesToWrite, TIMEOUT_NS); // If the stream is interrupted because the device suddenly changes, restart the stream. if (result.error() == Result::ErrorDisconnected) { - if (restartStream(i_oboeStream, 1)) + if (restartStream(oboeStream, 1)) return true; } @@ -705,15 +705,15 @@ bool OboeEngine::writeStream(OboeStream *i_oboeStream, const void *i_buffer, int * different from ErrorDisconnected. In case of ErrorDisconnected, the function returns * true if the stream is successfully restarted, and false otherwise. */ -bool OboeEngine::readStream(OboeStream *i_oboeStream, void *i_buffer, int32_t i_framesToRead) { +bool OboeEngine::readStream(OboeStream *oboeStream, void *buffer, int32_t framesToRead) { bool outcome = true; - OboeMediator* mediator = i_oboeStream->oboeMediator; + OboeMediator* mediator = oboeStream->oboeMediator; - ResultWithValue result = mediator->m_inputStream->read(i_buffer, i_framesToRead, TIMEOUT_NS); + ResultWithValue result = mediator->m_inputStream->read(buffer, framesToRead, TIMEOUT_NS); // If the stream is interrupted because the device suddenly changes, restart the stream. if (result.error() == Result::ErrorDisconnected) { - if (restartStream(i_oboeStream, 2)) + if (restartStream(oboeStream, 2)) return true; } @@ -729,9 +729,9 @@ bool OboeEngine::readStream(OboeStream *i_oboeStream, void *i_buffer, int32_t i_ * \brief Allocates the memory of an OboeStream, and sets its EngineAddress to this. * @return the address of the oboeStream. */ -void OboeEngine::constructOboeStream(OboeStream* i_oboeStream) { - m_terminableMediator = i_oboeStream->oboeMediator = new OboeMediator(i_oboeStream); - i_oboeStream->oboeMediator->setEngine(this); +void OboeEngine::constructOboeStream(OboeStream* oboeStream) { + m_terminableMediator = oboeStream->oboeMediator = new OboeMediator(oboeStream); + oboeStream->oboeMediator->setEngine(this); } @@ -740,9 +740,9 @@ void OboeEngine::constructOboeStream(OboeStream* i_oboeStream) { * @param paFormat the PaSampleFormat we want to convert. * @return the converted AudioFormat. */ -AudioFormat OboeEngine::PaToOboeFormat(PaSampleFormat i_paFormat) { +AudioFormat OboeEngine::PaToOboeFormat(PaSampleFormat paFormat) { AudioFormat oboeFormat; - switch (i_paFormat) { + switch (paFormat) { case paFloat32: oboeFormat = AudioFormat::Float; LOGI("[OboeEngine::PaToOboeFormat]\t REQUESTED OBOE FORMAT: FLOAT"); @@ -774,11 +774,11 @@ AudioFormat OboeEngine::PaToOboeFormat(PaSampleFormat i_paFormat) { * @param direction the Oboe::Direction for which we want to know the device Id. * @return the device Id of the appropriate direction. */ -int32_t OboeEngine::getSelectedDevice(Direction i_direction) { - if (i_direction == Direction::Input) - return g_inputDeviceId; +int32_t OboeEngine::getSelectedDevice(Direction direction) { + if (direction == Direction::Input) + return paOboe_inputDeviceId; else - return g_outputDeviceId; + return paOboe_outputDeviceId; } /*----------------------------- OboeMediator functions implementations -----------------------------*/ @@ -786,7 +786,7 @@ int32_t OboeEngine::getSelectedDevice(Direction i_direction) { * \brief Oboe's callback routine. */ DataCallbackResult -OboeMediator::onAudioReady(AudioStream *i_audioStream, void *i_audioData, int32_t i_numFrames) { +OboeMediator::onAudioReady(AudioStream *audioStream, void *audioData, int32_t numFrames) { clock_gettime(CLOCK_REALTIME, &m_timeSpec); m_timeInfo.currentTime = (PaTime)(m_timeSpec.tv_sec + (m_timeSpec.tv_nsec / 1000000000.0)); @@ -811,15 +811,15 @@ OboeMediator::onAudioReady(AudioStream *i_audioStream, void *i_audioData, int32_ &m_timeInfo, m_oboeCallbackStream->cbFlags); if (m_oboeCallbackStream->hasOutput) { - m_oboeCallbackStream->outputBuffers[m_oboeCallbackStream->currentOutputBuffer] = i_audioData; - PaUtil_SetOutputFrameCount(&m_oboeCallbackStream->bufferProcessor, i_numFrames); + m_oboeCallbackStream->outputBuffers[m_oboeCallbackStream->currentOutputBuffer] = audioData; + PaUtil_SetOutputFrameCount(&m_oboeCallbackStream->bufferProcessor, numFrames); PaUtil_SetInterleavedOutputChannels(&m_oboeCallbackStream->bufferProcessor, 0, (void *) ((PaInt16 **) m_oboeCallbackStream->outputBuffers)[ m_oboeCallbackStream->currentOutputBuffer], 0); } if (m_oboeCallbackStream->hasInput) { - i_audioData = m_oboeCallbackStream->inputBuffers[m_oboeCallbackStream->currentInputBuffer]; + audioData = m_oboeCallbackStream->inputBuffers[m_oboeCallbackStream->currentInputBuffer]; PaUtil_SetInputFrameCount(&m_oboeCallbackStream->bufferProcessor, 0); PaUtil_SetInterleavedInputChannels(&m_oboeCallbackStream->bufferProcessor, 0, (void *) ((PaInt16 **) m_oboeCallbackStream->inputBuffers)[ @@ -842,10 +842,10 @@ OboeMediator::onAudioReady(AudioStream *i_audioStream, void *i_audioData, int32_ if (m_framesProcessed > 0) { if (m_oboeCallbackStream->hasOutput) { m_oboeCallbackStream->currentOutputBuffer = - (m_oboeCallbackStream->currentOutputBuffer + 1) % g_numberOfBuffers; + (m_oboeCallbackStream->currentOutputBuffer + 1) % paOboe_numberOfBuffers; } if (m_oboeCallbackStream->hasInput) { - m_oboeCallbackStream->currentInputBuffer = (m_oboeCallbackStream->currentInputBuffer + 1) % g_numberOfBuffers; + m_oboeCallbackStream->currentInputBuffer = (m_oboeCallbackStream->currentInputBuffer + 1) % paOboe_numberOfBuffers; } } @@ -874,8 +874,8 @@ OboeMediator::onAudioReady(AudioStream *i_audioStream, void *i_audioData, int32_ * \brief If the data callback ends without returning DataCallbackResult::Stop, this routine tells * what error occurred, and tries to restart the stream if the error was ErrorDisconnected. */ -void OboeMediator::onErrorAfterClose(AudioStream *i_audioStream, Result i_error) { - if (i_error == oboe::Result::ErrorDisconnected) { +void OboeMediator::onErrorAfterClose(AudioStream *audioStream, Result error) { + if (error == oboe::Result::ErrorDisconnected) { OboeEngine* oboeEngine = getEngine(); LOGW("[OboeMediator::onErrorAfterClose]\t ErrorDisconnected - Restarting stream(s)"); int i = 0; @@ -886,7 +886,7 @@ void OboeMediator::onErrorAfterClose(AudioStream *i_audioStream, Result i_error) if (!oboeEngine->restartStream(m_oboeCallbackStream, i)) LOGE("[OboeMediator::onErrorAfterClose]\t Couldn't restart stream(s)"); } else - LOGE("[OboeMediator::onErrorAfterClose]\t Error was %s", oboe::convertToText(i_error)); + LOGE("[OboeMediator::onErrorAfterClose]\t Error was %s", oboe::convertToText(error)); } @@ -910,9 +910,9 @@ void OboeMediator::resetCallbackCounters() { * @return PaNoError regardless of the outcome of the check, but warns in the Logs if the sample * rate was changed by Oboe. */ -PaError IsOutputSampleRateSupported(PaOboeHostApiRepresentation *i_oboeHostApi, double i_sampleRate) { - if (!(i_oboeHostApi->oboeEngine->tryStream(Direction::Output, - i_sampleRate, +PaError IsOutputSampleRateSupported(PaOboeHostApiRepresentation *oboeHostApi, double sampleRate) { + if (!(oboeHostApi->oboeEngine->tryStream(Direction::Output, + sampleRate, kUnspecified))) LOGW("[PaOboe - IsOutputSampleRateSupported]\t Sample Rate was changed by Oboe."); @@ -932,9 +932,9 @@ PaError IsOutputSampleRateSupported(PaOboeHostApiRepresentation *i_oboeHostApi, * @return PaNoError regardless of the outcome of the check, but warns in the Logs if the sample * rate was changed by Oboe. */ -PaError IsInputSampleRateSupported(PaOboeHostApiRepresentation *i_oboeHostApi, double i_sampleRate) { - if (!(i_oboeHostApi->oboeEngine->tryStream(Direction::Input, - i_sampleRate, +PaError IsInputSampleRateSupported(PaOboeHostApiRepresentation *oboeHostApi, double sampleRate) { + if (!(oboeHostApi->oboeEngine->tryStream(Direction::Input, + sampleRate, kUnspecified))) LOGW("[PaOboe - IsInputSampleRateSupported]\t Sample Rate was changed by Oboe."); @@ -953,15 +953,15 @@ PaError IsInputSampleRateSupported(PaOboeHostApiRepresentation *i_oboeHostApi, d * @return PaNoError regardless of the outcome of the check, but warns in the Logs if the channel * count was changed by Oboe. */ -static PaError IsOutputChannelCountSupported(PaOboeHostApiRepresentation *i_oboeHostApi, int32_t i_numOfChannels) { - if (i_numOfChannels > 2 || i_numOfChannels == 0) { +static PaError IsOutputChannelCountSupported(PaOboeHostApiRepresentation *oboeHostApi, int32_t numOfChannels) { + if (numOfChannels > 2 || numOfChannels == 0) { LOGE("[PaOboe - IsOutputChannelCountSupported]\t Invalid channel count."); return paInvalidChannelCount; } - if (!(i_oboeHostApi->oboeEngine->tryStream(Direction::Output, + if (!(oboeHostApi->oboeEngine->tryStream(Direction::Output, kUnspecified, - i_numOfChannels))) + numOfChannels))) LOGW("[PaOboe - IsOutputChannelCountSupported]\t Channel Count was changed by Oboe. The device might not support stereo audio."); /* Since Oboe manages the channel count in a smart way, we can avoid blocking the process if @@ -979,15 +979,15 @@ static PaError IsOutputChannelCountSupported(PaOboeHostApiRepresentation *i_oboe * @return PaNoError regardless of the outcome of the check, but warns in the Logs if the channel * count was changed by Oboe. */ -static PaError IsInputChannelCountSupported(PaOboeHostApiRepresentation *i_oboeHostApi, int32_t i_numOfChannels) { - if (i_numOfChannels > 2 || i_numOfChannels == 0) { +static PaError IsInputChannelCountSupported(PaOboeHostApiRepresentation *oboeHostApi, int32_t numOfChannels) { + if (numOfChannels > 2 || numOfChannels == 0) { LOGE("[PaOboe - IsInputChannelCountSupported]\t Invalid channel count."); return paInvalidChannelCount; } - if (!(i_oboeHostApi->oboeEngine->tryStream(Direction::Input, + if (!(oboeHostApi->oboeEngine->tryStream(Direction::Input, kUnspecified, - i_numOfChannels))) + numOfChannels))) LOGW("[PaOboe - IsInputChannelCountSupported]\t Channel Count was changed by Oboe. The device might not support stereo audio."); /* Since Oboe manages the channel count in a smart way, we can avoid blocking the process if @@ -1004,7 +1004,7 @@ static PaError IsInputChannelCountSupported(PaOboeHostApiRepresentation *i_oboeH * @param hostApiIndex is a PaHostApiIndex, the type used to enumerate the host APIs at runtime. * @return paNoError if no errors occur, or paInsufficientMemory if memory allocation fails; */ -PaError PaOboe_Initialize(PaUtilHostApiRepresentation **i_hostApi, PaHostApiIndex i_hostApiIndex) { +PaError PaOboe_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex) { PaError result = paNoError; int deviceCount; PaOboeHostApiRepresentation *oboeHostApi; @@ -1026,20 +1026,20 @@ PaError PaOboe_Initialize(PaUtilHostApiRepresentation **i_hostApi, PaHostApiInde goto error; } - *i_hostApi = &oboeHostApi->inheritedHostApiRep; + *hostApi = &oboeHostApi->inheritedHostApiRep; // Info initialization. - (*i_hostApi)->info.structVersion = 1; - (*i_hostApi)->info.type = paInDevelopment; - (*i_hostApi)->info.name = "android Oboe"; - (*i_hostApi)->info.defaultOutputDevice = 0; - (*i_hostApi)->info.defaultInputDevice = 0; - (*i_hostApi)->info.deviceCount = 0; + (*hostApi)->info.structVersion = 1; + (*hostApi)->info.type = paInDevelopment; + (*hostApi)->info.name = "android Oboe"; + (*hostApi)->info.defaultOutputDevice = 0; + (*hostApi)->info.defaultInputDevice = 0; + (*hostApi)->info.deviceCount = 0; deviceCount = 1; - (*i_hostApi)->deviceInfos = (PaDeviceInfo **) PaUtil_GroupAllocateZeroInitializedMemory( + (*hostApi)->deviceInfos = (PaDeviceInfo **) PaUtil_GroupAllocateZeroInitializedMemory( oboeHostApi->allocations, sizeof(PaDeviceInfo * ) * deviceCount); - if (!(*i_hostApi)->deviceInfos) { + if (!(*hostApi)->deviceInfos) { result = paInsufficientMemory; goto error; } @@ -1055,7 +1055,7 @@ PaError PaOboe_Initialize(PaUtilHostApiRepresentation **i_hostApi, PaHostApiInde for (int i = 0; i < deviceCount; ++i) { PaDeviceInfo *deviceInfo = &deviceInfoArray[i]; deviceInfo->structVersion = 2; - deviceInfo->hostApi = i_hostApiIndex; + deviceInfo->hostApi = hostApiIndex; /* OboeEngine will handle manual device selection through the use of PaOboe_SetSelectedDevice. Portaudio doesn't need to know about this, so we just use a default device. */ @@ -1097,18 +1097,18 @@ PaError PaOboe_Initialize(PaUtilHostApiRepresentation **i_hostApi, PaHostApiInde if (deviceInfo->defaultSampleRate == 0) goto error; - /* If the user has set g_nativeBufferSize by querying the optimal buffer size via java, + /* If the user has set paOboe_nativeBufferSize by querying the optimal buffer size via java, use the user-defined value since that will offer the lowest possible latency. */ - if (g_nativeBufferSize != 0) { + if (paOboe_nativeBufferSize != 0) { deviceInfo->defaultLowInputLatency = - (double) g_nativeBufferSize / deviceInfo->defaultSampleRate; + (double) paOboe_nativeBufferSize / deviceInfo->defaultSampleRate; deviceInfo->defaultLowOutputLatency = - (double) g_nativeBufferSize / deviceInfo->defaultSampleRate; + (double) paOboe_nativeBufferSize / deviceInfo->defaultSampleRate; deviceInfo->defaultHighInputLatency = - (double) g_nativeBufferSize * 4 / deviceInfo->defaultSampleRate; + (double) paOboe_nativeBufferSize * 4 / deviceInfo->defaultSampleRate; deviceInfo->defaultHighOutputLatency = - (double) g_nativeBufferSize * 4 / deviceInfo->defaultSampleRate; + (double) paOboe_nativeBufferSize * 4 / deviceInfo->defaultSampleRate; } else { deviceInfo->defaultLowInputLatency = (double) GetApproximateLowBufferSize() / deviceInfo->defaultSampleRate; @@ -1120,13 +1120,13 @@ PaError PaOboe_Initialize(PaUtilHostApiRepresentation **i_hostApi, PaHostApiInde (double) GetApproximateLowBufferSize() * 4 / deviceInfo->defaultSampleRate; } - (*i_hostApi)->deviceInfos[i] = deviceInfo; - ++(*i_hostApi)->info.deviceCount; + (*hostApi)->deviceInfos[i] = deviceInfo; + ++(*hostApi)->info.deviceCount; } - (*i_hostApi)->Terminate = Terminate; - (*i_hostApi)->OpenStream = OpenStream; - (*i_hostApi)->IsFormatSupported = IsFormatSupported; + (*hostApi)->Terminate = Terminate; + (*hostApi)->OpenStream = OpenStream; + (*hostApi)->IsFormatSupported = IsFormatSupported; PaUtil_InitializeStreamInterface(&oboeHostApi->callbackStreamInterface, CloseStream, StartStream, StopStream, @@ -1170,8 +1170,8 @@ PaError PaOboe_Initialize(PaUtilHostApiRepresentation **i_hostApi, PaHostApiInde * @param hostApi points towards a *HostApiRepresentation, which is a structure representing the * interface to a host API (see struct in "pa_hostapi.h"). */ -static void Terminate(struct PaUtilHostApiRepresentation *i_hostApi) { - auto *oboeHostApi = (PaOboeHostApiRepresentation *) i_hostApi; +static void Terminate(struct PaUtilHostApiRepresentation *hostApi) { + auto *oboeHostApi = (PaOboeHostApiRepresentation *) hostApi; if (oboeHostApi->oboeEngine != nullptr) delete oboeHostApi->oboeEngine; @@ -1195,17 +1195,17 @@ static void Terminate(struct PaUtilHostApiRepresentation *i_hostApi) { * @return paNoError (== paFormatIsSupported) if no errors occur, otherwise returns an appropriate * PaError message. */ -static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *i_hostApi, - const PaStreamParameters *i_inputParameters, - const PaStreamParameters *i_outputParameters, - double i_sampleRate) { +static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *hostApi, + const PaStreamParameters *inputParameters, + const PaStreamParameters *outputParameters, + double sampleRate) { int inputChannelCount, outputChannelCount; PaSampleFormat inputSampleFormat, outputSampleFormat; - auto *oboeHostApi = (PaOboeHostApiRepresentation *) i_hostApi; + auto *oboeHostApi = (PaOboeHostApiRepresentation *) hostApi; - if (i_inputParameters) { - inputChannelCount = i_inputParameters->channelCount; - inputSampleFormat = i_inputParameters->sampleFormat; + if (inputParameters) { + inputChannelCount = inputParameters->channelCount; + inputSampleFormat = inputParameters->sampleFormat; /* all standard sample formats are supported by the buffer adapter, this implementation doesn't support any custom sample formats */ @@ -1215,21 +1215,21 @@ static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *i_hostApi, /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ - if (i_inputParameters->device == paUseHostApiSpecificDeviceSpecification) { + if (inputParameters->device == paUseHostApiSpecificDeviceSpecification) { return paInvalidDevice; } /* check that input device can support inputChannelCount */ if (inputChannelCount > - i_hostApi->deviceInfos[i_inputParameters->device]->maxInputChannels) { + hostApi->deviceInfos[inputParameters->device]->maxInputChannels) { return paInvalidChannelCount; } /* validate inputStreamInfo */ - if (i_inputParameters->hostApiSpecificStreamInfo) { + if (inputParameters->hostApiSpecificStreamInfo) { // Only has an effect on ANDROID_API>=28. InputPreset androidRecordingPreset = - ((PaOboeStreamInfo *) i_inputParameters->hostApiSpecificStreamInfo)->androidInputPreset; + ((PaOboeStreamInfo *) inputParameters->hostApiSpecificStreamInfo)->androidInputPreset; if (androidRecordingPreset != InputPreset::Generic && androidRecordingPreset != InputPreset::Camcorder && androidRecordingPreset != InputPreset::VoiceRecognition && @@ -1242,9 +1242,9 @@ static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *i_hostApi, inputChannelCount = 0; } - if (i_outputParameters) { - outputChannelCount = i_outputParameters->channelCount; - outputSampleFormat = i_outputParameters->sampleFormat; + if (outputParameters) { + outputChannelCount = outputParameters->channelCount; + outputSampleFormat = outputParameters->sampleFormat; /* all standard sample formats are supported by the buffer adapter, this implementation doesn't support any custom sample formats */ @@ -1254,20 +1254,20 @@ static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *i_hostApi, /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ - if (i_outputParameters->device == paUseHostApiSpecificDeviceSpecification) { + if (outputParameters->device == paUseHostApiSpecificDeviceSpecification) { return paInvalidDevice; } /* check that output device can support outputChannelCount */ - if (outputChannelCount > i_hostApi->deviceInfos[i_outputParameters->device]->maxOutputChannels) { + if (outputChannelCount > hostApi->deviceInfos[outputParameters->device]->maxOutputChannels) { return paInvalidChannelCount; } /* validate outputStreamInfo */ - if (i_outputParameters->hostApiSpecificStreamInfo) { + if (outputParameters->hostApiSpecificStreamInfo) { // Only has an effect on ANDROID_API>=28. Usage androidOutputUsage = - ((PaOboeStreamInfo *) i_outputParameters->hostApiSpecificStreamInfo)->androidOutputUsage; + ((PaOboeStreamInfo *) outputParameters->hostApiSpecificStreamInfo)->androidOutputUsage; if (androidOutputUsage != Usage::Media && androidOutputUsage != Usage::Notification && androidOutputUsage != Usage::NotificationEvent && @@ -1284,12 +1284,12 @@ static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *i_hostApi, } if (outputChannelCount > 0) { - if (IsOutputSampleRateSupported(oboeHostApi, i_sampleRate) != paNoError) { + if (IsOutputSampleRateSupported(oboeHostApi, sampleRate) != paNoError) { return paInvalidSampleRate; } } if (inputChannelCount > 0) { - if (IsInputSampleRateSupported(oboeHostApi, i_sampleRate) != paNoError) { + if (IsInputSampleRateSupported(oboeHostApi, sampleRate) != paNoError) { return paInvalidSampleRate; } } @@ -1310,13 +1310,13 @@ static PaError IsFormatSupported(struct PaUtilHostApiRepresentation *i_hostApi, * the correct amount of memory. * @return the value returned by OboeEngine::openStream. */ -static PaError InitializeOutputStream(OboeStream* i_oboeStream, PaOboeHostApiRepresentation *i_oboeHostApi, - Usage i_androidOutputUsage, double i_sampleRate) { +static PaError InitializeOutputStream(OboeStream* oboeStream, PaOboeHostApiRepresentation *oboeHostApi, + Usage androidOutputUsage, double sampleRate) { - return i_oboeHostApi->oboeEngine->openStream(i_oboeStream, + return oboeHostApi->oboeEngine->openStream(oboeStream, Direction::Output, - i_sampleRate, - i_androidOutputUsage, + sampleRate, + androidOutputUsage, Generic); //Input preset won't be used, so we put the default value. } @@ -1333,14 +1333,14 @@ static PaError InitializeOutputStream(OboeStream* i_oboeStream, PaOboeHostApiRep * the correct amount of memory. * @return the value returned by OboeEngine::openStream. */ -static PaError InitializeInputStream(OboeStream* i_oboeStream, PaOboeHostApiRepresentation *i_oboeHostApi, - InputPreset i_androidInputPreset, double i_sampleRate) { +static PaError InitializeInputStream(OboeStream* oboeStream, PaOboeHostApiRepresentation *oboeHostApi, + InputPreset androidInputPreset, double sampleRate) { - return i_oboeHostApi->oboeEngine->openStream(i_oboeStream, + return oboeHostApi->oboeEngine->openStream(oboeStream, Direction::Input, - i_sampleRate, + sampleRate, Usage::Media, //Usage won't be used, so we put the default value. - i_androidInputPreset); + androidInputPreset); } @@ -1361,17 +1361,17 @@ static PaError InitializeInputStream(OboeStream* i_oboeStream, PaOboeHostApiRepr * manipulation or checks. * @return paNoError if no errors occur, or other error codes accordingly with what goes wrong. */ -static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, - PaStream **i_paStream, - const PaStreamParameters *i_inputParameters, - const PaStreamParameters *i_outputParameters, - double i_sampleRate, - unsigned long i_framesPerBuffer, - PaStreamFlags i_streamFlags, - PaStreamCallback *i_streamCallback, - void *i_userData) { +static PaError OpenStream(struct PaUtilHostApiRepresentation *hostApi, + PaStream **paStream, + const PaStreamParameters *inputParameters, + const PaStreamParameters *outputParameters, + double sampleRate, + unsigned long framesPerBuffer, + PaStreamFlags streamFlags, + PaStreamCallback *streamCallback, + void *userData) { PaError error = paNoError; - auto oboeHostApi = (PaOboeHostApiRepresentation *) i_hostApi; + auto oboeHostApi = (PaOboeHostApiRepresentation *) hostApi; unsigned long framesPerHostBuffer; /* these may not be equivalent for all implementations */ int inputChannelCount, outputChannelCount; PaSampleFormat inputSampleFormat, outputSampleFormat; @@ -1390,25 +1390,25 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, LOGI("[PaOboe - OpenStream]\t OpenStream called."); - if (i_inputParameters) { - inputChannelCount = i_inputParameters->channelCount; - inputSampleFormat = i_inputParameters->sampleFormat; + if (inputParameters) { + inputChannelCount = inputParameters->channelCount; + inputSampleFormat = inputParameters->sampleFormat; /* Oboe supports alternate device specification with API>=28, but here we reject the use of paUseHostApiSpecificDeviceSpecification and stick with the default. Devices can be set via PaOboe_SetSelectedDevice. */ - if (i_inputParameters->device == paUseHostApiSpecificDeviceSpecification) + if (inputParameters->device == paUseHostApiSpecificDeviceSpecification) return paInvalidDevice; /* check that input device can support inputChannelCount */ - if (inputChannelCount > i_hostApi->deviceInfos[i_inputParameters->device]->maxInputChannels) + if (inputChannelCount > hostApi->deviceInfos[inputParameters->device]->maxInputChannels) return paInvalidChannelCount; /* validate inputStreamInfo */ - if (i_inputParameters->hostApiSpecificStreamInfo) { + if (inputParameters->hostApiSpecificStreamInfo) { // Only has an effect on ANDROID_API>=28. androidInputPreset = - ((PaOboeStreamInfo *) i_outputParameters->hostApiSpecificStreamInfo)->androidInputPreset; + ((PaOboeStreamInfo *) outputParameters->hostApiSpecificStreamInfo)->androidInputPreset; if (androidInputPreset != InputPreset::Generic && androidInputPreset != InputPreset::Camcorder && androidInputPreset != InputPreset::VoiceRecognition && @@ -1427,25 +1427,25 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, oboeStream->inputFormat = hostInputSampleFormat; } - if (i_outputParameters) { - outputChannelCount = i_outputParameters->channelCount; - outputSampleFormat = i_outputParameters->sampleFormat; + if (outputParameters) { + outputChannelCount = outputParameters->channelCount; + outputSampleFormat = outputParameters->sampleFormat; /* Oboe supports alternate device specification with API>=28, but here we reject the use of paUseHostApiSpecificDeviceSpecification and stick with the default. Devices can be set via PaOboe_SetSelectedDevice. */ - if (i_outputParameters->device == paUseHostApiSpecificDeviceSpecification) + if (outputParameters->device == paUseHostApiSpecificDeviceSpecification) return paInvalidDevice; /* check that output device can support outputChannelCount */ if (outputChannelCount > - i_hostApi->deviceInfos[i_outputParameters->device]->maxOutputChannels) + hostApi->deviceInfos[outputParameters->device]->maxOutputChannels) return paInvalidChannelCount; /* validate outputStreamInfo */ - if (i_outputParameters->hostApiSpecificStreamInfo) { + if (outputParameters->hostApiSpecificStreamInfo) { androidOutputUsage = - ((PaOboeStreamInfo *) i_outputParameters->hostApiSpecificStreamInfo)->androidOutputUsage; + ((PaOboeStreamInfo *) outputParameters->hostApiSpecificStreamInfo)->androidOutputUsage; if (androidOutputUsage != Usage::Media && androidOutputUsage != Usage::Notification && androidOutputUsage != Usage::NotificationEvent && @@ -1469,32 +1469,32 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, } /* validate platform specific flags */ - if ((i_streamFlags & paPlatformSpecificFlags) != 0) + if ((streamFlags & paPlatformSpecificFlags) != 0) return paInvalidFlag; /* unexpected platform specific flag */ - if (i_framesPerBuffer == paFramesPerBufferUnspecified) { - if (i_outputParameters) { + if (framesPerBuffer == paFramesPerBufferUnspecified) { + if (outputParameters) { framesPerHostBuffer = - (unsigned long) (i_outputParameters->suggestedLatency * i_sampleRate); + (unsigned long) (outputParameters->suggestedLatency * sampleRate); } else { framesPerHostBuffer = - (unsigned long) (i_inputParameters->suggestedLatency * i_sampleRate); + (unsigned long) (inputParameters->suggestedLatency * sampleRate); } } else { - framesPerHostBuffer = i_framesPerBuffer; + framesPerHostBuffer = framesPerBuffer; } - if (i_streamCallback) { + if (streamCallback) { PaUtil_InitializeStreamRepresentation(&(oboeStream->streamRepresentation), &oboeHostApi->callbackStreamInterface, - i_streamCallback, i_userData); + streamCallback, userData); } else { PaUtil_InitializeStreamRepresentation(&(oboeStream->streamRepresentation), &oboeHostApi->blockingStreamInterface, - i_streamCallback, i_userData); + streamCallback, userData); } - PaUtil_InitializeCpuLoadMeasurer(&(oboeStream->cpuLoadMeasurer), i_sampleRate); + PaUtil_InitializeCpuLoadMeasurer(&(oboeStream->cpuLoadMeasurer), sampleRate); error = PaUtil_InitializeBufferProcessor(&(oboeStream->bufferProcessor), inputChannelCount, @@ -1503,16 +1503,16 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, outputChannelCount, outputSampleFormat, hostOutputSampleFormat, - i_sampleRate, i_streamFlags, - i_framesPerBuffer, + sampleRate, streamFlags, + framesPerBuffer, framesPerHostBuffer, paUtilFixedHostBufferSize, - i_streamCallback, i_userData); + streamCallback, userData); if (error != paNoError) goto error; - oboeStream->streamRepresentation.streamInfo.sampleRate = i_sampleRate; - oboeStream->isBlocking = (i_streamCallback == nullptr); + oboeStream->streamRepresentation.streamInfo.sampleRate = sampleRate; + oboeStream->isBlocking = (streamCallback == nullptr); oboeStream->framesPerHostCallback = framesPerHostBuffer; oboeStream->bytesPerFrame = sizeof(int16_t); oboeStream->cbFlags = 0; @@ -1527,9 +1527,9 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, oboeStream->streamRepresentation.streamInfo.inputLatency = ((PaTime) PaUtil_GetBufferProcessorInputLatencyFrames( &(oboeStream->bufferProcessor)) + - oboeStream->framesPerHostCallback) / i_sampleRate; + oboeStream->framesPerHostCallback) / sampleRate; ENSURE(InitializeInputStream(oboeStream, oboeHostApi, - androidInputPreset, i_sampleRate), + androidInputPreset, sampleRate), "Initializing input stream failed") } else { oboeStream->hasInput = false; } @@ -1538,13 +1538,13 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, oboeStream->streamRepresentation.streamInfo.outputLatency = ((PaTime) PaUtil_GetBufferProcessorOutputLatencyFrames( &oboeStream->bufferProcessor) - + oboeStream->framesPerHostCallback) / i_sampleRate; + + oboeStream->framesPerHostCallback) / sampleRate; ENSURE(InitializeOutputStream(oboeStream, oboeHostApi, - androidOutputUsage, i_sampleRate), + androidOutputUsage, sampleRate), "Initializing output stream failed"); } else { oboeStream->hasOutput = false; } - *i_paStream = (PaStream *) oboeStream; + *paStream = (PaStream *) oboeStream; return error; error: @@ -1565,8 +1565,8 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *i_hostApi, * portaudio, which holds the information of our OboeStream. * @return paNoError, but warns in the logs if OboeEngine::closeStream failed. */ -static PaError CloseStream(PaStream *i_paStream) { - auto *oboeStream = (OboeStream *) i_paStream; +static PaError CloseStream(PaStream *paStream) { + auto *oboeStream = (OboeStream *) paStream; auto *oboeEngine = oboeStream->oboeMediator->getEngine(); if (!(oboeEngine->closeStream(oboeStream))) @@ -1575,7 +1575,7 @@ static PaError CloseStream(PaStream *i_paStream) { PaUtil_TerminateBufferProcessor(&oboeStream->bufferProcessor); PaUtil_TerminateStreamRepresentation(&oboeStream->streamRepresentation); - for (int i = 0; i < g_numberOfBuffers; ++i) { + for (int i = 0; i < paOboe_numberOfBuffers; ++i) { if (oboeStream->hasOutput) PaUtil_FreeMemory(oboeStream->outputBuffers[i]); if (oboeStream->hasInput) @@ -1599,8 +1599,8 @@ static PaError CloseStream(PaStream *i_paStream) { * portaudio, which holds the information of our OboeStream. * @return paNoError if no errors occur, paUnanticipatedHostError if OboeEngine::startStream fails. */ -static PaError StartStream(PaStream *i_paStream) { - auto *oboeStream = (OboeStream *) i_paStream; +static PaError StartStream(PaStream *paStream) { + auto *oboeStream = (OboeStream *) paStream; auto *oboeEngine = oboeStream->oboeMediator->getEngine(); PaUtil_ResetBufferProcessor(&oboeStream->bufferProcessor); @@ -1609,27 +1609,27 @@ static PaError StartStream(PaStream *i_paStream) { //TODO: check if it's working as expected (extensive testing needed, no problem spotted with situational tests) if (oboeStream->isActive) { LOGW("[PaOboe - StartStream]\t Stream was already active, stopping..."); - StopStream(i_paStream); + StopStream(paStream); LOGW("[PaOboe - StartStream]\t Restarting..."); - StartStream(i_paStream); + StartStream(paStream); } oboeStream->currentOutputBuffer = 0; oboeStream->currentInputBuffer = 0; /* Initialize buffers */ - for (int i = 0; i < g_numberOfBuffers; ++i) { + for (int i = 0; i < paOboe_numberOfBuffers; ++i) { if (oboeStream->hasOutput) { memset(oboeStream->outputBuffers[oboeStream->currentOutputBuffer], 0, oboeStream->framesPerHostCallback * oboeStream->bytesPerFrame * oboeStream->bufferProcessor.outputChannelCount); - oboeStream->currentOutputBuffer = (oboeStream->currentOutputBuffer + 1) % g_numberOfBuffers; + oboeStream->currentOutputBuffer = (oboeStream->currentOutputBuffer + 1) % paOboe_numberOfBuffers; } if (oboeStream->hasInput) { memset(oboeStream->inputBuffers[oboeStream->currentInputBuffer], 0, oboeStream->framesPerHostCallback * oboeStream->bytesPerFrame * oboeStream->bufferProcessor.inputChannelCount); - oboeStream->currentInputBuffer = (oboeStream->currentInputBuffer + 1) % g_numberOfBuffers; + oboeStream->currentInputBuffer = (oboeStream->currentInputBuffer + 1) % paOboe_numberOfBuffers; } } @@ -1657,9 +1657,9 @@ static PaError StartStream(PaStream *i_paStream) { * portaudio, which holds the information of our OboeStream. * @return paNoError if no errors occur, paUnanticipatedHostError if OboeStream::stopStream fails. */ -static PaError StopStream(PaStream *i_paStream) { +static PaError StopStream(PaStream *paStream) { PaError error = paNoError; - auto *oboeStream = (OboeStream *) i_paStream; + auto *oboeStream = (OboeStream *) paStream; auto *oboeEngine = oboeStream->oboeMediator->getEngine(); if (oboeStream->isStopped) { @@ -1691,9 +1691,9 @@ static PaError StopStream(PaStream *i_paStream) { * portaudio, which holds the information of our OboeStream. * @return paNoError if no errors occur, paUnanticipatedHostError if OboeStream::abortStream fails. */ -static PaError AbortStream(PaStream *i_paStream) { +static PaError AbortStream(PaStream *paStream) { PaError error = paNoError; - auto *oboeStream = (OboeStream *) i_paStream; + auto *oboeStream = (OboeStream *) paStream; auto *oboeEngine = oboeStream->oboeMediator->getEngine(); LOGI("[PaOboe - AbortStream]\t Aborting stream."); @@ -1725,22 +1725,22 @@ static PaError AbortStream(PaStream *i_paStream) { * @param frames is the total number of frames to read. * @return paInternalError if OboeEngine::readStream fails, paNoError otherwise. */ -static PaError ReadStream(PaStream *i_paStream, void *i_buffer, unsigned long i_frames) { - auto *oboeStream = (OboeStream *) i_paStream; +static PaError ReadStream(PaStream *paStream, void *buffer, unsigned long frames) { + auto *oboeStream = (OboeStream *) paStream; auto *oboeEngine = oboeStream->oboeMediator->getEngine(); - void *userBuffer = i_buffer; + void *userBuffer = buffer; unsigned framesToRead; PaError error = paNoError; - while (i_frames > 0) { - framesToRead = PA_MIN(oboeStream->framesPerHostCallback, i_frames); + while (frames > 0) { + framesToRead = PA_MIN(oboeStream->framesPerHostCallback, frames); if (!(oboeEngine->readStream(oboeStream, userBuffer, framesToRead * oboeStream->bufferProcessor.inputChannelCount))) error = paInternalError; - oboeStream->currentInputBuffer = (oboeStream->currentInputBuffer + 1) % g_numberOfBuffers; - i_frames -= framesToRead; + oboeStream->currentInputBuffer = (oboeStream->currentInputBuffer + 1) % paOboe_numberOfBuffers; + frames -= framesToRead; } return error; @@ -1755,22 +1755,22 @@ static PaError ReadStream(PaStream *i_paStream, void *i_buffer, unsigned long i_ * @param frames is the total number of frames to write. * @return paInternalError if OboeEngine::writeStream fails, paNoError otherwise. */ -static PaError WriteStream(PaStream *i_paStream, const void *i_buffer, unsigned long i_frames) { - auto *oboeStream = (OboeStream *) i_paStream; +static PaError WriteStream(PaStream *paStream, const void *buffer, unsigned long frames) { + auto *oboeStream = (OboeStream *) paStream; auto *oboeEngine = oboeStream->oboeMediator->getEngine(); - const void *userBuffer = i_buffer; + const void *userBuffer = buffer; unsigned framesToWrite; PaError error = paNoError; - while (i_frames > 0) { - framesToWrite = PA_MIN(oboeStream->framesPerHostCallback, i_frames); + while (frames > 0) { + framesToWrite = PA_MIN(oboeStream->framesPerHostCallback, frames); if (!(oboeEngine->writeStream(oboeStream, userBuffer, framesToWrite * oboeStream->bufferProcessor.outputChannelCount))) error = paInternalError; - oboeStream->currentOutputBuffer = (oboeStream->currentOutputBuffer + 1) % g_numberOfBuffers; - i_frames -= framesToWrite; + oboeStream->currentOutputBuffer = (oboeStream->currentOutputBuffer + 1) % paOboe_numberOfBuffers; + frames -= framesToWrite; } return error; @@ -1785,9 +1785,9 @@ static PaError WriteStream(PaStream *i_paStream, const void *i_buffer, unsigned * portaudio, which holds the information of our OboeStream. * @return the minimum number of frames that can be read without waiting. */ -static signed long GetStreamReadAvailable(PaStream *i_paStream) { - auto *oboeStream = (OboeStream *) i_paStream; - return oboeStream->framesPerHostCallback * (g_numberOfBuffers - oboeStream->currentInputBuffer); +static signed long GetStreamReadAvailable(PaStream *paStream) { + auto *oboeStream = (OboeStream *) paStream; + return oboeStream->framesPerHostCallback * (paOboe_numberOfBuffers - oboeStream->currentInputBuffer); } @@ -1797,9 +1797,9 @@ static signed long GetStreamReadAvailable(PaStream *i_paStream) { * portaudio, which holds the information of our OboeStream. * @return the minimum number of frames that can be written without waiting. */ -static signed long GetStreamWriteAvailable(PaStream *i_paStream) { - auto *oboeStream = (OboeStream *) i_paStream; - return oboeStream->framesPerHostCallback * (g_numberOfBuffers - oboeStream->currentOutputBuffer); +static signed long GetStreamWriteAvailable(PaStream *paStream) { + auto *oboeStream = (OboeStream *) paStream; + return oboeStream->framesPerHostCallback * (paOboe_numberOfBuffers - oboeStream->currentOutputBuffer); } @@ -1809,8 +1809,8 @@ static signed long GetStreamWriteAvailable(PaStream *i_paStream) { * portaudio, which holds the information of our OboeStream. * @return one (1) when the stream is stopped, or zero (0) when the stream is running. */ -static PaError IsStreamStopped(PaStream *i_paStream) { - auto *oboeStream = (OboeStream *) i_paStream; +static PaError IsStreamStopped(PaStream *paStream) { + auto *oboeStream = (OboeStream *) paStream; return oboeStream->isStopped; } @@ -1821,8 +1821,8 @@ static PaError IsStreamStopped(PaStream *i_paStream) { * portaudio, which holds the information of our OboeStream. * @return one (1) when the stream is active (ie playing or recording audio), or zero (0) otherwise. */ -static PaError IsStreamActive(PaStream *i_paStream) { - auto *oboeStream = (OboeStream *) i_paStream; +static PaError IsStreamActive(PaStream *paStream) { + auto *oboeStream = (OboeStream *) paStream; return oboeStream->isActive; } @@ -1833,7 +1833,7 @@ static PaError IsStreamActive(PaStream *i_paStream) { * portaudio, which holds the information of our OboeStream. * @return The stream's current time in seconds, or 0 if an error occurred. */ -static PaTime GetStreamTime(PaStream *i_paStream) { +static PaTime GetStreamTime(PaStream *paStream) { return PaUtil_GetTime(); } @@ -1849,8 +1849,8 @@ static PaTime GetStreamTime(PaStream *i_paStream) { * A value of 0.0 will always be returned for a blocking read/write stream, or if an error * occurs. */ -static double GetStreamCpuLoad(PaStream *i_paStream) { - auto *oboeStream = (OboeStream *) i_paStream; +static double GetStreamCpuLoad(PaStream *paStream) { + auto *oboeStream = (OboeStream *) paStream; return PaUtil_GetCpuLoad(&oboeStream->cpuLoadMeasurer); } @@ -1872,29 +1872,29 @@ static unsigned long GetApproximateLowBufferSize() { /*----------------------------- Implementation of PaOboe.h functions -----------------------------*/ -void PaOboe_SetSelectedDevice(Direction i_direction, int32_t i_deviceID) { +void PaOboe_SetSelectedDevice(Direction direction, int32_t deviceID) { LOGI("[PaOboe - SetSelectedDevice] Selecting device..."); - if (i_direction == Direction::Input) - g_inputDeviceId = i_deviceID; + if (direction == Direction::Input) + paOboe_inputDeviceId = deviceID; else - g_outputDeviceId = i_deviceID; + paOboe_outputDeviceId = deviceID; } -void PaOboe_SetPerformanceMode(oboe::Direction i_direction, oboe::PerformanceMode i_performanceMode) { - if (i_direction == Direction::Input) { - g_inputPerfMode = i_performanceMode; +void PaOboe_SetPerformanceMode(oboe::Direction direction, oboe::PerformanceMode performanceMode) { + if (direction == Direction::Input) { + paOboe_inputPerfMode = performanceMode; } else { - g_outputPerfMode = i_performanceMode; + paOboe_outputPerfMode = performanceMode; } } -void PaOboe_SetNativeBufferSize(unsigned long i_bufferSize) { - g_nativeBufferSize = i_bufferSize; +void PaOboe_SetNativeBufferSize(unsigned long bufferSize) { + paOboe_nativeBufferSize = bufferSize; } -void PaOboe_SetNumberOfBuffers(unsigned i_numberOfBuffers) { - g_numberOfBuffers = i_numberOfBuffers; +void PaOboe_SetNumberOfBuffers(unsigned numberOfBuffers) { + paOboe_numberOfBuffers = numberOfBuffers; } From 48947c05073a3b85d0795936b2dfaa8c9b0e293f Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Mon, 9 Oct 2023 11:02:18 +0200 Subject: [PATCH 21/26] replaced 'm_' prefix with 'm' prefix --- src/hostapi/oboe/pa_oboe.cpp | 215 +++++++++++++++++------------------ 1 file changed, 106 insertions(+), 109 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index ca1571a59..50e43f6dd 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -206,7 +206,7 @@ typedef struct OboeStream { class OboeMediator: public AudioStreamCallback{ public: OboeMediator(OboeStream* oboeStream) { - m_oboeCallbackStream = oboeStream; + mOboeCallbackStream = oboeStream; } //Callback function for non-blocking streams @@ -215,30 +215,30 @@ class OboeMediator: public AudioStreamCallback{ //Callback utils void onErrorAfterClose(AudioStream *audioStream, oboe::Result error) override; void resetCallbackCounters(); - void setOutputCallback() { m_outputBuilder.setDataCallback(this)->setErrorCallback(this); } - void setInputCallback() { m_inputBuilder.setDataCallback(this)->setErrorCallback(this); } + void setOutputCallback() { mOutputBuilder.setDataCallback(this)->setErrorCallback(this); } + void setInputCallback() { mInputBuilder.setDataCallback(this)->setErrorCallback(this); } - //getter and setter of m_oboeEngine and m_oboeCallbackStream - OboeEngine *getEngine() { return m_oboeEngine; } - void setEngine(OboeEngine *oboeEngine) { m_oboeEngine = oboeEngine; } + //getter and setter of mOboeEngine and mOboeCallbackStream + OboeEngine *getEngine() { return mOboeEngine; } + void setEngine(OboeEngine *oboeEngine) { mOboeEngine = oboeEngine; } - OboeStream *getStreamAddress() { return m_oboeCallbackStream; } - void setCallbackStream(OboeStream *oboeStream) { m_oboeCallbackStream = oboeStream; } + OboeStream *getStreamAddress() { return mOboeCallbackStream; } + void setCallbackStream(OboeStream *oboeStream) { mOboeCallbackStream = oboeStream; } //The only instances of output and input streams that will be used, and their builders - std::shared_ptr m_outputStream; - AudioStreamBuilder m_outputBuilder; - std::shared_ptr m_inputStream; - AudioStreamBuilder m_inputBuilder; + std::shared_ptr mOutputStream; + AudioStreamBuilder mOutputBuilder; + std::shared_ptr mInputStream; + AudioStreamBuilder mInputBuilder; private: - OboeEngine *m_oboeEngine; + OboeEngine *mOboeEngine; //callback utils - OboeStream *m_oboeCallbackStream; - unsigned long m_framesProcessed{}; - PaStreamCallbackTimeInfo m_timeInfo{}; - struct timespec m_timeSpec{}; + OboeStream *mOboeCallbackStream; + unsigned long mFramesProcessed{}; + PaStreamCallbackTimeInfo mTimeInfo{}; + struct timespec mTimeSpec{}; }; @@ -276,10 +276,10 @@ class OboeEngine { void constructOboeStream(OboeStream* oboeStream); private: - std::shared_ptr m_testStream; - AudioStreamBuilder m_testBuilder; + std::shared_ptr mTestStream; + AudioStreamBuilder mTestBuilder; - OboeMediator* m_terminableMediator; + OboeMediator* mTerminableMediator; //Conversion utils static AudioFormat PaToOboeFormat(PaSampleFormat paFormat); @@ -327,13 +327,13 @@ bool OboeEngine::tryStream(Direction direction, int32_t sampleRate, int32_t chan Result result; bool outcome = false; - m_testBuilder.setDeviceId(getSelectedDevice(direction)) + mTestBuilder.setDeviceId(getSelectedDevice(direction)) // Arbitrary format usually broadly supported. Later, we'll open streams with correct formats. ->setFormat(AudioFormat::Float) ->setDirection(direction) ->setSampleRate(sampleRate) ->setChannelCount(channelCount) - ->openStream(m_testStream); + ->openStream(mTestStream); if (result != Result::OK) { LOGE("[OboeEngine::TryStream]\t Couldn't open the stream in TryStream. Error: %s", @@ -342,23 +342,23 @@ bool OboeEngine::tryStream(Direction direction, int32_t sampleRate, int32_t chan } if (sampleRate != kUnspecified) { - outcome = (sampleRate == m_testBuilder.getSampleRate()); + outcome = (sampleRate == mTestBuilder.getSampleRate()); if (!outcome) { LOGW("[OboeEngine::TryStream]\t Tried sampleRate = %d, built sampleRate = %d", - sampleRate, m_testBuilder.getSampleRate()); + sampleRate, mTestBuilder.getSampleRate()); } } else if (channelCount != kUnspecified) { - outcome = (channelCount == m_testBuilder.getChannelCount()); + outcome = (channelCount == mTestBuilder.getChannelCount()); if (!outcome) { LOGW("[OboeEngine::TryStream]\t Tried channelCount = %d, built channelCount = %d", - channelCount, m_testBuilder.getChannelCount()); + channelCount, mTestBuilder.getChannelCount()); } } else { LOGE("[OboeEngine::TryStream]\t Logical failure. This message should NEVER occur."); outcome = false; } - m_testStream->close(); + mTestStream->close(); return outcome; } @@ -397,7 +397,7 @@ PaError OboeEngine::openStream(OboeStream *oboeStream, Direction direction, int3 } if (direction == Direction::Input) { - mediator->m_inputBuilder.setChannelCount(oboeStream->bufferProcessor.inputChannelCount) + mediator->mInputBuilder.setChannelCount(oboeStream->bufferProcessor.inputChannelCount) ->setFormat(PaToOboeFormat(oboeStream->inputFormat)) ->setSampleRate(sampleRate) ->setDirection(Direction::Input) @@ -410,7 +410,7 @@ PaError OboeEngine::openStream(OboeStream *oboeStream, Direction direction, int3 mediator->setInputCallback(); } - result = mediator->m_inputBuilder.openStream(mediator->m_inputStream); + result = mediator->mInputBuilder.openStream(mediator->mInputStream); if (result != Result::OK) { LOGE("[OboeEngine::OpenStream]\t Oboe couldn't open the input stream: %s", @@ -418,7 +418,7 @@ PaError OboeEngine::openStream(OboeStream *oboeStream, Direction direction, int3 return paUnanticipatedHostError; } - mediator->m_inputStream->setBufferSizeInFrames(mediator->m_inputStream->getFramesPerBurst() * + mediator->minputStream->setBufferSizeInFrames(mediator->mInputStream->getFramesPerBurst() * paOboe_numberOfBuffers); oboeStream->inputBuffers = (void **) PaUtil_AllocateZeroInitializedMemory(paOboe_numberOfBuffers * sizeof(int32_t * )); @@ -433,14 +433,14 @@ PaError OboeEngine::openStream(OboeStream *oboeStream, Direction direction, int3 for (int j = 0; j < i; ++j) PaUtil_FreeMemory(oboeStream->inputBuffers[j]); PaUtil_FreeMemory(oboeStream->inputBuffers); - mediator->m_inputStream->close(); + mediator->mInputStream->close(); error = paInsufficientMemory; break; } } oboeStream->currentInputBuffer = 0; } else { - mediator->m_outputBuilder.setChannelCount(oboeStream->bufferProcessor.outputChannelCount) + mediator->mOutputBuilder.setChannelCount(oboeStream->bufferProcessor.outputChannelCount) ->setFormat(PaToOboeFormat(oboeStream->outputFormat)) ->setSampleRate(sampleRate) ->setDirection(Direction::Output) @@ -453,14 +453,14 @@ PaError OboeEngine::openStream(OboeStream *oboeStream, Direction direction, int3 mediator->setOutputCallback(); } - result = mediator->m_outputBuilder.openStream(mediator->m_outputStream); + result = mediator->mOutputBuilder.openStream(mediator->mOutputStream); if (result != Result::OK) { LOGE("[OboeEngine::OpenStream]\t Oboe couldn't open the output stream: %s", convertToText(result)); return paUnanticipatedHostError; } - mediator->m_outputStream->setBufferSizeInFrames(mediator->m_outputStream->getFramesPerBurst() * + mediator->mOutputStream->setBufferSizeInFrames(mediator->mOutputStream->getFramesPerBurst() * paOboe_numberOfBuffers); oboeStream->outputBuffers = (void **) PaUtil_AllocateZeroInitializedMemory(paOboe_numberOfBuffers * sizeof(int32_t * )); @@ -475,7 +475,7 @@ PaError OboeEngine::openStream(OboeStream *oboeStream, Direction direction, int3 for (int j = 0; j < i; ++j) PaUtil_FreeMemory(oboeStream->outputBuffers[j]); PaUtil_FreeMemory(oboeStream->outputBuffers); - mediator->m_outputStream->close(); + mediator->mOutputStream->close(); error = paInsufficientMemory; break; } @@ -498,13 +498,13 @@ bool OboeEngine::startStream(OboeStream *oboeStream) { OboeMediator* mediator = oboeStream->oboeMediator; if (oboeStream->hasInput) { - inputResult = mediator->m_inputStream->requestStart(); + inputResult = mediator->mInputStream->requestStart(); if (inputResult != Result::OK) LOGE("[OboeEngine::startStream]\t Oboe couldn't start the input stream: %s", convertToText(inputResult)); } if (oboeStream->hasOutput) { - outputResult = mediator->m_outputStream->requestStart(); + outputResult = mediator->mOutputStream->requestStart(); if (outputResult != Result::OK) LOGE("[OboeEngine::startStream]\t Oboe couldn't start the output stream: %s", convertToText(outputResult)); @@ -525,13 +525,13 @@ bool OboeEngine::stopStream(OboeStream *oboeStream) { OboeMediator* mediator = oboeStream->oboeMediator; if (oboeStream->hasInput) { - inputResult = mediator->m_inputStream->requestStop(); + inputResult = mediator->mInputStream->requestStop(); if (inputResult != Result::OK) LOGE("[OboeEngine::stopStream]\t Oboe couldn't stop the input stream: %s", convertToText(inputResult)); } if (oboeStream->hasOutput) { - outputResult = mediator->m_outputStream->requestStop(); + outputResult = mediator->mOutputStream->requestStop(); if (outputResult != Result::OK) LOGE("[OboeEngine::stopStream]\t Oboe couldn't stop the output stream: %s", convertToText(outputResult)); @@ -556,11 +556,11 @@ bool OboeEngine::restartStream(OboeStream* oboeStream, int direction) { switch (direction) { case 1: //output-only - result = mediator->m_outputBuilder.openStream(mediator->m_outputStream); + result = mediator->mOutputBuilder.openStream(mediator->mOutputStream); if (result != Result::OK) LOGE("[OboeEngine::restartStream]\t Oboe couldn't reopen the output stream: %s", convertToText(result)); - result = mediator->m_outputStream->start(); + result = mediator->mOutputStream->start(); if (result != Result::OK) { LOGE("[OboeEngine::restartStream]\t Oboe couldn't restart the output stream: %s", convertToText(result)); @@ -569,11 +569,11 @@ bool OboeEngine::restartStream(OboeStream* oboeStream, int direction) { break; case 2: //input-only - result = mediator->m_inputBuilder.openStream(mediator->m_inputStream); + result = mediator->mInputBuilder.openStream(mediator->mInputStream); if (result != Result::OK) LOGE("[OboeEngine::restartStream]\t Oboe couldn't reopen the input stream: %s", convertToText(result)); - result = mediator->m_inputStream->start(); + result = mediator->mInputStream->start(); if (result != Result::OK) { LOGE("[OboeEngine::restartStream]\t Oboe couldn't restart the input stream: %s", convertToText(result)); @@ -609,14 +609,14 @@ bool OboeEngine::closeStream(OboeStream *oboeStream) { OboeMediator* mediator = oboeStream->oboeMediator; if (oboeStream->hasOutput) { - outputResult = mediator->m_outputStream->close(); + outputResult = mediator->mOutputStream->close(); if (outputResult == Result::ErrorClosed) { outputResult = Result::OK; LOGW("[OboeEngine::closeStream]\t Tried to close output stream, but was already closed."); } } if (oboeStream->hasInput) { - inputResult = mediator->m_inputStream->close(); + inputResult = mediator->mInputStream->close(); if (inputResult == Result::ErrorClosed) { inputResult = Result::OK; LOGW("[OboeEngine::closeStream]\t Tried to close input stream, but was already closed."); @@ -643,21 +643,21 @@ bool OboeEngine::abortStream(OboeStream *oboeStream) { OboeMediator* mediator = oboeStream->oboeMediator; if (oboeStream->hasInput) { - inputResult = mediator->m_inputStream->stop(); + inputResult = mediator->mInputStream->stop(); if (inputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the input stream to stop: %s", convertToText(inputResult)); - inputResult = mediator->m_inputStream->close(); + inputResult = mediator->mInputStream->close(); if (inputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the input stream to close: %s", convertToText(inputResult)); } if (oboeStream->hasOutput) { - outputResult = mediator->m_outputStream->stop(); + outputResult = mediator->mOutputStream->stop(); if (outputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the output stream to stop: %s", convertToText(outputResult)); - outputResult = mediator->m_outputStream->close(); + outputResult = mediator->mOutputStream->close(); if (outputResult != Result::OK) LOGE("[OboeEngine::abortStream]\t Couldn't force the output stream to close: %s", convertToText(outputResult)); @@ -680,7 +680,7 @@ bool OboeEngine::writeStream(OboeStream *oboeStream, const void buffer, int32_t bool outcome = true; OboeMediator* mediator = oboeStream->oboeMediator; - ResultWithValue result = mediator->m_outputStream->write(buffer, framesToWrite, TIMEOUT_NS); + ResultWithValue result = mediator->mOutputStream->write(buffer, framesToWrite, TIMEOUT_NS); // If the stream is interrupted because the device suddenly changes, restart the stream. if (result.error() == Result::ErrorDisconnected) { @@ -709,7 +709,7 @@ bool OboeEngine::readStream(OboeStream *oboeStream, void *buffer, int32_t frames bool outcome = true; OboeMediator* mediator = oboeStream->oboeMediator; - ResultWithValue result = mediator->m_inputStream->read(buffer, framesToRead, TIMEOUT_NS); + ResultWithValue result = mediator->mInputStream->read(buffer, framesToRead, TIMEOUT_NS); // If the stream is interrupted because the device suddenly changes, restart the stream. if (result.error() == Result::ErrorDisconnected) { @@ -730,7 +730,7 @@ bool OboeEngine::readStream(OboeStream *oboeStream, void *buffer, int32_t frames * @return the address of the oboeStream. */ void OboeEngine::constructOboeStream(OboeStream* oboeStream) { - m_terminableMediator = oboeStream->oboeMediator = new OboeMediator(oboeStream); + mTerminableMediator = oboeStream->oboeMediator = new OboeMediator(oboeStream); oboeStream->oboeMediator->setEngine(this); } @@ -788,85 +788,85 @@ int32_t OboeEngine::getSelectedDevice(Direction direction) { DataCallbackResult OboeMediator::onAudioReady(AudioStream *audioStream, void *audioData, int32_t numFrames) { - clock_gettime(CLOCK_REALTIME, &m_timeSpec); - m_timeInfo.currentTime = (PaTime)(m_timeSpec.tv_sec + (m_timeSpec.tv_nsec / 1000000000.0)); - m_timeInfo.outputBufferDacTime = (PaTime)(m_oboeCallbackStream->framesPerHostCallback + clock_gettime(CLOCK_REALTIME, &mTimeSpec); + mTimeInfo.currentTime = (PaTime)(mTimeSpec.tv_sec + (mTimeSpec.tv_nsec / 1000000000.0)); + mTimeInfo.outputBufferDacTime = (PaTime)(mOboeCallbackStream->framesPerHostCallback / - m_oboeCallbackStream->streamRepresentation.streamInfo.sampleRate - + m_timeInfo.currentTime); - m_timeInfo.inputBufferAdcTime = (PaTime)(m_oboeCallbackStream->framesPerHostCallback + mOboeCallbackStream->streamRepresentation.streamInfo.sampleRate + + mTimeInfo.currentTime); + mTimeInfo.inputBufferAdcTime = (PaTime)(mOboeCallbackStream->framesPerHostCallback / - m_oboeCallbackStream->streamRepresentation.streamInfo.sampleRate - + m_timeInfo.currentTime); + mOboeCallbackStream->streamRepresentation.streamInfo.sampleRate + + mTimeInfo.currentTime); /* check if StopStream or AbortStream was called */ - if (m_oboeCallbackStream->doStop) { - m_oboeCallbackStream->callbackResult = paComplete; - } else if (m_oboeCallbackStream->doAbort) { - m_oboeCallbackStream->callbackResult = paAbort; + if (mOboeCallbackStream->doStop) { + mOboeCallbackStream->callbackResult = paComplete; + } else if (mOboeCallbackStream->doAbort) { + mOboeCallbackStream->callbackResult = paAbort; } - PaUtil_BeginCpuLoadMeasurement(&m_oboeCallbackStream->cpuLoadMeasurer); - PaUtil_BeginBufferProcessing(&m_oboeCallbackStream->bufferProcessor, - &m_timeInfo, m_oboeCallbackStream->cbFlags); + PaUtil_BeginCpuLoadMeasurement(&mOboeCallbackStream->cpuLoadMeasurer); + PaUtil_BeginBufferProcessing(&mOboeCallbackStream->bufferProcessor, + &mTimeInfo, mOboeCallbackStream->cbFlags); - if (m_oboeCallbackStream->hasOutput) { - m_oboeCallbackStream->outputBuffers[m_oboeCallbackStream->currentOutputBuffer] = audioData; - PaUtil_SetOutputFrameCount(&m_oboeCallbackStream->bufferProcessor, numFrames); - PaUtil_SetInterleavedOutputChannels(&m_oboeCallbackStream->bufferProcessor, 0, - (void *) ((PaInt16 **) m_oboeCallbackStream->outputBuffers)[ - m_oboeCallbackStream->currentOutputBuffer], + if (mOboeCallbackStream->hasOutput) { + mOboeCallbackStream->outputBuffers[mOboeCallbackStream->currentOutputBuffer] = audioData; + PaUtil_SetOutputFrameCount(&mOboeCallbackStream->bufferProcessor, numFrames); + PaUtil_SetInterleavedOutputChannels(&mOboeCallbackStream->bufferProcessor, 0, + (void *) ((PaInt16 **) mOboeCallbackStream->outputBuffers)[ + mOboeCallbackStream->currentOutputBuffer], 0); } - if (m_oboeCallbackStream->hasInput) { - audioData = m_oboeCallbackStream->inputBuffers[m_oboeCallbackStream->currentInputBuffer]; - PaUtil_SetInputFrameCount(&m_oboeCallbackStream->bufferProcessor, 0); - PaUtil_SetInterleavedInputChannels(&m_oboeCallbackStream->bufferProcessor, 0, - (void *) ((PaInt16 **) m_oboeCallbackStream->inputBuffers)[ - m_oboeCallbackStream->currentInputBuffer], + if (mOboeCallbackStream->hasInput) { + audioData = mOboeCallbackStream->inputBuffers[mOboeCallbackStream->currentInputBuffer]; + PaUtil_SetInputFrameCount(&mOboeCallbackStream->bufferProcessor, 0); + PaUtil_SetInterleavedInputChannels(&mOboeCallbackStream->bufferProcessor, 0, + (void *) ((PaInt16 **) mOboeCallbackStream->inputBuffers)[ + mOboeCallbackStream->currentInputBuffer], 0); } /* continue processing user buffers if callback result is paContinue or * if it is paComplete and userBuffers aren't empty yet */ - if (m_oboeCallbackStream->callbackResult == paContinue - || (m_oboeCallbackStream->callbackResult == paComplete - && !PaUtil_IsBufferProcessorOutputEmpty(&m_oboeCallbackStream->bufferProcessor))) { - m_framesProcessed = PaUtil_EndBufferProcessing(&m_oboeCallbackStream->bufferProcessor, - &m_oboeCallbackStream->callbackResult); + if (mOboeCallbackStream->callbackResult == paContinue + || (mOboeCallbackStream->callbackResult == paComplete + && !PaUtil_IsBufferProcessorOutputEmpty(&mOboeCallbackStream->bufferProcessor))) { + mFramesProcessed = PaUtil_EndBufferProcessing(&mOboeCallbackStream->bufferProcessor, + &mOboeCallbackStream->callbackResult); } /* enqueue a buffer only when there are frames to be processed, * this will be 0 when paComplete + empty buffers or paAbort */ - if (m_framesProcessed > 0) { - if (m_oboeCallbackStream->hasOutput) { - m_oboeCallbackStream->currentOutputBuffer = - (m_oboeCallbackStream->currentOutputBuffer + 1) % paOboe_numberOfBuffers; + if (mFramesProcessed > 0) { + if (mOboeCallbackStream->hasOutput) { + mOboeCallbackStream->currentOutputBuffer = + (mOboeCallbackStream->currentOutputBuffer + 1) % paOboe_numberOfBuffers; } - if (m_oboeCallbackStream->hasInput) { - m_oboeCallbackStream->currentInputBuffer = (m_oboeCallbackStream->currentInputBuffer + 1) % paOboe_numberOfBuffers; + if (mOboeCallbackStream->hasInput) { + mOboeCallbackStream->currentInputBuffer = (mOboeCallbackStream->currentInputBuffer + 1) % paOboe_numberOfBuffers; } } - PaUtil_EndCpuLoadMeasurement(&m_oboeCallbackStream->cpuLoadMeasurer, m_framesProcessed); + PaUtil_EndCpuLoadMeasurement(&mOboeCallbackStream->cpuLoadMeasurer, mFramesProcessed); /* StopStream was called */ - if (m_framesProcessed == 0 && m_oboeCallbackStream->doStop) { - m_oboeCallbackStream->oboeCallbackResult = DataCallbackResult::Stop; + if (mFramesProcessed == 0 && mOboeCallbackStream->doStop) { + mOboeCallbackStream->oboeCallbackResult = DataCallbackResult::Stop; } /* if AbortStream or StopStream weren't called, stop from the cb */ - else if (m_framesProcessed == 0 && !(m_oboeCallbackStream->doAbort || m_oboeCallbackStream->doStop)) { - m_oboeCallbackStream->isActive = false; - m_oboeCallbackStream->isStopped = true; - if (m_oboeCallbackStream->streamRepresentation.streamFinishedCallback != nullptr) - m_oboeCallbackStream->streamRepresentation.streamFinishedCallback( - m_oboeCallbackStream->streamRepresentation.userData); - m_oboeCallbackStream->oboeCallbackResult = DataCallbackResult::Stop; //TODO: Resume this test (onAudioReady) + else if (mFramesProcessed == 0 && !(mOboeCallbackStream->doAbort || mOboeCallbackStream->doStop)) { + mOboeCallbackStream->isActive = false; + mOboeCallbackStream->isStopped = true; + if (mOboeCallbackStream->streamRepresentation.streamFinishedCallback != nullptr) + mOboeCallbackStream->streamRepresentation.streamFinishedCallback( + mOboeCallbackStream->streamRepresentation.userData); + mOboeCallbackStream->oboeCallbackResult = DataCallbackResult::Stop; //TODO: Resume this test (onAudioReady) } - return m_oboeCallbackStream->oboeCallbackResult; + return mOboeCallbackStream->oboeCallbackResult; } @@ -879,11 +879,11 @@ void OboeMediator::onErrorAfterClose(AudioStream *audioStream, Result error) { OboeEngine* oboeEngine = getEngine(); LOGW("[OboeMediator::onErrorAfterClose]\t ErrorDisconnected - Restarting stream(s)"); int i = 0; - if(m_oboeCallbackStream->hasOutput) + if(mOboeCallbackStream->hasOutput) i++; - if(m_oboeCallbackStream->hasInput) + if(mOboeCallbackStream->hasInput) i+=2; - if (!oboeEngine->restartStream(m_oboeCallbackStream, i)) + if (!oboeEngine->restartStream(mOboeCallbackStream, i)) LOGE("[OboeMediator::onErrorAfterClose]\t Couldn't restart stream(s)"); } else LOGE("[OboeMediator::onErrorAfterClose]\t Error was %s", oboe::convertToText(error)); @@ -894,8 +894,8 @@ void OboeMediator::onErrorAfterClose(AudioStream *audioStream, Result error) { * \brief Resets callback counters (called at the start of each iteration of onAudioReady). */ void OboeMediator::resetCallbackCounters() { - m_framesProcessed = 0; - m_timeInfo = {0, 0, 0}; + mFramesProcessed = 0; + mTimeInfo = {0, 0, 0}; } @@ -1880,7 +1880,6 @@ void PaOboe_SetSelectedDevice(Direction direction, int32_t deviceID) { paOboe_outputDeviceId = deviceID; } - void PaOboe_SetPerformanceMode(oboe::Direction direction, oboe::PerformanceMode performanceMode) { if (direction == Direction::Input) { paOboe_inputPerfMode = performanceMode; @@ -1889,12 +1888,10 @@ void PaOboe_SetPerformanceMode(oboe::Direction direction, oboe::PerformanceMode } } - void PaOboe_SetNativeBufferSize(unsigned long bufferSize) { paOboe_nativeBufferSize = bufferSize; } - void PaOboe_SetNumberOfBuffers(unsigned numberOfBuffers) { paOboe_numberOfBuffers = numberOfBuffers; } From cc9a83ecedfce04143b2e16e3af4b553f642707f Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Mon, 9 Oct 2023 11:25:52 +0200 Subject: [PATCH 22/26] fixed OboeEngine::tryStream as requested --- src/hostapi/oboe/pa_oboe.cpp | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index 50e43f6dd..5b0fd683a 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -276,9 +276,6 @@ class OboeEngine { void constructOboeStream(OboeStream* oboeStream); private: - std::shared_ptr mTestStream; - AudioStreamBuilder mTestBuilder; - OboeMediator* mTerminableMediator; //Conversion utils @@ -314,26 +311,28 @@ OboeEngine::OboeEngine() {} /** * \brief Tries to open a stream with the direction direction, sample rate sampleRate and/or - * channel count channelCount. It then checks if the stream was in fact opened with the - * desired settings, and then closes the stream. It's used to see if the requested + * channel count channelCount. It then closes the stream. It's used to see if the requested * parameters are supported by the devices that are going to be used. * @param direction the Direction of the stream; * @param sampleRate the sample rate we want to try; * @param channelCount the channel count we want to try; - * @return true if the requested sample rate / channel count is supported by the device, false if - * they aren't, or if tryStream couldn't open a stream. + * @return true if the stream was opened with Result::OK, false otherwise. */ bool OboeEngine::tryStream(Direction direction, int32_t sampleRate, int32_t channelCount) { Result result; bool outcome = false; - mTestBuilder.setDeviceId(getSelectedDevice(direction)) + std::shared_ptr stream; + AudioStreamBuilder builder; + + builder.setDeviceId(getSelectedDevice(direction)) // Arbitrary format usually broadly supported. Later, we'll open streams with correct formats. + // FIXME: if needed, modify this format to whatever you require ->setFormat(AudioFormat::Float) ->setDirection(direction) ->setSampleRate(sampleRate) ->setChannelCount(channelCount) - ->openStream(mTestStream); + ->openStream(stream); if (result != Result::OK) { LOGE("[OboeEngine::TryStream]\t Couldn't open the stream in TryStream. Error: %s", @@ -341,24 +340,7 @@ bool OboeEngine::tryStream(Direction direction, int32_t sampleRate, int32_t chan return outcome; } - if (sampleRate != kUnspecified) { - outcome = (sampleRate == mTestBuilder.getSampleRate()); - if (!outcome) { - LOGW("[OboeEngine::TryStream]\t Tried sampleRate = %d, built sampleRate = %d", - sampleRate, mTestBuilder.getSampleRate()); - } - } else if (channelCount != kUnspecified) { - outcome = (channelCount == mTestBuilder.getChannelCount()); - if (!outcome) { - LOGW("[OboeEngine::TryStream]\t Tried channelCount = %d, built channelCount = %d", - channelCount, mTestBuilder.getChannelCount()); - } - } else { - LOGE("[OboeEngine::TryStream]\t Logical failure. This message should NEVER occur."); - outcome = false; - } - - mTestStream->close(); + stream->close(); return outcome; } From 512ed423a34fe58c23f26496e134c3cb810443a5 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Mon, 9 Oct 2023 14:47:02 +0200 Subject: [PATCH 23/26] Fixed minor problem with TryStream --- src/hostapi/oboe/pa_oboe.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index 79a9b35e1..fb8ed9ca7 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -320,7 +320,6 @@ OboeEngine::OboeEngine() {} */ bool OboeEngine::tryStream(Direction direction, int32_t sampleRate, int32_t channelCount) { Result result; - bool outcome = false; std::shared_ptr stream; AudioStreamBuilder builder; @@ -337,12 +336,12 @@ bool OboeEngine::tryStream(Direction direction, int32_t sampleRate, int32_t chan if (result != Result::OK) { LOGE("[OboeEngine::TryStream]\t Couldn't open the stream in TryStream. Error: %s", convertToText(result)); - return outcome; + return false; } stream->close(); - return outcome; + return true; } From f88819adc4f5e8304a8bd9afe79f4a057fe6429a Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Tue, 10 Oct 2023 10:09:19 +0200 Subject: [PATCH 24/26] fixed long line in FindOboe.cmake --- cmake/modules/FindOboe.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/modules/FindOboe.cmake b/cmake/modules/FindOboe.cmake index ea66ec394..8dbf9daa3 100644 --- a/cmake/modules/FindOboe.cmake +++ b/cmake/modules/FindOboe.cmake @@ -22,8 +22,8 @@ endif() if(NOT OBOE_DIRECTORY) message(AUTHOR_WARNING - "If you're trying to use Oboe as a Host API, please specify the directory where you - cloned its repository. For further information, please read src/hostapi/oboe/README.md" + "If you're trying to use Oboe as a Host API, please specify the directory where you " + "cloned its repository. For further information, please read src/hostapi/oboe/README.md" ) set(OBOE_FOUND FALSE) else() From 6f84e76382212179d247685aa49fc0d5f086b2c2 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Tue, 10 Oct 2023 10:35:11 +0200 Subject: [PATCH 25/26] fixed typos in pa_oboe.cpp --- src/hostapi/oboe/pa_oboe.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index fb8ed9ca7..f278d3a63 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -399,7 +399,7 @@ PaError OboeEngine::openStream(PaOboeStream *paOboeStream, Direction direction, return paUnanticipatedHostError; } - mediator->minputStream->setBufferSizeInFrames(mediator->mInputStream->getFramesPerBurst() * + mediator->mInputStream->setBufferSizeInFrames(mediator->mInputStream->getFramesPerBurst() * paOboe_numberOfBuffers); paOboeStream->inputBuffers = (void **) PaUtil_AllocateZeroInitializedMemory(paOboe_numberOfBuffers * sizeof(int32_t * )); @@ -657,7 +657,7 @@ bool OboeEngine::abortStream(PaOboeStream *paOboeStream) { * different from ErrorDisconnected. In case of ErrorDisconnected, the function returns * true if the stream is successfully restarted, and false otherwise. */ -bool OboeEngine::writeStream(PaOboeStream *paOboeStream, const void buffer, int32_t framesToWrite) { +bool OboeEngine::writeStream(PaOboeStream *paOboeStream, const void *buffer, int32_t framesToWrite) { bool outcome = true; OboeMediator* mediator = paOboeStream->oboeMediator; From 5ed3d7f54f66ad0e66413b47cd5da912afb297c6 Mon Sep 17 00:00:00 2001 From: Carlo Benfatti Date: Tue, 10 Oct 2023 10:43:49 +0200 Subject: [PATCH 26/26] set to verbose some logs --- src/hostapi/oboe/pa_oboe.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hostapi/oboe/pa_oboe.cpp b/src/hostapi/oboe/pa_oboe.cpp index f278d3a63..30fab00c3 100644 --- a/src/hostapi/oboe/pa_oboe.cpp +++ b/src/hostapi/oboe/pa_oboe.cpp @@ -726,19 +726,19 @@ AudioFormat OboeEngine::PaToOboeFormat(PaSampleFormat paFormat) { switch (paFormat) { case paFloat32: oboeFormat = AudioFormat::Float; - LOGI("[OboeEngine::PaToOboeFormat]\t REQUESTED OBOE FORMAT: FLOAT"); + LOGV("[OboeEngine::PaToOboeFormat]\t REQUESTED OBOE FORMAT: FLOAT"); break; case paInt16: oboeFormat = AudioFormat::I16; - LOGI("[OboeEngine::PaToOboeFormat]\t REQUESTED OBOE FORMAT: I16"); + LOGV("[OboeEngine::PaToOboeFormat]\t REQUESTED OBOE FORMAT: I16"); break; case paInt32: oboeFormat = AudioFormat::I32; - LOGI("[OboeEngine::PaToOboeFormat]\t REQUESTED OBOE FORMAT: I32"); + LOGV("[OboeEngine::PaToOboeFormat]\t REQUESTED OBOE FORMAT: I32"); break; case paInt24: oboeFormat = AudioFormat::I24; - LOGI("[OboeEngine::PaToOboeFormat]\t REQUESTED OBOE FORMAT: I24"); + LOGV("[OboeEngine::PaToOboeFormat]\t REQUESTED OBOE FORMAT: I24"); break; default: oboeFormat = AudioFormat::Unspecified; @@ -1369,7 +1369,7 @@ static PaError OpenStream(struct PaUtilHostApiRepresentation *hostApi, goto error; } - LOGI("[PaOboe - OpenStream]\t OpenStream called."); + LOGV("[PaOboe - OpenStream]\t OpenStream called."); if (inputParameters) { inputChannelCount = inputParameters->channelCount;