Skip to content

Commit 0584a13

Browse files
committed
fix(analyser): expose additional methods and properties
1 parent b90d078 commit 0584a13

File tree

6 files changed

+102
-28
lines changed

6 files changed

+102
-28
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ function showVolume() {
8484
}
8585

8686
function showWaveform() {
87-
const frequencyData = monitor.frequencyData;
87+
const frequencyData = monitor.byteTimeDomainData;
8888
// Some kind of drawing code...
8989
requestAnimationFrame(showWaveform);
9090
}

src/analyser.ts

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
export class Analyser {
22
readonly node: AnalyserNode;
3-
readonly #data: Uint8Array<ArrayBuffer>;
3+
4+
#byteFrequencyData: Uint8Array<ArrayBuffer>;
5+
#byteTimeDomainData: Uint8Array<ArrayBuffer>;
6+
#floatFrequencyData: Float32Array<ArrayBuffer>;
7+
#floatTimeDomainData: Float32Array<ArrayBuffer>;
48

59
constructor(
610
readonly context: AudioContext = new AudioContext(),
@@ -36,22 +40,37 @@ export class Analyser {
3640
this.node.channelCountMode = options.channelCountMode;
3741
}
3842

39-
this.#data = new Uint8Array(this.node.frequencyBinCount);
43+
this.#byteFrequencyData = new Uint8Array(this.node.frequencyBinCount);
44+
this.#byteTimeDomainData = new Uint8Array(this.node.frequencyBinCount);
45+
this.#floatFrequencyData = new Float32Array(this.node.frequencyBinCount);
46+
this.#floatTimeDomainData = new Float32Array(this.node.frequencyBinCount);
4047
}
4148

42-
/**
43-
* Returns the frequency data provided by the default analyzer
44-
*/
45-
get frequencyData(): Uint8Array {
46-
this.node.getByteFrequencyData(this.#data);
47-
return this.#data;
49+
get byteFrequencyData(): Uint8Array {
50+
this.node.getByteFrequencyData(this.#byteFrequencyData);
51+
return this.#byteFrequencyData;
52+
}
53+
54+
get floatFrequencyData(): Float32Array {
55+
this.node.getFloatFrequencyData(this.#floatFrequencyData);
56+
return this.#floatFrequencyData;
57+
}
58+
59+
get byteTimeDomainData(): Uint8Array {
60+
this.node.getByteTimeDomainData(this.#byteTimeDomainData);
61+
return this.#byteTimeDomainData;
62+
}
63+
64+
get floatTimeDomainData(): Float32Array {
65+
this.node.getFloatTimeDomainData(this.#floatTimeDomainData);
66+
return this.#floatTimeDomainData;
4867
}
4968

5069
/**
5170
* Retrieves the current volume (average of amplitude^2)
5271
*/
5372
get volume(): number {
54-
const data = this.frequencyData;
73+
const data = this.byteFrequencyData;
5574

5675
let sum = 0;
5776

@@ -62,6 +81,39 @@ export class Analyser {
6281
return Math.sqrt(sum / data.length);
6382
}
6483

84+
disconnect(): void;
85+
disconnect(output: number): void;
86+
disconnect(destinationNode: AudioNode): void;
87+
disconnect(destinationNode: AudioNode, output: number): void;
88+
disconnect(destinationNode: AudioNode, output: number, input: number): void;
89+
disconnect(destinationParam: AudioParam): void;
90+
disconnect(destinationParam: AudioParam, output: number): void;
91+
disconnect(
92+
destinationNodeOrParam?: AudioNode | AudioParam | number,
93+
output?: number,
94+
input?: number,
95+
): void {
96+
if (destinationNodeOrParam === undefined) {
97+
this.node.disconnect();
98+
} else if (typeof destinationNodeOrParam === "number") {
99+
this.node.disconnect(destinationNodeOrParam);
100+
} else if (destinationNodeOrParam instanceof AudioNode) {
101+
if (output !== undefined && input !== undefined) {
102+
this.node.disconnect(destinationNodeOrParam, output, input);
103+
} else if (output !== undefined) {
104+
this.node.disconnect(destinationNodeOrParam, output);
105+
} else {
106+
this.node.disconnect(destinationNodeOrParam);
107+
}
108+
} else if (destinationNodeOrParam instanceof AudioParam) {
109+
if (output !== undefined) {
110+
this.node.disconnect(destinationNodeOrParam, output);
111+
} else {
112+
this.node.disconnect(destinationNodeOrParam);
113+
}
114+
}
115+
}
116+
65117
connectToDestination() {
66118
this.node.connect(this.context.destination);
67119
}

src/monitor.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export interface SetupAnalyzerArgs {
99

1010
export interface MonitorOptions {
1111
context?: AudioContext;
12+
analyserOptions?: AnalyserOptions;
1213
setupAnalyser?: ((args: SetupAnalyzerArgs) => void) | false;
1314
}
1415

@@ -27,7 +28,7 @@ export class Monitor {
2728
this.context = this.#options.context ?? new AudioContext();
2829
this.destination = this.context.destination;
2930
this.source = this.context.createMediaStreamSource(this.stream);
30-
this.analyser = new Analyser(this.context);
31+
this.analyser = new Analyser(this.context, this.#options.analyserOptions);
3132

3233
if (options.setupAnalyser) {
3334
options.setupAnalyser({
@@ -50,10 +51,31 @@ export class Monitor {
5051
}
5152

5253
/**
53-
* Retrieves the current analyzer's frequency data
54+
* Retrieves the current analyzer's frequency data as an Uint8Array
5455
*/
55-
get frequencyData() {
56-
return this.analyser.frequencyData;
56+
get byteFrequencyData(): Uint8Array {
57+
return this.analyser.byteFrequencyData;
58+
}
59+
60+
/**
61+
* Retrieves the current analyzer's frequency data as an Float32Array
62+
*/
63+
get floatFrequencyData(): Float32Array {
64+
return this.analyser.floatFrequencyData;
65+
}
66+
67+
/**
68+
* Retrieves the current analyzer's time domain data as an Uint8Array
69+
*/
70+
get byteTimeDomainData(): Uint8Array {
71+
return this.analyser.byteTimeDomainData;
72+
}
73+
74+
/**
75+
* Retrieves the current analyzer's time domain data as an Float32Array
76+
*/
77+
get floatTimeDomainData(): Float32Array {
78+
return this.analyser.floatTimeDomainData;
5779
}
5880

5981
/**

tests/analyser.spec.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ test.describe("Analyser", () => {
131131
// Allow some time for audio processing
132132
await new Promise((resolve) => setTimeout(resolve, 100));
133133

134-
const frequencyData = analyser.frequencyData;
134+
const frequencyData = analyser.byteFrequencyData;
135135

136136
return {
137137
isUint8Array: frequencyData instanceof Uint8Array,
@@ -325,7 +325,7 @@ test.describe("Monitor with Default Analyser", () => {
325325
// Allow some time for audio processing
326326
await new Promise((resolve) => setTimeout(resolve, 100));
327327

328-
const frequencyData = monitor.frequencyData;
328+
const frequencyData = monitor.byteFrequencyData;
329329

330330
return {
331331
isUint8Array: frequencyData instanceof Uint8Array,
@@ -417,8 +417,8 @@ test.describe("Monitor with Default Analyser", () => {
417417

418418
// Get multiple frequency data readings
419419
await new Promise((resolve) => setTimeout(resolve, 100));
420-
const data1 = monitor.frequencyData;
421-
const data2 = monitor.frequencyData;
420+
const data1 = monitor.byteFrequencyData;
421+
const data2 = monitor.byteFrequencyData;
422422

423423
return {
424424
sameLength: data1.length === data2.length,

tests/edge-cases.spec.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ test.describe("Edge Cases", () => {
2121

2222
await new Promise((resolve) => setTimeout(resolve, 10));
2323

24-
const frequencyData = analyser.frequencyData;
24+
const frequencyData = analyser.byteFrequencyData;
2525
const volume = analyser.volume;
2626

2727
return {
@@ -54,15 +54,15 @@ test.describe("Edge Cases", () => {
5454
await new Promise((resolve) => setTimeout(resolve, 100));
5555

5656
const volume1 = analyser.volume;
57-
const frequencyData1 = analyser.frequencyData;
57+
const frequencyData1 = analyser.byteFrequencyData;
5858

5959
// Resume the context
6060
await context.resume();
6161

6262
await new Promise((resolve) => setTimeout(resolve, 100));
6363

6464
const volume2 = analyser.volume;
65-
const frequencyData2 = analyser.frequencyData;
65+
const frequencyData2 = analyser.byteFrequencyData;
6666

6767
stream.getTracks().forEach((track) => {
6868
track.stop();
@@ -98,7 +98,7 @@ test.describe("Edge Cases", () => {
9898
success: true,
9999
fftSize: analyser.node.fftSize,
100100
frequencyBinCount: analyser.node.frequencyBinCount,
101-
frequencyDataLength: analyser.frequencyData.length,
101+
frequencyDataLength: analyser.byteFrequencyData.length,
102102
};
103103
} catch (error) {
104104
return {
@@ -129,7 +129,7 @@ test.describe("Edge Cases", () => {
129129
success: true,
130130
fftSize: analyser.node.fftSize,
131131
frequencyBinCount: analyser.node.frequencyBinCount,
132-
frequencyDataLength: analyser.frequencyData.length,
132+
frequencyDataLength: analyser.byteFrequencyData.length,
133133
};
134134
} catch (error) {
135135
return {
@@ -178,7 +178,7 @@ test.describe("Edge Cases", () => {
178178
await new Promise((resolve) => setTimeout(resolve, 200));
179179

180180
const volume = analyser.volume;
181-
const frequencyData = analyser.frequencyData;
181+
const frequencyData = analyser.byteFrequencyData;
182182

183183
stream.getTracks().forEach((track) => {
184184
track.stop();
@@ -270,7 +270,7 @@ test.describe("Edge Cases", () => {
270270
await new Promise((resolve) => setTimeout(resolve, 200));
271271

272272
const volume = analyser.volume;
273-
const frequencyData = analyser.frequencyData;
273+
const frequencyData = analyser.byteFrequencyData;
274274

275275
stream1.getTracks().forEach((track) => {
276276
track.stop();

tests/integration.spec.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ test.describe("Integration Tests", () => {
2222

2323
const monitorVolume = monitor.volume;
2424
const recorderVolume = recorder.volume;
25-
const monitorFreqData = monitor.frequencyData;
26-
const recorderFreqData = recorder.frequencyData;
25+
const monitorFreqData = monitor.byteFrequencyData;
26+
const recorderFreqData = recorder.byteFrequencyData;
2727

2828
const blob = await recorder.stop();
2929

@@ -524,7 +524,7 @@ test.describe("Resource Management Tests", () => {
524524
await new Promise((resolve) => setTimeout(resolve, 200));
525525

526526
const volume = monitor.volume;
527-
const frequencyData = monitor.frequencyData;
527+
const frequencyData = monitor.byteFrequencyData;
528528
const blob = await recorder.stop();
529529

530530
stream.getTracks().forEach((track) => {

0 commit comments

Comments
 (0)