|
11 | 11 | <p>
|
12 | 12 | Below here we have a <b style="color:orange;">Timpani Drum</b>. Try to hit it!
|
13 | 13 | <br />
|
14 |
| - <small>Soon I will add a <b style="color:green;">Bass Drum</b> as well.</small> |
| 14 | + <small>Soon I will add a <b style="color:grey;">Bass Drum</b> as well.</small> |
15 | 15 | </p>
|
16 | 16 |
|
17 | 17 | <svg width="200" height="200" @onpointerdown=PlayTimps>
|
18 | 18 | <circle cx="100" cy="100" r="90" fill="orange" stroke="orangered"></circle>
|
19 | 19 | </svg>
|
20 | 20 |
|
21 |
| -<h3>Time Domain</h3> |
22 |
| -<hr /> |
23 |
| -<Plot Data="timeDomainMeasurements" /> |
| 21 | +<svg width="180" height="180" @onpointerdown=PlayBass> |
| 22 | + <circle cx="90" cy="90" r="80" fill="silver" stroke="grey"></circle> |
| 23 | +</svg> |
| 24 | + |
24 | 25 | <h3>Spectrogram</h3>
|
25 | 26 | <hr />
|
26 | 27 | <SpectrogramPlot Analyser=analyser UpperFrequency="40" TimeInSeconds="8" />
|
27 | 28 |
|
28 | 29 | @code {
|
29 | 30 | bool makingMeasurements = false;
|
30 |
| - static readonly float[] timpsFrequencies = new float[] { 1.00f, 1.50f, 1.98f, 2.44f }; |
31 |
| - static readonly float[] timpsAmplitudes = new float[] { 1, 0.8f, 0.6f, 0.2f }; |
32 |
| - static readonly float[] timpsDecays = new float[] { 4.5f, 7.5f, 9f, 8.5f }; |
33 |
| - static readonly double[] lastTimpTime = new double[] { 0, 0, 0, 0 }; |
34 | 31 |
|
35 | 32 | AudioContext context = default!;
|
36 | 33 | GainNode mainNode = default!;
|
|
50 | 47 | }
|
51 | 48 | }
|
52 | 49 |
|
53 |
| - public async Task Analyze() |
54 |
| - { |
55 |
| - if (makingMeasurements) return; |
56 |
| - makingMeasurements = true; |
| 50 | + // public async Task Analyze() |
| 51 | + // { |
| 52 | + // if (makingMeasurements) return; |
| 53 | + // makingMeasurements = true; |
57 | 54 |
|
58 |
| - int bufferLength = (int)await analyser.GetFrequencyBinCountAsync(); |
59 |
| - var timeDomainDataArray = await Uint8Array.CreateAsync(JSRuntime, bufferLength); |
| 55 | + // int bufferLength = (int)await analyser.GetFrequencyBinCountAsync(); |
| 56 | + // var timeDomainDataArray = await Uint8Array.CreateAsync(JSRuntime, bufferLength); |
60 | 57 |
|
61 |
| - while (makingMeasurements) |
62 |
| - { |
63 |
| - await analyser.GetByteTimeDomainDataAsync(timeDomainDataArray); |
| 58 | + // while (makingMeasurements) |
| 59 | + // { |
| 60 | + // await analyser.GetByteTimeDomainDataAsync(timeDomainDataArray); |
64 | 61 |
|
65 |
| - timeDomainMeasurements = await timeDomainDataArray.GetByteArrayAsync(); |
66 |
| - await Task.Delay(1); |
67 |
| - StateHasChanged(); |
68 |
| - } |
69 |
| - } |
| 62 | + // timeDomainMeasurements = await timeDomainDataArray.GetByteArrayAsync(); |
| 63 | + // await Task.Delay(1); |
| 64 | + // StateHasChanged(); |
| 65 | + // } |
| 66 | + // } |
70 | 67 |
|
| 68 | + static readonly float[] timpsFrequencies = new float[] { 1.00f, 1.50f, 1.98f, 2.44f }; |
| 69 | + static readonly float[] timpsAmplitudes = new float[] { 1, 0.8f, 0.6f, 0.2f }; |
| 70 | + static readonly float[] timpsDecays = new float[] { 4.5f, 7.5f, 9f, 8.5f }; |
71 | 71 | public async Task PlayTimps(PointerEventArgs eventArgs)
|
72 | 72 | {
|
73 | 73 | await Initialize();
|
|
76 | 76 | if (distanceFromMid > 90) return;
|
77 | 77 | float pitch = 100 + distanceFromMid;
|
78 | 78 |
|
79 |
| - GainNode[]? timpOscillatorAmplifiers = new GainNode[4]; |
| 79 | + GainNode[]? oscillatorAmplifiers = new GainNode[4]; |
80 | 80 | for (int i = 0; i < 4; i++)
|
81 | 81 | {
|
82 | 82 | var oscillator = await OscillatorNode.CreateAsync(JSRuntime, context, new() { Type = OscillatorType.Sine, Frequency = timpsFrequencies[i] * pitch });
|
83 | 83 | var amplifier = await GainNode.CreateAsync(JSRuntime, context, new() { Gain = 0 });
|
84 | 84 | await oscillator.ConnectAsync(amplifier);
|
85 | 85 | await amplifier.ConnectAsync(mainNode);
|
86 |
| - timpOscillatorAmplifiers[i] = amplifier; |
| 86 | + oscillatorAmplifiers[i] = amplifier; |
87 | 87 | await oscillator.StartAsync();
|
88 | 88 | }
|
89 | 89 |
|
90 | 90 | var time = await context.GetCurrentTimeAsync();
|
91 | 91 |
|
92 | 92 | for (int i = 0; i < 4; i++)
|
93 | 93 | {
|
94 |
| - var gain = await timpOscillatorAmplifiers[i].GetGainAsync(); |
| 94 | + var gain = await oscillatorAmplifiers[i].GetGainAsync(); |
95 | 95 | await gain.SetValueAsync(await gain.GetValueAsync());
|
96 | 96 | await gain.LinearRampToValueAtTimeAsync(timpsAmplitudes[i] / timpsAmplitudes.Sum(), time + 0.3);
|
97 |
| - var endTime = time + timpsDecays[i] * 0.1; |
98 |
| - await gain.LinearRampToValueAtTimeAsync(0, endTime); |
99 |
| - lastTimpTime[i] = endTime; |
| 97 | + await gain.LinearRampToValueAtTimeAsync(0, time + timpsDecays[i] * 0.1); |
100 | 98 | }
|
101 | 99 |
|
102 | 100 | var noiseCarrier = await OscillatorNode.CreateAsync(JSRuntime, context, new() { Frequency = 100 });
|
103 | 101 | var noiseModulator = await OscillatorNode.CreateAsync(JSRuntime, context, new() { Frequency = 87 });
|
104 | 102 | var noiseRingModulator = await GainNode.CreateAsync(JSRuntime, context, new() { Gain = 0 });
|
105 | 103 | var noiseGain = await noiseRingModulator.GetGainAsync();
|
106 |
| - var noiseHighPassFilter = await BiquadFilterNode.CreateAsync(JSRuntime, context, new() { Type = BiquadFilterType.Highpass, Frequency = 150, Q = 1 }); |
| 104 | + var noiseHighPassFilter = await BiquadFilterNode.CreateAsync(JSRuntime, context, new() { Type = BiquadFilterType.Highpass, Frequency = 150, Q = 1 }); |
107 | 105 | var noiseAmplifier = await GainNode.CreateAsync(JSRuntime, context, new() { Gain = 0 });
|
108 | 106 | await noiseCarrier.ConnectAsync(noiseRingModulator);
|
109 | 107 | await noiseModulator.ConnectAsync(noiseGain);
|
|
115 | 113 | var noiseAmplifierGain = await noiseAmplifier.GetGainAsync();
|
116 | 114 | await noiseAmplifierGain.LinearRampToValueAtTimeAsync(0.2f, time + 0.3);
|
117 | 115 | await noiseAmplifierGain.LinearRampToValueAtTimeAsync(0, time + timpsDecays.Max() * 0.1);
|
| 116 | + } |
| 117 | + |
| 118 | + static readonly float[] bassFrequencies = new float[] { 1.00f, 1.86f, 2.72f, 3.64f, 4.50f, 5.46f }; |
| 119 | + public async Task PlayBass(PointerEventArgs eventArgs) |
| 120 | + { |
| 121 | + await Initialize(); |
118 | 122 |
|
119 |
| - await Analyze(); |
| 123 | + float distanceFromMid = (float)Math.Sqrt(Math.Pow(eventArgs.OffsetX - 100, 2) + Math.Pow(eventArgs.OffsetY - 100, 2)); |
| 124 | + if (distanceFromMid > 80) return; |
| 125 | + float pitch = 50 + distanceFromMid / 2; |
| 126 | + |
| 127 | + GainNode[]? oscillatorAmplifiers = new GainNode[4]; |
| 128 | + for (int i = 0; i < 4; i++) |
| 129 | + { |
| 130 | + var oscillator = await OscillatorNode.CreateAsync(JSRuntime, context, new() { Type = OscillatorType.Sine, Frequency = bassFrequencies[i] * pitch }); |
| 131 | + var amplifier = await GainNode.CreateAsync(JSRuntime, context, new() { Gain = 0 }); |
| 132 | + await oscillator.ConnectAsync(amplifier); |
| 133 | + await amplifier.ConnectAsync(mainNode); |
| 134 | + oscillatorAmplifiers[i] = amplifier; |
| 135 | + await oscillator.StartAsync(); |
| 136 | + } |
| 137 | + |
| 138 | + var time = await context.GetCurrentTimeAsync(); |
| 139 | + |
| 140 | + for (int i = 0; i < 4; i++) |
| 141 | + { |
| 142 | + var gain = await oscillatorAmplifiers[i].GetGainAsync(); |
| 143 | + await gain.SetValueAsync(await gain.GetValueAsync()); |
| 144 | + await gain.LinearRampToValueAtTimeAsync(1 / (float)6, time + 0.3); |
| 145 | + await gain.LinearRampToValueAtTimeAsync(0, time + 1); |
| 146 | + } |
120 | 147 | }
|
121 | 148 |
|
122 | 149 | public async Task StopSound()
|
|
0 commit comments