如何使用 vanilla javascript 从用户的媒体文件中获取频率?

How to get frequency from user's media file with vanilla javascript?

我需要使用 vanilla javascript 从用户的媒体文件中获取频率。 因为,我会在 canvas.

上绘制光谱

我确实在 Web 音频上使用了 createMediaElementSource 和 getByteTimeDomainData API。但是,我无法解决这个问题。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <input type="file" id="file">
    <canvas id="canvas" width="500" height="250"></canvas>
    <script>

        // draw an oscilloscope of the current audio source
        var canvas = document.getElementById('canvas');
        var canvasCtx = canvas.getContext('2d');
        var WIDTH = canvas.width;
        var HEIGHT = canvas.height;
        var audio = null;

        document.getElementById('file').addEventListener('change', function(e) {
            var audioCtx = new AudioContext();
            var file = e.target.files[0];
            var fileName = file.name;
            var fileReader = new FileReader();
            var audio = new Audio(fileName);
            var analyser = audioCtx.createAnalyser();

            fileReader.onload = function(e) {
                var buffer = e.target.result;
                var source = audioCtx.createMediaElementSource(audio);
                var dataArray = new Uint8Array(analyser.fftSize);
                source.connect(analyser);
                analyser.connect(audioCtx.destination);
                analyser.getByteTimeDomainData(dataArray);
                console.log(dataArray);
            }
            fileReader.readAsArrayBuffer(file);
        });
    </script>
</body>
</html>

我以为 dataArray 有媒体文件的频率。 但是,dataArray 只有 128.

您错过了几个重要步骤

  1. 解码音频数据
  2. 如果要提供缓冲区,则需要创建 BufferSource
  3. 您想 source.start() 开始播放

所以 - 这种方法可以满足您的需求,但我使用的是 setInterval 而不是您想要显示分析器输出的任何方法

    document.getElementById('file').addEventListener('change', function(e) {
        var audioCtx = new AudioContext();
        var file = e.target.files[0];
        var fileName = file.name;
        var fileReader = new FileReader();
        // you don't need this next line at all
        // var audio = new Audio(fileName);
        var analyser = audioCtx.createAnalyser();

        fileReader.onload = function(e) {
            var buffer = e.target.result;
            console.log(buffer);
            audioCtx.decodeAudioData(buffer).then(audioBuffer => {
                console.log(audioBuffer);
                var source = audioCtx.createBufferSource();
                var dataArray = new Uint8Array(analyser.fftSize);
                source.buffer = audioBuffer;
                source.connect(analyser);
                analyser.connect(audioCtx.destination);
                source.start();
                setInterval(() => {
                    console.log(source.context.currentTime);
                    analyser.getByteTimeDomainData(dataArray);
                    console.log(dataArray);
                }, 1000);
            });
        }
        fileReader.readAsArrayBuffer(file);
    });