How to play audio byte array (not file!) with JavaScript in a browser

后端 未结 4 2049
终归单人心
终归单人心 2021-02-08 14:51

For mostly security reasons, I\'m not allowed to store a WAV file on the server to be accessed by a browser. What I have is a byte array contains audio data (the data portion of

相关标签:
4条回答
  • 2021-02-08 15:32

    I accomplished this via the following code. I pass in a byte array containing the data from the wav file to the function playByteArray. My solution is similar to Peter Lee's, but I could not get his to work in my case (the output was garbled) whereas this solution works well for me. I verified that it works in Firefox and Chrome.

    window.onload = init;
    var context;    // Audio context
    var buf;        // Audio buffer
    
    function init() {
        if (!window.AudioContext) {
        if (!window.webkitAudioContext) {
            alert("Your browser does not support any AudioContext and cannot play back this audio.");
            return;
        }
            window.AudioContext = window.webkitAudioContext;
        }
    
        context = new AudioContext();
    }
    
    function playByteArray(byteArray) {
    
        var arrayBuffer = new ArrayBuffer(byteArray.length);
        var bufferView = new Uint8Array(arrayBuffer);
        for (i = 0; i < byteArray.length; i++) {
          bufferView[i] = byteArray[i];
        }
    
        context.decodeAudioData(arrayBuffer, function(buffer) {
            buf = buffer;
            play();
        });
    }
    
    // Play the loaded file
    function play() {
        // Create a source node from the buffer
        var source = context.createBufferSource();
        source.buffer = buf;
        // Connect to the final output node (the speakers)
        source.connect(context.destination);
        // Play immediately
        source.start(0);
    }
    
    0 讨论(0)
  • 2021-02-08 15:42

    I suspect you can achieve this with HTML5 Audio API easily enough:

    https://developer.mozilla.org/en/Introducing_the_Audio_API_Extension

    This library might come in handy too, though I'm not sure if it reflects the latest browser behaviours:

    https://github.com/jussi-kalliokoski/audiolib.js

    0 讨论(0)
  • 2021-02-08 15:47

    The following code will play the sine wave at 0.5 and 2.0. Call the function play_buffersource() in your button or anywhere you want.

    Tested using Chrome with Web Audio flag enabled. For your case, all that you need to do is just to shuffle your audio bytes to the buf.

    <script type="text/javascript">
    const kSampleRate = 44100; // Other sample rates might not work depending on the your browser's AudioContext
    const kNumSamples = 16834;
    const kFrequency  = 440;
    const kPI_2       = Math.PI * 2;
    
    function play_buffersource() {
        if (!window.AudioContext) {
            if (!window.webkitAudioContext) {
                alert("Your browser sucks because it does NOT support any AudioContext!");
                return;
            }
            window.AudioContext = window.webkitAudioContext;
        }
    
        var ctx = new AudioContext();
    
        var buffer = ctx.createBuffer(1, kNumSamples, kSampleRate);
        var buf    = buffer.getChannelData(0);
        for (i = 0; i < kNumSamples; ++i) {
            buf[i] = Math.sin(kFrequency * kPI_2 * i / kSampleRate);
        }
    
        var node = ctx.createBufferSource(0);
        node.buffer = buffer;
        node.connect(ctx.destination);
        node.noteOn(ctx.currentTime + 0.5);
    
        node = ctx.createBufferSource(0);
        node.buffer = buffer;
        node.connect(ctx.destination);
        node.noteOn(ctx.currentTime + 2.0);
    }
    </script>
    

    References:

    • http://epx.com.br/artigos/audioapi.php
    • https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html

    If you need to resample the audio, you can use a JavaScript resampler: https://github.com/grantgalitz/XAudioJS

    If you need to decode the base64 data, there are a lot of JavaScript base64 decoder: https://github.com/carlo/jquery-base64

    0 讨论(0)
  • 2021-02-08 15:48

    If you have the bytes on the server then I would suggest that you create some kind of handler on the server that will stream the bytes to the response as a wav file. This "file" would only be in memory on the server and not on disk. Then the browser can just handle it like a normal wav file. More details on the server stack would be needed to give more information on how this could be done in your environment.

    0 讨论(0)
提交回复
热议问题