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,174 @@
|
|
|
1
|
+
#import "IosAudioSource.h"
|
|
2
|
+
#import <AVFoundation/AVFoundation.h>
|
|
3
|
+
|
|
4
|
+
@implementation IosAudioSource {
|
|
5
|
+
AVAudioEngine* _engine;
|
|
6
|
+
AVAudioInputNode* _inputNode;
|
|
7
|
+
float _sampleRate;
|
|
8
|
+
BOOL _isRunning;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
- (instancetype)init {
|
|
12
|
+
self = [super init];
|
|
13
|
+
if (self) {
|
|
14
|
+
_sampleRate = 48000.0f;
|
|
15
|
+
_isRunning = NO;
|
|
16
|
+
[self registerNotifications];
|
|
17
|
+
}
|
|
18
|
+
return self;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
- (void)dealloc {
|
|
22
|
+
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
23
|
+
[self stop];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
- (float)sampleRate {
|
|
27
|
+
return _sampleRate;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
- (BOOL)startWithError:(NSError **)error {
|
|
31
|
+
if (_isRunning) return YES;
|
|
32
|
+
|
|
33
|
+
AVAudioSession* session = [AVAudioSession sharedInstance];
|
|
34
|
+
|
|
35
|
+
NSError* sessionError = nil;
|
|
36
|
+
[session setCategory:AVAudioSessionCategoryPlayAndRecord
|
|
37
|
+
withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker |
|
|
38
|
+
AVAudioSessionCategoryOptionAllowBluetooth
|
|
39
|
+
error:&sessionError];
|
|
40
|
+
if (sessionError) {
|
|
41
|
+
if (error) *error = sessionError;
|
|
42
|
+
return NO;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
[session setMode:AVAudioSessionModeMeasurement error:&sessionError];
|
|
46
|
+
if (sessionError) {
|
|
47
|
+
NSLog(@"[IosAudioSource] setMode error (non-fatal): %@", sessionError.localizedDescription);
|
|
48
|
+
sessionError = nil;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
[session setPreferredSampleRate:48000.0 error:&sessionError];
|
|
52
|
+
if (sessionError) {
|
|
53
|
+
NSLog(@"[IosAudioSource] setPreferredSampleRate error (non-fatal): %@", sessionError.localizedDescription);
|
|
54
|
+
sessionError = nil;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
[session setPreferredIOBufferDuration:0.0213 error:&sessionError];
|
|
58
|
+
if (sessionError) {
|
|
59
|
+
NSLog(@"[IosAudioSource] setPreferredIOBufferDuration error (non-fatal): %@", sessionError.localizedDescription);
|
|
60
|
+
sessionError = nil;
|
|
61
|
+
}
|
|
62
|
+
[session setActive:YES error:&sessionError];
|
|
63
|
+
if (sessionError) {
|
|
64
|
+
if (error) *error = sessionError;
|
|
65
|
+
return NO;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
_sampleRate = (float)session.sampleRate;
|
|
69
|
+
_engine = [[AVAudioEngine alloc] init];
|
|
70
|
+
_inputNode = _engine.inputNode;
|
|
71
|
+
|
|
72
|
+
AVAudioFormat* recordingFormat =
|
|
73
|
+
[[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32
|
|
74
|
+
sampleRate:_sampleRate
|
|
75
|
+
channels:1
|
|
76
|
+
interleaved:YES];
|
|
77
|
+
|
|
78
|
+
__weak __typeof__(self) weakSelf = self;
|
|
79
|
+
|
|
80
|
+
[_inputNode installTapOnBus:0
|
|
81
|
+
bufferSize:2048
|
|
82
|
+
format:recordingFormat
|
|
83
|
+
block:^(AVAudioPCMBuffer* buffer, AVAudioTime* when) {
|
|
84
|
+
(void)when;
|
|
85
|
+
__strong __typeof__(weakSelf) strongSelf = weakSelf;
|
|
86
|
+
if (!strongSelf || !strongSelf->_isRunning) return;
|
|
87
|
+
|
|
88
|
+
const float* data = buffer.floatChannelData[0];
|
|
89
|
+
const AVAudioFrameCount frames = buffer.frameLength;
|
|
90
|
+
|
|
91
|
+
AudioSamplesCallback cb = strongSelf.onSamples;
|
|
92
|
+
if (cb && frames > 0) {
|
|
93
|
+
cb(data, (int)frames, strongSelf->_sampleRate);
|
|
94
|
+
}
|
|
95
|
+
}];
|
|
96
|
+
|
|
97
|
+
NSError* engineError = nil;
|
|
98
|
+
[_engine prepare];
|
|
99
|
+
[_engine startAndReturnError:&engineError];
|
|
100
|
+
if (engineError) {
|
|
101
|
+
if (error) *error = engineError;
|
|
102
|
+
[_inputNode removeTapOnBus:0];
|
|
103
|
+
_engine = nil;
|
|
104
|
+
return NO;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
_isRunning = YES;
|
|
108
|
+
return YES;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
- (void)stop {
|
|
112
|
+
if (!_isRunning) return;
|
|
113
|
+
_isRunning = NO;
|
|
114
|
+
|
|
115
|
+
if (_inputNode) {
|
|
116
|
+
[_inputNode removeTapOnBus:0];
|
|
117
|
+
}
|
|
118
|
+
if (_engine && _engine.isRunning) {
|
|
119
|
+
[_engine stop];
|
|
120
|
+
}
|
|
121
|
+
_engine = nil;
|
|
122
|
+
_inputNode = nil;
|
|
123
|
+
|
|
124
|
+
[[AVAudioSession sharedInstance] setActive:NO
|
|
125
|
+
withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
|
|
126
|
+
error:nil];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
#pragma mark - Notifications
|
|
130
|
+
|
|
131
|
+
- (void)registerNotifications {
|
|
132
|
+
[[NSNotificationCenter defaultCenter]
|
|
133
|
+
addObserver:self
|
|
134
|
+
selector:@selector(handleInterruption:)
|
|
135
|
+
name:AVAudioSessionInterruptionNotification
|
|
136
|
+
object:nil];
|
|
137
|
+
|
|
138
|
+
[[NSNotificationCenter defaultCenter]
|
|
139
|
+
addObserver:self
|
|
140
|
+
selector:@selector(handleRouteChange:)
|
|
141
|
+
name:AVAudioSessionRouteChangeNotification
|
|
142
|
+
object:nil];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
- (void)handleInterruption:(NSNotification *)notification {
|
|
146
|
+
NSDictionary* info = notification.userInfo;
|
|
147
|
+
AVAudioSessionInterruptionType type =
|
|
148
|
+
(AVAudioSessionInterruptionType)[info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
|
|
149
|
+
|
|
150
|
+
if (type == AVAudioSessionInterruptionTypeBegan) {
|
|
151
|
+
[self stop];
|
|
152
|
+
} else if (type == AVAudioSessionInterruptionTypeEnded) {
|
|
153
|
+
AVAudioSessionInterruptionOptions options =
|
|
154
|
+
(AVAudioSessionInterruptionOptions)[info[AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
|
|
155
|
+
if (options & AVAudioSessionInterruptionOptionShouldResume) {
|
|
156
|
+
NSError* err = nil;
|
|
157
|
+
[self startWithError:&err];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
- (void)handleRouteChange:(NSNotification *)notification {
|
|
163
|
+
NSDictionary* info = notification.userInfo;
|
|
164
|
+
AVAudioSessionRouteChangeReason reason =
|
|
165
|
+
(AVAudioSessionRouteChangeReason)[info[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
|
|
166
|
+
|
|
167
|
+
if (reason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
|
|
168
|
+
[self stop];
|
|
169
|
+
NSError* err = nil;
|
|
170
|
+
[self startWithError:&err];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import <Foundation/Foundation.h>
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
typedef void (^PitchEventCallback)(NSDictionary* event);
|
|
8
|
+
|
|
9
|
+
@interface TunerBridge : NSObject
|
|
10
|
+
|
|
11
|
+
@property(nonatomic, copy, nullable) PitchEventCallback onPitch;
|
|
12
|
+
|
|
13
|
+
- (void)configure:(NSDictionary *)opts;
|
|
14
|
+
- (void)startWithCompletion:(void(^)(NSError* _Nullable error))completion;
|
|
15
|
+
- (void)stop;
|
|
16
|
+
- (void)setA4:(float)hz;
|
|
17
|
+
- (void)setInstrument:(NSString *)name;
|
|
18
|
+
- (void)setTuning:(NSString *)name;
|
|
19
|
+
- (void)setTemperament:(NSString *)name;
|
|
20
|
+
- (NSDictionary *)getStatus;
|
|
21
|
+
|
|
22
|
+
@end
|
|
23
|
+
|
|
24
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#import "TunerBridge.h"
|
|
2
|
+
#import "IosAudioSource.h"
|
|
3
|
+
#include "AudioFrameDispatcher.hpp"
|
|
4
|
+
#include "PostProcessor.hpp"
|
|
5
|
+
#include <memory>
|
|
6
|
+
|
|
7
|
+
@implementation TunerBridge {
|
|
8
|
+
IosAudioSource* _audioSource;
|
|
9
|
+
std::unique_ptr<AudioFrameDispatcher> _dispatcher;
|
|
10
|
+
bool _isRunning;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
- (instancetype)init {
|
|
14
|
+
self = [super init];
|
|
15
|
+
if (self) {
|
|
16
|
+
_isRunning = false;
|
|
17
|
+
}
|
|
18
|
+
return self;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
- (void)configure:(NSDictionary *)opts {
|
|
22
|
+
float sampleRate = opts[@"sampleRate"] ? [opts[@"sampleRate"] floatValue] : 48000.0f;
|
|
23
|
+
int frameSize = opts[@"frameSize"] ? [opts[@"frameSize"] intValue] : 2048;
|
|
24
|
+
float overlapRatio = opts[@"overlapRatio"] ? [opts[@"overlapRatio"] floatValue] : 0.0f;
|
|
25
|
+
|
|
26
|
+
[self buildDispatcherWithSampleRate:sampleRate frameSize:frameSize overlapRatio:overlapRatio opts:opts];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
- (void)buildDispatcherWithSampleRate:(float)sr frameSize:(int)fs overlapRatio:(float)overlap opts:(NSDictionary*)opts {
|
|
30
|
+
__weak __typeof__(self) weakSelf = self;
|
|
31
|
+
|
|
32
|
+
_dispatcher = std::make_unique<AudioFrameDispatcher>(fs, sr,
|
|
33
|
+
[weakSelf](const PitchResult& r) {
|
|
34
|
+
__strong __typeof__(weakSelf) strongSelf = weakSelf;
|
|
35
|
+
if (!strongSelf || !strongSelf.onPitch) return;
|
|
36
|
+
|
|
37
|
+
NSDictionary* event = @{
|
|
38
|
+
@"hasPitch": @(r.hasPitch),
|
|
39
|
+
@"frequency": @(r.frequency),
|
|
40
|
+
@"confidence": @(r.confidence),
|
|
41
|
+
@"rmsDb": @(r.rmsDb),
|
|
42
|
+
@"noteName": @(r.noteName.c_str()),
|
|
43
|
+
@"octave": @(r.octave),
|
|
44
|
+
@"cents": @(r.cents),
|
|
45
|
+
@"nearestString": @(r.nearestString.c_str()),
|
|
46
|
+
@"stringDeviation": @(r.stringDeviation)
|
|
47
|
+
};
|
|
48
|
+
strongSelf.onPitch(event);
|
|
49
|
+
},
|
|
50
|
+
overlap
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
if (opts[@"noiseGateDb"]) _dispatcher->setNoiseGateDb([opts[@"noiseGateDb"] floatValue]);
|
|
54
|
+
if (opts[@"confidenceThreshold"]) _dispatcher->setConfidenceThreshold([opts[@"confidenceThreshold"] floatValue]);
|
|
55
|
+
if (opts[@"minFrequency"] && opts[@"maxFrequency"]) {
|
|
56
|
+
_dispatcher->setFrequencyRange([opts[@"minFrequency"] floatValue], [opts[@"maxFrequency"] floatValue]);
|
|
57
|
+
}
|
|
58
|
+
if (opts[@"a4"]) _dispatcher->setA4([opts[@"a4"] floatValue]);
|
|
59
|
+
if (opts[@"hpfCutoffHz"]) _dispatcher->setHpfCutoff([opts[@"hpfCutoffHz"] floatValue]);
|
|
60
|
+
if (opts[@"emaAlpha"] || opts[@"hysteresisFrames"]) {
|
|
61
|
+
PostProcessor::Config cfg;
|
|
62
|
+
if (opts[@"emaAlpha"]) cfg.emaAlpha = [opts[@"emaAlpha"] floatValue];
|
|
63
|
+
if (opts[@"hysteresisFrames"]) cfg.hysteresisFrames = [opts[@"hysteresisFrames"] intValue];
|
|
64
|
+
_dispatcher->setPostProcessorConfig(cfg);
|
|
65
|
+
}
|
|
66
|
+
if (opts[@"onsetDetection"]) {
|
|
67
|
+
_dispatcher->setOnsetDetectionEnabled([opts[@"onsetDetection"] boolValue]);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
- (void)startWithCompletion:(void(^)(NSError* _Nullable error))completion {
|
|
72
|
+
if (_isRunning) {
|
|
73
|
+
completion(nil);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
_audioSource = [[IosAudioSource alloc] init];
|
|
78
|
+
|
|
79
|
+
// Spin up dispatcher if not yet configured
|
|
80
|
+
if (!_dispatcher) {
|
|
81
|
+
[self buildDispatcherWithSampleRate:48000.0f frameSize:2048 overlapRatio:0.0f opts:@{}];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
__weak __typeof__(self) weakSelf = self;
|
|
85
|
+
_audioSource.onSamples = ^(const float* samples, int count, float sampleRate) {
|
|
86
|
+
__strong __typeof__(weakSelf) strongSelf = weakSelf;
|
|
87
|
+
if (!strongSelf || !strongSelf->_dispatcher) return;
|
|
88
|
+
strongSelf->_dispatcher->push(samples, count);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
NSError* error = nil;
|
|
92
|
+
if (![_audioSource startWithError:&error]) {
|
|
93
|
+
completion(error);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Sync dispatcher sample rate to what AVAudioSession actually gave us
|
|
98
|
+
const float actualSampleRate = _audioSource.sampleRate;
|
|
99
|
+
_dispatcher->setSampleRate(actualSampleRate);
|
|
100
|
+
_dispatcher->start();
|
|
101
|
+
_isRunning = true;
|
|
102
|
+
|
|
103
|
+
completion(nil);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
- (void)stop {
|
|
107
|
+
if (!_isRunning) return;
|
|
108
|
+
_isRunning = false;
|
|
109
|
+
|
|
110
|
+
if (_dispatcher) _dispatcher->stop();
|
|
111
|
+
[_audioSource stop];
|
|
112
|
+
_audioSource = nil;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
- (void)setA4:(float)hz {
|
|
116
|
+
if (_dispatcher) _dispatcher->setA4(hz);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
- (void)setInstrument:(NSString *)name {
|
|
120
|
+
if (_dispatcher) _dispatcher->setInstrument(std::string([name UTF8String]));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
- (void)setTuning:(NSString *)name {
|
|
124
|
+
if (_dispatcher) _dispatcher->setTuning(std::string([name UTF8String]));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
- (void)setTemperament:(NSString *)name {}
|
|
128
|
+
|
|
129
|
+
- (NSDictionary *)getStatus {
|
|
130
|
+
return @{
|
|
131
|
+
@"isRunning": @(_isRunning),
|
|
132
|
+
@"engineReady": @(_dispatcher != nullptr)
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#import "TunerEngine.h"
|
|
2
|
+
#import "TunerBridge.h"
|
|
3
|
+
#import <AVFoundation/AVFoundation.h>
|
|
4
|
+
#import <ReactCommon/RCTTurboModule.h>
|
|
5
|
+
#import <ReactCommon/CallInvoker.h>
|
|
6
|
+
#import <jsi/jsi.h>
|
|
7
|
+
|
|
8
|
+
@implementation TunerEngine {
|
|
9
|
+
TunerBridge* _tunerBridge;
|
|
10
|
+
std::shared_ptr<facebook::react::CallInvoker> _jsInvoker;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
RCT_EXPORT_MODULE(TunerEngine)
|
|
14
|
+
|
|
15
|
+
- (instancetype)init {
|
|
16
|
+
self = [super init];
|
|
17
|
+
if (self) {
|
|
18
|
+
[super addListener:@"onPitch"]; // keeps _listenerCount=1 for old-arch fallback
|
|
19
|
+
_tunerBridge = [[TunerBridge alloc] init];
|
|
20
|
+
}
|
|
21
|
+
return self;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
- (NSArray<NSString *> *)supportedEvents {
|
|
25
|
+
return @[@"onPitch"];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
- (void)addListener:(NSString *)eventName {}
|
|
29
|
+
- (void)removeListeners:(double)count {}
|
|
30
|
+
|
|
31
|
+
- (void)configure:(NSDictionary *)opts
|
|
32
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
33
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
34
|
+
[_tunerBridge configure:opts];
|
|
35
|
+
resolve(nil);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
- (void)start:(RCTPromiseResolveBlock)resolve
|
|
39
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
40
|
+
[_tunerBridge startWithCompletion:^(NSError* error) {
|
|
41
|
+
if (error) {
|
|
42
|
+
reject(@"START_ERROR", error.localizedDescription, error);
|
|
43
|
+
} else {
|
|
44
|
+
resolve(nil);
|
|
45
|
+
}
|
|
46
|
+
}];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
- (void)stop:(RCTPromiseResolveBlock)resolve
|
|
50
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
51
|
+
[_tunerBridge stop];
|
|
52
|
+
resolve(nil);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
- (void)setA4:(double)hz {
|
|
56
|
+
[_tunerBridge setA4:(float)hz];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
- (void)setInstrument:(NSString *)name {
|
|
60
|
+
[_tunerBridge setInstrument:name];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
- (void)setTuning:(NSString *)name {
|
|
64
|
+
[_tunerBridge setTuning:name];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
- (void)setTemperament:(NSString *)name {
|
|
68
|
+
[_tunerBridge setTemperament:name];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
- (void)requestPermission:(RCTPromiseResolveBlock)resolve
|
|
72
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
73
|
+
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
|
|
74
|
+
resolve(@(granted));
|
|
75
|
+
}];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
- (NSDictionary *)getStatus {
|
|
79
|
+
return [_tunerBridge getStatus];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
+ (BOOL)requiresMainQueueSetup {
|
|
83
|
+
return NO;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
87
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
88
|
+
{
|
|
89
|
+
_jsInvoker = params.jsInvoker;
|
|
90
|
+
|
|
91
|
+
__weak __typeof__(self) weakSelf = self;
|
|
92
|
+
_tunerBridge.onPitch = ^(NSDictionary* event) {
|
|
93
|
+
__strong __typeof__(weakSelf) strongSelf = weakSelf;
|
|
94
|
+
if (!strongSelf) return;
|
|
95
|
+
|
|
96
|
+
auto jsInvoker = strongSelf->_jsInvoker;
|
|
97
|
+
if (!jsInvoker) {
|
|
98
|
+
[strongSelf sendEventWithName:@"onPitch" body:event];
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Extract primitives before crossing thread boundary
|
|
103
|
+
bool hasPitch = [event[@"hasPitch"] boolValue];
|
|
104
|
+
double frequency = [event[@"frequency"] doubleValue];
|
|
105
|
+
double confidence = [event[@"confidence"] doubleValue];
|
|
106
|
+
double rmsDb = [event[@"rmsDb"] doubleValue];
|
|
107
|
+
std::string note = std::string([event[@"noteName"] UTF8String]);
|
|
108
|
+
int octave = [event[@"octave"] intValue];
|
|
109
|
+
double cents = [event[@"cents"] doubleValue];
|
|
110
|
+
std::string nearestStr = event[@"nearestString"]
|
|
111
|
+
? std::string([event[@"nearestString"] UTF8String]) : std::string();
|
|
112
|
+
double stringDev = [event[@"stringDeviation"] doubleValue];
|
|
113
|
+
|
|
114
|
+
jsInvoker->invokeAsync([weakSelf, hasPitch, frequency, confidence, rmsDb,
|
|
115
|
+
note, octave, cents, nearestStr, stringDev](facebook::jsi::Runtime& rt) {
|
|
116
|
+
__strong __typeof__(weakSelf) innerSelf = weakSelf;
|
|
117
|
+
if (!innerSelf) return; // Module deallocated — bail out
|
|
118
|
+
|
|
119
|
+
auto cb = rt.global().getProperty(rt, "__tunerEngineOnPitch");
|
|
120
|
+
if (!cb.isObject()) return;
|
|
121
|
+
auto fn = cb.asObject(rt);
|
|
122
|
+
if (!fn.isFunction(rt)) return;
|
|
123
|
+
|
|
124
|
+
facebook::jsi::Object obj(rt);
|
|
125
|
+
obj.setProperty(rt, "hasPitch", facebook::jsi::Value(hasPitch));
|
|
126
|
+
obj.setProperty(rt, "frequency", facebook::jsi::Value(frequency));
|
|
127
|
+
obj.setProperty(rt, "confidence", facebook::jsi::Value(confidence));
|
|
128
|
+
obj.setProperty(rt, "rmsDb", facebook::jsi::Value(rmsDb));
|
|
129
|
+
obj.setProperty(rt, "noteName",
|
|
130
|
+
facebook::jsi::String::createFromUtf8(rt, note));
|
|
131
|
+
obj.setProperty(rt, "octave", facebook::jsi::Value(octave));
|
|
132
|
+
obj.setProperty(rt, "cents", facebook::jsi::Value(cents));
|
|
133
|
+
obj.setProperty(rt, "nearestString",
|
|
134
|
+
facebook::jsi::String::createFromUtf8(rt, nearestStr));
|
|
135
|
+
obj.setProperty(rt, "stringDeviation", facebook::jsi::Value(stringDev));
|
|
136
|
+
|
|
137
|
+
fn.asFunction(rt).call(rt, std::move(obj));
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
return std::make_shared<facebook::react::NativeTunerEngineSpecJSI>(params);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeTunerEngine.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AAgBpE,eAAeA,mBAAmB,CAACC,YAAY,CAAO,aAAa,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { DeviceEventEmitter } from 'react-native';
|
|
4
|
+
import NativeTunerEngine from "./NativeTunerEngine.js";
|
|
5
|
+
class TunerEngine {
|
|
6
|
+
configure(opts) {
|
|
7
|
+
return NativeTunerEngine.configure(opts);
|
|
8
|
+
}
|
|
9
|
+
start() {
|
|
10
|
+
return NativeTunerEngine.start();
|
|
11
|
+
}
|
|
12
|
+
stop() {
|
|
13
|
+
return NativeTunerEngine.stop();
|
|
14
|
+
}
|
|
15
|
+
requestPermission() {
|
|
16
|
+
return NativeTunerEngine.requestPermission();
|
|
17
|
+
}
|
|
18
|
+
setA4(hz) {
|
|
19
|
+
NativeTunerEngine.setA4(hz);
|
|
20
|
+
}
|
|
21
|
+
setInstrument(name) {
|
|
22
|
+
NativeTunerEngine.setInstrument(name);
|
|
23
|
+
}
|
|
24
|
+
setTemperament(name) {
|
|
25
|
+
NativeTunerEngine.setTemperament(name);
|
|
26
|
+
}
|
|
27
|
+
setTuning(name) {
|
|
28
|
+
NativeTunerEngine.setTuning(name);
|
|
29
|
+
}
|
|
30
|
+
getStatus() {
|
|
31
|
+
return NativeTunerEngine.getStatus();
|
|
32
|
+
}
|
|
33
|
+
onPitch(callback) {
|
|
34
|
+
globalThis.__tunerEngineOnPitch = callback;
|
|
35
|
+
const sub = DeviceEventEmitter.addListener('onPitch', callback);
|
|
36
|
+
return () => {
|
|
37
|
+
globalThis.__tunerEngineOnPitch = undefined;
|
|
38
|
+
sub.remove();
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export default new TunerEngine();
|
|
43
|
+
//# sourceMappingURL=TunerEngine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["DeviceEventEmitter","NativeTunerEngine","TunerEngine","configure","opts","start","stop","requestPermission","setA4","hz","setInstrument","name","setTemperament","setTuning","getStatus","onPitch","callback","globalThis","__tunerEngineOnPitch","sub","addListener","undefined","remove"],"sourceRoot":"../../src","sources":["TunerEngine.ts"],"mappings":";;AAAA,SAASA,kBAAkB,QAAQ,cAAc;AACjD,OAAOC,iBAAiB,MAAM,wBAAqB;AAanD,MAAMC,WAAW,CAAC;EAChBC,SAASA,CAACC,IAAiB,EAAiB;IAC1C,OAAOH,iBAAiB,CAACE,SAAS,CAACC,IAAI,CAAC;EAC1C;EAEAC,KAAKA,CAAA,EAAkB;IACrB,OAAOJ,iBAAiB,CAACI,KAAK,CAAC,CAAC;EAClC;EAEAC,IAAIA,CAAA,EAAkB;IACpB,OAAOL,iBAAiB,CAACK,IAAI,CAAC,CAAC;EACjC;EAEAC,iBAAiBA,CAAA,EAAqB;IACpC,OAAON,iBAAiB,CAACM,iBAAiB,CAAC,CAAC;EAC9C;EAEAC,KAAKA,CAACC,EAAU,EAAQ;IACtBR,iBAAiB,CAACO,KAAK,CAACC,EAAE,CAAC;EAC7B;EAEAC,aAAaA,CAACC,IAAgB,EAAQ;IACpCV,iBAAiB,CAACS,aAAa,CAACC,IAAI,CAAC;EACvC;EAEAC,cAAcA,CAACD,IAAiB,EAAQ;IACtCV,iBAAiB,CAACW,cAAc,CAACD,IAAI,CAAC;EACxC;EAEAE,SAASA,CAACF,IAAuB,EAAQ;IACvCV,iBAAiB,CAACY,SAAS,CAACF,IAAI,CAAC;EACnC;EAEAG,SAASA,CAAA,EAAiB;IACxB,OAAOb,iBAAiB,CAACa,SAAS,CAAC,CAAC;EACtC;EAEAC,OAAOA,CAACC,QAAuB,EAAe;IAC3CC,UAAU,CAASC,oBAAoB,GAAGF,QAAQ;IACnD,MAAMG,GAAG,GAAGnB,kBAAkB,CAACoB,WAAW,CAAC,SAAS,EAAEJ,QAAQ,CAAC;IAC/D,OAAO,MAAM;MACVC,UAAU,CAASC,oBAAoB,GAAGG,SAAS;MACpDF,GAAG,CAACG,MAAM,CAAC,CAAC;IACd,CAAC;EACH;AACF;AAEA,eAAe,IAAIpB,WAAW,CAAC,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["default","TunerEngine","useTuner"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,OAAO,IAAIC,WAAW,QAAQ,kBAAe;AACtD,SAASC,QAAQ,QAAQ,eAAY","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
+
import TunerEngine from "./TunerEngine.js";
|
|
5
|
+
export function useTuner(opts = {}) {
|
|
6
|
+
const [latest, setLatest] = useState(null);
|
|
7
|
+
const [isRunning, setIsRunning] = useState(false);
|
|
8
|
+
const [error, setError] = useState(null);
|
|
9
|
+
const optsRef = useRef(opts);
|
|
10
|
+
optsRef.current = opts;
|
|
11
|
+
const unsubscribeRef = useRef(null);
|
|
12
|
+
const stop = useCallback(async () => {
|
|
13
|
+
unsubscribeRef.current?.();
|
|
14
|
+
unsubscribeRef.current = null;
|
|
15
|
+
await TunerEngine.stop();
|
|
16
|
+
setIsRunning(false);
|
|
17
|
+
}, []);
|
|
18
|
+
const start = useCallback(async () => {
|
|
19
|
+
setError(null);
|
|
20
|
+
try {
|
|
21
|
+
const granted = await TunerEngine.requestPermission();
|
|
22
|
+
if (!granted) {
|
|
23
|
+
throw new Error('Microphone permission denied');
|
|
24
|
+
}
|
|
25
|
+
const {
|
|
26
|
+
instrument,
|
|
27
|
+
a4,
|
|
28
|
+
...config
|
|
29
|
+
} = optsRef.current;
|
|
30
|
+
await TunerEngine.configure(config);
|
|
31
|
+
if (instrument) TunerEngine.setInstrument(instrument);
|
|
32
|
+
if (a4 !== undefined) TunerEngine.setA4(a4);
|
|
33
|
+
unsubscribeRef.current = TunerEngine.onPitch(setLatest);
|
|
34
|
+
await TunerEngine.start();
|
|
35
|
+
setIsRunning(true);
|
|
36
|
+
} catch (e) {
|
|
37
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
38
|
+
setIsRunning(false);
|
|
39
|
+
}
|
|
40
|
+
}, []);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
return () => {
|
|
43
|
+
unsubscribeRef.current?.();
|
|
44
|
+
TunerEngine.stop();
|
|
45
|
+
};
|
|
46
|
+
}, []);
|
|
47
|
+
return {
|
|
48
|
+
start,
|
|
49
|
+
stop,
|
|
50
|
+
latest,
|
|
51
|
+
isRunning,
|
|
52
|
+
error
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=useTuner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useCallback","useEffect","useRef","useState","TunerEngine","useTuner","opts","latest","setLatest","isRunning","setIsRunning","error","setError","optsRef","current","unsubscribeRef","stop","start","granted","requestPermission","Error","instrument","a4","config","configure","setInstrument","undefined","setA4","onPitch","e","String"],"sourceRoot":"../../src","sources":["useTuner.ts"],"mappings":";;AAAA,SAASA,WAAW,EAAEC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;AAChE,OAAOC,WAAW,MAAM,kBAAe;AAgBvC,OAAO,SAASC,QAAQA,CAACC,IAAqB,GAAG,CAAC,CAAC,EAAkB;EACnE,MAAM,CAACC,MAAM,EAAEC,SAAS,CAAC,GAAGL,QAAQ,CAAoB,IAAI,CAAC;EAC7D,MAAM,CAACM,SAAS,EAAEC,YAAY,CAAC,GAAGP,QAAQ,CAAC,KAAK,CAAC;EACjD,MAAM,CAACQ,KAAK,EAAEC,QAAQ,CAAC,GAAGT,QAAQ,CAAe,IAAI,CAAC;EAEtD,MAAMU,OAAO,GAAGX,MAAM,CAACI,IAAI,CAAC;EAC5BO,OAAO,CAACC,OAAO,GAAGR,IAAI;EAEtB,MAAMS,cAAc,GAAGb,MAAM,CAAsB,IAAI,CAAC;EAExD,MAAMc,IAAI,GAAGhB,WAAW,CAAC,YAAY;IACnCe,cAAc,CAACD,OAAO,GAAG,CAAC;IAC1BC,cAAc,CAACD,OAAO,GAAG,IAAI;IAC7B,MAAMV,WAAW,CAACY,IAAI,CAAC,CAAC;IACxBN,YAAY,CAAC,KAAK,CAAC;EACrB,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMO,KAAK,GAAGjB,WAAW,CAAC,YAAY;IACpCY,QAAQ,CAAC,IAAI,CAAC;IACd,IAAI;MACF,MAAMM,OAAO,GAAG,MAAMd,WAAW,CAACe,iBAAiB,CAAC,CAAC;MACrD,IAAI,CAACD,OAAO,EAAE;QACZ,MAAM,IAAIE,KAAK,CAAC,8BAA8B,CAAC;MACjD;MAEA,MAAM;QAAEC,UAAU;QAAEC,EAAE;QAAE,GAAGC;MAAO,CAAC,GAAGV,OAAO,CAACC,OAAO;MACrD,MAAMV,WAAW,CAACoB,SAAS,CAACD,MAAM,CAAC;MAEnC,IAAIF,UAAU,EAAEjB,WAAW,CAACqB,aAAa,CAACJ,UAAU,CAAC;MACrD,IAAIC,EAAE,KAAKI,SAAS,EAAEtB,WAAW,CAACuB,KAAK,CAACL,EAAE,CAAC;MAE3CP,cAAc,CAACD,OAAO,GAAGV,WAAW,CAACwB,OAAO,CAACpB,SAAS,CAAC;MAEvD,MAAMJ,WAAW,CAACa,KAAK,CAAC,CAAC;MACzBP,YAAY,CAAC,IAAI,CAAC;IACpB,CAAC,CAAC,OAAOmB,CAAC,EAAE;MACVjB,QAAQ,CAACiB,CAAC,YAAYT,KAAK,GAAGS,CAAC,GAAG,IAAIT,KAAK,CAACU,MAAM,CAACD,CAAC,CAAC,CAAC,CAAC;MACvDnB,YAAY,CAAC,KAAK,CAAC;IACrB;EACF,CAAC,EAAE,EAAE,CAAC;EAENT,SAAS,CAAC,MAAM;IACd,OAAO,MAAM;MACXc,cAAc,CAACD,OAAO,GAAG,CAAC;MAC1BV,WAAW,CAACY,IAAI,CAAC,CAAC;IACpB,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EAEN,OAAO;IAAEC,KAAK;IAAED,IAAI;IAAET,MAAM;IAAEE,SAAS;IAAEE;EAAM,CAAC;AAClD","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type TurboModule } from 'react-native';
|
|
2
|
+
export interface Spec extends TurboModule {
|
|
3
|
+
configure(opts: Object): Promise<void>;
|
|
4
|
+
start(): Promise<void>;
|
|
5
|
+
stop(): Promise<void>;
|
|
6
|
+
setA4(hz: number): void;
|
|
7
|
+
setInstrument(name: string): void;
|
|
8
|
+
setTemperament(name: string): void;
|
|
9
|
+
setTuning(name: string): void;
|
|
10
|
+
requestPermission(): Promise<boolean>;
|
|
11
|
+
getStatus(): Object;
|
|
12
|
+
addListener(eventName: string): void;
|
|
13
|
+
removeListeners(count: number): void;
|
|
14
|
+
}
|
|
15
|
+
declare const _default: Spec;
|
|
16
|
+
export default _default;
|
|
17
|
+
//# sourceMappingURL=NativeTunerEngine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeTunerEngine.d.ts","sourceRoot":"","sources":["../../../src/NativeTunerEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAErE,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,SAAS,IAAI,MAAM,CAAC;IACpB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;;AAED,wBAAqE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { EngineStatus, Instrument, PitchEvent, Temperament, TunerConfig, TuningPreset } from './types';
|
|
2
|
+
type PitchCallback = (event: PitchEvent) => void;
|
|
3
|
+
type Unsubscribe = () => void;
|
|
4
|
+
declare class TunerEngine {
|
|
5
|
+
configure(opts: TunerConfig): Promise<void>;
|
|
6
|
+
start(): Promise<void>;
|
|
7
|
+
stop(): Promise<void>;
|
|
8
|
+
requestPermission(): Promise<boolean>;
|
|
9
|
+
setA4(hz: number): void;
|
|
10
|
+
setInstrument(name: Instrument): void;
|
|
11
|
+
setTemperament(name: Temperament): void;
|
|
12
|
+
setTuning(name: TuningPreset | ''): void;
|
|
13
|
+
getStatus(): EngineStatus;
|
|
14
|
+
onPitch(callback: PitchCallback): Unsubscribe;
|
|
15
|
+
}
|
|
16
|
+
declare const _default: TunerEngine;
|
|
17
|
+
export default _default;
|
|
18
|
+
//# sourceMappingURL=TunerEngine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TunerEngine.d.ts","sourceRoot":"","sources":["../../../src/TunerEngine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,UAAU,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;AACjD,KAAK,WAAW,GAAG,MAAM,IAAI,CAAC;AAE9B,cAAM,WAAW;IACf,SAAS,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIvB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAIrC,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAIvC,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,EAAE,GAAG,IAAI;IAIxC,SAAS,IAAI,YAAY;IAIzB,OAAO,CAAC,QAAQ,EAAE,aAAa,GAAG,WAAW;CAQ9C;;AAED,wBAAiC"}
|