react-native-simple-note-pitch-detector 0.3.3 → 0.3.6

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.
@@ -6,7 +6,6 @@ import be.tarsos.dsp.io.android.AudioDispatcherFactory
6
6
  import be.tarsos.dsp.pitch.PitchDetectionHandler
7
7
  import be.tarsos.dsp.pitch.PitchProcessor
8
8
  import be.tarsos.dsp.pitch.PitchProcessor.PitchEstimationAlgorithm
9
- import kotlin.math.floor
10
9
  import kotlin.math.log2
11
10
  import kotlin.math.round
12
11
 
@@ -21,7 +20,7 @@ class PitchAnalyzer {
21
20
  private val notesBuffer = Array(6) { NoteAndDecibel() }
22
21
  private var counter = 0
23
22
 
24
- private lateinit var onChangePitch: (String) -> Unit
23
+ private lateinit var onChangeNote: (String) -> Unit
25
24
  private var isRecording = false
26
25
 
27
26
  private var dispatcher: AudioDispatcher? = null
@@ -42,21 +41,18 @@ class PitchAnalyzer {
42
41
  }
43
42
 
44
43
  private fun process(pitchInHz: Float, decibel: Float) {
45
- val freq = round(12 * (log2(pitchInHz / 440) / log2(2f)) + 69)
46
- val octave = (floor(freq / 12) - 1).toInt()
47
- val index = freq % 12
44
+ val index = round(12 * (log2(pitchInHz / 440) / log2(2f)) + 69) % 12
48
45
 
49
46
  if (!index.isNaN() && pitchInHz > 0) {
50
47
  val note = notes[index.toInt()]
51
48
  var noteAndDecibel = NoteAndDecibel(note, decibel)
52
49
 
53
50
  if (counter == notesBuffer.size) {
54
- var s = ""
55
- for (noteAndDecibel in notesBuffer) {
56
- s += noteAndDecibel.note + "*" + noteAndDecibel.decibel + ","
51
+ var mostFrequentNote = getMostFrequentNote(notesBuffer)
52
+
53
+ if (mostFrequentNote != null) {
54
+ onChangeNote(mostFrequentNote)
57
55
  }
58
- this.onChangePitch(s.substring(0, s.length - 1))
59
- counter = 0
60
56
  }
61
57
 
62
58
  notesBuffer[counter] = noteAndDecibel
@@ -64,8 +60,8 @@ class PitchAnalyzer {
64
60
  }
65
61
  }
66
62
 
67
- fun addOnChangePitchListener(onChangePitch: (String) -> Unit) {
68
- this.onChangePitch = onChangePitch
63
+ fun addOnChangeNoteListener(onChangeNote: (String) -> Unit) {
64
+ this.onChangeNote = onChangeNote
69
65
  }
70
66
 
71
67
  fun start() {
@@ -83,4 +79,31 @@ class PitchAnalyzer {
83
79
  fun isRecording(): Boolean {
84
80
  return isRecording
85
81
  }
82
+
83
+ private fun getMostFrequentNote(notes: Array<NoteAndDecibel>) : String? {
84
+ val noteToDecibel = mutableMapOf<String, Float>();
85
+ notes.forEach {
86
+ if (!noteToDecibel.containsKey(it.note)) {
87
+ noteToDecibel[it.note] = 0f
88
+ }
89
+
90
+ noteToDecibel[it.note] = noteToDecibel[it.note]!! + it.decibel
91
+ }
92
+
93
+ var mostFrequentNote = ""
94
+ var maxDecibel = 0f
95
+
96
+ noteToDecibel.forEach {
97
+ if (mostFrequentNote == "" || it.value < maxDecibel) {
98
+ mostFrequentNote = it.key
99
+ maxDecibel = it.value
100
+ }
101
+ }
102
+
103
+ if (mostFrequentNote == "") {
104
+ return null
105
+ }
106
+
107
+ return mostFrequentNote
108
+ }
86
109
  }
@@ -13,17 +13,17 @@ class ReactNativeSimpleNotePitchDetectorModule : Module() {
13
13
 
14
14
  Name("ReactNativeSimpleNotePitchDetector")
15
15
 
16
- Events("onChangePitch")
16
+ Events("onChangeNote")
17
17
 
18
18
  Function("isRecording") {
19
19
  pitchAnalyzer.isRecording()
20
20
  }
21
21
 
22
22
  Function("start") {
23
- pitchAnalyzer.addOnChangePitchListener { note: String->
23
+ pitchAnalyzer.addOnChangeNoteListener { note: String ->
24
24
  this@ReactNativeSimpleNotePitchDetectorModule.sendEvent(
25
- "onChangePitch",
26
- bundleOf("note" to note, "soundPressure" to "")
25
+ "onChangeNote",
26
+ bundleOf("note" to note)
27
27
  )
28
28
  }
29
29
 
@@ -1,6 +1,5 @@
1
1
  export type ChangeEventPayload = {
2
2
  note: string;
3
- soundPressure: number;
4
3
  };
5
4
  export type ReactNativeSimpleNotePitchDetectorViewProps = {
6
5
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ReactNativeSimpleNotePitchDetector.types.d.ts","sourceRoot":"","sources":["../src/ReactNativeSimpleNotePitchDetector.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,2CAA2C,GAAG;IACxD,IAAI,EAAE,MAAM,CAAC;CACd,CAAC"}
1
+ {"version":3,"file":"ReactNativeSimpleNotePitchDetector.types.d.ts","sourceRoot":"","sources":["../src/ReactNativeSimpleNotePitchDetector.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,2CAA2C,GAAG;IACxD,IAAI,EAAE,MAAM,CAAC;CACd,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReactNativeSimpleNotePitchDetector.types.js","sourceRoot":"","sources":["../src/ReactNativeSimpleNotePitchDetector.types.ts"],"names":[],"mappings":"","sourcesContent":["export type ChangeEventPayload = {\n note: string;\n soundPressure: number;\n};\n\nexport type ReactNativeSimpleNotePitchDetectorViewProps = {\n name: string;\n};\n"]}
1
+ {"version":3,"file":"ReactNativeSimpleNotePitchDetector.types.js","sourceRoot":"","sources":["../src/ReactNativeSimpleNotePitchDetector.types.ts"],"names":[],"mappings":"","sourcesContent":["export type ChangeEventPayload = {\n note: string;\n};\n\nexport type ReactNativeSimpleNotePitchDetectorViewProps = {\n name: string;\n};\n"]}
@@ -1,4 +1,4 @@
1
1
  import * as React from "react";
2
2
  import { ReactNativeSimpleNotePitchDetectorViewProps } from "./ReactNativeSimpleNotePitchDetector.types";
3
- export default function ExpoSettingsView(props: ReactNativeSimpleNotePitchDetectorViewProps): React.JSX.Element;
3
+ export default function ReactNativeSimpleNotePitchDetectorView(props: ReactNativeSimpleNotePitchDetectorViewProps): React.JSX.Element;
4
4
  //# sourceMappingURL=ReactNativeSimpleNotePitchDetector.web.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReactNativeSimpleNotePitchDetector.web.d.ts","sourceRoot":"","sources":["../src/ReactNativeSimpleNotePitchDetector.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,2CAA2C,EAAE,MAAM,4CAA4C,CAAC;AAEzG,MAAM,CAAC,OAAO,UAAU,gBAAgB,CACtC,KAAK,EAAE,2CAA2C,qBAOnD"}
1
+ {"version":3,"file":"ReactNativeSimpleNotePitchDetector.web.d.ts","sourceRoot":"","sources":["../src/ReactNativeSimpleNotePitchDetector.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,2CAA2C,EAAE,MAAM,4CAA4C,CAAC;AAEzG,MAAM,CAAC,OAAO,UAAU,sCAAsC,CAC5D,KAAK,EAAE,2CAA2C,qBAOnD"}
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- export default function ExpoSettingsView(props) {
2
+ export default function ReactNativeSimpleNotePitchDetectorView(props) {
3
3
  return (React.createElement("div", null,
4
4
  React.createElement("span", null, props.name)));
5
5
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ReactNativeSimpleNotePitchDetector.web.js","sourceRoot":"","sources":["../src/ReactNativeSimpleNotePitchDetector.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,CAAC,OAAO,UAAU,gBAAgB,CACtC,KAAkD;IAElD,OAAO,CACL;QACE,kCAAO,KAAK,CAAC,IAAI,CAAQ,CACrB,CACP,CAAC;AACJ,CAAC","sourcesContent":["import * as React from \"react\";\n\nimport { ReactNativeSimpleNotePitchDetectorViewProps } from \"./ReactNativeSimpleNotePitchDetector.types\";\n\nexport default function ExpoSettingsView(\n props: ReactNativeSimpleNotePitchDetectorViewProps\n) {\n return (\n <div>\n <span>{props.name}</span>\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"ReactNativeSimpleNotePitchDetector.web.js","sourceRoot":"","sources":["../src/ReactNativeSimpleNotePitchDetector.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,CAAC,OAAO,UAAU,sCAAsC,CAC5D,KAAkD;IAElD,OAAO,CACL;QACE,kCAAO,KAAK,CAAC,IAAI,CAAQ,CACrB,CACP,CAAC;AACJ,CAAC","sourcesContent":["import * as React from \"react\";\n\nimport { ReactNativeSimpleNotePitchDetectorViewProps } from \"./ReactNativeSimpleNotePitchDetector.types\";\n\nexport default function ReactNativeSimpleNotePitchDetectorView(\n props: ReactNativeSimpleNotePitchDetectorViewProps\n) {\n return (\n <div>\n <span>{props.name}</span>\n </div>\n );\n}\n"]}
package/build/index.d.ts CHANGED
@@ -3,6 +3,6 @@ import { ChangeEventPayload, ReactNativeSimpleNotePitchDetectorViewProps } from
3
3
  export declare function start(): any;
4
4
  export declare function stop(): any;
5
5
  export declare function isRecording(): any;
6
- export declare function onChangePitch(listener: (event: ChangeEventPayload) => void): Subscription;
6
+ export declare function onChangeNote(listener: (event: ChangeEventPayload) => void): Subscription;
7
7
  export { ReactNativeSimpleNotePitchDetectorViewProps, ChangeEventPayload };
8
8
  //# 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;AAOD,wBAAgB,aAAa,CAC3B,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;AAOD,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAC5C,YAAY,CAEd;AAED,OAAO,EAAE,2CAA2C,EAAE,kBAAkB,EAAE,CAAC"}
package/build/index.js CHANGED
@@ -11,7 +11,7 @@ export function isRecording() {
11
11
  }
12
12
  const emitter = new EventEmitter(ReactNativeSimpleNotePitchDetectorModule ??
13
13
  NativeModulesProxy.ReactNativeSimpleNotePitchDetector);
14
- export function onChangePitch(listener) {
15
- return emitter.addListener("onChangePitch", listener);
14
+ export function onChangeNote(listener) {
15
+ return emitter.addListener("onChangeNote", listener);
16
16
  }
17
17
  //# 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,MAAM,OAAO,GAAG,IAAI,YAAY,CAC9B,wCAAwC;IACtC,kBAAkB,CAAC,kCAAkC,CACxD,CAAC;AAEF,MAAM,UAAU,aAAa,CAC3B,QAA6C;IAE7C,OAAO,OAAO,CAAC,WAAW,CAAqB,eAAe,EAAE,QAAQ,CAAC,CAAC;AAC5E,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\nconst emitter = new EventEmitter(\n ReactNativeSimpleNotePitchDetectorModule ??\n NativeModulesProxy.ReactNativeSimpleNotePitchDetector\n);\n\nexport function onChangePitch(\n listener: (event: ChangeEventPayload) => void\n): Subscription {\n return emitter.addListener<ChangeEventPayload>(\"onChangePitch\", 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,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\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"]}
@@ -2,12 +2,33 @@ import ExpoModulesCore
2
2
  import Beethoven
3
3
  import Pitchy
4
4
 
5
+
6
+ let NOTE_BUFFER_SIZE = 3
7
+
5
8
  public class ReactNativeSimpleNotePitchDetectorModule: Module {
6
9
 
7
- var bufferSize = 3
8
- var notes = Array(repeating: "", count: 3)
10
+ var notes = Array(repeating: "", count: NOTE_BUFFER_SIZE)
9
11
  var counter = 0
10
12
 
13
+ public func definition() -> ModuleDefinition {
14
+
15
+ Name("ReactNativeSimpleNotePitchDetector")
16
+
17
+ Events("onChangeNote")
18
+
19
+ Function("start") {
20
+ pitchEngine.start()
21
+ }
22
+
23
+ Function("stop") {
24
+ pitchEngine.stop()
25
+ }
26
+
27
+ Function("isRecording") {
28
+ return pitchEngine.active
29
+ }
30
+ }
31
+
11
32
  lazy var pitchEngine: PitchEngine = { [weak self] in
12
33
  let config = Config(estimationStrategy: .yin)
13
34
  let pitchEngine = PitchEngine(config: config, delegate: self)
@@ -15,13 +36,11 @@ public class ReactNativeSimpleNotePitchDetectorModule: Module {
15
36
  return pitchEngine
16
37
  }()
17
38
 
18
- func mostFrequent(array: [String]) -> String? {
39
+ func getMostFrequentNote(notes: [String]) -> String? {
19
40
  var counts = [String: Int]()
20
41
 
21
- // Count the values with using forEach
22
- array.forEach { counts[$0] = (counts[$0] ?? 0) + 1 }
23
-
24
- // Find the most frequent value and its count with max(by:)
42
+ notes.forEach { counts[$0] = (counts[$0] ?? 0) + 1 }
43
+
25
44
  if let (value, count) = counts.max(by: {$0.1 < $1.1}) {
26
45
  if (count <= 1) {
27
46
  return nil
@@ -31,29 +50,6 @@ public class ReactNativeSimpleNotePitchDetectorModule: Module {
31
50
 
32
51
  return nil
33
52
  }
34
-
35
- var isRecording = false
36
-
37
- public func definition() -> ModuleDefinition {
38
-
39
- Name("ReactNativeSimpleNotePitchDetector")
40
-
41
- Events("onChangePitch")
42
-
43
- Function("start") {
44
- pitchEngine.start()
45
- isRecording = true
46
- }
47
-
48
- Function("stop") {
49
- pitchEngine.stop()
50
- isRecording = false
51
- }
52
-
53
- Function("isRecording") {
54
- return isRecording
55
- }
56
- }
57
53
  }
58
54
 
59
55
  extension ReactNativeSimpleNotePitchDetectorModule: PitchEngineDelegate {
@@ -67,10 +63,10 @@ extension ReactNativeSimpleNotePitchDetectorModule: PitchEngineDelegate {
67
63
  return
68
64
  }
69
65
 
70
- if (counter == bufferSize) {
71
- var result = mostFrequent(array: notes)
72
- if (result != nil) {
73
- self.sendEvent("onChangePitch", ["note" : result, "soundPressure" : ""])
66
+ if (counter == notes.count) {
67
+ var note = getMostFrequentNote(notes: notes)
68
+ if (note != nil) {
69
+ self.sendEvent("onChangeNote", ["note" : note])
74
70
  }
75
71
  counter = 0
76
72
  }
@@ -82,8 +78,6 @@ extension ReactNativeSimpleNotePitchDetectorModule: PitchEngineDelegate {
82
78
  } catch {
83
79
 
84
80
  }
85
-
86
- // self.sendEvent("onChangePitch", ["note" : pitch.note.string, "soundPressure" : pitchEngine.signalLevel])
87
81
  }
88
82
 
89
83
  public func pitchEngine(_ pitchEngine: PitchEngine, didReceiveError error: Error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-simple-note-pitch-detector",
3
- "version": "0.3.3",
3
+ "version": "0.3.6",
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",
@@ -1,6 +1,5 @@
1
1
  export type ChangeEventPayload = {
2
2
  note: string;
3
- soundPressure: number;
4
3
  };
5
4
 
6
5
  export type ReactNativeSimpleNotePitchDetectorViewProps = {
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
 
3
3
  import { ReactNativeSimpleNotePitchDetectorViewProps } from "./ReactNativeSimpleNotePitchDetector.types";
4
4
 
5
- export default function ExpoSettingsView(
5
+ export default function ReactNativeSimpleNotePitchDetectorView(
6
6
  props: ReactNativeSimpleNotePitchDetectorViewProps
7
7
  ) {
8
8
  return (
package/src/index.ts CHANGED
@@ -27,10 +27,10 @@ const emitter = new EventEmitter(
27
27
  NativeModulesProxy.ReactNativeSimpleNotePitchDetector
28
28
  );
29
29
 
30
- export function onChangePitch(
30
+ export function onChangeNote(
31
31
  listener: (event: ChangeEventPayload) => void
32
32
  ): Subscription {
33
- return emitter.addListener<ChangeEventPayload>("onChangePitch", listener);
33
+ return emitter.addListener<ChangeEventPayload>("onChangeNote", listener);
34
34
  }
35
35
 
36
36
  export { ReactNativeSimpleNotePitchDetectorViewProps, ChangeEventPayload };