react-native-simple-note-pitch-detector 0.6.0 → 0.6.1

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.
@@ -1,5 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <project version="4">
3
+ <component name="GradleMigrationSettings" migrationVersion="1" />
3
4
  <component name="GradleSettings">
4
5
  <option name="linkedExternalProjectsSettings">
5
6
  <GradleProjectSettings>
@@ -1,4 +1,3 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
1
  <project version="4">
3
2
  <component name="ExternalStorageConfigurationManager" enabled="true" />
4
3
  <component name="ProjectRootManager">
@@ -1,5 +1,6 @@
1
1
  package expo.modules.simplepitchdetector
2
2
 
3
+ import android.util.Log
3
4
  import be.tarsos.dsp.AudioDispatcher
4
5
  import be.tarsos.dsp.AudioProcessor
5
6
  import be.tarsos.dsp.io.android.AudioDispatcherFactory
@@ -11,6 +12,8 @@ import kotlin.math.round
11
12
  import kotlin.math.pow
12
13
  import kotlin.math.abs
13
14
 
15
+ private const val TAG = "PitchAnalyzer"
16
+
14
17
  data class PitchData(
15
18
  val note: String,
16
19
  val octave: Int,
@@ -24,6 +27,7 @@ class PitchAnalyzer {
24
27
  private val notes = arrayOf("C","C#","D","D#","E","F","F#","G","G#","A","A#","B")
25
28
 
26
29
  private lateinit var onPitchDetected: (PitchData) -> Unit
30
+ private var onStatus: ((String, String) -> Unit)? = null
27
31
  private var isRecording = false
28
32
  private var levelThreshold = -30f
29
33
  // Configurable buffer size - can be changed from JS
@@ -43,15 +47,26 @@ class PitchAnalyzer {
43
47
  val decibel = e.getdBSPL().toFloat()
44
48
  // Only process if above the level threshold
45
49
  if (decibel > levelThreshold) {
50
+ // Note: Not logging every pitch detection to JS to avoid flooding
51
+ // Use adb logcat for verbose pitch logs
52
+ Log.v(TAG, "Pitch detected: ${pitchInHz}Hz at ${decibel}dB")
46
53
  process(pitchInHz, decibel)
47
54
  }
48
55
  }
49
56
 
50
57
  private fun prepare() {
51
- processor =
52
- PitchProcessor(algorithm, 22050f, bufferSize, handler)
53
- dispatcher = AudioDispatcherFactory.fromDefaultMicrophone(22050, bufferSize, 0)
54
- dispatcher?.addAudioProcessor(processor)
58
+ try {
59
+ logStatus("debug", "prepare() called with bufferSize=$bufferSize, algorithm=$algorithmName")
60
+ processor = PitchProcessor(algorithm, 22050f, bufferSize, handler)
61
+ logStatus("debug", "PitchProcessor created successfully")
62
+ dispatcher = AudioDispatcherFactory.fromDefaultMicrophone(22050, bufferSize, 0)
63
+ logStatus("debug", "AudioDispatcher created successfully: $dispatcher")
64
+ dispatcher?.addAudioProcessor(processor)
65
+ logStatus("debug", "AudioProcessor added to dispatcher")
66
+ } catch (e: Exception) {
67
+ logStatus("error", "Error in prepare(): ${e.message}")
68
+ throw e
69
+ }
55
70
  }
56
71
 
57
72
  private fun process(pitchInHz: Float, decibel: Float) {
@@ -89,6 +104,20 @@ class PitchAnalyzer {
89
104
  this.onPitchDetected = listener
90
105
  }
91
106
 
107
+ fun setOnStatusListener(listener: (String, String) -> Unit) {
108
+ this.onStatus = listener
109
+ }
110
+
111
+ private fun logStatus(level: String, message: String) {
112
+ when (level) {
113
+ "debug" -> Log.d(TAG, message)
114
+ "error" -> Log.e(TAG, message)
115
+ "verbose" -> Log.v(TAG, message)
116
+ else -> Log.d(TAG, message)
117
+ }
118
+ onStatus?.invoke(level, message)
119
+ }
120
+
92
121
  fun setLevelThreshold(threshold: Float) {
93
122
  this.levelThreshold = threshold
94
123
  }
@@ -119,10 +148,18 @@ class PitchAnalyzer {
119
148
  }
120
149
 
121
150
  fun start() {
122
- prepare()
123
- runner = Thread(dispatcher)
124
- runner?.start()
125
- isRecording = true
151
+ try {
152
+ logStatus("debug", "start() called")
153
+ prepare()
154
+ runner = Thread(dispatcher)
155
+ logStatus("debug", "Thread created, starting...")
156
+ runner?.start()
157
+ isRecording = true
158
+ logStatus("debug", "Recording started successfully")
159
+ } catch (e: Exception) {
160
+ logStatus("error", "Error in start(): ${e.message}")
161
+ isRecording = false
162
+ }
126
163
  }
127
164
 
128
165
  fun stop() {
@@ -10,11 +10,21 @@ class ReactNativeSimpleNotePitchDetectorModule : Module() {
10
10
 
11
11
  private val pitchAnalyzer = PitchAnalyzer()
12
12
 
13
+ private fun sendStatus(level: String, message: String) {
14
+ this.sendEvent(
15
+ "onStatus",
16
+ bundleOf(
17
+ "level" to level,
18
+ "message" to message
19
+ )
20
+ )
21
+ }
22
+
13
23
  override fun definition() = ModuleDefinition {
14
24
 
15
25
  Name("ReactNativeSimpleNotePitchDetector")
16
26
 
17
- Events("onChangeNote")
27
+ Events("onChangeNote", "onStatus")
18
28
 
19
29
  Function("isRecording") {
20
30
  pitchAnalyzer.isRecording()
@@ -33,6 +43,10 @@ class ReactNativeSimpleNotePitchDetectorModule : Module() {
33
43
  )
34
44
  }
35
45
 
46
+ pitchAnalyzer.setOnStatusListener { level: String, message: String ->
47
+ this@ReactNativeSimpleNotePitchDetectorModule.sendStatus(level, message)
48
+ }
49
+
36
50
  pitchAnalyzer.start()
37
51
  }
38
52
 
package/build/index.d.ts CHANGED
@@ -67,5 +67,15 @@ export declare function setAlgorithm(algorithm: string): any;
67
67
  */
68
68
  export declare function getAlgorithm(): string;
69
69
  export declare function onChangeNote(listener: (event: ChangeEventPayload) => void): Subscription;
70
+ export interface StatusEventPayload {
71
+ level: "debug" | "error" | "verbose";
72
+ message: string;
73
+ }
74
+ /**
75
+ * Listen for status/debug messages from the native module.
76
+ * Useful for debugging audio initialization issues.
77
+ * @param listener - Callback that receives status events with level and message
78
+ */
79
+ export declare function onStatus(listener: (event: StatusEventPayload) => void): Subscription;
70
80
  export { ReactNativeSimpleNotePitchDetectorViewProps, ChangeEventPayload };
71
81
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,EACb,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,kBAAkB,EAClB,2CAA2C,EAC5C,MAAM,4CAA4C,CAAC;AAEpD,wBAAgB,KAAK,QAEpB;AAED,wBAAgB,IAAI,QAEnB;AAED,wBAAgB,WAAW,QAE1B;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,OAElD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,OAEzC;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,OAE7C;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAOD,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAC5C,YAAY,CAEd;AAED,OAAO,EAAE,2CAA2C,EAAE,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,EACb,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,kBAAkB,EAClB,2CAA2C,EAC5C,MAAM,4CAA4C,CAAC;AAEpD,wBAAgB,KAAK,QAEpB;AAED,wBAAgB,IAAI,QAEnB;AAED,wBAAgB,WAAW,QAE1B;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,OAElD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,OAEzC;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,OAE7C;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAOD,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAC5C,YAAY,CAEd;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAC5C,YAAY,CAEd;AAED,OAAO,EAAE,2CAA2C,EAAE,kBAAkB,EAAE,CAAC"}
package/build/index.js CHANGED
@@ -87,4 +87,12 @@ const emitter = new EventEmitter(ReactNativeSimpleNotePitchDetectorModule ??
87
87
  export function onChangeNote(listener) {
88
88
  return emitter.addListener("onChangeNote", listener);
89
89
  }
90
+ /**
91
+ * Listen for status/debug messages from the native module.
92
+ * Useful for debugging audio initialization issues.
93
+ * @param listener - Callback that receives status events with level and message
94
+ */
95
+ export function onStatus(listener) {
96
+ return emitter.addListener("onStatus", listener);
97
+ }
90
98
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,YAAY,GAEb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,wCAAwC,MAAM,4CAA4C,CAAC;AAMlG,MAAM,UAAU,KAAK;IACnB,OAAO,wCAAwC,CAAC,KAAK,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,OAAO,wCAAwC,CAAC,IAAI,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,wCAAwC,CAAC,WAAW,EAAE,CAAC;AAChE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,OAAO,wCAAwC,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;AAC/E,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,wCAAwC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;AACtE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,wCAAwC,CAAC,aAAa,EAAE,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,OAAO,wCAAwC,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;AAC1E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,wCAAwC,CAAC,YAAY,EAAE,CAAC;AACjE,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,YAAY,CAC9B,wCAAwC;IACtC,kBAAkB,CAAC,kCAAkC,CACxD,CAAC;AAEF,MAAM,UAAU,YAAY,CAC1B,QAA6C;IAE7C,OAAO,OAAO,CAAC,WAAW,CAAqB,cAAc,EAAE,QAAQ,CAAC,CAAC;AAC3E,CAAC","sourcesContent":["import {\n NativeModulesProxy,\n EventEmitter,\n Subscription,\n} from \"expo-modules-core\";\n\nimport ReactNativeSimpleNotePitchDetectorModule from \"./ReactNativeSimpleNotePitchDetectorModule\";\nimport {\n ChangeEventPayload,\n ReactNativeSimpleNotePitchDetectorViewProps,\n} from \"./ReactNativeSimpleNotePitchDetector.types\";\n\nexport function start() {\n return ReactNativeSimpleNotePitchDetectorModule.start();\n}\n\nexport function stop() {\n return ReactNativeSimpleNotePitchDetectorModule.stop();\n}\n\nexport function isRecording() {\n return ReactNativeSimpleNotePitchDetectorModule.isRecording();\n}\n\n/**\n * Set the minimum audio level threshold for pitch detection.\n * Values are in dB (e.g., -30 means sounds quieter than -30dB are ignored).\n * Lower values = more sensitive (picks up quieter sounds).\n * Default is -30.\n * @param threshold - Level threshold in dB (e.g., -30, -35, -40)\n */\nexport function setLevelThreshold(threshold: number) {\n return ReactNativeSimpleNotePitchDetectorModule.setLevelThreshold(threshold);\n}\n\n/**\n * Set the buffer size for pitch detection.\n * Must be called before start() or will restart the engine if already running.\n *\n * Buffer size affects the trade-off between frequency range and responsiveness:\n * - Smaller buffer (2048-4096): Better for high frequencies, faster response, but less accurate for low notes\n * - Larger buffer (8192-16384): Better for low frequencies, more accurate, but slightly more latency\n *\n * iOS defaults to 8192, Android defaults to 2048.\n *\n * Recommended values:\n * - 4096: Good balance for most use cases\n * - 8192: Better for bass instruments or full piano range (iOS default)\n * - 2048: Better for high-pitched instruments, faster response (Android default)\n *\n * @param size - Buffer size (must be power of 2: 1024, 2048, 4096, 8192, 16384)\n */\nexport function setBufferSize(size: number) {\n return ReactNativeSimpleNotePitchDetectorModule.setBufferSize(size);\n}\n\n/**\n * Get the current buffer size.\n * @returns Current buffer size\n */\nexport function getBufferSize(): number {\n return ReactNativeSimpleNotePitchDetectorModule.getBufferSize();\n}\n\n/**\n * Set the pitch estimation algorithm.\n * Must be called before start() or will restart the engine if already running.\n *\n * Available algorithms differ by platform:\n *\n * **iOS (Beethoven library):**\n * - \"yin\" (default) - YIN algorithm, good for monophonic instruments\n * - \"hps\" - Harmonic Product Spectrum\n * - \"barycentric\" - Barycentric interpolation\n * - \"quadradic\" - Quadratic interpolation\n * - \"jains\" - Jain's method\n * - \"quinnsFirst\" - Quinn's first estimator\n * - \"quinnsSecond\" - Quinn's second estimator\n * - \"maxValue\" - Maximum value method\n *\n * **Android (TarsosDSP library):**\n * - \"fft_yin\" (default) - FFT-based YIN, faster than pure YIN\n * - \"yin\" - Pure YIN algorithm\n * - \"mpm\" - McLeod Pitch Method, good for speech and music\n * - \"fft_pitch\" - FFT bin with most energy\n * - \"dynamic_wavelet\" - Dynamic wavelet algorithm\n * - \"amdf\" - Average Magnitude Difference Function\n *\n * @param algorithm - Algorithm name (case-insensitive)\n */\nexport function setAlgorithm(algorithm: string) {\n return ReactNativeSimpleNotePitchDetectorModule.setAlgorithm(algorithm);\n}\n\n/**\n * Get the current algorithm name.\n * @returns Current algorithm name\n */\nexport function getAlgorithm(): string {\n return ReactNativeSimpleNotePitchDetectorModule.getAlgorithm();\n}\n\nconst emitter = new EventEmitter(\n ReactNativeSimpleNotePitchDetectorModule ??\n NativeModulesProxy.ReactNativeSimpleNotePitchDetector\n);\n\nexport function onChangeNote(\n listener: (event: ChangeEventPayload) => void\n): Subscription {\n return emitter.addListener<ChangeEventPayload>(\"onChangeNote\", listener);\n}\n\nexport { ReactNativeSimpleNotePitchDetectorViewProps, ChangeEventPayload };\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,YAAY,GAEb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,wCAAwC,MAAM,4CAA4C,CAAC;AAMlG,MAAM,UAAU,KAAK;IACnB,OAAO,wCAAwC,CAAC,KAAK,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,OAAO,wCAAwC,CAAC,IAAI,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,wCAAwC,CAAC,WAAW,EAAE,CAAC;AAChE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,OAAO,wCAAwC,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;AAC/E,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,wCAAwC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;AACtE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,wCAAwC,CAAC,aAAa,EAAE,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,OAAO,wCAAwC,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;AAC1E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,wCAAwC,CAAC,YAAY,EAAE,CAAC;AACjE,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,YAAY,CAC9B,wCAAwC;IACtC,kBAAkB,CAAC,kCAAkC,CACxD,CAAC;AAEF,MAAM,UAAU,YAAY,CAC1B,QAA6C;IAE7C,OAAO,OAAO,CAAC,WAAW,CAAqB,cAAc,EAAE,QAAQ,CAAC,CAAC;AAC3E,CAAC;AAOD;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CACtB,QAA6C;IAE7C,OAAO,OAAO,CAAC,WAAW,CAAqB,UAAU,EAAE,QAAQ,CAAC,CAAC;AACvE,CAAC","sourcesContent":["import {\n NativeModulesProxy,\n EventEmitter,\n Subscription,\n} from \"expo-modules-core\";\n\nimport ReactNativeSimpleNotePitchDetectorModule from \"./ReactNativeSimpleNotePitchDetectorModule\";\nimport {\n ChangeEventPayload,\n ReactNativeSimpleNotePitchDetectorViewProps,\n} from \"./ReactNativeSimpleNotePitchDetector.types\";\n\nexport function start() {\n return ReactNativeSimpleNotePitchDetectorModule.start();\n}\n\nexport function stop() {\n return ReactNativeSimpleNotePitchDetectorModule.stop();\n}\n\nexport function isRecording() {\n return ReactNativeSimpleNotePitchDetectorModule.isRecording();\n}\n\n/**\n * Set the minimum audio level threshold for pitch detection.\n * Values are in dB (e.g., -30 means sounds quieter than -30dB are ignored).\n * Lower values = more sensitive (picks up quieter sounds).\n * Default is -30.\n * @param threshold - Level threshold in dB (e.g., -30, -35, -40)\n */\nexport function setLevelThreshold(threshold: number) {\n return ReactNativeSimpleNotePitchDetectorModule.setLevelThreshold(threshold);\n}\n\n/**\n * Set the buffer size for pitch detection.\n * Must be called before start() or will restart the engine if already running.\n *\n * Buffer size affects the trade-off between frequency range and responsiveness:\n * - Smaller buffer (2048-4096): Better for high frequencies, faster response, but less accurate for low notes\n * - Larger buffer (8192-16384): Better for low frequencies, more accurate, but slightly more latency\n *\n * iOS defaults to 8192, Android defaults to 2048.\n *\n * Recommended values:\n * - 4096: Good balance for most use cases\n * - 8192: Better for bass instruments or full piano range (iOS default)\n * - 2048: Better for high-pitched instruments, faster response (Android default)\n *\n * @param size - Buffer size (must be power of 2: 1024, 2048, 4096, 8192, 16384)\n */\nexport function setBufferSize(size: number) {\n return ReactNativeSimpleNotePitchDetectorModule.setBufferSize(size);\n}\n\n/**\n * Get the current buffer size.\n * @returns Current buffer size\n */\nexport function getBufferSize(): number {\n return ReactNativeSimpleNotePitchDetectorModule.getBufferSize();\n}\n\n/**\n * Set the pitch estimation algorithm.\n * Must be called before start() or will restart the engine if already running.\n *\n * Available algorithms differ by platform:\n *\n * **iOS (Beethoven library):**\n * - \"yin\" (default) - YIN algorithm, good for monophonic instruments\n * - \"hps\" - Harmonic Product Spectrum\n * - \"barycentric\" - Barycentric interpolation\n * - \"quadradic\" - Quadratic interpolation\n * - \"jains\" - Jain's method\n * - \"quinnsFirst\" - Quinn's first estimator\n * - \"quinnsSecond\" - Quinn's second estimator\n * - \"maxValue\" - Maximum value method\n *\n * **Android (TarsosDSP library):**\n * - \"fft_yin\" (default) - FFT-based YIN, faster than pure YIN\n * - \"yin\" - Pure YIN algorithm\n * - \"mpm\" - McLeod Pitch Method, good for speech and music\n * - \"fft_pitch\" - FFT bin with most energy\n * - \"dynamic_wavelet\" - Dynamic wavelet algorithm\n * - \"amdf\" - Average Magnitude Difference Function\n *\n * @param algorithm - Algorithm name (case-insensitive)\n */\nexport function setAlgorithm(algorithm: string) {\n return ReactNativeSimpleNotePitchDetectorModule.setAlgorithm(algorithm);\n}\n\n/**\n * Get the current algorithm name.\n * @returns Current algorithm name\n */\nexport function getAlgorithm(): string {\n return ReactNativeSimpleNotePitchDetectorModule.getAlgorithm();\n}\n\nconst emitter = new EventEmitter(\n ReactNativeSimpleNotePitchDetectorModule ??\n NativeModulesProxy.ReactNativeSimpleNotePitchDetector\n);\n\nexport function onChangeNote(\n listener: (event: ChangeEventPayload) => void\n): Subscription {\n return emitter.addListener<ChangeEventPayload>(\"onChangeNote\", listener);\n}\n\nexport interface StatusEventPayload {\n level: \"debug\" | \"error\" | \"verbose\";\n message: string;\n}\n\n/**\n * Listen for status/debug messages from the native module.\n * Useful for debugging audio initialization issues.\n * @param listener - Callback that receives status events with level and message\n */\nexport function onStatus(\n listener: (event: StatusEventPayload) => void\n): Subscription {\n return emitter.addListener<StatusEventPayload>(\"onStatus\", listener);\n}\n\nexport { ReactNativeSimpleNotePitchDetectorViewProps, ChangeEventPayload };\n"]}
@@ -12,14 +12,23 @@ public class ReactNativeSimpleNotePitchDetectorModule: Module {
12
12
  private var estimationStrategy: EstimationStrategy = .yin
13
13
  private var _pitchEngine: PitchEngine?
14
14
 
15
+ private func sendStatus(_ level: String, _ message: String) {
16
+ self.sendEvent("onStatus", [
17
+ "level": level,
18
+ "message": message
19
+ ])
20
+ }
21
+
15
22
  public func definition() -> ModuleDefinition {
16
23
 
17
24
  Name("ReactNativeSimpleNotePitchDetector")
18
25
 
19
- Events("onChangeNote")
26
+ Events("onChangeNote", "onStatus")
20
27
 
21
28
  Function("start") {
29
+ self.sendStatus("debug", "start() called with bufferSize=\(self.bufferSize), algorithm=\(self.estimationStrategy)")
22
30
  self.pitchEngine.start()
31
+ self.sendStatus("debug", "Recording started successfully")
23
32
  }
24
33
 
25
34
  Function("stop") {
@@ -150,7 +159,7 @@ extension ReactNativeSimpleNotePitchDetectorModule: PitchEngineDelegate {
150
159
  }
151
160
 
152
161
  public func pitchEngine(_ pitchEngine: PitchEngine, didReceiveError error: Error) {
153
- // Optionally send error events to JS
162
+ self.sendStatus("error", "PitchEngine error: \(error.localizedDescription)")
154
163
  }
155
164
 
156
165
  public func pitchEngineWentBelowLevelThreshold(_ pitchEngine: PitchEngine) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-simple-note-pitch-detector",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "a simple react native library to detect the pitch of the input recording",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -39,4 +39,4 @@
39
39
  "react": "*",
40
40
  "react-native": "*"
41
41
  }
42
- }
42
+ }
package/src/index.ts CHANGED
@@ -111,4 +111,20 @@ export function onChangeNote(
111
111
  return emitter.addListener<ChangeEventPayload>("onChangeNote", listener);
112
112
  }
113
113
 
114
+ export interface StatusEventPayload {
115
+ level: "debug" | "error" | "verbose";
116
+ message: string;
117
+ }
118
+
119
+ /**
120
+ * Listen for status/debug messages from the native module.
121
+ * Useful for debugging audio initialization issues.
122
+ * @param listener - Callback that receives status events with level and message
123
+ */
124
+ export function onStatus(
125
+ listener: (event: StatusEventPayload) => void
126
+ ): Subscription {
127
+ return emitter.addListener<StatusEventPayload>("onStatus", listener);
128
+ }
129
+
114
130
  export { ReactNativeSimpleNotePitchDetectorViewProps, ChangeEventPayload };