react-native-audio-api 0.1.0 → 0.3.0-rc1

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 (217) hide show
  1. package/README.md +10 -8
  2. package/RNAudioAPI.podspec +5 -0
  3. package/android/CMakeLists.txt +21 -10
  4. package/android/libs/fftw3/arm64-v8a/libfftw3.a +0 -0
  5. package/android/libs/fftw3/armeabi-v7a/libfftw3.a +0 -0
  6. package/android/libs/fftw3/x86/libfftw3.a +0 -0
  7. package/android/libs/fftw3/x86_64/libfftw3.a +0 -0
  8. package/android/libs/include/fftw3/fftw3.h +413 -0
  9. package/android/src/main/cpp/AudioPlayer/AudioPlayer.cpp +32 -2
  10. package/android/src/main/cpp/AudioPlayer/AudioPlayer.h +6 -2
  11. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.cpp +5 -3
  12. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.h +5 -1
  13. package/common/cpp/HostObjects/AudioBufferHostObject.cpp +6 -0
  14. package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.cpp +13 -1
  15. package/common/cpp/HostObjects/AudioContextHostObject.cpp +12 -149
  16. package/common/cpp/HostObjects/AudioContextHostObject.h +8 -14
  17. package/common/cpp/HostObjects/AudioNodeHostObject.cpp +0 -6
  18. package/common/cpp/HostObjects/BaseAudioContextHostObject.cpp +240 -0
  19. package/common/cpp/HostObjects/BaseAudioContextHostObject.h +41 -0
  20. package/common/cpp/HostObjects/BiquadFilterNodeHostObject.cpp +44 -0
  21. package/common/cpp/HostObjects/OscillatorNodeHostObject.cpp +21 -0
  22. package/common/cpp/HostObjects/OscillatorNodeHostObject.h +1 -0
  23. package/common/cpp/HostObjects/PeriodicWaveHostObject.cpp +33 -0
  24. package/common/cpp/HostObjects/PeriodicWaveHostObject.h +33 -0
  25. package/common/cpp/core/AudioArray.cpp +117 -0
  26. package/common/cpp/core/AudioArray.h +48 -0
  27. package/common/cpp/core/AudioBuffer.cpp +23 -80
  28. package/common/cpp/core/AudioBuffer.h +12 -13
  29. package/common/cpp/core/AudioBufferSourceNode.cpp +112 -25
  30. package/common/cpp/core/AudioBufferSourceNode.h +10 -6
  31. package/common/cpp/core/AudioBus.cpp +518 -0
  32. package/common/cpp/core/AudioBus.h +83 -0
  33. package/common/cpp/core/AudioContext.cpp +7 -77
  34. package/common/cpp/core/AudioContext.h +3 -60
  35. package/common/cpp/core/AudioDestinationNode.cpp +27 -15
  36. package/common/cpp/core/AudioDestinationNode.h +13 -5
  37. package/common/cpp/core/AudioNode.cpp +184 -22
  38. package/common/cpp/core/AudioNode.h +37 -37
  39. package/common/cpp/core/AudioNodeManager.cpp +75 -0
  40. package/common/cpp/core/AudioNodeManager.h +42 -0
  41. package/common/cpp/core/AudioParam.cpp +8 -11
  42. package/common/cpp/core/AudioParam.h +8 -8
  43. package/common/cpp/core/AudioScheduledSourceNode.cpp +19 -5
  44. package/common/cpp/core/AudioScheduledSourceNode.h +6 -2
  45. package/common/cpp/core/BaseAudioContext.cpp +191 -0
  46. package/common/cpp/core/BaseAudioContext.h +87 -0
  47. package/common/cpp/core/BiquadFilterNode.cpp +92 -69
  48. package/common/cpp/core/BiquadFilterNode.h +53 -57
  49. package/common/cpp/core/GainNode.cpp +12 -12
  50. package/common/cpp/core/GainNode.h +5 -3
  51. package/common/cpp/core/OscillatorNode.cpp +38 -29
  52. package/common/cpp/core/OscillatorNode.h +29 -69
  53. package/common/cpp/core/ParamChange.h +6 -6
  54. package/common/cpp/core/PeriodicWave.cpp +362 -0
  55. package/common/cpp/core/PeriodicWave.h +119 -0
  56. package/common/cpp/core/StereoPannerNode.cpp +31 -30
  57. package/common/cpp/core/StereoPannerNode.h +6 -6
  58. package/common/cpp/types/BiquadFilterType.h +19 -0
  59. package/common/cpp/types/ChannelCountMode.h +10 -0
  60. package/common/cpp/types/ChannelInterpretation.h +10 -0
  61. package/common/cpp/types/ContextState.h +10 -0
  62. package/common/cpp/types/OscillatorType.h +11 -0
  63. package/common/cpp/utils/FFTFrame.h +67 -0
  64. package/common/cpp/utils/JsiPromise.cpp +59 -0
  65. package/common/cpp/utils/JsiPromise.h +42 -0
  66. package/common/cpp/utils/Locker.h +49 -0
  67. package/common/cpp/utils/VectorMath.cpp +88 -3
  68. package/common/cpp/utils/VectorMath.h +7 -1
  69. package/common/cpp/utils/android/FFTFrame.cpp +23 -0
  70. package/common/cpp/utils/ios/FFTFrame.cpp +29 -0
  71. package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.cpp +10 -0
  72. package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.h +3 -2
  73. package/common/cpp/wrappers/AudioBufferWrapper.h +5 -5
  74. package/common/cpp/wrappers/AudioContextWrapper.cpp +7 -60
  75. package/common/cpp/wrappers/AudioContextWrapper.h +5 -26
  76. package/common/cpp/wrappers/AudioNodeWrapper.h +5 -5
  77. package/common/cpp/wrappers/AudioParamWrapper.h +4 -4
  78. package/common/cpp/wrappers/BaseAudioContextWrapper.cpp +83 -0
  79. package/common/cpp/wrappers/BaseAudioContextWrapper.h +50 -0
  80. package/common/cpp/wrappers/BiquadFilterNodeWrapper.cpp +9 -0
  81. package/common/cpp/wrappers/BiquadFilterNodeWrapper.h +9 -4
  82. package/common/cpp/wrappers/GainNodeWrapper.h +1 -1
  83. package/common/cpp/wrappers/OscillatorNodeWrapper.cpp +6 -0
  84. package/common/cpp/wrappers/OscillatorNodeWrapper.h +5 -2
  85. package/common/cpp/wrappers/PeriodicWaveWrapper.h +17 -0
  86. package/common/cpp/wrappers/StereoPannerNodeWrapper.h +1 -1
  87. package/ios/AudioAPIModule.h +20 -1
  88. package/ios/AudioAPIModule.mm +6 -4
  89. package/ios/AudioDecoder/AudioDecoder.h +17 -0
  90. package/ios/AudioDecoder/AudioDecoder.m +167 -0
  91. package/ios/AudioDecoder/IOSAudioDecoder.h +26 -0
  92. package/ios/AudioDecoder/IOSAudioDecoder.mm +40 -0
  93. package/ios/AudioPlayer/AudioPlayer.h +3 -2
  94. package/ios/AudioPlayer/AudioPlayer.m +14 -17
  95. package/ios/AudioPlayer/IOSAudioPlayer.h +7 -3
  96. package/ios/AudioPlayer/IOSAudioPlayer.mm +31 -7
  97. package/lib/module/core/AudioBuffer.js +37 -0
  98. package/lib/module/core/AudioBuffer.js.map +1 -0
  99. package/lib/module/core/AudioBufferSourceNode.js +28 -0
  100. package/lib/module/core/AudioBufferSourceNode.js.map +1 -0
  101. package/lib/module/core/AudioContext.js +10 -0
  102. package/lib/module/core/AudioContext.js.map +1 -0
  103. package/lib/module/core/AudioDestinationNode.js +7 -0
  104. package/lib/module/core/AudioDestinationNode.js.map +1 -0
  105. package/lib/module/core/AudioNode.js +22 -0
  106. package/lib/module/core/AudioNode.js.map +1 -0
  107. package/lib/module/core/AudioParam.js +35 -0
  108. package/lib/module/core/AudioParam.js.map +1 -0
  109. package/lib/module/core/AudioScheduledSourceNode.js +28 -0
  110. package/lib/module/core/AudioScheduledSourceNode.js.map +1 -0
  111. package/lib/module/core/BaseAudioContext.js +62 -0
  112. package/lib/module/core/BaseAudioContext.js.map +1 -0
  113. package/lib/module/core/BiquadFilterNode.js +25 -0
  114. package/lib/module/core/BiquadFilterNode.js.map +1 -0
  115. package/lib/module/core/GainNode.js +9 -0
  116. package/lib/module/core/GainNode.js.map +1 -0
  117. package/lib/module/core/OscillatorNode.js +24 -0
  118. package/lib/module/core/OscillatorNode.js.map +1 -0
  119. package/lib/module/core/PeriodicWave.js +8 -0
  120. package/lib/module/core/PeriodicWave.js.map +1 -0
  121. package/lib/module/core/StereoPannerNode.js +9 -0
  122. package/lib/module/core/StereoPannerNode.js.map +1 -0
  123. package/lib/module/core/types.js.map +1 -0
  124. package/lib/module/errors/IndexSizeError.js +8 -0
  125. package/lib/module/errors/IndexSizeError.js.map +1 -0
  126. package/lib/module/errors/InvalidAccessError.js +8 -0
  127. package/lib/module/errors/InvalidAccessError.js.map +1 -0
  128. package/lib/module/errors/InvalidStateError.js +8 -0
  129. package/lib/module/errors/InvalidStateError.js.map +1 -0
  130. package/lib/module/errors/RangeError.js +8 -0
  131. package/lib/module/errors/RangeError.js.map +1 -0
  132. package/lib/module/errors/index.js +5 -0
  133. package/lib/module/errors/index.js.map +1 -0
  134. package/lib/module/index.js +212 -15
  135. package/lib/module/index.js.map +1 -1
  136. package/lib/module/index.native.js +18 -0
  137. package/lib/module/index.native.js.map +1 -0
  138. package/lib/module/interfaces.js +2 -0
  139. package/lib/module/interfaces.js.map +1 -0
  140. package/lib/module/utils/resolveAudioSource.js +10 -0
  141. package/lib/module/utils/resolveAudioSource.js.map +1 -0
  142. package/lib/typescript/core/AudioBuffer.d.ts +12 -0
  143. package/lib/typescript/core/AudioBuffer.d.ts.map +1 -0
  144. package/lib/typescript/core/AudioBufferSourceNode.d.ts +12 -0
  145. package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -0
  146. package/lib/typescript/core/AudioContext.d.ts +6 -0
  147. package/lib/typescript/core/AudioContext.d.ts.map +1 -0
  148. package/lib/typescript/core/AudioDestinationNode.d.ts +7 -0
  149. package/lib/typescript/core/AudioDestinationNode.d.ts.map +1 -0
  150. package/lib/typescript/core/AudioNode.d.ts +16 -0
  151. package/lib/typescript/core/AudioNode.d.ts.map +1 -0
  152. package/lib/typescript/core/AudioParam.d.ts +14 -0
  153. package/lib/typescript/core/AudioParam.d.ts.map +1 -0
  154. package/lib/typescript/core/AudioScheduledSourceNode.d.ts +10 -0
  155. package/lib/typescript/core/AudioScheduledSourceNode.d.ts.map +1 -0
  156. package/lib/typescript/core/BaseAudioContext.d.ts +27 -0
  157. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -0
  158. package/lib/typescript/core/BiquadFilterNode.d.ts +16 -0
  159. package/lib/typescript/core/BiquadFilterNode.d.ts.map +1 -0
  160. package/lib/typescript/core/GainNode.d.ts +9 -0
  161. package/lib/typescript/core/GainNode.d.ts.map +1 -0
  162. package/lib/typescript/core/OscillatorNode.d.ts +15 -0
  163. package/lib/typescript/core/OscillatorNode.d.ts.map +1 -0
  164. package/lib/typescript/core/PeriodicWave.d.ts +5 -0
  165. package/lib/typescript/core/PeriodicWave.d.ts.map +1 -0
  166. package/lib/typescript/core/StereoPannerNode.d.ts +9 -0
  167. package/lib/typescript/core/StereoPannerNode.d.ts.map +1 -0
  168. package/lib/typescript/core/types.d.ts +15 -0
  169. package/lib/typescript/core/types.d.ts.map +1 -0
  170. package/lib/typescript/errors/IndexSizeError.d.ts +5 -0
  171. package/lib/typescript/errors/IndexSizeError.d.ts.map +1 -0
  172. package/lib/typescript/errors/InvalidAccessError.d.ts +5 -0
  173. package/lib/typescript/errors/InvalidAccessError.d.ts.map +1 -0
  174. package/lib/typescript/errors/InvalidStateError.d.ts +5 -0
  175. package/lib/typescript/errors/InvalidStateError.d.ts.map +1 -0
  176. package/lib/typescript/errors/RangeError.d.ts +5 -0
  177. package/lib/typescript/errors/RangeError.d.ts.map +1 -0
  178. package/lib/typescript/errors/index.d.ts +5 -0
  179. package/lib/typescript/errors/index.d.ts.map +1 -0
  180. package/lib/typescript/index.d.ts +88 -5
  181. package/lib/typescript/index.d.ts.map +1 -1
  182. package/lib/typescript/index.native.d.ts +14 -0
  183. package/lib/typescript/index.native.d.ts.map +1 -0
  184. package/lib/typescript/interfaces.d.ts +79 -0
  185. package/lib/typescript/interfaces.d.ts.map +1 -0
  186. package/lib/typescript/utils/resolveAudioSource.d.ts +3 -0
  187. package/lib/typescript/utils/resolveAudioSource.d.ts.map +1 -0
  188. package/package.json +4 -2
  189. package/src/core/AudioBuffer.ts +68 -0
  190. package/src/core/AudioBufferSourceNode.ts +35 -0
  191. package/src/core/AudioContext.ts +12 -0
  192. package/src/core/AudioDestinationNode.ts +9 -0
  193. package/src/core/AudioNode.ts +38 -0
  194. package/src/core/AudioParam.ts +55 -0
  195. package/src/core/AudioScheduledSourceNode.ts +43 -0
  196. package/src/core/BaseAudioContext.ts +108 -0
  197. package/src/core/BiquadFilterNode.ts +49 -0
  198. package/src/core/GainNode.ts +13 -0
  199. package/src/core/OscillatorNode.ts +37 -0
  200. package/src/core/PeriodicWave.ts +10 -0
  201. package/src/core/StereoPannerNode.ts +13 -0
  202. package/src/core/types.ts +33 -0
  203. package/src/errors/IndexSizeError.ts +8 -0
  204. package/src/errors/InvalidAccessError.ts +8 -0
  205. package/src/errors/InvalidStateError.ts +8 -0
  206. package/src/errors/RangeError.ts +8 -0
  207. package/src/errors/index.ts +4 -0
  208. package/src/index.native.ts +25 -0
  209. package/src/index.ts +380 -40
  210. package/src/interfaces.ts +121 -0
  211. package/src/modules/global.d.ts +3 -3
  212. package/src/utils/resolveAudioSource.ts +14 -0
  213. package/lib/module/types.js.map +0 -1
  214. package/lib/typescript/types.d.ts +0 -76
  215. package/lib/typescript/types.d.ts.map +0 -1
  216. package/src/types.ts +0 -108
  217. /package/lib/module/{types.js → core/types.js} +0 -0
@@ -0,0 +1,49 @@
1
+ import { InvalidAccessError } from '../errors';
2
+ import { IBiquadFilterNode } from '../interfaces';
3
+ import AudioNode from './AudioNode';
4
+ import AudioParam from './AudioParam';
5
+ import BaseAudioContext from './BaseAudioContext';
6
+ import { BiquadFilterType } from './types';
7
+
8
+ export default class BiquadFilterNode extends AudioNode {
9
+ readonly frequency: AudioParam;
10
+ readonly detune: AudioParam;
11
+ readonly Q: AudioParam;
12
+ readonly gain: AudioParam;
13
+
14
+ constructor(context: BaseAudioContext, biquadFilter: IBiquadFilterNode) {
15
+ super(context, biquadFilter);
16
+ this.frequency = new AudioParam(biquadFilter.frequency);
17
+ this.detune = new AudioParam(biquadFilter.detune);
18
+ this.Q = new AudioParam(biquadFilter.Q);
19
+ this.gain = new AudioParam(biquadFilter.gain);
20
+ }
21
+
22
+ public get type(): BiquadFilterType {
23
+ return (this.node as IBiquadFilterNode).type;
24
+ }
25
+
26
+ public set type(value: BiquadFilterType) {
27
+ (this.node as IBiquadFilterNode).type = value;
28
+ }
29
+
30
+ public getFrequencyResponse(
31
+ frequencyArray: number[],
32
+ magResponseOutput: number[],
33
+ phaseResponseOutput: number[]
34
+ ) {
35
+ if (
36
+ frequencyArray.length !== magResponseOutput.length ||
37
+ frequencyArray.length !== phaseResponseOutput.length
38
+ ) {
39
+ throw new InvalidAccessError(
40
+ `The lengths of the arrays are not the same frequencyArray: ${frequencyArray.length}, magResponseOutput: ${magResponseOutput.length}, phaseResponseOutput: ${phaseResponseOutput.length}`
41
+ );
42
+ }
43
+ (this.node as IBiquadFilterNode).getFrequencyResponse(
44
+ frequencyArray,
45
+ magResponseOutput,
46
+ phaseResponseOutput
47
+ );
48
+ }
49
+ }
@@ -0,0 +1,13 @@
1
+ import { IGainNode } from '../interfaces';
2
+ import AudioNode from './AudioNode';
3
+ import AudioParam from './AudioParam';
4
+ import BaseAudioContext from './BaseAudioContext';
5
+
6
+ export default class GainNode extends AudioNode {
7
+ readonly gain: AudioParam;
8
+
9
+ constructor(context: BaseAudioContext, gain: IGainNode) {
10
+ super(context, gain);
11
+ this.gain = new AudioParam(gain.gain);
12
+ }
13
+ }
@@ -0,0 +1,37 @@
1
+ import { IOscillatorNode } from '../interfaces';
2
+ import { OscillatorType } from './types';
3
+ import AudioScheduledSourceNode from './AudioScheduledSourceNode';
4
+ import AudioParam from './AudioParam';
5
+ import BaseAudioContext from './BaseAudioContext';
6
+ import PeriodicWave from './PeriodicWave';
7
+ import { InvalidStateError } from '../errors';
8
+
9
+ export default class OscillatorNode extends AudioScheduledSourceNode {
10
+ readonly frequency: AudioParam;
11
+ readonly detune: AudioParam;
12
+
13
+ constructor(context: BaseAudioContext, node: IOscillatorNode) {
14
+ super(context, node);
15
+ this.frequency = new AudioParam(node.frequency);
16
+ this.detune = new AudioParam(node.detune);
17
+ this.type = node.type;
18
+ }
19
+
20
+ public get type(): OscillatorType {
21
+ return (this.node as IOscillatorNode).type;
22
+ }
23
+
24
+ public set type(value: OscillatorType) {
25
+ if (value === 'custom') {
26
+ throw new InvalidStateError(
27
+ "'type' cannot be set directly to 'custom'. Use setPeriodicWave() to create a custom Oscillator type."
28
+ );
29
+ }
30
+
31
+ (this.node as IOscillatorNode).type = value;
32
+ }
33
+
34
+ public setPeriodicWave(wave: PeriodicWave): void {
35
+ (this.node as IOscillatorNode).setPeriodicWave(wave.periodicWave);
36
+ }
37
+ }
@@ -0,0 +1,10 @@
1
+ import { IPeriodicWave } from '../interfaces';
2
+
3
+ export default class PeriodicWave {
4
+ /** @internal */
5
+ public readonly periodicWave: IPeriodicWave;
6
+
7
+ constructor(periodicWave: IPeriodicWave) {
8
+ this.periodicWave = periodicWave;
9
+ }
10
+ }
@@ -0,0 +1,13 @@
1
+ import { IStereoPannerNode } from '../interfaces';
2
+ import AudioNode from './AudioNode';
3
+ import AudioParam from './AudioParam';
4
+ import BaseAudioContext from './BaseAudioContext';
5
+
6
+ export default class StereoPannerNode extends AudioNode {
7
+ readonly pan: AudioParam;
8
+
9
+ constructor(context: BaseAudioContext, pan: IStereoPannerNode) {
10
+ super(context, pan);
11
+ this.pan = new AudioParam(pan.pan);
12
+ }
13
+ }
@@ -0,0 +1,33 @@
1
+ export type ChannelCountMode = 'max' | 'clamped-max' | 'explicit';
2
+
3
+ export type ChannelInterpretation = 'speakers' | 'discrete';
4
+
5
+ export type BiquadFilterType =
6
+ | 'lowpass'
7
+ | 'highpass'
8
+ | 'bandpass'
9
+ | 'lowshelf'
10
+ | 'highshelf'
11
+ | 'peaking'
12
+ | 'notch'
13
+ | 'allpass';
14
+
15
+ export type ContextState = 'running' | 'closed';
16
+
17
+ export type OscillatorType =
18
+ | 'sine'
19
+ | 'square'
20
+ | 'sawtooth'
21
+ | 'triangle'
22
+ | 'custom';
23
+
24
+ export interface PeriodicWaveConstraints {
25
+ disableNormalization: boolean;
26
+ }
27
+
28
+ /**
29
+ * A type that defines the source of the audio which can be expressed in several forms:
30
+ * 1. A string path, which could be an HTTPS URL or a local file path.
31
+ * 2. A string, which is a result of resolving an asset source.
32
+ */
33
+ export type AudioSource = string;
@@ -0,0 +1,8 @@
1
+ class IndexSizeError extends Error {
2
+ constructor(message: string) {
3
+ super(message);
4
+ this.name = 'IndexSizeError';
5
+ }
6
+ }
7
+
8
+ export default IndexSizeError;
@@ -0,0 +1,8 @@
1
+ class InvalidAccessError extends Error {
2
+ constructor(message: string) {
3
+ super(message);
4
+ this.name = 'InvalidAccessError';
5
+ }
6
+ }
7
+
8
+ export default InvalidAccessError;
@@ -0,0 +1,8 @@
1
+ class InvalidStateError extends Error {
2
+ constructor(message: string) {
3
+ super(message);
4
+ this.name = 'InvalidStateError';
5
+ }
6
+ }
7
+
8
+ export default InvalidStateError;
@@ -0,0 +1,8 @@
1
+ class RangeError extends Error {
2
+ constructor(message: string) {
3
+ super(message);
4
+ this.name = 'RangeError';
5
+ }
6
+ }
7
+
8
+ export default RangeError;
@@ -0,0 +1,4 @@
1
+ export { default as IndexSizeError } from './IndexSizeError';
2
+ export { default as InvalidAccessError } from './InvalidAccessError';
3
+ export { default as InvalidStateError } from './InvalidStateError';
4
+ export { default as RangeError } from './RangeError';
@@ -0,0 +1,25 @@
1
+ import { installModule } from './utils/install';
2
+
3
+ if (global.__AudioAPIInstaller == null) {
4
+ installModule();
5
+ }
6
+
7
+ export { default as AudioBuffer } from './core/AudioBuffer';
8
+ export { default as AudioBufferSourceNode } from './core/AudioBufferSourceNode';
9
+ export { default as AudioContext } from './core/AudioContext';
10
+ export { default as AudioDestinationNode } from './core/AudioDestinationNode';
11
+ export { default as AudioNode } from './core/AudioNode';
12
+ export { default as AudioParam } from './core/AudioParam';
13
+ export { default as AudioScheduledSourceNode } from './core/AudioScheduledSourceNode';
14
+ export { default as BaseAudioContext } from './core/BaseAudioContext';
15
+ export { default as BiquadFilterNode } from './core/BiquadFilterNode';
16
+ export { default as GainNode } from './core/GainNode';
17
+ export { default as OscillatorNode } from './core/OscillatorNode';
18
+ export { default as StereoPannerNode } from './core/StereoPannerNode';
19
+ export {
20
+ OscillatorType,
21
+ BiquadFilterType,
22
+ ChannelCountMode,
23
+ ChannelInterpretation,
24
+ ContextState,
25
+ } from './core/types';
package/src/index.ts CHANGED
@@ -1,58 +1,374 @@
1
- import type {
2
- BaseAudioContext,
3
- AudioDestinationNode,
4
- GainNode,
5
- StereoPannerNode,
6
- OscillatorNode,
7
- BiquadFilterNode,
8
- AudioBufferSourceNode,
9
- AudioBuffer,
10
- WaveType,
11
- } from './types';
12
- import { installModule } from './utils/install';
13
-
14
- if (global.__AudioAPIInstaller == null) {
15
- installModule();
1
+ import {
2
+ AudioSource,
3
+ ContextState,
4
+ PeriodicWaveConstraints,
5
+ } from './core/types';
6
+
7
+ export class AudioBuffer {
8
+ readonly length: number;
9
+ readonly duration: number;
10
+ readonly sampleRate: number;
11
+ readonly numberOfChannels: number;
12
+
13
+ public readonly buffer: globalThis.AudioBuffer;
14
+
15
+ constructor(buffer: globalThis.AudioBuffer) {
16
+ this.buffer = buffer;
17
+ this.length = buffer.length;
18
+ this.duration = buffer.duration;
19
+ this.sampleRate = buffer.sampleRate;
20
+ this.numberOfChannels = buffer.numberOfChannels;
21
+ }
22
+
23
+ public getChannelData(channel: number): number[] {
24
+ if (channel < 0 || channel >= this.numberOfChannels) {
25
+ throw new Error(
26
+ `The channel number provided (${channel}) is outside the range [0, ${this.numberOfChannels - 1}]`
27
+ );
28
+ }
29
+
30
+ // TODO: we probably will want to move to Float32Array on native side too
31
+ return Array.from(this.buffer.getChannelData(channel));
32
+ }
33
+
34
+ public copyFromChannel(
35
+ destination: number[],
36
+ channelNumber: number,
37
+ startInChannel: number = 0
38
+ ): void {
39
+ if (channelNumber < 0 || channelNumber >= this.numberOfChannels) {
40
+ throw new Error(
41
+ `The channel number provided (${channelNumber}) is outside the range [0, ${this.numberOfChannels - 1}]`
42
+ );
43
+ }
44
+
45
+ if (startInChannel < 0 || startInChannel >= this.length) {
46
+ throw new Error(
47
+ `The startInChannel number provided (${startInChannel}) is outside the range [0, ${this.length - 1}]`
48
+ );
49
+ }
50
+
51
+ this.buffer.copyFromChannel(
52
+ new Float32Array(destination),
53
+ channelNumber,
54
+ startInChannel
55
+ );
56
+ }
57
+
58
+ public copyToChannel(
59
+ source: number[],
60
+ channelNumber: number,
61
+ startInChannel: number = 0
62
+ ): void {
63
+ if (channelNumber < 0 || channelNumber >= this.numberOfChannels) {
64
+ throw new Error(
65
+ `The channel number provided (${channelNumber}) is outside the range [0, ${this.numberOfChannels - 1}]`
66
+ );
67
+ }
68
+
69
+ if (startInChannel < 0 || startInChannel >= this.length) {
70
+ throw new Error(
71
+ `The startInChannel number provided (${startInChannel}) is outside the range [0, ${this.length - 1}]`
72
+ );
73
+ }
74
+
75
+ this.buffer.copyToChannel(
76
+ new Float32Array(source),
77
+ channelNumber,
78
+ startInChannel
79
+ );
80
+ }
81
+ }
82
+
83
+ export class AudioNode {
84
+ readonly context: AudioContext;
85
+ readonly numberOfInputs: number;
86
+ readonly numberOfOutputs: number;
87
+ readonly channelCount: number;
88
+ readonly channelCountMode: ChannelCountMode;
89
+ readonly channelInterpretation: ChannelInterpretation;
90
+
91
+ protected readonly node: globalThis.AudioNode;
92
+
93
+ constructor(context: AudioContext, node: globalThis.AudioNode) {
94
+ this.context = context;
95
+ this.node = node;
96
+ this.numberOfInputs = this.node.numberOfInputs;
97
+ this.numberOfOutputs = this.node.numberOfOutputs;
98
+ this.channelCount = this.node.channelCount;
99
+ this.channelCountMode = this.node.channelCountMode;
100
+ this.channelInterpretation = this.node.channelInterpretation;
101
+ }
102
+
103
+ public connect(node: AudioNode): void {
104
+ if (this.context !== node.context) {
105
+ throw new Error('The AudioNodes are from different BaseAudioContexts');
106
+ }
107
+
108
+ this.node.connect(node.node);
109
+ }
110
+
111
+ public disconnect(node: AudioNode): void {
112
+ this.node.disconnect(node.node);
113
+ }
114
+ }
115
+
116
+ export class AudioScheduledSourceNode extends AudioNode {
117
+ private hasBeenStarted: boolean = false;
118
+
119
+ constructor(
120
+ context: AudioContext,
121
+ node: globalThis.AudioScheduledSourceNode
122
+ ) {
123
+ super(context, node);
124
+ }
125
+
126
+ public start(when: number = 0): void {
127
+ if (when < 0) {
128
+ throw new RangeError(
129
+ `Time must be a finite non-negative number: ${when}`
130
+ );
131
+ }
132
+
133
+ if (this.hasBeenStarted) {
134
+ throw new Error('Cannot call start more than once');
135
+ }
136
+
137
+ this.hasBeenStarted = true;
138
+ (this.node as globalThis.AudioScheduledSourceNode).start(when);
139
+ }
140
+
141
+ public stop(when: number = 0): void {
142
+ if (when < 0) {
143
+ throw new RangeError(
144
+ `Time must be a finite non-negative number: ${when}`
145
+ );
146
+ }
147
+
148
+ if (!this.hasBeenStarted) {
149
+ throw new Error('Cannot call stop without calling start first');
150
+ }
151
+
152
+ (this.node as globalThis.AudioScheduledSourceNode).stop(when);
153
+ }
154
+ }
155
+
156
+ export class AudioBufferSourceNode extends AudioScheduledSourceNode {
157
+ constructor(context: AudioContext, node: globalThis.AudioBufferSourceNode) {
158
+ super(context, node);
159
+ }
160
+
161
+ public get buffer(): AudioBuffer | null {
162
+ const buffer = (this.node as globalThis.AudioBufferSourceNode).buffer;
163
+
164
+ if (!buffer) {
165
+ return null;
166
+ }
167
+
168
+ return new AudioBuffer(buffer);
169
+ }
170
+
171
+ public set buffer(buffer: AudioBuffer | null) {
172
+ if (!buffer) {
173
+ (this.node as globalThis.AudioBufferSourceNode | null) = null;
174
+ return;
175
+ }
176
+
177
+ (this.node as globalThis.AudioBufferSourceNode).buffer = buffer.buffer;
178
+ }
179
+
180
+ public get loop(): boolean {
181
+ return (this.node as globalThis.AudioBufferSourceNode).loop;
182
+ }
183
+
184
+ public set loop(value: boolean) {
185
+ (this.node as globalThis.AudioBufferSourceNode).loop = value;
186
+ }
187
+ }
188
+
189
+ export class AudioDestinationNode extends AudioNode {
190
+ constructor(context: AudioContext, node: globalThis.AudioDestinationNode) {
191
+ super(context, node);
192
+ }
193
+ }
194
+
195
+ export class AudioParam {
196
+ readonly defaultValue: number;
197
+ readonly minValue: number;
198
+ readonly maxValue: number;
199
+
200
+ private readonly param: globalThis.AudioParam;
201
+
202
+ constructor(param: globalThis.AudioParam) {
203
+ this.param = param;
204
+ this.defaultValue = param.defaultValue;
205
+ this.minValue = param.minValue;
206
+ this.maxValue = param.maxValue;
207
+ }
208
+
209
+ public get value(): number {
210
+ return this.param.value;
211
+ }
212
+
213
+ public set value(value: number) {
214
+ this.param.value = value;
215
+ }
216
+
217
+ public setValueAtTime(value: number, startTime: number): void {
218
+ this.param.setValueAtTime(value, startTime);
219
+ }
220
+
221
+ public linearRampToValueAtTime(value: number, endTime: number): void {
222
+ this.param.linearRampToValueAtTime(value, endTime);
223
+ }
224
+
225
+ public exponentialRampToValueAtTime(value: number, endTime: number): void {
226
+ this.param.exponentialRampToValueAtTime(value, endTime);
227
+ }
228
+ }
229
+
230
+ export class BiquadFilterNode extends AudioNode {
231
+ readonly frequency: AudioParam;
232
+ readonly detune: AudioParam;
233
+ readonly Q: AudioParam;
234
+ readonly gain: AudioParam;
235
+
236
+ constructor(
237
+ context: AudioContext,
238
+ biquadFilter: globalThis.BiquadFilterNode
239
+ ) {
240
+ super(context, biquadFilter);
241
+ this.frequency = new AudioParam(biquadFilter.frequency);
242
+ this.detune = new AudioParam(biquadFilter.detune);
243
+ this.Q = new AudioParam(biquadFilter.Q);
244
+ this.gain = new AudioParam(biquadFilter.gain);
245
+ }
246
+
247
+ public get type(): BiquadFilterType {
248
+ return (this.node as globalThis.BiquadFilterNode).type;
249
+ }
250
+
251
+ public set type(value: BiquadFilterType) {
252
+ (this.node as globalThis.BiquadFilterNode).type = value;
253
+ }
254
+
255
+ public getFrequencyResponse(
256
+ frequencyArray: number[],
257
+ magResponseOutput: number[],
258
+ phaseResponseOutput: number[]
259
+ ) {
260
+ if (
261
+ frequencyArray.length !== magResponseOutput.length ||
262
+ frequencyArray.length !== phaseResponseOutput.length
263
+ ) {
264
+ throw new Error(
265
+ `The lengths of the arrays are not the same frequencyArray: ${frequencyArray.length}, magResponseOutput: ${magResponseOutput.length}, phaseResponseOutput: ${phaseResponseOutput.length}`
266
+ );
267
+ }
268
+
269
+ (this.node as globalThis.BiquadFilterNode).getFrequencyResponse(
270
+ new Float32Array(frequencyArray),
271
+ new Float32Array(magResponseOutput),
272
+ new Float32Array(phaseResponseOutput)
273
+ );
274
+ }
275
+ }
276
+
277
+ export class PeriodicWave {
278
+ readonly periodicWave: globalThis.PeriodicWave;
279
+
280
+ constructor(periodicWave: globalThis.PeriodicWave) {
281
+ this.periodicWave = periodicWave;
282
+ }
283
+ }
284
+
285
+ export class OscillatorNode extends AudioScheduledSourceNode {
286
+ readonly frequency: AudioParam;
287
+ readonly detune: AudioParam;
288
+
289
+ constructor(context: AudioContext, node: globalThis.OscillatorNode) {
290
+ super(context, node);
291
+
292
+ this.detune = new AudioParam(node.detune);
293
+ this.frequency = new AudioParam(node.frequency);
294
+ }
295
+
296
+ public get type(): OscillatorType {
297
+ return (this.node as globalThis.OscillatorNode).type;
298
+ }
299
+
300
+ public set type(value: OscillatorType) {
301
+ if (value === 'custom') {
302
+ throw new Error(
303
+ "'type' cannot be set directly to 'custom'. Use setPeriodicWave() to create a custom Oscillator type."
304
+ );
305
+ }
306
+
307
+ (this.node as globalThis.OscillatorNode).type = value;
308
+ }
309
+
310
+ public setPeriodicWave(wave: PeriodicWave): void {
311
+ (this.node as globalThis.OscillatorNode).setPeriodicWave(wave.periodicWave);
312
+ }
313
+ }
314
+
315
+ export class GainNode extends AudioNode {
316
+ readonly gain: AudioParam;
317
+
318
+ constructor(context: AudioContext, gain: globalThis.GainNode) {
319
+ super(context, gain);
320
+ this.gain = new AudioParam(gain.gain);
321
+ }
322
+ }
323
+
324
+ export class StereoPannerNode extends AudioNode {
325
+ readonly pan: AudioParam;
326
+
327
+ constructor(context: AudioContext, pan: globalThis.StereoPannerNode) {
328
+ super(context, pan);
329
+ this.pan = new AudioParam(pan.pan);
330
+ }
16
331
  }
17
332
 
18
- export class AudioContext implements BaseAudioContext {
333
+ export class AudioContext {
334
+ protected readonly context: globalThis.AudioContext;
335
+
19
336
  readonly destination: AudioDestinationNode;
20
337
  readonly sampleRate: number;
21
- private readonly __AudioContext: BaseAudioContext;
22
338
 
23
339
  constructor() {
24
- this.__AudioContext = global.__AudioAPIInstaller.createAudioContext();
340
+ this.context = new window.AudioContext();
25
341
 
26
- this.destination = this.__AudioContext.destination;
27
- this.sampleRate = this.__AudioContext.sampleRate;
342
+ this.sampleRate = this.context.sampleRate;
343
+ this.destination = new AudioDestinationNode(this, this.context.destination);
28
344
  }
29
345
 
30
- public get currentTime() {
31
- return this.__AudioContext.currentTime;
346
+ public get currentTime(): number {
347
+ return this.context.currentTime;
32
348
  }
33
349
 
34
- public get state() {
35
- return this.__AudioContext.state;
350
+ public get state(): ContextState {
351
+ return this.context.state as ContextState;
36
352
  }
37
353
 
38
354
  createOscillator(): OscillatorNode {
39
- return this.__AudioContext.createOscillator();
355
+ return new OscillatorNode(this, this.context.createOscillator());
40
356
  }
41
357
 
42
358
  createGain(): GainNode {
43
- return this.__AudioContext.createGain();
359
+ return new GainNode(this, this.context.createGain());
44
360
  }
45
361
 
46
362
  createStereoPanner(): StereoPannerNode {
47
- return this.__AudioContext.createStereoPanner();
363
+ return new StereoPannerNode(this, this.context.createStereoPanner());
48
364
  }
49
365
 
50
366
  createBiquadFilter(): BiquadFilterNode {
51
- return this.__AudioContext.createBiquadFilter();
367
+ return new BiquadFilterNode(this, this.context.createBiquadFilter());
52
368
  }
53
369
 
54
370
  createBufferSource(): AudioBufferSourceNode {
55
- return this.__AudioContext.createBufferSource();
371
+ return new AudioBufferSourceNode(this, this.context.createBufferSource());
56
372
  }
57
373
 
58
374
  createBuffer(
@@ -60,20 +376,44 @@ export class AudioContext implements BaseAudioContext {
60
376
  length: number,
61
377
  sampleRate: number
62
378
  ): AudioBuffer {
63
- return this.__AudioContext.createBuffer(numOfChannels, length, sampleRate);
379
+ return new AudioBuffer(
380
+ this.context.createBuffer(numOfChannels, length, sampleRate)
381
+ );
382
+ }
383
+
384
+ createPeriodicWave(
385
+ real: number[],
386
+ imag: number[],
387
+ constraints?: PeriodicWaveConstraints
388
+ ): PeriodicWave {
389
+ return new PeriodicWave(
390
+ this.context.createPeriodicWave(real, imag, constraints)
391
+ );
392
+ }
393
+
394
+ async decodeAudioDataSource(
395
+ source: AudioSource | number
396
+ ): Promise<AudioBuffer> {
397
+ if (typeof source === 'number') {
398
+ throw new Error('Not yet implemented');
399
+ }
400
+
401
+ const arrayBuffer = await fetch(source).then((response) =>
402
+ response.arrayBuffer()
403
+ );
404
+
405
+ return new AudioBuffer(await this.context.decodeAudioData(arrayBuffer));
64
406
  }
65
407
 
66
408
  close(): void {
67
- this.__AudioContext.close();
409
+ this.context.close();
68
410
  }
69
411
  }
70
412
 
71
- export type {
72
- GainNode,
73
- StereoPannerNode,
74
- OscillatorNode,
75
- BiquadFilterNode,
76
- AudioBufferSourceNode,
77
- AudioBuffer,
78
- WaveType,
79
- };
413
+ export {
414
+ ContextState,
415
+ OscillatorType,
416
+ BiquadFilterType,
417
+ ChannelCountMode,
418
+ ChannelInterpretation,
419
+ } from './core/types';