react-native-audio-api 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -1
- package/RNAudioAPI.podspec +41 -0
- package/android/CMakeLists.txt +63 -0
- package/android/build.gradle +194 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/AndroidManifestNew.xml +2 -0
- package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.cpp +22 -0
- package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.h +48 -0
- package/android/src/main/cpp/AudioPlayer/AudioPlayer.cpp +45 -0
- package/android/src/main/cpp/AudioPlayer/AudioPlayer.h +30 -0
- package/android/src/main/cpp/OnLoad.cpp +9 -0
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +14 -0
- package/android/src/main/java/com/swmansion/audioapi/module/AudioAPIInstaller.kt +21 -0
- package/android/src/main/java/com/swmansion/audioapi/nativemodules/AudioAPIModule.kt +25 -0
- package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.cpp +52 -0
- package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.h +45 -0
- package/common/cpp/AudioAPIInstaller/AudioAPIInstallerWrapper.h +38 -0
- package/common/cpp/AudioAPIInstaller/android/AudioAPIInstallerWrapper.cpp +16 -0
- package/common/cpp/AudioAPIInstaller/ios/AudioAPIInstallerWrapper.cpp +12 -0
- package/common/cpp/HostObjects/AudioBufferHostObject.cpp +143 -0
- package/common/cpp/HostObjects/AudioBufferHostObject.h +33 -0
- package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.cpp +67 -0
- package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.h +37 -0
- package/common/cpp/HostObjects/AudioContextHostObject.cpp +191 -0
- package/common/cpp/HostObjects/AudioContextHostObject.h +43 -0
- package/common/cpp/HostObjects/AudioDestinationNodeHostObject.cpp +33 -0
- package/common/cpp/HostObjects/AudioDestinationNodeHostObject.h +31 -0
- package/common/cpp/HostObjects/AudioNodeHostObject.cpp +108 -0
- package/common/cpp/HostObjects/AudioNodeHostObject.h +29 -0
- package/common/cpp/HostObjects/AudioParamHostObject.cpp +115 -0
- package/common/cpp/HostObjects/AudioParamHostObject.h +34 -0
- package/common/cpp/HostObjects/AudioScheduledSourceNodeHostObject.cpp +73 -0
- package/common/cpp/HostObjects/AudioScheduledSourceNodeHostObject.h +31 -0
- package/common/cpp/HostObjects/BiquadFilterNodeHostObject.cpp +81 -0
- package/common/cpp/HostObjects/BiquadFilterNodeHostObject.h +42 -0
- package/common/cpp/HostObjects/Constants.h +22 -0
- package/common/cpp/HostObjects/GainNodeHostObject.cpp +41 -0
- package/common/cpp/HostObjects/GainNodeHostObject.h +32 -0
- package/common/cpp/HostObjects/OscillatorNodeHostObject.cpp +67 -0
- package/common/cpp/HostObjects/OscillatorNodeHostObject.h +40 -0
- package/common/cpp/HostObjects/StereoPannerNodeHostObject.cpp +41 -0
- package/common/cpp/HostObjects/StereoPannerNodeHostObject.h +36 -0
- package/common/cpp/core/AudioBuffer.cpp +115 -0
- package/common/cpp/core/AudioBuffer.h +42 -0
- package/common/cpp/core/AudioBufferSourceNode.cpp +58 -0
- package/common/cpp/core/AudioBufferSourceNode.h +26 -0
- package/common/cpp/core/AudioContext.cpp +90 -0
- package/common/cpp/core/AudioContext.h +73 -0
- package/common/cpp/core/AudioDestinationNode.cpp +35 -0
- package/common/cpp/core/AudioDestinationNode.h +24 -0
- package/common/cpp/core/AudioNode.cpp +68 -0
- package/common/cpp/core/AudioNode.h +74 -0
- package/common/cpp/core/AudioParam.cpp +136 -0
- package/common/cpp/core/AudioParam.h +50 -0
- package/common/cpp/core/AudioScheduledSourceNode.cpp +39 -0
- package/common/cpp/core/AudioScheduledSourceNode.h +30 -0
- package/common/cpp/core/BiquadFilterNode.cpp +364 -0
- package/common/cpp/core/BiquadFilterNode.h +128 -0
- package/common/cpp/core/GainNode.cpp +30 -0
- package/common/cpp/core/GainNode.h +23 -0
- package/common/cpp/core/OscillatorNode.cpp +66 -0
- package/common/cpp/core/OscillatorNode.h +112 -0
- package/common/cpp/core/ParamChange.cpp +46 -0
- package/common/cpp/core/ParamChange.h +34 -0
- package/common/cpp/core/StereoPannerNode.cpp +58 -0
- package/common/cpp/core/StereoPannerNode.h +26 -0
- package/common/cpp/utils/VectorMath.cpp +609 -0
- package/common/cpp/utils/VectorMath.h +65 -0
- package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.cpp +35 -0
- package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.h +25 -0
- package/common/cpp/wrappers/AudioBufferWrapper.cpp +46 -0
- package/common/cpp/wrappers/AudioBufferWrapper.h +30 -0
- package/common/cpp/wrappers/AudioContextWrapper.cpp +70 -0
- package/common/cpp/wrappers/AudioContextWrapper.h +40 -0
- package/common/cpp/wrappers/AudioDestinationNodeWrapper.h +16 -0
- package/common/cpp/wrappers/AudioNodeWrapper.cpp +37 -0
- package/common/cpp/wrappers/AudioNodeWrapper.h +25 -0
- package/common/cpp/wrappers/AudioParamWrapper.cpp +42 -0
- package/common/cpp/wrappers/AudioParamWrapper.h +25 -0
- package/common/cpp/wrappers/AudioScheduledSourceNodeWrapper.cpp +23 -0
- package/common/cpp/wrappers/AudioScheduledSourceNodeWrapper.h +23 -0
- package/common/cpp/wrappers/BiquadFilterNodeWrapper.cpp +51 -0
- package/common/cpp/wrappers/BiquadFilterNodeWrapper.h +32 -0
- package/common/cpp/wrappers/GainNodeWrapper.cpp +14 -0
- package/common/cpp/wrappers/GainNodeWrapper.h +20 -0
- package/common/cpp/wrappers/OscillatorNodeWrapper.cpp +38 -0
- package/common/cpp/wrappers/OscillatorNodeWrapper.h +28 -0
- package/common/cpp/wrappers/StereoPannerNodeWrapper.cpp +16 -0
- package/common/cpp/wrappers/StereoPannerNodeWrapper.h +21 -0
- package/ios/AudioAPIModule.h +5 -0
- package/ios/AudioAPIModule.mm +44 -0
- package/ios/AudioPlayer/AudioPlayer.h +27 -0
- package/ios/AudioPlayer/AudioPlayer.m +121 -0
- package/ios/AudioPlayer/IOSAudioPlayer.h +29 -0
- package/ios/AudioPlayer/IOSAudioPlayer.mm +34 -0
- package/lib/module/index.js +39 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/modules/global.d.js +2 -0
- package/lib/module/modules/global.d.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/install.js +22 -0
- package/lib/module/utils/install.js.map +1 -0
- package/lib/typescript/index.d.ts +18 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +76 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/lib/typescript/utils/install.d.ts +7 -0
- package/lib/typescript/utils/install.d.ts.map +1 -0
- package/package.json +104 -5
- package/src/index.ts +79 -0
- package/src/modules/global.d.ts +10 -0
- package/src/types.ts +108 -0
- package/src/utils/install.ts +39 -0
- package/index.ts +0 -1
package/README.md
CHANGED
|
@@ -1,3 +1,60 @@
|
|
|
1
|
+
<img src="./docs/assets/react-native-audio-api-gh-cover.png?v0.0.1" alt="React Native Audio API" width="100%">
|
|
2
|
+
|
|
3
|
+
### ⚠️ Pre-Alpha
|
|
4
|
+
|
|
5
|
+
This library is at a very early stage of development. There are known performance issues and the library is not yet suitable for real production applications. We will be publishing the first alpha version of the library in the upcoming days, stay tuned! 🎶
|
|
6
|
+
|
|
7
|
+
If you have questions about the library, our progress, plans or just want to say "hi!" you can reach us in our <a href="https://discord.swmansion.com" target="_blank" rel="noopener noreferrer">discord server</a>
|
|
8
|
+
|
|
1
9
|
### React Native Audio API
|
|
2
10
|
|
|
3
|
-
react-native-audio-api
|
|
11
|
+
`react-native-audio-api` provides system for controlling audio in React Native environment compatible with Web Audio API specification,
|
|
12
|
+
allowing developers to generate and modify audio in exact same way it is possible in browsers.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
1. Install `react-native-audio-api` library
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# using npm
|
|
20
|
+
npm install react-native-audio-api
|
|
21
|
+
|
|
22
|
+
# or using yarn
|
|
23
|
+
yarn add react-native-audio-api
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Documentation
|
|
27
|
+
|
|
28
|
+
`react-native-audio-api` tries to strictly follow the Web Audi API specification, which can be found at [https://www.w3.org/TR/webaudio/](https://www.w3.org/TR/webaudio/).
|
|
29
|
+
<br />
|
|
30
|
+
[MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API) is useful resource to get familiar with audio processing basics.
|
|
31
|
+
|
|
32
|
+
## Coverage
|
|
33
|
+
|
|
34
|
+
Our current coverage of Web Audio API specification can be found here: [Web Audio API coverage](./docs/web-audio-coverage.md).
|
|
35
|
+
|
|
36
|
+
## Examples
|
|
37
|
+
|
|
38
|
+
The source code for the example application is under the [`/apps/common-app`](./apps/common-app/) directory. If you want to play with the API but don't feel like trying it on a real app, you can run the example project. Check [Example README](./apps/common-example/README.md) for installation instructions.
|
|
39
|
+
|
|
40
|
+
## Your feedback
|
|
41
|
+
|
|
42
|
+
We are open to new ideas and general feedback. If you want to share your opinion about `react-native-audio-api` or have some thoughts about how it could be further developed, don't hesitate to create an issue or contact the maintainers directly.
|
|
43
|
+
|
|
44
|
+
## License
|
|
45
|
+
|
|
46
|
+
react-native-audio-api library is licensed under [The MIT License](./LICENSE). Some of the source code uses implementation directly copied from Webkit and copyrights are held by respective organizations, check [COPYING](./COPYING) file for further details
|
|
47
|
+
|
|
48
|
+
## Credits
|
|
49
|
+
|
|
50
|
+
This project has been built and is maintained thanks to the support from [Software Mansion](https://swmansion.com)
|
|
51
|
+
|
|
52
|
+
[](https://swmansion.com)
|
|
53
|
+
|
|
54
|
+
## Community Discord
|
|
55
|
+
|
|
56
|
+
<a href="https://discord.swmansion.com" target="_blank" rel="noopener noreferrer">Join the Software Mansion Community Discord</a> to chat about React Native Audio API or other Software Mansion libraries.
|
|
57
|
+
|
|
58
|
+
## react-native-audio-api is created by Software Mansion
|
|
59
|
+
|
|
60
|
+
Since 2012 [Software Mansion](https://swmansion.com) is a software agency with experience in building web and mobile apps. We are Core React Native Contributors and experts in dealing with all kinds of React Native issues. We can help you build your next dream product – [Hire us](https://swmansion.com/contact/projects?utm_source=reanimated&utm_medium=readme).
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
|
5
|
+
|
|
6
|
+
Pod::Spec.new do |s|
|
|
7
|
+
s.name = "RNAudioAPI"
|
|
8
|
+
s.version = package["version"]
|
|
9
|
+
s.summary = package["description"]
|
|
10
|
+
s.homepage = package["homepage"]
|
|
11
|
+
s.license = package["license"]
|
|
12
|
+
s.authors = package["author"]
|
|
13
|
+
|
|
14
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
15
|
+
s.source = { :git => "https://github.com/software-mansion-labs/react-native-audio-api.git", :tag => "#{s.version}" }
|
|
16
|
+
|
|
17
|
+
s.source_files = "ios/**/*.{h,m,mm}", "common/cpp/**/*.{hpp,cpp,c,h}"
|
|
18
|
+
|
|
19
|
+
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
|
20
|
+
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
|
|
21
|
+
if respond_to?(:install_modules_dependencies, true)
|
|
22
|
+
install_modules_dependencies(s)
|
|
23
|
+
else
|
|
24
|
+
s.dependency "React-Core"
|
|
25
|
+
|
|
26
|
+
# Don't install the dependencies when we run `pod install` in the old architecture.
|
|
27
|
+
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
|
28
|
+
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
29
|
+
s.pod_target_xcconfig = {
|
|
30
|
+
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
31
|
+
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
32
|
+
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
33
|
+
}
|
|
34
|
+
s.dependency "React-Codegen"
|
|
35
|
+
s.dependency "RCT-Folly"
|
|
36
|
+
s.dependency "RCTRequired"
|
|
37
|
+
s.dependency "RCTTypeSafety"
|
|
38
|
+
s.dependency "ReactCommon/turbomodule/core"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.9.0)
|
|
2
|
+
project(react-native-audio-api)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
5
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
6
|
+
|
|
7
|
+
# Detect the operating system
|
|
8
|
+
if(APPLE)
|
|
9
|
+
set(HAVE_ACCELERATE TRUE)
|
|
10
|
+
endif()
|
|
11
|
+
|
|
12
|
+
# Detect the processor and SIMD support
|
|
13
|
+
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
|
|
14
|
+
set(HAVE_ARM_NEON_INTRINSICS TRUE)
|
|
15
|
+
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64")
|
|
16
|
+
set(HAVE_X86_SSE2 TRUE)
|
|
17
|
+
endif()
|
|
18
|
+
|
|
19
|
+
include("${REACT_NATIVE_DIR}/ReactAndroid/cmake-utils/folly-flags.cmake")
|
|
20
|
+
add_compile_options(${folly_FLAGS})
|
|
21
|
+
|
|
22
|
+
file(GLOB_RECURSE SOURCE_FILES
|
|
23
|
+
"src/main/cpp/*.cpp"
|
|
24
|
+
"src/main/cpp/*.h"
|
|
25
|
+
"../common/cpp/*.cpp"
|
|
26
|
+
"../common/cpp/*.h"
|
|
27
|
+
"../common/cpp/core/*.cpp"
|
|
28
|
+
"../common/cpp/core/*.h"
|
|
29
|
+
"../common/cpp/wrappers/*.cpp"
|
|
30
|
+
"../common/cpp/wrappers/*.h"
|
|
31
|
+
"../common/cpp/HostObjects/*.cpp"
|
|
32
|
+
"../common/cpp/HostObjects/*.h"
|
|
33
|
+
"../common/cpp/utils/*.cpp"
|
|
34
|
+
"../common/cpp/utils/*.h"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
add_library(react-native-audio-api SHARED ${SOURCE_FILES})
|
|
38
|
+
|
|
39
|
+
file(GLOB DIRS CONFIGURE_DEPENDS "src/main/cpp/**" "../common/cpp/**")
|
|
40
|
+
|
|
41
|
+
target_include_directories(
|
|
42
|
+
react-native-audio-api
|
|
43
|
+
PRIVATE
|
|
44
|
+
${DIRS}
|
|
45
|
+
"${REACT_NATIVE_DIR}/ReactCommon/jsi"
|
|
46
|
+
"${REACT_NATIVE_DIR}/ReactAndroid/src/main/jni/react/jni"
|
|
47
|
+
"${REACT_NATIVE_DIR}/ReactAndroid/src/main/jni/third-party/folly"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
find_package(ReactAndroid REQUIRED CONFIG)
|
|
51
|
+
find_package(fbjni REQUIRED CONFIG)
|
|
52
|
+
find_package (oboe REQUIRED CONFIG)
|
|
53
|
+
|
|
54
|
+
set(LINK_LIBRARIES
|
|
55
|
+
ReactAndroid::reactnative
|
|
56
|
+
ReactAndroid::jsi
|
|
57
|
+
fbjni::fbjni
|
|
58
|
+
android
|
|
59
|
+
log
|
|
60
|
+
oboe::oboe
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
target_link_libraries(react-native-audio-api ${LINK_LIBRARIES})
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import com.android.Version
|
|
2
|
+
import org.apache.tools.ant.taskdefs.condition.Os
|
|
3
|
+
|
|
4
|
+
buildscript {
|
|
5
|
+
repositories {
|
|
6
|
+
google()
|
|
7
|
+
mavenCentral()
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
dependencies {
|
|
11
|
+
classpath "com.android.tools.build:gradle:7.2.2"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
def reactNativeArchitectures() {
|
|
16
|
+
def value = rootProject.getProperties().get("reactNativeArchitectures")
|
|
17
|
+
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
def isNewArchitectureEnabled() {
|
|
21
|
+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
apply plugin: "com.android.library"
|
|
25
|
+
apply plugin: 'org.jetbrains.kotlin.android'
|
|
26
|
+
|
|
27
|
+
if (isNewArchitectureEnabled()) {
|
|
28
|
+
apply plugin: "com.facebook.react"
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
def getExtOrDefault(name) {
|
|
32
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["AudioAPI_" + name]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
def getExtOrIntegerDefault(name) {
|
|
36
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["AudioAPI_" + name]).toInteger()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
def resolveBuildType() {
|
|
40
|
+
Gradle gradle = getGradle()
|
|
41
|
+
String tskReqStr = gradle.getStartParameter().getTaskRequests()['args'].toString()
|
|
42
|
+
return tskReqStr.contains('Release') ? 'release' : 'debug'
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
def safeAppExtGet(prop, fallback) {
|
|
46
|
+
def appProject = rootProject.allprojects.find { it.plugins.hasPlugin('com.android.application') }
|
|
47
|
+
appProject?.ext?.has(prop) ? appProject.ext.get(prop) : fallback
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
def resolveReactNativeDirectory() {
|
|
51
|
+
def reactNativeLocation = safeAppExtGet("REACT_NATIVE_NODE_MODULES_DIR", null)
|
|
52
|
+
|
|
53
|
+
if (reactNativeLocation !== null) {
|
|
54
|
+
return file(reactNativeLocation)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Fallback to node resolver for custom directory structures like monorepos.
|
|
58
|
+
def reactNativePackage = file(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim())
|
|
59
|
+
if(reactNativePackage.exists()) {
|
|
60
|
+
return reactNativePackage.parentFile
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
throw new GradleException(
|
|
64
|
+
"[AudioAPI] Unable to resolve react-native location in node_modules. You should project extension property (in `app/build.gradle`) `REACT_NATIVE_NODE_MODULES_DIR` with path to react-native."
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
def toPlatformFileString(String path) {
|
|
69
|
+
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
|
70
|
+
path = path.replace(File.separatorChar, '/' as char)
|
|
71
|
+
}
|
|
72
|
+
return path
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
def reactNativeRootDir = resolveReactNativeDirectory()
|
|
76
|
+
|
|
77
|
+
static def supportsNamespace() {
|
|
78
|
+
def parsed = Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
|
|
79
|
+
def major = parsed[0].toInteger()
|
|
80
|
+
def minor = parsed[1].toInteger()
|
|
81
|
+
|
|
82
|
+
// Namespace support was added in 7.3.0
|
|
83
|
+
return (major == 7 && minor >= 3) || major >= 8
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
android {
|
|
87
|
+
if (supportsNamespace()) {
|
|
88
|
+
namespace "com.swmansion.audioapi"
|
|
89
|
+
|
|
90
|
+
sourceSets {
|
|
91
|
+
main {
|
|
92
|
+
manifest.srcFile "src/main/AndroidManifestNew.xml"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
ndkVersion getExtOrDefault("ndkVersion")
|
|
98
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
99
|
+
|
|
100
|
+
defaultConfig {
|
|
101
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
102
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
103
|
+
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
104
|
+
|
|
105
|
+
externalNativeBuild {
|
|
106
|
+
cmake {
|
|
107
|
+
cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all"
|
|
108
|
+
abiFilters (*reactNativeArchitectures())
|
|
109
|
+
arguments "-DANDROID_STL=c++_shared",
|
|
110
|
+
"-DREACT_NATIVE_DIR=${toPlatformFileString(reactNativeRootDir.path)}"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
packagingOptions {
|
|
116
|
+
excludes = ["**/libc++_shared.so", "**/libfbjni.so", "**/libjsi.so", "**/libreactnativejni.so", "**/libfolly_json.so", "**/libreanimated.so", "**/libjscexecutor.so", "**/libhermes.so"]
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
externalNativeBuild {
|
|
120
|
+
cmake {
|
|
121
|
+
path "CMakeLists.txt"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
buildFeatures {
|
|
126
|
+
buildConfig true
|
|
127
|
+
prefab true
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
buildTypes {
|
|
131
|
+
release {
|
|
132
|
+
minifyEnabled false
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
lintOptions {
|
|
137
|
+
disable "GradleCompatible"
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
compileOptions {
|
|
141
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
142
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
143
|
+
|
|
144
|
+
packagingOptions {
|
|
145
|
+
doNotStrip resolveBuildType() == 'debug' ? "**/**/*.so" : ''
|
|
146
|
+
|
|
147
|
+
excludes = [
|
|
148
|
+
"**/libjsi.so",
|
|
149
|
+
"**/libfolly_runtime.so",
|
|
150
|
+
"**/libreactnativejni.so",
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
sourceSets {
|
|
156
|
+
main {
|
|
157
|
+
if (isNewArchitectureEnabled()) {
|
|
158
|
+
java.srcDirs += [
|
|
159
|
+
// This is needed to build Kotlin project with NewArch enabled
|
|
160
|
+
"${project.buildDir}/generated/source/codegen/java"
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
kotlinOptions {
|
|
166
|
+
jvmTarget = '17'
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
repositories {
|
|
171
|
+
mavenCentral()
|
|
172
|
+
google()
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
dependencies {
|
|
177
|
+
// For < 0.71, this will be from the local maven repo
|
|
178
|
+
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
|
179
|
+
//noinspection GradleDynamicVersion
|
|
180
|
+
implementation "com.facebook.react:react-native:+"
|
|
181
|
+
implementation 'androidx.core:core-ktx:1.13.1'
|
|
182
|
+
implementation 'com.facebook.fbjni:fbjni:0.6.0'
|
|
183
|
+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2"
|
|
184
|
+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2"
|
|
185
|
+
implementation 'com.google.oboe:oboe:1.9.0'
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (isNewArchitectureEnabled()) {
|
|
189
|
+
react {
|
|
190
|
+
jsRootDir = file("../src/")
|
|
191
|
+
libraryName = "react-native-audio-api"
|
|
192
|
+
codegenJavaPackageName = "com.swmansion.audioapi"
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#include "AudioAPIInstaller.h"
|
|
2
|
+
|
|
3
|
+
namespace audioapi {
|
|
4
|
+
|
|
5
|
+
using namespace facebook::jni;
|
|
6
|
+
|
|
7
|
+
AudioAPIInstaller::AudioAPIInstaller(
|
|
8
|
+
jni::alias_ref<AudioAPIInstaller::jhybridobject> &jThis)
|
|
9
|
+
: javaPart_(make_global(jThis)) {}
|
|
10
|
+
|
|
11
|
+
void AudioAPIInstaller::install(jlong jsContext) {
|
|
12
|
+
auto audioAPIInstallerWrapper =
|
|
13
|
+
std::make_shared<AudioAPIInstallerWrapper>(this);
|
|
14
|
+
AudioAPIInstallerHostObject::createAndInstallFromWrapper(
|
|
15
|
+
audioAPIInstallerWrapper, jsContext);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
std::shared_ptr<AudioContext> AudioAPIInstaller::createAudioContext() {
|
|
19
|
+
return std::make_shared<AudioContext>();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <fbjni/fbjni.h>
|
|
4
|
+
#include <jsi/jsi.h>
|
|
5
|
+
#include <react/jni/CxxModuleWrapper.h>
|
|
6
|
+
#include <react/jni/JMessageQueueThread.h>
|
|
7
|
+
#include <memory>
|
|
8
|
+
#include <utility>
|
|
9
|
+
|
|
10
|
+
#include "AudioAPIInstallerHostObject.h"
|
|
11
|
+
#include "AudioAPIInstallerWrapper.h"
|
|
12
|
+
#include "AudioContext.h"
|
|
13
|
+
|
|
14
|
+
namespace audioapi {
|
|
15
|
+
|
|
16
|
+
using namespace facebook;
|
|
17
|
+
using namespace facebook::jni;
|
|
18
|
+
|
|
19
|
+
class AudioAPIInstaller : public jni::HybridClass<AudioAPIInstaller> {
|
|
20
|
+
public:
|
|
21
|
+
static auto constexpr kJavaDescriptor =
|
|
22
|
+
"Lcom/swmansion/audioapi/module/AudioAPIInstaller;";
|
|
23
|
+
|
|
24
|
+
static jni::local_ref<AudioAPIInstaller::jhybriddata> initHybrid(
|
|
25
|
+
jni::alias_ref<jhybridobject> jThis) {
|
|
26
|
+
return makeCxxInstance(jThis);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static void registerNatives() {
|
|
30
|
+
registerHybrid({
|
|
31
|
+
makeNativeMethod("initHybrid", AudioAPIInstaller::initHybrid),
|
|
32
|
+
makeNativeMethod("install", AudioAPIInstaller::install),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
std::shared_ptr<AudioContext> createAudioContext();
|
|
37
|
+
void install(jlong jsContext);
|
|
38
|
+
|
|
39
|
+
private:
|
|
40
|
+
friend HybridBase;
|
|
41
|
+
|
|
42
|
+
global_ref<AudioAPIInstaller::javaobject> javaPart_;
|
|
43
|
+
|
|
44
|
+
explicit AudioAPIInstaller(
|
|
45
|
+
jni::alias_ref<AudioAPIInstaller::jhybridobject> &jThis);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#include "AudioPlayer.h"
|
|
2
|
+
#include "AudioContext.h"
|
|
3
|
+
|
|
4
|
+
namespace audioapi {
|
|
5
|
+
AudioPlayer::AudioPlayer(const std::function<void(float *, int)> &renderAudio)
|
|
6
|
+
: renderAudio_(renderAudio) {
|
|
7
|
+
AudioStreamBuilder builder;
|
|
8
|
+
builder.setSharingMode(SharingMode::Exclusive)
|
|
9
|
+
->setFormat(AudioFormat::Float)
|
|
10
|
+
->setFormatConversionAllowed(true)
|
|
11
|
+
->setPerformanceMode(PerformanceMode::LowLatency)
|
|
12
|
+
->setChannelCount(CHANNEL_COUNT)
|
|
13
|
+
->setSampleRateConversionQuality(SampleRateConversionQuality::Medium)
|
|
14
|
+
->setDataCallback(this)
|
|
15
|
+
->openStream(mStream_);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
int AudioPlayer::getSampleRate() const {
|
|
19
|
+
return mStream_->getSampleRate();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
void AudioPlayer::start() {
|
|
23
|
+
if (mStream_) {
|
|
24
|
+
mStream_->requestStart();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
void AudioPlayer::stop() {
|
|
29
|
+
if (mStream_) {
|
|
30
|
+
mStream_->requestStop();
|
|
31
|
+
mStream_->close();
|
|
32
|
+
mStream_.reset();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
DataCallbackResult AudioPlayer::onAudioReady(
|
|
37
|
+
AudioStream *oboeStream,
|
|
38
|
+
void *audioData,
|
|
39
|
+
int32_t numFrames) {
|
|
40
|
+
auto buffer = static_cast<float *>(audioData);
|
|
41
|
+
renderAudio_(buffer, numFrames);
|
|
42
|
+
|
|
43
|
+
return DataCallbackResult::Continue;
|
|
44
|
+
}
|
|
45
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <oboe/Oboe.h>
|
|
4
|
+
#include <memory>
|
|
5
|
+
|
|
6
|
+
namespace audioapi {
|
|
7
|
+
|
|
8
|
+
using namespace oboe;
|
|
9
|
+
|
|
10
|
+
class AudioContext;
|
|
11
|
+
|
|
12
|
+
class AudioPlayer : public AudioStreamDataCallback {
|
|
13
|
+
public:
|
|
14
|
+
explicit AudioPlayer(const std::function<void(float *, int)> &renderAudio);
|
|
15
|
+
|
|
16
|
+
int getSampleRate() const;
|
|
17
|
+
void start();
|
|
18
|
+
void stop();
|
|
19
|
+
|
|
20
|
+
DataCallbackResult onAudioReady(
|
|
21
|
+
AudioStream *oboeStream,
|
|
22
|
+
void *audioData,
|
|
23
|
+
int32_t numFrames) override;
|
|
24
|
+
|
|
25
|
+
private:
|
|
26
|
+
std::function<void(float *, int)> renderAudio_;
|
|
27
|
+
std::shared_ptr<AudioStream> mStream_;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
package com.swmansion.audioapi
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
import com.swmansion.audioapi.nativemodules.AudioAPIModule
|
|
8
|
+
|
|
9
|
+
class AudioAPIPackage : ReactPackage {
|
|
10
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> =
|
|
11
|
+
listOf<NativeModule>(AudioAPIModule(reactContext))
|
|
12
|
+
|
|
13
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> = emptyList()
|
|
14
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
package com.swmansion.audioapi.module
|
|
2
|
+
|
|
3
|
+
import com.facebook.jni.HybridData
|
|
4
|
+
|
|
5
|
+
class AudioAPIInstaller {
|
|
6
|
+
private val mHybridData: HybridData?
|
|
7
|
+
|
|
8
|
+
companion object {
|
|
9
|
+
init {
|
|
10
|
+
System.loadLibrary("react-native-audio-api")
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
init {
|
|
15
|
+
mHybridData = initHybrid()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
external fun initHybrid(): HybridData?
|
|
19
|
+
|
|
20
|
+
external fun install(jsContext: Long)
|
|
21
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
package com.swmansion.audioapi.nativemodules
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
5
|
+
import com.facebook.react.bridge.ReactMethod
|
|
6
|
+
import com.swmansion.audioapi.module.AudioAPIInstaller
|
|
7
|
+
|
|
8
|
+
class AudioAPIModule(
|
|
9
|
+
private val reactContext: ReactApplicationContext,
|
|
10
|
+
) : ReactContextBaseJavaModule(reactContext) {
|
|
11
|
+
override fun getName(): String = NAME
|
|
12
|
+
|
|
13
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
14
|
+
fun install(): Boolean {
|
|
15
|
+
val audioAPIInstaller = AudioAPIInstaller()
|
|
16
|
+
val jsContext = reactContext.javaScriptContextHolder!!.get()
|
|
17
|
+
audioAPIInstaller.install(jsContext)
|
|
18
|
+
|
|
19
|
+
return true
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
companion object {
|
|
23
|
+
const val NAME: String = "AudioAPIModule"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#include "AudioAPIInstallerHostObject.h"
|
|
2
|
+
|
|
3
|
+
namespace audioapi {
|
|
4
|
+
using namespace facebook;
|
|
5
|
+
|
|
6
|
+
AudioAPIInstallerHostObject::AudioAPIInstallerHostObject(
|
|
7
|
+
const std::shared_ptr<AudioAPIInstallerWrapper> &wrapper)
|
|
8
|
+
: wrapper_(wrapper) {}
|
|
9
|
+
|
|
10
|
+
std::vector<jsi::PropNameID> AudioAPIInstallerHostObject::getPropertyNames(
|
|
11
|
+
jsi::Runtime &runtime) {
|
|
12
|
+
std::vector<jsi::PropNameID> propertyNames;
|
|
13
|
+
propertyNames.push_back(
|
|
14
|
+
jsi::PropNameID::forUtf8(runtime, "createAudioContext"));
|
|
15
|
+
return propertyNames;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
jsi::Value AudioAPIInstallerHostObject::get(
|
|
19
|
+
jsi::Runtime &runtime,
|
|
20
|
+
const jsi::PropNameID &propNameId) {
|
|
21
|
+
auto propName = propNameId.utf8(runtime);
|
|
22
|
+
|
|
23
|
+
if (propName == "createAudioContext") {
|
|
24
|
+
return jsi::Function::createFromHostFunction(
|
|
25
|
+
runtime,
|
|
26
|
+
propNameId,
|
|
27
|
+
0,
|
|
28
|
+
[this](
|
|
29
|
+
jsi::Runtime &runtime,
|
|
30
|
+
const jsi::Value &thisValue,
|
|
31
|
+
const jsi::Value *arguments,
|
|
32
|
+
size_t count) -> jsi::Value {
|
|
33
|
+
auto audioContext = wrapper_->createAudioContext();
|
|
34
|
+
auto audioContextHostObject =
|
|
35
|
+
AudioContextHostObject::createFromWrapper(audioContext);
|
|
36
|
+
return jsi::Object::createFromHostObject(
|
|
37
|
+
runtime, audioContextHostObject);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
throw std::runtime_error("Not yet implemented!");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
void AudioAPIInstallerHostObject::set(
|
|
45
|
+
jsi::Runtime &runtime,
|
|
46
|
+
const jsi::PropNameID &propNameId,
|
|
47
|
+
const jsi::Value &value) {
|
|
48
|
+
auto propName = propNameId.utf8(runtime);
|
|
49
|
+
|
|
50
|
+
throw std::runtime_error("Not yet implemented!");
|
|
51
|
+
}
|
|
52
|
+
} // namespace audioapi
|