diff --git a/samples/KristofferStrube.Blazor.WebAudio.WasmExample/KristofferStrube.Blazor.WebAudio.WasmExample.csproj b/samples/KristofferStrube.Blazor.WebAudio.WasmExample/KristofferStrube.Blazor.WebAudio.WasmExample.csproj index bf22fde..78be7a9 100644 --- a/samples/KristofferStrube.Blazor.WebAudio.WasmExample/KristofferStrube.Blazor.WebAudio.WasmExample.csproj +++ b/samples/KristofferStrube.Blazor.WebAudio.WasmExample/KristofferStrube.Blazor.WebAudio.WasmExample.csproj @@ -21,11 +21,4 @@ - - - - true - - - diff --git a/samples/KristofferStrube.Blazor.WebAudio.WasmExample/Pages/DotNetBot.razor b/samples/KristofferStrube.Blazor.WebAudio.WasmExample/Pages/DotNetBot.razor new file mode 100644 index 0000000..72bbb05 --- /dev/null +++ b/samples/KristofferStrube.Blazor.WebAudio.WasmExample/Pages/DotNetBot.razor @@ -0,0 +1,162 @@ +@page "/DotNetBot" +@using KristofferStrube.Blazor.MediaCaptureStreams; +@using KristofferStrube.Blazor.WebIDL; +@using KristofferStrube.Blazor.WebIDL.Exceptions; +@implements IAsyncDisposable +@inject IJSRuntime JSRuntime +@inject IMediaDevicesService MediaDevicesService +WebAudio - DotNet Bot +

.NET Bot

+ +

+ On this page we will use your microphone input and then use an analyzer to make the .NET BOT "dance" to the tune of whatever music you hear. +

+ + + + + + + + + + + + + + + +
+@if (legValues.Count > 0) +{ + +} +
+@if (error is { } errorMessage) +{ +

@errorMessage

+} +else if (mediaStreamAudioSourceNode is null) +{ + +} +else +{ + @if (audioOptions.Count > 0) + { + + + } +} + +@code { + AudioContext audioContext = default!; + string? error; + bool stopped; + + private byte[] frequencies = Array.Empty(); + + Queue legValues = new(); + byte arms = 0; + + double CalcLeftLeg => Math.Round(legValues.Count > 0 ? ((legValues.Take(5).Average() - legValues.Min()) / (legValues.Max() - (float)legValues.Min())) * 255 : 1); + + double CalcRightLeg => Math.Round(legValues.Count > 0 ? (1 - ((legValues.Take(5).Average() - legValues.Min()) / (legValues.Max() - (float)legValues.Min()))) * 255 : 1); + + MediaDevices? mediaDevices; + MediaStream? mediaStream; + MediaStreamAudioSourceNode? mediaStreamAudioSourceNode; + List<(string label, string id)> audioOptions = new(); + string? selectedAudioSource; + + async Task OpenAudio() + { + await StopAudioTrack(); + + try + { + if (audioContext is null) + { + audioContext = await AudioContext.CreateAsync(JSRuntime); + } + if (mediaDevices is null) + { + mediaDevices = await MediaDevicesService.GetMediaDevicesAsync(); + } + + MediaTrackConstraints mediaTrackConstraints = new MediaTrackConstraints + { + EchoCancellation = false, + NoiseSuppression = false, + AutoGainControl = false, + DeviceId = selectedAudioSource is null ? null : new ConstrainDomString(selectedAudioSource) + }; + mediaStream = await mediaDevices.GetUserMediaAsync(new MediaStreamConstraints() { Audio = mediaTrackConstraints }); + + var deviceInfos = await mediaDevices.EnumerateDevicesAsync(); + audioOptions.Clear(); + foreach (var device in deviceInfos) + { + if (await device.GetKindAsync() is MediaDeviceKind.AudioInput) + { + audioOptions.Add((await device.GetLabelAsync(), await device.GetDeviceIdAsync())); + } + } + + mediaStreamAudioSourceNode = await audioContext.CreateMediaStreamSourceAsync(mediaStream); + + var analyserNode = await audioContext.CreateAnalyserAsync(); + + await mediaStreamAudioSourceNode.ConnectAsync(analyserNode); + + await Task.Delay(500); + + int bufferLength = (int)await analyserNode.GetFrequencyBinCountAsync(); + var dataArray = await Uint8Array.CreateAsync(JSRuntime, bufferLength); + + for (int i = 0; i < 200; i++) + { + legValues.Enqueue(0); + } + + stopped = false; + while (!stopped) + { + await analyserNode.GetByteFrequencyDataAsync(dataArray); + + frequencies = await dataArray.GetAsArrayAsync(); + legValues.Enqueue(frequencies[20]); + legValues.Dequeue(); + await Task.Delay(10); + StateHasChanged(); + } + } + catch (Exception ex) + { + error = $"{ex.GetType().Name}: {ex.Message}"; + } + } + + async Task StopAudioTrack() + { + stopped = true; + if (mediaStream is null) return; + var audioTrack = (await mediaStream.GetAudioTracksAsync()).FirstOrDefault(); + if (audioTrack is not null) + { + await audioTrack.StopAsync(); + } + } + + public async ValueTask DisposeAsync() + { + await StopAudioTrack(); + } +} + +