react-native-tuner-engine 1.0.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/LICENSE +20 -0
- package/README.md +188 -0
- package/TunerEngine.podspec +32 -0
- package/android/build.gradle +86 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/cpp/CMakeLists.txt +31 -0
- package/android/src/main/cpp/OboeAudioSource.cpp +101 -0
- package/android/src/main/cpp/OboeAudioSource.h +41 -0
- package/android/src/main/cpp/TunerEngineJni.cpp +220 -0
- package/android/src/main/java/com/tunerengine/TunerEngineModule.kt +183 -0
- package/android/src/main/java/com/tunerengine/TunerEnginePackage.kt +31 -0
- package/cpp/CMakeLists.txt +25 -0
- package/cpp/build/CMakeCache.txt +347 -0
- package/cpp/build/CMakeFiles/4.3.2/CMakeCXXCompiler.cmake +102 -0
- package/cpp/build/CMakeFiles/4.3.2/CMakeDetermineCompilerABI_CXX.bin +0 -0
- package/cpp/build/CMakeFiles/4.3.2/CMakeSystem.cmake +15 -0
- package/cpp/build/CMakeFiles/4.3.2/CompilerIdCXX/CMakeCXXCompilerId.cpp +949 -0
- package/cpp/build/CMakeFiles/4.3.2/CompilerIdCXX/a.out +0 -0
- package/cpp/build/CMakeFiles/4.3.2/CompilerIdCXX/apple-sdk.cpp +1 -0
- package/cpp/build/CMakeFiles/CMakeConfigureLog.yaml +1619 -0
- package/cpp/build/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
- package/cpp/build/CMakeFiles/InstallScripts.json +7 -0
- package/cpp/build/CMakeFiles/Makefile.cmake +118 -0
- package/cpp/build/CMakeFiles/Makefile2 +122 -0
- package/cpp/build/CMakeFiles/TargetDirectories.txt +3 -0
- package/cpp/build/CMakeFiles/cmake.check_cache +1 -0
- package/cpp/build/CMakeFiles/progress.marks +1 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/DependInfo.cmake +36 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/build.make +322 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/cmake_clean.cmake +37 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/cmake_clean_target.cmake +3 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/compiler_depend.make +2 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/compiler_depend.ts +2 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/depend.make +2 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/flags.make +12 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/link.txt +2 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/progress.make +16 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/AudioFrameDispatcher.cpp.o +0 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/AudioFrameDispatcher.cpp.o.d +814 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/BiquadHpf.cpp.o +0 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/BiquadHpf.cpp.o.d +206 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/CepstrumPitchDetector.cpp.o +0 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/CepstrumPitchDetector.cpp.o.d +797 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/EnsembleSelector.cpp.o +0 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/EnsembleSelector.cpp.o.d +755 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/NoteMapper.cpp.o +0 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/NoteMapper.cpp.o.d +669 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/OnsetDetector.cpp.o +0 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/OnsetDetector.cpp.o.d +648 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/Pipeline.cpp.o +0 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/Pipeline.cpp.o.d +765 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/PostProcessor.cpp.o +0 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/PostProcessor.cpp.o.d +648 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/PyinPitchDetector.cpp.o +0 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/PyinPitchDetector.cpp.o.d +755 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/SnrEstimator.cpp.o +0 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/SnrEstimator.cpp.o.d +648 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/StringMatcher.cpp.o +0 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/StringMatcher.cpp.o.d +665 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/TunerEngine.cpp.o +0 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/TunerEngine.cpp.o.d +811 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/Window.cpp.o +0 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/Window.cpp.o.d +754 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/YinPitchDetector.cpp.o +0 -0
- package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/YinPitchDetector.cpp.o.d +755 -0
- package/cpp/build/Makefile +532 -0
- package/cpp/build/cmake_install.cmake +61 -0
- package/cpp/build/libtuner_engine_core.a +0 -0
- package/cpp/include/AudioFrameDispatcher.hpp +87 -0
- package/cpp/include/BiquadHpf.hpp +22 -0
- package/cpp/include/CepstrumPitchDetector.hpp +33 -0
- package/cpp/include/EnsembleSelector.hpp +25 -0
- package/cpp/include/Fft.hpp +44 -0
- package/cpp/include/IPitchDetector.hpp +21 -0
- package/cpp/include/InstrumentPresets.hpp +33 -0
- package/cpp/include/NoteMapper.hpp +15 -0
- package/cpp/include/OnsetDetector.hpp +37 -0
- package/cpp/include/Pipeline.hpp +55 -0
- package/cpp/include/PitchResult.hpp +24 -0
- package/cpp/include/PostProcessor.hpp +51 -0
- package/cpp/include/PyinPitchDetector.hpp +35 -0
- package/cpp/include/RingBuffer.hpp +72 -0
- package/cpp/include/SnrEstimator.hpp +21 -0
- package/cpp/include/StringMatcher.hpp +27 -0
- package/cpp/include/TunerEngine.hpp +32 -0
- package/cpp/include/TuningPresets.hpp +103 -0
- package/cpp/include/Window.hpp +13 -0
- package/cpp/include/YinPitchDetector.hpp +37 -0
- package/cpp/src/AudioFrameDispatcher.cpp +180 -0
- package/cpp/src/BiquadHpf.cpp +35 -0
- package/cpp/src/CepstrumPitchDetector.cpp +116 -0
- package/cpp/src/EnsembleSelector.cpp +91 -0
- package/cpp/src/NoteMapper.cpp +47 -0
- package/cpp/src/OnsetDetector.cpp +39 -0
- package/cpp/src/Pipeline.cpp +133 -0
- package/cpp/src/PostProcessor.cpp +111 -0
- package/cpp/src/PyinPitchDetector.cpp +134 -0
- package/cpp/src/SnrEstimator.cpp +33 -0
- package/cpp/src/StringMatcher.cpp +37 -0
- package/cpp/src/TunerEngine.cpp +67 -0
- package/cpp/src/Window.cpp +21 -0
- package/cpp/src/YinPitchDetector.cpp +118 -0
- package/cpp/tests/CMakeLists.txt +23 -0
- package/cpp/tests/bench.cpp +160 -0
- package/cpp/tests/build/CMakeCache.txt +356 -0
- package/cpp/tests/build/CMakeFiles/4.3.2/CMakeCXXCompiler.cmake +102 -0
- package/cpp/tests/build/CMakeFiles/4.3.2/CMakeDetermineCompilerABI_CXX.bin +0 -0
- package/cpp/tests/build/CMakeFiles/4.3.2/CMakeSystem.cmake +15 -0
- package/cpp/tests/build/CMakeFiles/4.3.2/CompilerIdCXX/CMakeCXXCompilerId.cpp +949 -0
- package/cpp/tests/build/CMakeFiles/4.3.2/CompilerIdCXX/a.out +0 -0
- package/cpp/tests/build/CMakeFiles/4.3.2/CompilerIdCXX/apple-sdk.cpp +1 -0
- package/cpp/tests/build/CMakeFiles/CMakeConfigureLog.yaml +1619 -0
- package/cpp/tests/build/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
- package/cpp/tests/build/CMakeFiles/InstallScripts.json +8 -0
- package/cpp/tests/build/CMakeFiles/Makefile.cmake +122 -0
- package/cpp/tests/build/CMakeFiles/Makefile2 +211 -0
- package/cpp/tests/build/CMakeFiles/TargetDirectories.txt +9 -0
- package/cpp/tests/build/CMakeFiles/cmake.check_cache +1 -0
- package/cpp/tests/build/CMakeFiles/progress.marks +1 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/DependInfo.cmake +23 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/bench.cpp.o +0 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/bench.cpp.o.d +813 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/build.make +114 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/cmake_clean.cmake +11 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/compiler_depend.make +2 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/compiler_depend.ts +2 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/depend.make +2 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/flags.make +12 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/link.txt +1 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/progress.make +3 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/DependInfo.cmake +23 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/build.make +114 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/cmake_clean.cmake +11 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/compiler_depend.make +2 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/compiler_depend.ts +2 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/depend.make +2 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/flags.make +12 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/link.txt +1 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/main.cpp.o +0 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/main.cpp.o.d +823 -0
- package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/progress.make +3 -0
- package/cpp/tests/build/CTestTestfile.cmake +9 -0
- package/cpp/tests/build/Makefile +247 -0
- package/cpp/tests/build/cmake_install.cmake +66 -0
- package/cpp/tests/build/tuner_engine_bench +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/progress.marks +1 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/DependInfo.cmake +36 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/build.make +322 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/cmake_clean.cmake +37 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/cmake_clean_target.cmake +3 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/compiler_depend.make +2 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/compiler_depend.ts +2 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/depend.make +2 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/flags.make +12 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/link.txt +2 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/progress.make +16 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/AudioFrameDispatcher.cpp.o +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/AudioFrameDispatcher.cpp.o.d +814 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/BiquadHpf.cpp.o +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/BiquadHpf.cpp.o.d +206 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/CepstrumPitchDetector.cpp.o +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/CepstrumPitchDetector.cpp.o.d +797 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/EnsembleSelector.cpp.o +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/EnsembleSelector.cpp.o.d +755 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/NoteMapper.cpp.o +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/NoteMapper.cpp.o.d +669 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/OnsetDetector.cpp.o +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/OnsetDetector.cpp.o.d +648 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/Pipeline.cpp.o +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/Pipeline.cpp.o.d +765 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/PostProcessor.cpp.o +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/PostProcessor.cpp.o.d +648 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/PyinPitchDetector.cpp.o +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/PyinPitchDetector.cpp.o.d +755 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/SnrEstimator.cpp.o +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/SnrEstimator.cpp.o.d +648 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/StringMatcher.cpp.o +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/StringMatcher.cpp.o.d +665 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/TunerEngine.cpp.o +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/TunerEngine.cpp.o.d +811 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/Window.cpp.o +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/Window.cpp.o.d +754 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/YinPitchDetector.cpp.o +0 -0
- package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/YinPitchDetector.cpp.o.d +755 -0
- package/cpp/tests/build/tuner_engine_core/Makefile +544 -0
- package/cpp/tests/build/tuner_engine_core/cmake_install.cmake +45 -0
- package/cpp/tests/build/tuner_engine_core/libtuner_engine_core.a +0 -0
- package/cpp/tests/build/tuner_engine_tests +0 -0
- package/cpp/tests/main.cpp +624 -0
- package/ios/IosAudioSource.h +23 -0
- package/ios/IosAudioSource.mm +174 -0
- package/ios/TunerBridge.h +24 -0
- package/ios/TunerBridge.mm +136 -0
- package/ios/TunerEngine.h +6 -0
- package/ios/TunerEngine.mm +144 -0
- package/lib/module/NativeTunerEngine.js +5 -0
- package/lib/module/NativeTunerEngine.js.map +1 -0
- package/lib/module/TunerEngine.js +43 -0
- package/lib/module/TunerEngine.js.map +1 -0
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/useTuner.js +55 -0
- package/lib/module/useTuner.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeTunerEngine.d.ts +17 -0
- package/lib/typescript/src/NativeTunerEngine.d.ts.map +1 -0
- package/lib/typescript/src/TunerEngine.d.ts +18 -0
- package/lib/typescript/src/TunerEngine.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +86 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/useTuner.d.ts +15 -0
- package/lib/typescript/src/useTuner.d.ts.map +1 -0
- package/package.json +141 -0
- package/src/NativeTunerEngine.ts +17 -0
- package/src/TunerEngine.ts +62 -0
- package/src/index.tsx +11 -0
- package/src/types.ts +109 -0
- package/src/useTuner.ts +67 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
#include <jni.h>
|
|
2
|
+
#include <android/log.h>
|
|
3
|
+
#include <memory>
|
|
4
|
+
#include <string>
|
|
5
|
+
#include "AudioFrameDispatcher.hpp"
|
|
6
|
+
#include "OboeAudioSource.h"
|
|
7
|
+
#include "OnsetDetector.hpp"
|
|
8
|
+
#include "PostProcessor.hpp"
|
|
9
|
+
|
|
10
|
+
#define LOG_TAG "TunerEngineJni"
|
|
11
|
+
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
|
|
12
|
+
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
|
|
13
|
+
|
|
14
|
+
// Globals — one engine per process (single-instance module assumption)
|
|
15
|
+
static std::unique_ptr<AudioFrameDispatcher> gDispatcher;
|
|
16
|
+
static std::shared_ptr<OboeAudioSource> gAudioSource;
|
|
17
|
+
|
|
18
|
+
// JNI back-reference for pitch callbacks
|
|
19
|
+
static JavaVM* gJvm = nullptr;
|
|
20
|
+
static jobject gModuleRef = nullptr; // strong global ref to TunerEngineModule kotlin object
|
|
21
|
+
static jmethodID gOnPitchMethod = nullptr;
|
|
22
|
+
|
|
23
|
+
// Called from C++ worker thread; marshals PitchResult → Java
|
|
24
|
+
static void onPitchResult(const PitchResult& r) {
|
|
25
|
+
if (!gJvm || !gModuleRef || !gOnPitchMethod) return;
|
|
26
|
+
|
|
27
|
+
JNIEnv* env = nullptr;
|
|
28
|
+
bool didAttach = false;
|
|
29
|
+
|
|
30
|
+
jint attachResult = gJvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
|
|
31
|
+
if (attachResult == JNI_EDETACHED) {
|
|
32
|
+
if (gJvm->AttachCurrentThread(&env, nullptr) == JNI_OK) {
|
|
33
|
+
didAttach = true;
|
|
34
|
+
} else {
|
|
35
|
+
LOGE("Failed to attach thread");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
} else if (attachResult != JNI_OK) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (gModuleRef) {
|
|
43
|
+
jstring noteName = env->NewStringUTF(r.noteName.c_str());
|
|
44
|
+
jstring nearestStr = env->NewStringUTF(r.nearestString.c_str());
|
|
45
|
+
env->CallVoidMethod(
|
|
46
|
+
gModuleRef,
|
|
47
|
+
gOnPitchMethod,
|
|
48
|
+
static_cast<jboolean>(r.hasPitch),
|
|
49
|
+
static_cast<jfloat>(r.frequency),
|
|
50
|
+
static_cast<jfloat>(r.confidence),
|
|
51
|
+
static_cast<jfloat>(r.rmsDb),
|
|
52
|
+
noteName,
|
|
53
|
+
static_cast<jint>(r.octave),
|
|
54
|
+
static_cast<jfloat>(r.cents),
|
|
55
|
+
nearestStr,
|
|
56
|
+
static_cast<jfloat>(r.stringDeviation)
|
|
57
|
+
);
|
|
58
|
+
env->DeleteLocalRef(noteName);
|
|
59
|
+
env->DeleteLocalRef(nearestStr);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (didAttach) {
|
|
63
|
+
gJvm->DetachCurrentThread();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
extern "C" {
|
|
68
|
+
|
|
69
|
+
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/) {
|
|
70
|
+
gJvm = vm;
|
|
71
|
+
return JNI_VERSION_1_6;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
JNIEXPORT void JNICALL
|
|
75
|
+
Java_com_tunerengine_TunerEngineModule_nativeInit(
|
|
76
|
+
JNIEnv* env, jobject thiz,
|
|
77
|
+
jfloat sampleRate, jint frameSize, jfloat overlapRatio
|
|
78
|
+
) {
|
|
79
|
+
// Store strong global ref to the Kotlin module object for callbacks
|
|
80
|
+
if (gModuleRef) env->DeleteGlobalRef(gModuleRef);
|
|
81
|
+
gModuleRef = env->NewGlobalRef(thiz);
|
|
82
|
+
|
|
83
|
+
// Cache the callback method ID
|
|
84
|
+
jclass cls = env->GetObjectClass(thiz);
|
|
85
|
+
gOnPitchMethod = env->GetMethodID(cls, "onPitchDetected",
|
|
86
|
+
"(ZFFFLjava/lang/String;IFLjava/lang/String;F)V");
|
|
87
|
+
|
|
88
|
+
gDispatcher = std::make_unique<AudioFrameDispatcher>(
|
|
89
|
+
static_cast<int>(frameSize),
|
|
90
|
+
static_cast<float>(sampleRate),
|
|
91
|
+
onPitchResult,
|
|
92
|
+
static_cast<float>(overlapRatio)
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
LOGI("nativeInit: sampleRate=%.0f frameSize=%d overlapRatio=%.2f", (float)sampleRate, (int)frameSize, (float)overlapRatio);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
JNIEXPORT jboolean JNICALL
|
|
99
|
+
Java_com_tunerengine_TunerEngineModule_nativeStart(
|
|
100
|
+
JNIEnv* env, jobject thiz
|
|
101
|
+
) {
|
|
102
|
+
if (!gDispatcher) {
|
|
103
|
+
Java_com_tunerengine_TunerEngineModule_nativeInit(env, thiz, 48000.0f, 2048, 0.0f);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
gAudioSource = std::make_shared<OboeAudioSource>(
|
|
107
|
+
[](const float* samples, int count, float /*sr*/) {
|
|
108
|
+
if (gDispatcher) gDispatcher->push(samples, count);
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
if (!gAudioSource->start()) {
|
|
113
|
+
LOGE("Failed to start Oboe stream");
|
|
114
|
+
gAudioSource.reset();
|
|
115
|
+
return JNI_FALSE;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Sync dispatcher to actual sample rate reported by Oboe
|
|
119
|
+
if (gDispatcher) {
|
|
120
|
+
gDispatcher->setSampleRate(gAudioSource->sampleRate());
|
|
121
|
+
gDispatcher->start();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
LOGI("Audio capture started");
|
|
125
|
+
return JNI_TRUE;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
JNIEXPORT void JNICALL
|
|
129
|
+
Java_com_tunerengine_TunerEngineModule_nativeStop(
|
|
130
|
+
JNIEnv* env, jobject /*thiz*/
|
|
131
|
+
) {
|
|
132
|
+
if (gDispatcher) gDispatcher->stop();
|
|
133
|
+
if (gAudioSource) {
|
|
134
|
+
gAudioSource->stop();
|
|
135
|
+
gAudioSource.reset();
|
|
136
|
+
}
|
|
137
|
+
// Release global ref to allow GC of the module object
|
|
138
|
+
if (gModuleRef) {
|
|
139
|
+
env->DeleteGlobalRef(gModuleRef);
|
|
140
|
+
gModuleRef = nullptr;
|
|
141
|
+
}
|
|
142
|
+
LOGI("Audio capture stopped");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
JNIEXPORT void JNICALL
|
|
146
|
+
Java_com_tunerengine_TunerEngineModule_nativeConfigure(
|
|
147
|
+
JNIEnv* env, jobject thiz,
|
|
148
|
+
jfloat sampleRate, jint frameSize,
|
|
149
|
+
jfloat noiseGateDb, jfloat confidenceThreshold,
|
|
150
|
+
jfloat minFrequency, jfloat maxFrequency,
|
|
151
|
+
jfloat a4, jfloat overlapRatio
|
|
152
|
+
) {
|
|
153
|
+
Java_com_tunerengine_TunerEngineModule_nativeInit(env, thiz, sampleRate, frameSize, overlapRatio);
|
|
154
|
+
if (gDispatcher) {
|
|
155
|
+
gDispatcher->setNoiseGateDb(noiseGateDb);
|
|
156
|
+
gDispatcher->setConfidenceThreshold(confidenceThreshold);
|
|
157
|
+
gDispatcher->setFrequencyRange(minFrequency, maxFrequency);
|
|
158
|
+
gDispatcher->setA4(a4);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
JNIEXPORT void JNICALL
|
|
163
|
+
Java_com_tunerengine_TunerEngineModule_nativeSetA4(
|
|
164
|
+
JNIEnv* /*env*/, jobject /*thiz*/, jfloat hz
|
|
165
|
+
) {
|
|
166
|
+
if (gDispatcher) gDispatcher->setA4(hz);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
JNIEXPORT void JNICALL
|
|
170
|
+
Java_com_tunerengine_TunerEngineModule_nativeSetHpfCutoff(
|
|
171
|
+
JNIEnv* /*env*/, jobject /*thiz*/, jfloat hz
|
|
172
|
+
) {
|
|
173
|
+
if (gDispatcher) gDispatcher->setHpfCutoff(static_cast<float>(hz));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
JNIEXPORT void JNICALL
|
|
177
|
+
Java_com_tunerengine_TunerEngineModule_nativeSetPostProcessorConfig(
|
|
178
|
+
JNIEnv* /*env*/, jobject /*thiz*/, jfloat emaAlpha, jint hysteresisFrames
|
|
179
|
+
) {
|
|
180
|
+
if (gDispatcher) {
|
|
181
|
+
PostProcessor::Config cfg;
|
|
182
|
+
cfg.emaAlpha = static_cast<float>(emaAlpha);
|
|
183
|
+
cfg.hysteresisFrames = static_cast<int>(hysteresisFrames);
|
|
184
|
+
gDispatcher->setPostProcessorConfig(cfg);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
JNIEXPORT void JNICALL
|
|
189
|
+
Java_com_tunerengine_TunerEngineModule_nativeSetInstrument(
|
|
190
|
+
JNIEnv* env, jobject /*thiz*/, jstring name
|
|
191
|
+
) {
|
|
192
|
+
const char* nameChars = env->GetStringUTFChars(name, nullptr);
|
|
193
|
+
if (gDispatcher && nameChars) gDispatcher->setInstrument(std::string(nameChars));
|
|
194
|
+
env->ReleaseStringUTFChars(name, nameChars);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
JNIEXPORT void JNICALL
|
|
198
|
+
Java_com_tunerengine_TunerEngineModule_nativeSetTuning(
|
|
199
|
+
JNIEnv* env, jobject /*thiz*/, jstring name
|
|
200
|
+
) {
|
|
201
|
+
const char* nameChars = env->GetStringUTFChars(name, nullptr);
|
|
202
|
+
if (gDispatcher && nameChars) gDispatcher->setTuning(std::string(nameChars));
|
|
203
|
+
env->ReleaseStringUTFChars(name, nameChars);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
JNIEXPORT jboolean JNICALL
|
|
207
|
+
Java_com_tunerengine_TunerEngineModule_nativeIsRunning(
|
|
208
|
+
JNIEnv* /*env*/, jobject /*thiz*/
|
|
209
|
+
) {
|
|
210
|
+
return static_cast<jboolean>(gAudioSource != nullptr);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
JNIEXPORT void JNICALL
|
|
214
|
+
Java_com_tunerengine_TunerEngineModule_nativeSetOnsetDetection(
|
|
215
|
+
JNIEnv* /*env*/, jobject /*thiz*/, jboolean enabled
|
|
216
|
+
) {
|
|
217
|
+
if (gDispatcher) gDispatcher->setOnsetDetectionEnabled(static_cast<bool>(enabled));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
} // extern "C"
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
package com.tunerengine
|
|
2
|
+
|
|
3
|
+
import android.Manifest
|
|
4
|
+
import android.content.pm.PackageManager
|
|
5
|
+
import androidx.core.app.ActivityCompat
|
|
6
|
+
import com.facebook.react.bridge.Arguments
|
|
7
|
+
import com.facebook.react.bridge.Promise
|
|
8
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
9
|
+
import com.facebook.react.bridge.ReadableMap
|
|
10
|
+
import com.facebook.react.bridge.WritableMap
|
|
11
|
+
import com.facebook.react.bridge.WritableNativeMap
|
|
12
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
13
|
+
import com.facebook.react.modules.core.PermissionAwareActivity
|
|
14
|
+
import com.facebook.react.modules.core.PermissionListener
|
|
15
|
+
|
|
16
|
+
class TunerEngineModule(reactContext: ReactApplicationContext) :
|
|
17
|
+
NativeTunerEngineSpec(reactContext) {
|
|
18
|
+
|
|
19
|
+
private var isRunning = false
|
|
20
|
+
|
|
21
|
+
override fun configure(opts: ReadableMap?, promise: Promise) {
|
|
22
|
+
val sampleRate = opts?.getDouble("sampleRate")?.toFloat() ?: 48000.0f
|
|
23
|
+
val frameSize = if (opts?.hasKey("frameSize") == true) opts.getInt("frameSize") else 2048
|
|
24
|
+
val noiseGateDb = opts?.getDouble("noiseGateDb")?.toFloat() ?: -55.0f
|
|
25
|
+
val confidenceThreshold = opts?.getDouble("confidenceThreshold")?.toFloat() ?: 0.75f
|
|
26
|
+
val minFrequency = opts?.getDouble("minFrequency")?.toFloat() ?: 60.0f
|
|
27
|
+
val maxFrequency = opts?.getDouble("maxFrequency")?.toFloat() ?: 1200.0f
|
|
28
|
+
val a4 = opts?.getDouble("a4")?.toFloat() ?: 440.0f
|
|
29
|
+
val overlapRatio = opts?.getDouble("overlapRatio")?.toFloat() ?: 0.0f
|
|
30
|
+
|
|
31
|
+
nativeConfigure(sampleRate, frameSize, noiseGateDb, confidenceThreshold, minFrequency, maxFrequency, a4, overlapRatio)
|
|
32
|
+
|
|
33
|
+
val hpfCutoffHz = opts?.getDouble("hpfCutoffHz")?.toFloat()
|
|
34
|
+
if (hpfCutoffHz != null) nativeSetHpfCutoff(hpfCutoffHz)
|
|
35
|
+
|
|
36
|
+
val emaAlpha = opts?.getDouble("emaAlpha")?.toFloat()
|
|
37
|
+
val hysteresisFrames = if (opts?.hasKey("hysteresisFrames") == true) opts.getInt("hysteresisFrames") else null
|
|
38
|
+
if (emaAlpha != null || hysteresisFrames != null) {
|
|
39
|
+
nativeSetPostProcessorConfig(emaAlpha ?: 0.35f, hysteresisFrames ?: 3)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (opts?.hasKey("onsetDetection") == true) {
|
|
43
|
+
nativeSetOnsetDetection(opts.getBoolean("onsetDetection"))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
promise.resolve(null)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
override fun start(promise: Promise) {
|
|
50
|
+
val started = nativeStart()
|
|
51
|
+
if (started) {
|
|
52
|
+
isRunning = true
|
|
53
|
+
promise.resolve(null)
|
|
54
|
+
} else {
|
|
55
|
+
promise.reject("START_ERROR", "Failed to start audio capture")
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
override fun stop(promise: Promise) {
|
|
60
|
+
nativeStop()
|
|
61
|
+
isRunning = false
|
|
62
|
+
promise.resolve(null)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
override fun setA4(hz: Double) {
|
|
66
|
+
nativeSetA4(hz.toFloat())
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
override fun setInstrument(name: String) {
|
|
70
|
+
nativeSetInstrument(name)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
override fun setTuning(name: String) {
|
|
74
|
+
nativeSetTuning(name)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
override fun setTemperament(name: String) {
|
|
78
|
+
// Temperament support added in M2
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
override fun requestPermission(promise: Promise) {
|
|
82
|
+
val activity = currentActivity
|
|
83
|
+
if (activity == null) {
|
|
84
|
+
promise.resolve(false)
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO)
|
|
89
|
+
== PackageManager.PERMISSION_GRANTED) {
|
|
90
|
+
promise.resolve(true)
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
val permissionAwareActivity = activity as? PermissionAwareActivity
|
|
95
|
+
if (permissionAwareActivity == null) {
|
|
96
|
+
promise.resolve(false)
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
permissionAwareActivity.requestPermissions(
|
|
101
|
+
arrayOf(Manifest.permission.RECORD_AUDIO),
|
|
102
|
+
REQUEST_PERMISSION_CODE,
|
|
103
|
+
PermissionListener { requestCode, _, grantResults ->
|
|
104
|
+
if (requestCode == REQUEST_PERMISSION_CODE) {
|
|
105
|
+
val granted = grantResults.isNotEmpty() &&
|
|
106
|
+
grantResults[0] == PackageManager.PERMISSION_GRANTED
|
|
107
|
+
promise.resolve(granted)
|
|
108
|
+
true
|
|
109
|
+
} else {
|
|
110
|
+
false
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
override fun getStatus(): WritableMap {
|
|
117
|
+
val map = WritableNativeMap()
|
|
118
|
+
map.putBoolean("isRunning", isRunning)
|
|
119
|
+
map.putBoolean("engineReady", nativeIsRunning())
|
|
120
|
+
return map
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
override fun addListener(eventName: String) {}
|
|
124
|
+
|
|
125
|
+
override fun removeListeners(count: Double) {}
|
|
126
|
+
|
|
127
|
+
// Called from the C++ worker thread via JNI
|
|
128
|
+
@Suppress("unused")
|
|
129
|
+
fun onPitchDetected(
|
|
130
|
+
hasPitch: Boolean,
|
|
131
|
+
frequency: Float,
|
|
132
|
+
confidence: Float,
|
|
133
|
+
rmsDb: Float,
|
|
134
|
+
noteName: String,
|
|
135
|
+
octave: Int,
|
|
136
|
+
cents: Float,
|
|
137
|
+
nearestString: String,
|
|
138
|
+
stringDeviation: Float
|
|
139
|
+
) {
|
|
140
|
+
val params = Arguments.createMap().apply {
|
|
141
|
+
putBoolean("hasPitch", hasPitch)
|
|
142
|
+
putDouble("frequency", frequency.toDouble())
|
|
143
|
+
putDouble("confidence", confidence.toDouble())
|
|
144
|
+
putDouble("rmsDb", rmsDb.toDouble())
|
|
145
|
+
putString("noteName", noteName)
|
|
146
|
+
putInt("octave", octave)
|
|
147
|
+
putDouble("cents", cents.toDouble())
|
|
148
|
+
putString("nearestString", nearestString)
|
|
149
|
+
putDouble("stringDeviation", stringDeviation.toDouble())
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
reactApplicationContext
|
|
153
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
154
|
+
.emit("onPitch", params)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// JNI methods
|
|
158
|
+
private external fun nativeInit(sampleRate: Float, frameSize: Int, overlapRatio: Float)
|
|
159
|
+
private external fun nativeStart(): Boolean
|
|
160
|
+
private external fun nativeStop()
|
|
161
|
+
private external fun nativeConfigure(
|
|
162
|
+
sampleRate: Float, frameSize: Int,
|
|
163
|
+
noiseGateDb: Float, confidenceThreshold: Float,
|
|
164
|
+
minFrequency: Float, maxFrequency: Float,
|
|
165
|
+
a4: Float, overlapRatio: Float
|
|
166
|
+
)
|
|
167
|
+
private external fun nativeSetA4(hz: Float)
|
|
168
|
+
private external fun nativeSetInstrument(name: String)
|
|
169
|
+
private external fun nativeSetTuning(name: String)
|
|
170
|
+
private external fun nativeSetHpfCutoff(hz: Float)
|
|
171
|
+
private external fun nativeSetPostProcessorConfig(emaAlpha: Float, hysteresisFrames: Int)
|
|
172
|
+
private external fun nativeSetOnsetDetection(enabled: Boolean)
|
|
173
|
+
private external fun nativeIsRunning(): Boolean
|
|
174
|
+
|
|
175
|
+
companion object {
|
|
176
|
+
const val NAME = NativeTunerEngineSpec.NAME
|
|
177
|
+
private const val REQUEST_PERMISSION_CODE = 1001
|
|
178
|
+
|
|
179
|
+
init {
|
|
180
|
+
System.loadLibrary("tunerengine")
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
package com.tunerengine
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.BaseReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
|
+
import java.util.HashMap
|
|
9
|
+
|
|
10
|
+
class TunerEnginePackage : BaseReactPackage() {
|
|
11
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
12
|
+
return if (name == TunerEngineModule.NAME) {
|
|
13
|
+
TunerEngineModule(reactContext)
|
|
14
|
+
} else {
|
|
15
|
+
null
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override fun getReactModuleInfoProvider() = ReactModuleInfoProvider {
|
|
20
|
+
mapOf(
|
|
21
|
+
TunerEngineModule.NAME to ReactModuleInfo(
|
|
22
|
+
name = TunerEngineModule.NAME,
|
|
23
|
+
className = TunerEngineModule.NAME,
|
|
24
|
+
canOverrideExistingModule = false,
|
|
25
|
+
needsEagerInit = false,
|
|
26
|
+
isCxxModule = false,
|
|
27
|
+
isTurboModule = true
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.20)
|
|
2
|
+
|
|
3
|
+
project(TunerEngineCore LANGUAGES CXX)
|
|
4
|
+
|
|
5
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
6
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
7
|
+
|
|
8
|
+
add_library(tuner_engine_core STATIC
|
|
9
|
+
src/NoteMapper.cpp
|
|
10
|
+
src/YinPitchDetector.cpp
|
|
11
|
+
src/Window.cpp
|
|
12
|
+
src/BiquadHpf.cpp
|
|
13
|
+
src/SnrEstimator.cpp
|
|
14
|
+
src/OnsetDetector.cpp
|
|
15
|
+
src/PostProcessor.cpp
|
|
16
|
+
src/Pipeline.cpp
|
|
17
|
+
src/TunerEngine.cpp
|
|
18
|
+
src/AudioFrameDispatcher.cpp
|
|
19
|
+
src/CepstrumPitchDetector.cpp
|
|
20
|
+
src/PyinPitchDetector.cpp
|
|
21
|
+
src/EnsembleSelector.cpp
|
|
22
|
+
src/StringMatcher.cpp
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
target_include_directories(tuner_engine_core PUBLIC include)
|