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.
Files changed (224) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +188 -0
  3. package/TunerEngine.podspec +32 -0
  4. package/android/build.gradle +86 -0
  5. package/android/src/main/AndroidManifest.xml +3 -0
  6. package/android/src/main/cpp/CMakeLists.txt +31 -0
  7. package/android/src/main/cpp/OboeAudioSource.cpp +101 -0
  8. package/android/src/main/cpp/OboeAudioSource.h +41 -0
  9. package/android/src/main/cpp/TunerEngineJni.cpp +220 -0
  10. package/android/src/main/java/com/tunerengine/TunerEngineModule.kt +183 -0
  11. package/android/src/main/java/com/tunerengine/TunerEnginePackage.kt +31 -0
  12. package/cpp/CMakeLists.txt +25 -0
  13. package/cpp/build/CMakeCache.txt +347 -0
  14. package/cpp/build/CMakeFiles/4.3.2/CMakeCXXCompiler.cmake +102 -0
  15. package/cpp/build/CMakeFiles/4.3.2/CMakeDetermineCompilerABI_CXX.bin +0 -0
  16. package/cpp/build/CMakeFiles/4.3.2/CMakeSystem.cmake +15 -0
  17. package/cpp/build/CMakeFiles/4.3.2/CompilerIdCXX/CMakeCXXCompilerId.cpp +949 -0
  18. package/cpp/build/CMakeFiles/4.3.2/CompilerIdCXX/a.out +0 -0
  19. package/cpp/build/CMakeFiles/4.3.2/CompilerIdCXX/apple-sdk.cpp +1 -0
  20. package/cpp/build/CMakeFiles/CMakeConfigureLog.yaml +1619 -0
  21. package/cpp/build/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
  22. package/cpp/build/CMakeFiles/InstallScripts.json +7 -0
  23. package/cpp/build/CMakeFiles/Makefile.cmake +118 -0
  24. package/cpp/build/CMakeFiles/Makefile2 +122 -0
  25. package/cpp/build/CMakeFiles/TargetDirectories.txt +3 -0
  26. package/cpp/build/CMakeFiles/cmake.check_cache +1 -0
  27. package/cpp/build/CMakeFiles/progress.marks +1 -0
  28. package/cpp/build/CMakeFiles/tuner_engine_core.dir/DependInfo.cmake +36 -0
  29. package/cpp/build/CMakeFiles/tuner_engine_core.dir/build.make +322 -0
  30. package/cpp/build/CMakeFiles/tuner_engine_core.dir/cmake_clean.cmake +37 -0
  31. package/cpp/build/CMakeFiles/tuner_engine_core.dir/cmake_clean_target.cmake +3 -0
  32. package/cpp/build/CMakeFiles/tuner_engine_core.dir/compiler_depend.make +2 -0
  33. package/cpp/build/CMakeFiles/tuner_engine_core.dir/compiler_depend.ts +2 -0
  34. package/cpp/build/CMakeFiles/tuner_engine_core.dir/depend.make +2 -0
  35. package/cpp/build/CMakeFiles/tuner_engine_core.dir/flags.make +12 -0
  36. package/cpp/build/CMakeFiles/tuner_engine_core.dir/link.txt +2 -0
  37. package/cpp/build/CMakeFiles/tuner_engine_core.dir/progress.make +16 -0
  38. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/AudioFrameDispatcher.cpp.o +0 -0
  39. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/AudioFrameDispatcher.cpp.o.d +814 -0
  40. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/BiquadHpf.cpp.o +0 -0
  41. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/BiquadHpf.cpp.o.d +206 -0
  42. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/CepstrumPitchDetector.cpp.o +0 -0
  43. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/CepstrumPitchDetector.cpp.o.d +797 -0
  44. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/EnsembleSelector.cpp.o +0 -0
  45. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/EnsembleSelector.cpp.o.d +755 -0
  46. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/NoteMapper.cpp.o +0 -0
  47. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/NoteMapper.cpp.o.d +669 -0
  48. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/OnsetDetector.cpp.o +0 -0
  49. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/OnsetDetector.cpp.o.d +648 -0
  50. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/Pipeline.cpp.o +0 -0
  51. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/Pipeline.cpp.o.d +765 -0
  52. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/PostProcessor.cpp.o +0 -0
  53. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/PostProcessor.cpp.o.d +648 -0
  54. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/PyinPitchDetector.cpp.o +0 -0
  55. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/PyinPitchDetector.cpp.o.d +755 -0
  56. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/SnrEstimator.cpp.o +0 -0
  57. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/SnrEstimator.cpp.o.d +648 -0
  58. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/StringMatcher.cpp.o +0 -0
  59. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/StringMatcher.cpp.o.d +665 -0
  60. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/TunerEngine.cpp.o +0 -0
  61. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/TunerEngine.cpp.o.d +811 -0
  62. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/Window.cpp.o +0 -0
  63. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/Window.cpp.o.d +754 -0
  64. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/YinPitchDetector.cpp.o +0 -0
  65. package/cpp/build/CMakeFiles/tuner_engine_core.dir/src/YinPitchDetector.cpp.o.d +755 -0
  66. package/cpp/build/Makefile +532 -0
  67. package/cpp/build/cmake_install.cmake +61 -0
  68. package/cpp/build/libtuner_engine_core.a +0 -0
  69. package/cpp/include/AudioFrameDispatcher.hpp +87 -0
  70. package/cpp/include/BiquadHpf.hpp +22 -0
  71. package/cpp/include/CepstrumPitchDetector.hpp +33 -0
  72. package/cpp/include/EnsembleSelector.hpp +25 -0
  73. package/cpp/include/Fft.hpp +44 -0
  74. package/cpp/include/IPitchDetector.hpp +21 -0
  75. package/cpp/include/InstrumentPresets.hpp +33 -0
  76. package/cpp/include/NoteMapper.hpp +15 -0
  77. package/cpp/include/OnsetDetector.hpp +37 -0
  78. package/cpp/include/Pipeline.hpp +55 -0
  79. package/cpp/include/PitchResult.hpp +24 -0
  80. package/cpp/include/PostProcessor.hpp +51 -0
  81. package/cpp/include/PyinPitchDetector.hpp +35 -0
  82. package/cpp/include/RingBuffer.hpp +72 -0
  83. package/cpp/include/SnrEstimator.hpp +21 -0
  84. package/cpp/include/StringMatcher.hpp +27 -0
  85. package/cpp/include/TunerEngine.hpp +32 -0
  86. package/cpp/include/TuningPresets.hpp +103 -0
  87. package/cpp/include/Window.hpp +13 -0
  88. package/cpp/include/YinPitchDetector.hpp +37 -0
  89. package/cpp/src/AudioFrameDispatcher.cpp +180 -0
  90. package/cpp/src/BiquadHpf.cpp +35 -0
  91. package/cpp/src/CepstrumPitchDetector.cpp +116 -0
  92. package/cpp/src/EnsembleSelector.cpp +91 -0
  93. package/cpp/src/NoteMapper.cpp +47 -0
  94. package/cpp/src/OnsetDetector.cpp +39 -0
  95. package/cpp/src/Pipeline.cpp +133 -0
  96. package/cpp/src/PostProcessor.cpp +111 -0
  97. package/cpp/src/PyinPitchDetector.cpp +134 -0
  98. package/cpp/src/SnrEstimator.cpp +33 -0
  99. package/cpp/src/StringMatcher.cpp +37 -0
  100. package/cpp/src/TunerEngine.cpp +67 -0
  101. package/cpp/src/Window.cpp +21 -0
  102. package/cpp/src/YinPitchDetector.cpp +118 -0
  103. package/cpp/tests/CMakeLists.txt +23 -0
  104. package/cpp/tests/bench.cpp +160 -0
  105. package/cpp/tests/build/CMakeCache.txt +356 -0
  106. package/cpp/tests/build/CMakeFiles/4.3.2/CMakeCXXCompiler.cmake +102 -0
  107. package/cpp/tests/build/CMakeFiles/4.3.2/CMakeDetermineCompilerABI_CXX.bin +0 -0
  108. package/cpp/tests/build/CMakeFiles/4.3.2/CMakeSystem.cmake +15 -0
  109. package/cpp/tests/build/CMakeFiles/4.3.2/CompilerIdCXX/CMakeCXXCompilerId.cpp +949 -0
  110. package/cpp/tests/build/CMakeFiles/4.3.2/CompilerIdCXX/a.out +0 -0
  111. package/cpp/tests/build/CMakeFiles/4.3.2/CompilerIdCXX/apple-sdk.cpp +1 -0
  112. package/cpp/tests/build/CMakeFiles/CMakeConfigureLog.yaml +1619 -0
  113. package/cpp/tests/build/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
  114. package/cpp/tests/build/CMakeFiles/InstallScripts.json +8 -0
  115. package/cpp/tests/build/CMakeFiles/Makefile.cmake +122 -0
  116. package/cpp/tests/build/CMakeFiles/Makefile2 +211 -0
  117. package/cpp/tests/build/CMakeFiles/TargetDirectories.txt +9 -0
  118. package/cpp/tests/build/CMakeFiles/cmake.check_cache +1 -0
  119. package/cpp/tests/build/CMakeFiles/progress.marks +1 -0
  120. package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/DependInfo.cmake +23 -0
  121. package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/bench.cpp.o +0 -0
  122. package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/bench.cpp.o.d +813 -0
  123. package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/build.make +114 -0
  124. package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/cmake_clean.cmake +11 -0
  125. package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/compiler_depend.make +2 -0
  126. package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/compiler_depend.ts +2 -0
  127. package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/depend.make +2 -0
  128. package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/flags.make +12 -0
  129. package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/link.txt +1 -0
  130. package/cpp/tests/build/CMakeFiles/tuner_engine_bench.dir/progress.make +3 -0
  131. package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/DependInfo.cmake +23 -0
  132. package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/build.make +114 -0
  133. package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/cmake_clean.cmake +11 -0
  134. package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/compiler_depend.make +2 -0
  135. package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/compiler_depend.ts +2 -0
  136. package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/depend.make +2 -0
  137. package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/flags.make +12 -0
  138. package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/link.txt +1 -0
  139. package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/main.cpp.o +0 -0
  140. package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/main.cpp.o.d +823 -0
  141. package/cpp/tests/build/CMakeFiles/tuner_engine_tests.dir/progress.make +3 -0
  142. package/cpp/tests/build/CTestTestfile.cmake +9 -0
  143. package/cpp/tests/build/Makefile +247 -0
  144. package/cpp/tests/build/cmake_install.cmake +66 -0
  145. package/cpp/tests/build/tuner_engine_bench +0 -0
  146. package/cpp/tests/build/tuner_engine_core/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
  147. package/cpp/tests/build/tuner_engine_core/CMakeFiles/progress.marks +1 -0
  148. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/DependInfo.cmake +36 -0
  149. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/build.make +322 -0
  150. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/cmake_clean.cmake +37 -0
  151. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/cmake_clean_target.cmake +3 -0
  152. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/compiler_depend.make +2 -0
  153. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/compiler_depend.ts +2 -0
  154. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/depend.make +2 -0
  155. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/flags.make +12 -0
  156. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/link.txt +2 -0
  157. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/progress.make +16 -0
  158. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/AudioFrameDispatcher.cpp.o +0 -0
  159. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/AudioFrameDispatcher.cpp.o.d +814 -0
  160. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/BiquadHpf.cpp.o +0 -0
  161. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/BiquadHpf.cpp.o.d +206 -0
  162. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/CepstrumPitchDetector.cpp.o +0 -0
  163. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/CepstrumPitchDetector.cpp.o.d +797 -0
  164. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/EnsembleSelector.cpp.o +0 -0
  165. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/EnsembleSelector.cpp.o.d +755 -0
  166. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/NoteMapper.cpp.o +0 -0
  167. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/NoteMapper.cpp.o.d +669 -0
  168. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/OnsetDetector.cpp.o +0 -0
  169. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/OnsetDetector.cpp.o.d +648 -0
  170. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/Pipeline.cpp.o +0 -0
  171. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/Pipeline.cpp.o.d +765 -0
  172. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/PostProcessor.cpp.o +0 -0
  173. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/PostProcessor.cpp.o.d +648 -0
  174. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/PyinPitchDetector.cpp.o +0 -0
  175. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/PyinPitchDetector.cpp.o.d +755 -0
  176. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/SnrEstimator.cpp.o +0 -0
  177. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/SnrEstimator.cpp.o.d +648 -0
  178. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/StringMatcher.cpp.o +0 -0
  179. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/StringMatcher.cpp.o.d +665 -0
  180. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/TunerEngine.cpp.o +0 -0
  181. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/TunerEngine.cpp.o.d +811 -0
  182. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/Window.cpp.o +0 -0
  183. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/Window.cpp.o.d +754 -0
  184. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/YinPitchDetector.cpp.o +0 -0
  185. package/cpp/tests/build/tuner_engine_core/CMakeFiles/tuner_engine_core.dir/src/YinPitchDetector.cpp.o.d +755 -0
  186. package/cpp/tests/build/tuner_engine_core/Makefile +544 -0
  187. package/cpp/tests/build/tuner_engine_core/cmake_install.cmake +45 -0
  188. package/cpp/tests/build/tuner_engine_core/libtuner_engine_core.a +0 -0
  189. package/cpp/tests/build/tuner_engine_tests +0 -0
  190. package/cpp/tests/main.cpp +624 -0
  191. package/ios/IosAudioSource.h +23 -0
  192. package/ios/IosAudioSource.mm +174 -0
  193. package/ios/TunerBridge.h +24 -0
  194. package/ios/TunerBridge.mm +136 -0
  195. package/ios/TunerEngine.h +6 -0
  196. package/ios/TunerEngine.mm +144 -0
  197. package/lib/module/NativeTunerEngine.js +5 -0
  198. package/lib/module/NativeTunerEngine.js.map +1 -0
  199. package/lib/module/TunerEngine.js +43 -0
  200. package/lib/module/TunerEngine.js.map +1 -0
  201. package/lib/module/index.js +5 -0
  202. package/lib/module/index.js.map +1 -0
  203. package/lib/module/package.json +1 -0
  204. package/lib/module/types.js +2 -0
  205. package/lib/module/types.js.map +1 -0
  206. package/lib/module/useTuner.js +55 -0
  207. package/lib/module/useTuner.js.map +1 -0
  208. package/lib/typescript/package.json +1 -0
  209. package/lib/typescript/src/NativeTunerEngine.d.ts +17 -0
  210. package/lib/typescript/src/NativeTunerEngine.d.ts.map +1 -0
  211. package/lib/typescript/src/TunerEngine.d.ts +18 -0
  212. package/lib/typescript/src/TunerEngine.d.ts.map +1 -0
  213. package/lib/typescript/src/index.d.ts +4 -0
  214. package/lib/typescript/src/index.d.ts.map +1 -0
  215. package/lib/typescript/src/types.d.ts +86 -0
  216. package/lib/typescript/src/types.d.ts.map +1 -0
  217. package/lib/typescript/src/useTuner.d.ts +15 -0
  218. package/lib/typescript/src/useTuner.d.ts.map +1 -0
  219. package/package.json +141 -0
  220. package/src/NativeTunerEngine.ts +17 -0
  221. package/src/TunerEngine.ts +62 -0
  222. package/src/index.tsx +11 -0
  223. package/src/types.ts +109 -0
  224. 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)