Skip to content

Commit 19d7f4a

Browse files
Refactor to have initialized audio context and added tests for BiquadFilterNode.
1 parent 0e842d7 commit 19d7f4a

24 files changed

+290
-127
lines changed

src/KristofferStrube.Blazor.WebAudio/AudioNodes/AudioDestinationNode.cs

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ protected AudioDestinationNode(IJSRuntime jSRuntime, IJSObjectReference jSRefere
3535
/// An <see cref="AudioDestinationNode"/> representing the audio hardware end-point (the normal case) can potentially output more than <c>2</c> channels of audio if the audio hardware is multi-channel.
3636
/// maxChannelCount is the maximum number of channels that this hardware is capable of supporting.
3737
/// </summary>
38-
/// <returns></returns>
3938
public async Task<ulong> GetMaxChannelCountAsync()
4039
{
4140
IJSObjectReference helper = await webAudioHelperTask.Value;

src/KristofferStrube.Blazor.WebAudio/AudioNodes/BiquadFilterNode.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,18 @@ private BiquadFilterNode(IJSRuntime jSRuntime, IJSObjectReference jSReference, C
5151
/// <summary>
5252
/// Gets the type of this <see cref="BiquadFilterNode"/>.
5353
/// Its default value is <see cref="BiquadFilterType.Lowpass"/>.
54-
/// The exact meaning of the other parameters depend on the value of the this attribute.
54+
/// The exact meaning of the other parameters depend on the value of this attribute.
5555
/// </summary>
5656
public async Task<BiquadFilterType> GetTypeAsync()
5757
{
5858
IJSObjectReference helper = await webAudioHelperTask.Value;
5959
return await helper.InvokeAsync<BiquadFilterType>("getAttribute", JSReference, "type");
6060
}
61+
6162
/// <summary>
6263
/// Sets the type of this <see cref="BiquadFilterNode"/>.
6364
/// Its default value is <see cref="BiquadFilterType.Lowpass"/>.
64-
/// The exact meaning of the other parameters depend on the value of the this attribute.
65+
/// The exact meaning of the other parameters depend on the value of this attribute.
6566
/// </summary>
6667
public async Task SetTypeAsync(BiquadFilterType value)
6768
{
@@ -120,7 +121,7 @@ public async Task<AudioParam> GetGainAsync()
120121
/// </summary>
121122
/// <remarks>
122123
/// It throws an <see cref="InvalidAccessErrorException"/> if the <see cref="Float32Array"/> parameters are not the same length.<br />
123-
/// If a value in <paramref name="frequencyHz"/> is not within <c>[0, sampleRate/2]</c>, where <c>sampleRate</c> is the same as <see cref="BaseAudioContext.GetSampleRateAsync"/>, the corresponding value at the same index of the <paramref name="magResponse"/> and <paramref name="phaseResponse"/> arrays will be <c>NaN</c>.
124+
/// If a value in <paramref name="frequencyHz"/> is not within <c>[0, sampleRate/2]</c>, where <c>sampleRate</c> is the same as <see cref="BaseAudioContext.GetSampleRateAsync"/>, the corresponding value at the same index of the <paramref name="magResponse"/> and <paramref name="phaseResponse"/> arrays will be <c>NaN</c>.
124125
/// </remarks>
125126
/// <param name="frequencyHz">This parameter specifies an array of frequencies, in Hz, at which the response values will be calculated.</param>
126127
/// <param name="magResponse">This parameter specifies an output array receiving the linear magnitude response values.</param>

src/KristofferStrube.Blazor.WebAudio/Options/BiquadFilterOptions.cs

+15
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,45 @@ public class BiquadFilterOptions : AudioNodeOptions
1111
/// <summary>
1212
/// The desired initial type of the filter.
1313
/// </summary>
14+
/// <remarks>
15+
/// The default value is <see cref="BiquadFilterType.Lowpass"/>.
16+
/// </remarks>
1417
[JsonPropertyName("type")]
1518
public BiquadFilterType Type { get; set; } = BiquadFilterType.Lowpass;
1619

1720
/// <summary>
1821
/// The desired initial value for Q.
1922
/// </summary>
23+
/// <remarks>
24+
/// The default value is <c>1</c>.
25+
/// </remarks>
2026
[JsonPropertyName("Q")]
2127
public float Q { get; set; } = 1;
2228

2329
/// <summary>
2430
/// The desired initial value for detune.
2531
/// </summary>
32+
/// <remarks>
33+
/// The default value is <c>0</c>.
34+
/// </remarks>
2635
[JsonPropertyName("detune")]
2736
public float Detune { get; set; } = 0;
2837

2938
/// <summary>
3039
/// The desired initial value for frequency.
3140
/// </summary>
41+
/// <remarks>
42+
/// The default value is <c>350</c>.
43+
/// </remarks>
3244
[JsonPropertyName("frequency")]
3345
public float Frequency { get; set; } = 350;
3446

3547
/// <summary>
3648
/// The desired initial value for gain.
3749
/// </summary>
50+
/// <remarks>
51+
/// The default value is <c>0</c>.
52+
/// </remarks>
3853
[JsonPropertyName("gain")]
3954
public float Gain { get; set; } = 0;
4055
}

tests/IntegrationTests/AudioNodeTests/AnalyserNodeTest.cs

+24-60
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,14 @@ namespace IntegrationTests.AudioNodeTests;
88
public class AnalyserNodeTest : AudioNodeWithAudioNodeOptions<AnalyserNode, AnalyserOptions>
99
{
1010
public override Task<AnalyserNode> CreateAsync(IJSRuntime jSRuntime, AudioContext context, AnalyserOptions? options)
11-
=> AnalyserNode.CreateAsync(jSRuntime, context, options);
11+
=> AnalyserNode.CreateAsync(JSRuntime, AudioContext, options);
1212

1313
[Test]
1414
public async Task GetFloatFrequencyDataAsync_ShouldPopulateBuffer()
1515
{
1616
// Arrange
17-
await using AudioContext context = await GetAudioContextAsync();
18-
19-
await using OscillatorNode oscillator = await OscillatorNode.CreateAsync(JSRuntime, context);
20-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context);
17+
await using OscillatorNode oscillator = await OscillatorNode.CreateAsync(JSRuntime, AudioContext);
18+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext);
2119
await oscillator.ConnectAsync(node);
2220
await oscillator.StartAsync();
2321

@@ -37,10 +35,8 @@ public async Task GetFloatFrequencyDataAsync_ShouldPopulateBuffer()
3735
public async Task GetByteFrequencyDataAsync_ShouldPopulateBuffer()
3836
{
3937
// Arrange
40-
await using AudioContext context = await GetAudioContextAsync();
41-
42-
await using OscillatorNode oscillator = await OscillatorNode.CreateAsync(JSRuntime, context);
43-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context);
38+
await using OscillatorNode oscillator = await OscillatorNode.CreateAsync(JSRuntime, AudioContext);
39+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext);
4440
await oscillator.ConnectAsync(node);
4541
await oscillator.StartAsync();
4642

@@ -59,10 +55,8 @@ public async Task GetByteFrequencyDataAsync_ShouldPopulateBuffer()
5955
public async Task GetFloatTimeDomainDataAsync_ShouldPopulateBuffer()
6056
{
6157
// Arrange
62-
await using AudioContext context = await GetAudioContextAsync();
63-
64-
await using OscillatorNode oscillator = await OscillatorNode.CreateAsync(JSRuntime, context);
65-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context);
58+
await using OscillatorNode oscillator = await OscillatorNode.CreateAsync(JSRuntime, AudioContext);
59+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext);
6660
await oscillator.ConnectAsync(node);
6761
await oscillator.StartAsync();
6862

@@ -81,10 +75,8 @@ public async Task GetFloatTimeDomainDataAsync_ShouldPopulateBuffer()
8175
public async Task GetByteTimeDomainDataAsync_ShouldPopulateBuffer()
8276
{
8377
// Arrange
84-
await using AudioContext context = await GetAudioContextAsync();
85-
86-
await using OscillatorNode oscillator = await OscillatorNode.CreateAsync(JSRuntime, context);
87-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context);
78+
await using OscillatorNode oscillator = await OscillatorNode.CreateAsync(JSRuntime, AudioContext);
79+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext);
8880
await oscillator.ConnectAsync(node);
8981
await oscillator.StartAsync();
9082

@@ -106,13 +98,11 @@ public async Task GetByteTimeDomainDataAsync_ShouldPopulateBuffer()
10698
public async Task GetFftSizeAsync_ShouldRetrieveFftSize(ulong fftSize)
10799
{
108100
// Arrange
109-
await using AudioContext context = await GetAudioContextAsync();
110-
111-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context, new()
101+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext, new()
112102
{
113103
FftSize = fftSize
114104
});
115-
105+
116106
// Act
117107
ulong readFftSize = await node.GetFftSizeAsync();
118108

@@ -126,9 +116,7 @@ public async Task GetFftSizeAsync_ShouldRetrieveFftSize(ulong fftSize)
126116
public async Task SetFftSizeAsync_ShouldUpdateFftSize(ulong fftSize)
127117
{
128118
// Arrange
129-
await using AudioContext context = await GetAudioContextAsync();
130-
131-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context);
119+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext);
132120

133121
// Act
134122
await node.SetFftSizeAsync(fftSize);
@@ -144,9 +132,7 @@ public async Task SetFftSizeAsync_ShouldUpdateFftSize(ulong fftSize)
144132
public async Task SetFftSizeAsync_ThrowsIndexSizeErrorException_WhenFftSizeIsOutOfBounds(ulong fftSize)
145133
{
146134
// Arrange
147-
await using AudioContext context = await GetAudioContextAsync();
148-
149-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context);
135+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext);
150136

151137
// Act
152138
Func<Task> action = async () => await node.SetFftSizeAsync(fftSize);
@@ -161,9 +147,7 @@ public async Task SetFftSizeAsync_ThrowsIndexSizeErrorException_WhenFftSizeIsOut
161147
public async Task SetFftSizeAsync_ThrowsIndexSizeErrorException_WhenFftSizeIsNotAPowerOfTwo(ulong fftSize)
162148
{
163149
// Arrange
164-
await using AudioContext context = await GetAudioContextAsync();
165-
166-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context);
150+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext);
167151

168152
// Act
169153
Func<Task> action = async () => await node.SetFftSizeAsync(fftSize);
@@ -178,9 +162,7 @@ public async Task SetFftSizeAsync_ThrowsIndexSizeErrorException_WhenFftSizeIsNot
178162
public async Task GetFrequencyBinCountAsync_ShouldRetrieveFrequncyBinCount(ulong fftSize)
179163
{
180164
// Arrange
181-
await using AudioContext context = await GetAudioContextAsync();
182-
183-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context, new()
165+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext, new()
184166
{
185167
FftSize = fftSize
186168
});
@@ -198,9 +180,7 @@ public async Task GetFrequencyBinCountAsync_ShouldRetrieveFrequncyBinCount(ulong
198180
public async Task GetMaxDecibelsAsync_ShouldRetrieveMaxDecibels(double maxDecibels)
199181
{
200182
// Arrange
201-
await using AudioContext context = await GetAudioContextAsync();
202-
203-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context, new()
183+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext, new()
204184
{
205185
MaxDecibels = maxDecibels
206186
});
@@ -218,9 +198,7 @@ public async Task GetMaxDecibelsAsync_ShouldRetrieveMaxDecibels(double maxDecibe
218198
public async Task SetMaxDecibelsAsync_ShouldUpdateMaxDecibels(double maxDecibels)
219199
{
220200
// Arrange
221-
await using AudioContext context = await GetAudioContextAsync();
222-
223-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context);
201+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext);
224202

225203
// Act
226204
await node.SetMaxDecibelsAsync(maxDecibels);
@@ -236,9 +214,7 @@ public async Task SetMaxDecibelsAsync_ShouldUpdateMaxDecibels(double maxDecibels
236214
public async Task SetMaxDecibelsAsync_ThrowsIndexSizeErrorException_WhenSetLowerThanMinDecibels(double minDecibels, double maxDecibels)
237215
{
238216
// Arrange
239-
await using AudioContext context = await GetAudioContextAsync();
240-
241-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context, new()
217+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext, new()
242218
{
243219
MinDecibels = minDecibels,
244220
MaxDecibels = minDecibels + 1,
@@ -257,9 +233,7 @@ public async Task SetMaxDecibelsAsync_ThrowsIndexSizeErrorException_WhenSetLower
257233
public async Task GetMinDecibelsAsync_ShouldRetrieveMinDecibels(double minDecibels)
258234
{
259235
// Arrange
260-
await using AudioContext context = await GetAudioContextAsync();
261-
262-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context, new()
236+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext, new()
263237
{
264238
MinDecibels = minDecibels
265239
});
@@ -277,9 +251,7 @@ public async Task GetMinDecibelsAsync_ShouldRetrieveMinDecibels(double minDecibe
277251
public async Task SetMinDecibelsAsync_ShouldUpdateMinDecibels(double minDecibels)
278252
{
279253
// Arrange
280-
await using AudioContext context = await GetAudioContextAsync();
281-
282-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context);
254+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext);
283255

284256
// Act
285257
await node.SetMinDecibelsAsync(minDecibels);
@@ -295,9 +267,7 @@ public async Task SetMinDecibelsAsync_ShouldUpdateMinDecibels(double minDecibels
295267
public async Task SetMinDecibelsAsync_ThrowsIndexSizeErrorException_WhenSetHigherThanMaxDecibels(double minDecibels, double maxDecibels)
296268
{
297269
// Arrange
298-
await using AudioContext context = await GetAudioContextAsync();
299-
300-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context, new()
270+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext, new()
301271
{
302272
MinDecibels = maxDecibels - 1,
303273
MaxDecibels = maxDecibels,
@@ -316,9 +286,7 @@ public async Task SetMinDecibelsAsync_ThrowsIndexSizeErrorException_WhenSetHighe
316286
public async Task GetSmoothingTimeConstantAsync_ShouldRetrieveSmoothingTimeConstant(double smoothingTimeConstant)
317287
{
318288
// Arrange
319-
await using AudioContext context = await GetAudioContextAsync();
320-
321-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context, new()
289+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext, new()
322290
{
323291
SmoothingTimeConstant = smoothingTimeConstant
324292
});
@@ -336,9 +304,7 @@ public async Task GetSmoothingTimeConstantAsync_ShouldRetrieveSmoothingTimeConst
336304
public async Task SetSmoothingTimeConstantAsync_ShouldUpdateSmoothingTimeConstant(double smoothingTimeConstant)
337305
{
338306
// Arrange
339-
await using AudioContext context = await GetAudioContextAsync();
340-
341-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context);
307+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext);
342308

343309
// Act
344310
await node.SetSmoothingTimeConstantAsync(smoothingTimeConstant);
@@ -354,9 +320,7 @@ public async Task SetSmoothingTimeConstantAsync_ShouldUpdateSmoothingTimeConstan
354320
public async Task SetMinDecibelsAsync_ThrowsIndexSizeErrorException_WhenSetToValueOutsideRange(double smoothingTimeConstant)
355321
{
356322
// Arrange
357-
await using AudioContext context = await GetAudioContextAsync();
358-
359-
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, context);
323+
await using AnalyserNode node = await AnalyserNode.CreateAsync(JSRuntime, AudioContext);
360324

361325
// Act
362326
Func<Task> action = async () => await node.SetSmoothingTimeConstantAsync(smoothingTimeConstant);

0 commit comments

Comments
 (0)