react-native-audio-api 0.4.8-rc1 → 0.4.8
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/android/build.gradle +25 -2
- package/android/src/main/cpp/core/AudioDecoder.cpp +10 -1
- package/android/src/main/cpp/core/AudioPlayer.cpp +6 -3
- package/common/cpp/core/AnalyserNode.cpp +2 -6
- package/common/cpp/core/AudioBuffer.cpp +1 -1
- package/common/cpp/core/AudioBufferSourceNode.cpp +26 -16
- package/common/cpp/core/AudioBus.cpp +105 -13
- package/common/cpp/core/AudioBus.h +6 -4
- package/common/cpp/core/AudioContext.cpp +4 -3
- package/common/cpp/core/AudioContext.h +4 -4
- package/common/cpp/core/AudioDestinationNode.cpp +2 -3
- package/common/cpp/core/AudioNode.cpp +78 -58
- package/common/cpp/core/AudioNode.h +10 -1
- package/common/cpp/core/AudioNodeManager.cpp +13 -1
- package/common/cpp/core/AudioNodeManager.h +2 -0
- package/common/cpp/core/AudioScheduledSourceNode.cpp +5 -1
- package/common/cpp/core/BaseAudioContext.cpp +4 -1
- package/common/cpp/core/BaseAudioContext.h +4 -2
- package/common/cpp/core/StereoPannerNode.cpp +9 -12
- package/ios/core/AudioDecoder.mm +10 -1
- package/ios/core/AudioPlayer.m +4 -24
- package/ios/core/IOSAudioPlayer.mm +3 -3
- package/lib/module/core/AudioBufferSourceNode.js +2 -2
- package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
- package/lib/module/index.js +19 -335
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +18 -0
- package/lib/module/index.web.js.map +1 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/web-core/AnalyserNode.js +48 -0
- package/lib/module/web-core/AnalyserNode.js.map +1 -0
- package/lib/module/web-core/AudioBuffer.js +43 -0
- package/lib/module/web-core/AudioBuffer.js.map +1 -0
- package/lib/module/web-core/AudioBufferSourceNode.js +62 -0
- package/lib/module/web-core/AudioBufferSourceNode.js.map +1 -0
- package/lib/module/web-core/AudioContext.js +69 -0
- package/lib/module/web-core/AudioContext.js.map +1 -0
- package/lib/module/web-core/AudioDestinationNode.js +5 -0
- package/lib/module/web-core/AudioDestinationNode.js.map +1 -0
- package/lib/module/web-core/AudioNode.js +27 -0
- package/lib/module/web-core/AudioNode.js.map +1 -0
- package/lib/module/web-core/AudioParam.js +60 -0
- package/lib/module/web-core/AudioParam.js.map +1 -0
- package/lib/module/web-core/AudioScheduledSourceNode.js +27 -0
- package/lib/module/web-core/AudioScheduledSourceNode.js.map +1 -0
- package/lib/module/web-core/BaseAudioContext.js +2 -0
- package/lib/module/{core/types.js.map → web-core/BaseAudioContext.js.map} +1 -1
- package/lib/module/web-core/BiquadFilterNode.js +35 -0
- package/lib/module/web-core/BiquadFilterNode.js.map +1 -0
- package/lib/module/web-core/GainNode.js +11 -0
- package/lib/module/web-core/GainNode.js.map +1 -0
- package/lib/module/web-core/OscillatorNode.js +25 -0
- package/lib/module/web-core/OscillatorNode.js.map +1 -0
- package/lib/module/web-core/PeriodicWave.js +10 -0
- package/lib/module/web-core/PeriodicWave.js.map +1 -0
- package/lib/module/web-core/StereoPannerNode.js +11 -0
- package/lib/module/web-core/StereoPannerNode.js.map +1 -0
- package/lib/typescript/core/AnalyserNode.d.ts +1 -1
- package/lib/typescript/core/AnalyserNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioNode.d.ts +1 -1
- package/lib/typescript/core/AudioNode.d.ts.map +1 -1
- package/lib/typescript/core/BaseAudioContext.d.ts +1 -1
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/core/BiquadFilterNode.d.ts +1 -1
- package/lib/typescript/core/BiquadFilterNode.d.ts.map +1 -1
- package/lib/typescript/core/OscillatorNode.d.ts +1 -1
- package/lib/typescript/core/OscillatorNode.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +15 -126
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/index.web.d.ts +16 -0
- package/lib/typescript/index.web.d.ts.map +1 -0
- package/lib/typescript/interfaces.d.ts +1 -1
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/lib/typescript/types.d.ts.map +1 -0
- package/lib/typescript/web-core/AnalyserNode.d.ts +18 -0
- package/lib/typescript/web-core/AnalyserNode.d.ts.map +1 -0
- package/lib/typescript/web-core/AudioBuffer.d.ts +13 -0
- package/lib/typescript/web-core/AudioBuffer.d.ts.map +1 -0
- package/lib/typescript/web-core/AudioBufferSourceNode.d.ts +19 -0
- package/lib/typescript/web-core/AudioBufferSourceNode.d.ts.map +1 -0
- package/lib/typescript/web-core/AudioContext.d.ts +30 -0
- package/lib/typescript/web-core/AudioContext.d.ts.map +1 -0
- package/lib/typescript/web-core/AudioDestinationNode.d.ts +4 -0
- package/lib/typescript/web-core/AudioDestinationNode.d.ts.map +1 -0
- package/lib/typescript/web-core/AudioNode.d.ts +15 -0
- package/lib/typescript/web-core/AudioNode.d.ts.map +1 -0
- package/lib/typescript/web-core/AudioParam.d.ts +17 -0
- package/lib/typescript/web-core/AudioParam.d.ts.map +1 -0
- package/lib/typescript/web-core/AudioScheduledSourceNode.d.ts +7 -0
- package/lib/typescript/web-core/AudioScheduledSourceNode.d.ts.map +1 -0
- package/lib/typescript/web-core/BaseAudioContext.d.ts +27 -0
- package/lib/typescript/web-core/BaseAudioContext.d.ts.map +1 -0
- package/lib/typescript/web-core/BiquadFilterNode.d.ts +15 -0
- package/lib/typescript/web-core/BiquadFilterNode.d.ts.map +1 -0
- package/lib/typescript/web-core/GainNode.d.ts +8 -0
- package/lib/typescript/web-core/GainNode.d.ts.map +1 -0
- package/lib/typescript/web-core/OscillatorNode.d.ts +14 -0
- package/lib/typescript/web-core/OscillatorNode.d.ts.map +1 -0
- package/lib/typescript/web-core/PeriodicWave.d.ts +6 -0
- package/lib/typescript/web-core/PeriodicWave.d.ts.map +1 -0
- package/lib/typescript/web-core/StereoPannerNode.d.ts +8 -0
- package/lib/typescript/web-core/StereoPannerNode.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/core/AnalyserNode.ts +1 -1
- package/src/core/AudioBufferSourceNode.ts +2 -2
- package/src/core/AudioNode.ts +1 -1
- package/src/core/BaseAudioContext.ts +1 -1
- package/src/core/BiquadFilterNode.ts +1 -1
- package/src/core/OscillatorNode.ts +1 -1
- package/src/index.ts +30 -568
- package/src/index.web.ts +30 -0
- package/src/interfaces.ts +1 -1
- package/src/web-core/AnalyserNode.tsx +69 -0
- package/src/web-core/AudioBuffer.tsx +79 -0
- package/src/web-core/AudioBufferSourceNode.tsx +94 -0
- package/src/web-core/AudioContext.tsx +114 -0
- package/src/web-core/AudioDestinationNode.tsx +3 -0
- package/src/web-core/AudioNode.tsx +40 -0
- package/src/web-core/AudioParam.tsx +106 -0
- package/src/web-core/AudioScheduledSourceNode.tsx +37 -0
- package/src/web-core/BaseAudioContext.tsx +37 -0
- package/src/web-core/BiquadFilterNode.tsx +62 -0
- package/src/web-core/GainNode.tsx +12 -0
- package/src/web-core/OscillatorNode.tsx +36 -0
- package/src/web-core/PeriodicWave.tsx +8 -0
- package/src/web-core/StereoPannerNode.tsx +12 -0
- package/lib/module/index.native.js +0 -21
- package/lib/module/index.native.js.map +0 -1
- package/lib/typescript/core/types.d.ts.map +0 -1
- package/lib/typescript/index.native.d.ts +0 -15
- package/lib/typescript/index.native.d.ts.map +0 -1
- package/src/index.native.ts +0 -27
- /package/lib/module/{core/types.js → types.js} +0 -0
- /package/lib/typescript/{core/types.d.ts → types.d.ts} +0 -0
- /package/src/{core/types.ts → types.ts} +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { IndexSizeError } from '../errors';
|
|
2
|
+
|
|
3
|
+
export default class AudioBuffer {
|
|
4
|
+
readonly length: number;
|
|
5
|
+
readonly duration: number;
|
|
6
|
+
readonly sampleRate: number;
|
|
7
|
+
readonly numberOfChannels: number;
|
|
8
|
+
|
|
9
|
+
/** @internal */
|
|
10
|
+
public readonly buffer: globalThis.AudioBuffer;
|
|
11
|
+
|
|
12
|
+
constructor(buffer: globalThis.AudioBuffer) {
|
|
13
|
+
this.buffer = buffer;
|
|
14
|
+
this.length = buffer.length;
|
|
15
|
+
this.duration = buffer.duration;
|
|
16
|
+
this.sampleRate = buffer.sampleRate;
|
|
17
|
+
this.numberOfChannels = buffer.numberOfChannels;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public getChannelData(channel: number): number[] {
|
|
21
|
+
if (channel < 0 || channel >= this.numberOfChannels) {
|
|
22
|
+
throw new IndexSizeError(
|
|
23
|
+
`The channel number provided (${channel}) is outside the range [0, ${this.numberOfChannels - 1}]`
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return Array.from(this.buffer.getChannelData(channel));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public copyFromChannel(
|
|
31
|
+
destination: number[],
|
|
32
|
+
channelNumber: number,
|
|
33
|
+
startInChannel: number = 0
|
|
34
|
+
): void {
|
|
35
|
+
if (channelNumber < 0 || channelNumber >= this.numberOfChannels) {
|
|
36
|
+
throw new IndexSizeError(
|
|
37
|
+
`The channel number provided (${channelNumber}) is outside the range [0, ${this.numberOfChannels - 1}]`
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (startInChannel < 0 || startInChannel >= this.length) {
|
|
42
|
+
throw new IndexSizeError(
|
|
43
|
+
`The startInChannel number provided (${startInChannel}) is outside the range [0, ${this.length - 1}]`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const array = new Float32Array(destination);
|
|
48
|
+
|
|
49
|
+
this.buffer.copyFromChannel(array, channelNumber, startInChannel);
|
|
50
|
+
|
|
51
|
+
for (let i = 0; i < destination.length; i++) {
|
|
52
|
+
destination[i] = array[i];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public copyToChannel(
|
|
57
|
+
source: number[],
|
|
58
|
+
channelNumber: number,
|
|
59
|
+
startInChannel: number = 0
|
|
60
|
+
): void {
|
|
61
|
+
if (channelNumber < 0 || channelNumber >= this.numberOfChannels) {
|
|
62
|
+
throw new IndexSizeError(
|
|
63
|
+
`The channel number provided (${channelNumber}) is outside the range [0, ${this.numberOfChannels - 1}]`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (startInChannel < 0 || startInChannel >= this.length) {
|
|
68
|
+
throw new IndexSizeError(
|
|
69
|
+
`The startInChannel number provided (${startInChannel}) is outside the range [0, ${this.length - 1}]`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
this.buffer.copyToChannel(
|
|
74
|
+
new Float32Array(source),
|
|
75
|
+
channelNumber,
|
|
76
|
+
startInChannel
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import AudioScheduledSourceNode from './AudioScheduledSourceNode';
|
|
2
|
+
import AudioParam from './AudioParam';
|
|
3
|
+
import AudioBuffer from './AudioBuffer';
|
|
4
|
+
import { InvalidStateError, RangeError } from '../errors';
|
|
5
|
+
import BaseAudioContext from './BaseAudioContext';
|
|
6
|
+
|
|
7
|
+
export default class AudioBufferSourceNode extends AudioScheduledSourceNode {
|
|
8
|
+
readonly playbackRate: AudioParam;
|
|
9
|
+
readonly detune: AudioParam;
|
|
10
|
+
|
|
11
|
+
constructor(
|
|
12
|
+
context: BaseAudioContext,
|
|
13
|
+
node: globalThis.AudioBufferSourceNode
|
|
14
|
+
) {
|
|
15
|
+
super(context, node);
|
|
16
|
+
|
|
17
|
+
this.detune = new AudioParam(node.detune);
|
|
18
|
+
this.playbackRate = new AudioParam(node.playbackRate);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public get buffer(): AudioBuffer | null {
|
|
22
|
+
const buffer = (this.node as globalThis.AudioBufferSourceNode).buffer;
|
|
23
|
+
|
|
24
|
+
if (!buffer) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return new AudioBuffer(buffer);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public set buffer(buffer: AudioBuffer | null) {
|
|
32
|
+
if (!buffer) {
|
|
33
|
+
(this.node as globalThis.AudioBufferSourceNode | null) = null;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
(this.node as globalThis.AudioBufferSourceNode).buffer = buffer.buffer;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public get loop(): boolean {
|
|
41
|
+
return (this.node as globalThis.AudioBufferSourceNode).loop;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public set loop(value: boolean) {
|
|
45
|
+
(this.node as globalThis.AudioBufferSourceNode).loop = value;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public get loopStart(): number {
|
|
49
|
+
return (this.node as globalThis.AudioBufferSourceNode).loopStart;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public set loopStart(value: number) {
|
|
53
|
+
(this.node as globalThis.AudioBufferSourceNode).loopStart = value;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public get loopEnd(): number {
|
|
57
|
+
return (this.node as globalThis.AudioBufferSourceNode).loopEnd;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public set loopEnd(value: number) {
|
|
61
|
+
(this.node as globalThis.AudioBufferSourceNode).loopEnd = value;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public start(when?: number, offset?: number, duration?: number): void {
|
|
65
|
+
if (when && when < 0) {
|
|
66
|
+
throw new RangeError(
|
|
67
|
+
`when must be a finite non-negative number: ${when}`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (offset && offset < 0) {
|
|
72
|
+
throw new RangeError(
|
|
73
|
+
`offset must be a finite non-negative number: ${offset}`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (duration && duration < 0) {
|
|
78
|
+
throw new RangeError(
|
|
79
|
+
`duration must be a finite non-negative number: ${duration}`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (this.hasBeenStarted) {
|
|
84
|
+
throw new InvalidStateError('Cannot call start more than once');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
this.hasBeenStarted = true;
|
|
88
|
+
(this.node as globalThis.AudioBufferSourceNode).start(
|
|
89
|
+
when,
|
|
90
|
+
offset,
|
|
91
|
+
duration
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { ContextState, PeriodicWaveConstraints } from '../types';
|
|
2
|
+
import { RangeError, InvalidAccessError } from '../errors';
|
|
3
|
+
import BaseAudioContext from './BaseAudioContext';
|
|
4
|
+
import AnalyserNode from './AnalyserNode';
|
|
5
|
+
import AudioDestinationNode from './AudioDestinationNode';
|
|
6
|
+
import AudioBuffer from './AudioBuffer';
|
|
7
|
+
import AudioBufferSourceNode from './AudioBufferSourceNode';
|
|
8
|
+
import BiquadFilterNode from './BiquadFilterNode';
|
|
9
|
+
import GainNode from './GainNode';
|
|
10
|
+
import OscillatorNode from './OscillatorNode';
|
|
11
|
+
import PeriodicWave from './PeriodicWave';
|
|
12
|
+
import StereoPannerNode from './StereoPannerNode';
|
|
13
|
+
|
|
14
|
+
export default class AudioContext implements BaseAudioContext {
|
|
15
|
+
readonly context: globalThis.AudioContext;
|
|
16
|
+
|
|
17
|
+
readonly destination: AudioDestinationNode;
|
|
18
|
+
readonly sampleRate: number;
|
|
19
|
+
|
|
20
|
+
constructor(_sampleRate?: number) {
|
|
21
|
+
this.context = new window.AudioContext();
|
|
22
|
+
|
|
23
|
+
this.sampleRate = this.context.sampleRate;
|
|
24
|
+
this.destination = new AudioDestinationNode(this, this.context.destination);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public get currentTime(): number {
|
|
28
|
+
return this.context.currentTime;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public get state(): ContextState {
|
|
32
|
+
return this.context.state as ContextState;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
createOscillator(): OscillatorNode {
|
|
36
|
+
return new OscillatorNode(this, this.context.createOscillator());
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
createGain(): GainNode {
|
|
40
|
+
return new GainNode(this, this.context.createGain());
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
createStereoPanner(): StereoPannerNode {
|
|
44
|
+
return new StereoPannerNode(this, this.context.createStereoPanner());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
createBiquadFilter(): BiquadFilterNode {
|
|
48
|
+
return new BiquadFilterNode(this, this.context.createBiquadFilter());
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
createBufferSource(): AudioBufferSourceNode {
|
|
52
|
+
return new AudioBufferSourceNode(this, this.context.createBufferSource());
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
createBuffer(
|
|
56
|
+
numOfChannels: number,
|
|
57
|
+
length: number,
|
|
58
|
+
sampleRate: number
|
|
59
|
+
): AudioBuffer {
|
|
60
|
+
if (numOfChannels < 1 || numOfChannels >= 32) {
|
|
61
|
+
throw new RangeError(
|
|
62
|
+
`The number of channels provided (${numOfChannels}) is outside the range [1, 32]`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (length <= 0) {
|
|
67
|
+
throw new RangeError(
|
|
68
|
+
`The number of frames provided (${length}) is less than or equal to the minimum bound (0)`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (sampleRate <= 0) {
|
|
73
|
+
throw new RangeError(
|
|
74
|
+
`The sample rate provided (${sampleRate}) is outside the range [3000, 768000]`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return new AudioBuffer(
|
|
79
|
+
this.context.createBuffer(numOfChannels, length, sampleRate)
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
createPeriodicWave(
|
|
84
|
+
real: number[],
|
|
85
|
+
imag: number[],
|
|
86
|
+
constraints?: PeriodicWaveConstraints
|
|
87
|
+
): PeriodicWave {
|
|
88
|
+
if (real.length !== imag.length) {
|
|
89
|
+
throw new InvalidAccessError(
|
|
90
|
+
`The lengths of the real (${real.length}) and imaginary (${imag.length}) arrays must match.`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return new PeriodicWave(
|
|
95
|
+
this.context.createPeriodicWave(real, imag, constraints)
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
createAnalyser(): AnalyserNode {
|
|
100
|
+
return new AnalyserNode(this, this.context.createAnalyser());
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async decodeAudioDataSource(source: string): Promise<AudioBuffer> {
|
|
104
|
+
const arrayBuffer = await fetch(source).then((response) =>
|
|
105
|
+
response.arrayBuffer()
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
return new AudioBuffer(await this.context.decodeAudioData(arrayBuffer));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async close(): Promise<void> {
|
|
112
|
+
await this.context.close();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import BaseAudioContext from './BaseAudioContext';
|
|
2
|
+
import { ChannelCountMode, ChannelInterpretation } from '../types';
|
|
3
|
+
|
|
4
|
+
export default class AudioNode {
|
|
5
|
+
readonly context: BaseAudioContext;
|
|
6
|
+
readonly numberOfInputs: number;
|
|
7
|
+
readonly numberOfOutputs: number;
|
|
8
|
+
readonly channelCount: number;
|
|
9
|
+
readonly channelCountMode: ChannelCountMode;
|
|
10
|
+
readonly channelInterpretation: ChannelInterpretation;
|
|
11
|
+
|
|
12
|
+
protected readonly node: globalThis.AudioNode;
|
|
13
|
+
|
|
14
|
+
constructor(context: BaseAudioContext, node: globalThis.AudioNode) {
|
|
15
|
+
this.context = context;
|
|
16
|
+
this.node = node;
|
|
17
|
+
this.numberOfInputs = this.node.numberOfInputs;
|
|
18
|
+
this.numberOfOutputs = this.node.numberOfOutputs;
|
|
19
|
+
this.channelCount = this.node.channelCount;
|
|
20
|
+
this.channelCountMode = this.node.channelCountMode;
|
|
21
|
+
this.channelInterpretation = this.node.channelInterpretation;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public connect(destination: AudioNode): void {
|
|
25
|
+
if (this.context !== destination.context) {
|
|
26
|
+
throw new Error('The AudioNodes are from different BaseAudioContexts');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.node.connect(destination.node);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public disconnect(destination?: AudioNode): void {
|
|
33
|
+
if (destination === undefined) {
|
|
34
|
+
this.node.disconnect();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
this.node.disconnect(destination.node);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { RangeError } from '../errors';
|
|
2
|
+
|
|
3
|
+
export default class AudioParam {
|
|
4
|
+
readonly defaultValue: number;
|
|
5
|
+
readonly minValue: number;
|
|
6
|
+
readonly maxValue: number;
|
|
7
|
+
|
|
8
|
+
private readonly param: globalThis.AudioParam;
|
|
9
|
+
|
|
10
|
+
constructor(param: globalThis.AudioParam) {
|
|
11
|
+
this.param = param;
|
|
12
|
+
this.defaultValue = param.defaultValue;
|
|
13
|
+
this.minValue = param.minValue;
|
|
14
|
+
this.maxValue = param.maxValue;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public get value(): number {
|
|
18
|
+
return this.param.value;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public set value(value: number) {
|
|
22
|
+
this.param.value = value;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public setValueAtTime(value: number, startTime: number): void {
|
|
26
|
+
if (startTime < 0) {
|
|
27
|
+
throw new RangeError(
|
|
28
|
+
`Time must be a finite non-negative number: ${startTime}`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this.param.setValueAtTime(value, startTime);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public linearRampToValueAtTime(value: number, endTime: number): void {
|
|
36
|
+
if (endTime < 0) {
|
|
37
|
+
throw new RangeError(
|
|
38
|
+
`Time must be a finite non-negative number: ${endTime}`
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
this.param.linearRampToValueAtTime(value, endTime);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public exponentialRampToValueAtTime(value: number, endTime: number): void {
|
|
46
|
+
if (endTime < 0) {
|
|
47
|
+
throw new RangeError(
|
|
48
|
+
`Time must be a finite non-negative number: ${endTime}`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.param.exponentialRampToValueAtTime(value, endTime);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public setTargetAtTime(
|
|
56
|
+
target: number,
|
|
57
|
+
startTime: number,
|
|
58
|
+
timeConstant: number
|
|
59
|
+
): void {
|
|
60
|
+
if (startTime < 0) {
|
|
61
|
+
throw new RangeError(
|
|
62
|
+
`Time must be a finite non-negative number: ${startTime}`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.param.setTargetAtTime(target, startTime, timeConstant);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public setValueCurveAtTime(
|
|
70
|
+
values: number[],
|
|
71
|
+
startTime: number,
|
|
72
|
+
duration: number
|
|
73
|
+
): void {
|
|
74
|
+
if (startTime < 0) {
|
|
75
|
+
throw new RangeError(
|
|
76
|
+
`Time must be a finite non-negative number: ${startTime}`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
this.param.setValueCurveAtTime(
|
|
81
|
+
new Float32Array(values),
|
|
82
|
+
startTime,
|
|
83
|
+
duration
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public cancelScheduledValues(cancelTime: number): void {
|
|
88
|
+
if (cancelTime < 0) {
|
|
89
|
+
throw new RangeError(
|
|
90
|
+
`Time must be a finite non-negative number: ${cancelTime}`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.param.cancelScheduledValues(cancelTime);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public cancelAndHoldAtTime(cancelTime: number): void {
|
|
98
|
+
if (cancelTime < 0) {
|
|
99
|
+
throw new RangeError(
|
|
100
|
+
`Time must be a finite non-negative number: ${cancelTime}`
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
this.param.cancelAndHoldAtTime(cancelTime);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import AudioNode from './AudioNode';
|
|
2
|
+
import { RangeError, InvalidStateError } from '../errors';
|
|
3
|
+
|
|
4
|
+
export default class AudioScheduledSourceNode extends AudioNode {
|
|
5
|
+
protected hasBeenStarted: boolean = false;
|
|
6
|
+
|
|
7
|
+
public start(when: number = 0): void {
|
|
8
|
+
if (when < 0) {
|
|
9
|
+
throw new RangeError(
|
|
10
|
+
`when must be a finite non-negative number: ${when}`
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (this.hasBeenStarted) {
|
|
15
|
+
throw new InvalidStateError('Cannot call start more than once');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
this.hasBeenStarted = true;
|
|
19
|
+
(this.node as globalThis.AudioScheduledSourceNode).start(when);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public stop(when: number = 0): void {
|
|
23
|
+
if (when < 0) {
|
|
24
|
+
throw new RangeError(
|
|
25
|
+
`when must be a finite non-negative number: ${when}`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!this.hasBeenStarted) {
|
|
30
|
+
throw new InvalidStateError(
|
|
31
|
+
'Cannot call stop without calling start first'
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
(this.node as globalThis.AudioScheduledSourceNode).stop(when);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ContextState, PeriodicWaveConstraints } from '../types';
|
|
2
|
+
import AnalyserNode from './AnalyserNode';
|
|
3
|
+
import AudioDestinationNode from './AudioDestinationNode';
|
|
4
|
+
import AudioBuffer from './AudioBuffer';
|
|
5
|
+
import AudioBufferSourceNode from './AudioBufferSourceNode';
|
|
6
|
+
import BiquadFilterNode from './BiquadFilterNode';
|
|
7
|
+
import GainNode from './GainNode';
|
|
8
|
+
import OscillatorNode from './OscillatorNode';
|
|
9
|
+
import PeriodicWave from './PeriodicWave';
|
|
10
|
+
import StereoPannerNode from './StereoPannerNode';
|
|
11
|
+
|
|
12
|
+
export default interface BaseAudioContext {
|
|
13
|
+
readonly context: globalThis.BaseAudioContext;
|
|
14
|
+
|
|
15
|
+
readonly destination: AudioDestinationNode;
|
|
16
|
+
readonly sampleRate: number;
|
|
17
|
+
|
|
18
|
+
get currentTime(): number;
|
|
19
|
+
get state(): ContextState;
|
|
20
|
+
createOscillator(): OscillatorNode;
|
|
21
|
+
createGain(): GainNode;
|
|
22
|
+
createStereoPanner(): StereoPannerNode;
|
|
23
|
+
createBiquadFilter(): BiquadFilterNode;
|
|
24
|
+
createBufferSource(): AudioBufferSourceNode;
|
|
25
|
+
createBuffer(
|
|
26
|
+
numOfChannels: number,
|
|
27
|
+
length: number,
|
|
28
|
+
sampleRate: number
|
|
29
|
+
): AudioBuffer;
|
|
30
|
+
createPeriodicWave(
|
|
31
|
+
real: number[],
|
|
32
|
+
imag: number[],
|
|
33
|
+
constraints?: PeriodicWaveConstraints
|
|
34
|
+
): PeriodicWave;
|
|
35
|
+
createAnalyser(): AnalyserNode;
|
|
36
|
+
decodeAudioDataSource(source: string): Promise<AudioBuffer>;
|
|
37
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import AudioParam from './AudioParam';
|
|
2
|
+
import AudioNode from './AudioNode';
|
|
3
|
+
import BaseAudioContext from './BaseAudioContext';
|
|
4
|
+
import { BiquadFilterType } from '../types';
|
|
5
|
+
import { InvalidAccessError } from '../errors';
|
|
6
|
+
|
|
7
|
+
export default class BiquadFilterNode extends AudioNode {
|
|
8
|
+
readonly frequency: AudioParam;
|
|
9
|
+
readonly detune: AudioParam;
|
|
10
|
+
readonly Q: AudioParam;
|
|
11
|
+
readonly gain: AudioParam;
|
|
12
|
+
|
|
13
|
+
constructor(
|
|
14
|
+
context: BaseAudioContext,
|
|
15
|
+
biquadFilter: globalThis.BiquadFilterNode
|
|
16
|
+
) {
|
|
17
|
+
super(context, biquadFilter);
|
|
18
|
+
this.frequency = new AudioParam(biquadFilter.frequency);
|
|
19
|
+
this.detune = new AudioParam(biquadFilter.detune);
|
|
20
|
+
this.Q = new AudioParam(biquadFilter.Q);
|
|
21
|
+
this.gain = new AudioParam(biquadFilter.gain);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public get type(): BiquadFilterType {
|
|
25
|
+
return (this.node as globalThis.BiquadFilterNode).type;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public set type(value: BiquadFilterType) {
|
|
29
|
+
(this.node as globalThis.BiquadFilterNode).type = value;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public getFrequencyResponse(
|
|
33
|
+
frequencyArray: number[],
|
|
34
|
+
magResponseOutput: number[],
|
|
35
|
+
phaseResponseOutput: number[]
|
|
36
|
+
) {
|
|
37
|
+
if (
|
|
38
|
+
frequencyArray.length !== magResponseOutput.length ||
|
|
39
|
+
frequencyArray.length !== phaseResponseOutput.length
|
|
40
|
+
) {
|
|
41
|
+
throw new InvalidAccessError(
|
|
42
|
+
`The lengths of the arrays are not the same frequencyArray: ${frequencyArray.length}, magResponseOutput: ${magResponseOutput.length}, phaseResponseOutput: ${phaseResponseOutput.length}`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
const magData = new Float32Array(magResponseOutput);
|
|
46
|
+
const phaseData = new Float32Array(phaseResponseOutput);
|
|
47
|
+
|
|
48
|
+
(this.node as globalThis.BiquadFilterNode).getFrequencyResponse(
|
|
49
|
+
new Float32Array(frequencyArray),
|
|
50
|
+
magData,
|
|
51
|
+
phaseData
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
for (let i = 0; i < magData.length; i++) {
|
|
55
|
+
magResponseOutput[i] = magData[i];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
for (let i = 0; i < phaseData.length; i++) {
|
|
59
|
+
phaseResponseOutput[i] = phaseData[i];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import BaseAudioContext from './BaseAudioContext';
|
|
2
|
+
import AudioNode from './AudioNode';
|
|
3
|
+
import AudioParam from './AudioParam';
|
|
4
|
+
|
|
5
|
+
export default class GainNode extends AudioNode {
|
|
6
|
+
readonly gain: AudioParam;
|
|
7
|
+
|
|
8
|
+
constructor(context: BaseAudioContext, gain: globalThis.GainNode) {
|
|
9
|
+
super(context, gain);
|
|
10
|
+
this.gain = new AudioParam(gain.gain);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { OscillatorType } from '../types';
|
|
2
|
+
import { InvalidStateError } from '../errors';
|
|
3
|
+
import AudioScheduledSourceNode from './AudioScheduledSourceNode';
|
|
4
|
+
import BaseAudioContext from './BaseAudioContext';
|
|
5
|
+
import AudioParam from './AudioParam';
|
|
6
|
+
import PeriodicWave from './PeriodicWave';
|
|
7
|
+
|
|
8
|
+
export default class OscillatorNode extends AudioScheduledSourceNode {
|
|
9
|
+
readonly frequency: AudioParam;
|
|
10
|
+
readonly detune: AudioParam;
|
|
11
|
+
|
|
12
|
+
constructor(context: BaseAudioContext, node: globalThis.OscillatorNode) {
|
|
13
|
+
super(context, node);
|
|
14
|
+
|
|
15
|
+
this.detune = new AudioParam(node.detune);
|
|
16
|
+
this.frequency = new AudioParam(node.frequency);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public get type(): OscillatorType {
|
|
20
|
+
return (this.node as globalThis.OscillatorNode).type;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public set type(value: OscillatorType) {
|
|
24
|
+
if (value === 'custom') {
|
|
25
|
+
throw new InvalidStateError(
|
|
26
|
+
"'type' cannot be set directly to 'custom'. Use setPeriodicWave() to create a custom Oscillator type."
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
(this.node as globalThis.OscillatorNode).type = value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public setPeriodicWave(wave: PeriodicWave): void {
|
|
34
|
+
(this.node as globalThis.OscillatorNode).setPeriodicWave(wave.periodicWave);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import BaseAudioContext from './BaseAudioContext';
|
|
2
|
+
import AudioNode from './AudioNode';
|
|
3
|
+
import AudioParam from './AudioParam';
|
|
4
|
+
|
|
5
|
+
export default class StereoPannerNode extends AudioNode {
|
|
6
|
+
readonly pan: AudioParam;
|
|
7
|
+
|
|
8
|
+
constructor(context: BaseAudioContext, pan: globalThis.StereoPannerNode) {
|
|
9
|
+
super(context, pan);
|
|
10
|
+
this.pan = new AudioParam(pan.pan);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { installModule } from "./specs/install.js";
|
|
4
|
-
if (global.__AudioAPIInstaller == null) {
|
|
5
|
-
installModule();
|
|
6
|
-
}
|
|
7
|
-
export { default as AudioBuffer } from "./core/AudioBuffer.js";
|
|
8
|
-
export { default as AudioBufferSourceNode } from "./core/AudioBufferSourceNode.js";
|
|
9
|
-
export { default as AudioContext } from "./core/AudioContext.js";
|
|
10
|
-
export { default as AudioDestinationNode } from "./core/AudioDestinationNode.js";
|
|
11
|
-
export { default as AudioNode } from "./core/AudioNode.js";
|
|
12
|
-
export { default as AnalyserNode } from "./core/AnalyserNode.js";
|
|
13
|
-
export { default as AudioParam } from "./core/AudioParam.js";
|
|
14
|
-
export { default as AudioScheduledSourceNode } from "./core/AudioScheduledSourceNode.js";
|
|
15
|
-
export { default as BaseAudioContext } from "./core/BaseAudioContext.js";
|
|
16
|
-
export { default as BiquadFilterNode } from "./core/BiquadFilterNode.js";
|
|
17
|
-
export { default as GainNode } from "./core/GainNode.js";
|
|
18
|
-
export { default as OscillatorNode } from "./core/OscillatorNode.js";
|
|
19
|
-
export { default as StereoPannerNode } from "./core/StereoPannerNode.js";
|
|
20
|
-
export { OscillatorType, BiquadFilterType, ChannelCountMode, ChannelInterpretation, ContextState, WindowType } from "./core/types.js";
|
|
21
|
-
//# sourceMappingURL=index.native.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["installModule","global","__AudioAPIInstaller","default","AudioBuffer","AudioBufferSourceNode","AudioContext","AudioDestinationNode","AudioNode","AnalyserNode","AudioParam","AudioScheduledSourceNode","BaseAudioContext","BiquadFilterNode","GainNode","OscillatorNode","StereoPannerNode","OscillatorType","BiquadFilterType","ChannelCountMode","ChannelInterpretation","ContextState","WindowType"],"sourceRoot":"../../src","sources":["index.native.ts"],"mappings":";;AAAA,SAASA,aAAa,QAAQ,oBAAiB;AAE/C,IAAIC,MAAM,CAACC,mBAAmB,IAAI,IAAI,EAAE;EACtCF,aAAa,CAAC,CAAC;AACjB;AAEA,SAASG,OAAO,IAAIC,WAAW,QAAQ,uBAAoB;AAC3D,SAASD,OAAO,IAAIE,qBAAqB,QAAQ,iCAA8B;AAC/E,SAASF,OAAO,IAAIG,YAAY,QAAQ,wBAAqB;AAC7D,SAASH,OAAO,IAAII,oBAAoB,QAAQ,gCAA6B;AAC7E,SAASJ,OAAO,IAAIK,SAAS,QAAQ,qBAAkB;AACvD,SAASL,OAAO,IAAIM,YAAY,QAAQ,wBAAqB;AAC7D,SAASN,OAAO,IAAIO,UAAU,QAAQ,sBAAmB;AACzD,SAASP,OAAO,IAAIQ,wBAAwB,QAAQ,oCAAiC;AACrF,SAASR,OAAO,IAAIS,gBAAgB,QAAQ,4BAAyB;AACrE,SAAST,OAAO,IAAIU,gBAAgB,QAAQ,4BAAyB;AACrE,SAASV,OAAO,IAAIW,QAAQ,QAAQ,oBAAiB;AACrD,SAASX,OAAO,IAAIY,cAAc,QAAQ,0BAAuB;AACjE,SAASZ,OAAO,IAAIa,gBAAgB,QAAQ,4BAAyB;AACrE,SACEC,cAAc,EACdC,gBAAgB,EAChBC,gBAAgB,EAChBC,qBAAqB,EACrBC,YAAY,EACZC,UAAU,QACL,iBAAc","ignoreList":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,aAAa,GAAG,UAAU,CAAC;AAElE,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG,UAAU,CAAC;AAE5D,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,UAAU,GACV,UAAU,GACV,UAAU,GACV,WAAW,GACX,SAAS,GACT,OAAO,GACP,SAAS,CAAC;AAEd,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEhD,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,QAAQ,GACR,UAAU,GACV,UAAU,GACV,QAAQ,CAAC;AAEb,MAAM,WAAW,uBAAuB;IACtC,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC"}
|