Blazor 在没有文件的情况下播放生成的声音

Eri*_*ell 5 html javascript audio web-audio-api blazor

在 Blazor 项目中,我生成声音/噪声信号作为 @DanW 的粉红噪声示例,该示例生成double[]值在 -1.0 - 1.0 之间的 。是否可以在浏览器中直接播放该数组作为音频?到目前为止,我所发现的有关声音/音频和浏览器的所有内容都是从现有文件中播放音频。

编辑:我正在使用 C# 中的一些本机 dll 进行一些过滤,并且在 C# 中比在 javascript 中更舒服,因此尝试在 C# 而不是 javascript 中完成大部分工作。

Eri*_*ell 6

因此,我使用 WebAudio API 来弄清楚如何:

JavaScript:

// for cross browser compatibility
const AudioContext = window.AudioContext || window.webkitAudioContext;
audioCtx = {};

function initAudio() {
    // creation of audio context cannot not be done on loading file, must be done afterwards
    audioCtx = new AudioContext();
    return audioCtx.sampleRate;
}

// floats is a 1-D array with channel data after each other:
// ch1 = floats.slice(0,nSamples)
// ch2 = floats.slice(nSamples,nSamples*2)
function playNoise(floats, nChannels) {
    const bufferSize = floats.length / nChannels;
    let arrayBuffer = audioCtx.createBuffer(nChannels, bufferSize, audioCtx.sampleRate);

    for (var i = 0; i < nChannels; i++) {
        let f32arr = new Float32Array(floats.slice(i * bufferSize, (i + 1) * bufferSize));
        arrayBuffer.copyToChannel(f32arr, i, 0);
    }

    // Creating AudioBufferSourceNode
    let noise = audioCtx.createBufferSource();
    noise.buffer = arrayBuffer;
    noise.connect(audioCtx.destination);
    noise.start();
    return true;
}
Run Code Online (Sandbox Code Playgroud)

Blazor 页面(我使用Blazorise ( Button)):

@page "/Tests"
@inject IJSRuntime js
<h3>Test</h3>
<Button Clicked="@(async () => await TestJS())" Color="Color.Primary">Test JS</Button>

@code {
    double fs;
    protected override async Task OnInitializedAsync()
    {
        fs = await js.InvokeAsync<double>("initAudio");
        await base.OnInitializedAsync();
    }

    private async Task TestJS()
    {
        var nChannels = 2;
        var nSecs = 5;
        var nSampels = (int)fs * nSecs * nChannels;
        var floats = new float[nSampels];
        var freq = 440;
        for (int i = 0; i < nSampels / nChannels; i++)
        {
            floats[i] = (float)Math.Sin(i * freq * 2 * Math.PI / fs);
            floats[i + nSampels / 2] = (float)Math.Sin(i * freq * 2 * 2 * Math.PI / fs);
        }
        var ok = await js.InvokeAsync<bool>("playNoise", floats, nChannels);
    }
}
Run Code Online (Sandbox Code Playgroud)

该按钮在左通道(通道 1)中播放 440 Hz 音调,在右通道(通道 2)中播放 880 Hz 音调。

编辑:采样率不必与AudioContext. 请在此处查看规格。

  • 干得好,埃里克!我有点惊讶缓冲区传输如此简单。 (2认同)