Javascript 使用AnalyzerNode进行频率截止

Javascript 使用AnalyzerNode进行频率截止,javascript,webkit,web-audio-api,webkitaudiocontext,audiocontext,Javascript,Webkit,Web Audio Api,Webkitaudiocontext,Audiocontext,我正在使用Web API创建一个音频条可视化工具,我希望这些条仅显示~40Hz到~10kHz。我发现的唯一东西是频域,但它并没有提供我想要的东西(AnalyserNode.fftSize)。有没有一种方法可以只直观地看到这种频率?这是我的密码: .controller('PlayerCtrl', function(PlayerService, $scope){ $scope.title = PlayerService.songName; $scope.art =

我正在使用Web API创建一个音频条可视化工具,我希望这些条仅显示~40Hz到~10kHz。我发现的唯一东西是频域,但它并没有提供我想要的东西(AnalyserNode.fftSize)。有没有一种方法可以只直观地看到这种频率?这是我的密码:

.controller('PlayerCtrl', function(PlayerService, $scope){
        $scope.title = PlayerService.songName;
        $scope.art = PlayerService.songArt;
        $scope.url = PlayerService.songUrl + '?client_id=54970813fe2081a104a874f0f870bcfe';

        if (! window.AudioContext) {
            if (! window.webkitAudioContext) {
                alert('no audiocontext found, update your browser yo');
            }
            window.AudioContext = window.webkitAudioContext;
        }
        var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
        var analyser = audioCtx.createAnalyser();
        analyser.minDecibels = -60;
        analyser.maxDecibels = 0;
        analyser.smoothingTimeConstant = 0.85;

        var audioBuffer;
        var sourceNode;
        var javascriptNode;

        var canvas = document.querySelector('.visualizer');
        var canvasCtx = canvas.getContext("2d");

        var intendedWidth = document.querySelector('.now-playing').clientWidth;

        canvas.setAttribute('width',intendedWidth);

        var visualSelect = document.getElementById("visual");

        var drawVisual;

        setupAudioNodes();
        loadSound($scope.url); //music file

        function loadSound(url) {
            var request = new XMLHttpRequest();
            request.open('GET', url, true);
            request.responseType = 'arraybuffer';

            request.onload = function() {
                audioCtx.decodeAudioData(request.response, function(buffer) {
                    playSound(buffer);
                }, function(error){
                    console.log(error)
                });
            };
            request.send();
        }

        function playSound(buffer) {
            sourceNode.buffer = buffer;
            sourceNode.start(0);
            $(".content").show();
            $("#hue").hide();
        }


        function setupAudioNodes() {
            console.log('audio nodes')
            javascriptNode = audioCtx.createScriptProcessor(2048, 1, 1);
            javascriptNode.connect(audioCtx.destination);

            sourceNode = audioCtx.createBufferSource();
            sourceNode.connect(analyser);
            analyser.connect(javascriptNode);

            sourceNode.connect(audioCtx.destination);

            visualize();
        }

        function visualize() {
            console.log('viz');
            WIDTH = canvas.width;
            HEIGHT = canvas.height;

            analyser.fftSize = 64;
            var bufferLength = analyser.frequencyBinCount;
            console.log(bufferLength);
            var dataArray = new Uint8Array(bufferLength);

            canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);

            function draw() {
                drawVisual = requestAnimationFrame(draw);

                analyser.getByteFrequencyData(dataArray);

                canvasCtx.fillStyle = 'rgb(0, 0, 0)';
                canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);

                var barWidth = (WIDTH / bufferLength) * 2.5;
                var barHeight;
                var x = 0;

                for (var i = 0; i < bufferLength; i++) {
                    barHeight = dataArray[i];

                    canvasCtx.fillStyle = 'rgb(' + (barHeight + 100) + ',50,50)';
                    canvasCtx.fillRect(i*17, HEIGHT - barHeight / 2, 10, barHeight);

                    x += barWidth + 1;
                }
            }
            draw()
        }

    })
.controller('PlayerCtrl',函数(PlayerService,$scope){
$scope.title=PlayerService.songName;
$scope.art=PlayerService.songArt;
$scope.url=PlayerService.songUrl+'?客户端id=54970813fe2081a104a874f0f870bcfe';
如果(!window.AudioContext){
如果(!window.webkitadiocontext){
警报(“未找到音频上下文,请更新您的浏览器”);
}
window.AudioContext=window.webkitadiocontext;
}
var audioCtx=new(window.AudioContext | | window.webkitadiocontext)();
var Analyzer=audioCtx.createAnalyzer();
分析仪。minDecibels=-60;
分析仪最大分贝=0;
分析仪.平滑时间常数=0.85;
无功音频缓冲器;
var源节点;
var-javascriptNode;
var canvas=document.querySelector('.visualizer');
var canvasCtx=canvas.getContext(“2d”);
var intendedWidth=document.querySelector('.now playing').clientWidth;
canvas.setAttribute('width',intendedWidth);
var visualSelect=document.getElementById(“可视”);
视觉变化;
setupAudioNodes();
loadSound($scope.url);//音乐文件
函数loadSound(url){
var request=new XMLHttpRequest();
打开('GET',url,true);
request.responseType='arraybuffer';
request.onload=函数(){
audioCtx.decodeAudioData(请求、响应、功能(缓冲区){
播放声音(缓冲);
},函数(错误){
console.log(错误)
});
};
request.send();
}
功能播放声音(缓冲区){
sourceNode.buffer=缓冲区;
sourceNode.start(0);
$(“.content”).show();
$(“#色调”).hide();
}
函数setupAudioNodes(){
console.log('音频节点')
javascriptNode=audioCtx.createScriptProcessor(2048,1,1);
connect(audioCtx.destination);
sourceNode=audioCtx.createBufferSource();
连接(分析仪);
connect(javascriptNode);
sourceNode.connect(audioCtx.destination);
形象化();
}
函数可视化(){
控制台日志('viz');
宽度=画布宽度;
高度=画布高度;
Analyzer.fftSize=64;
var bufferLength=分析仪频率BINCOUNT;
console.log(缓冲区长度);
var DATARRAY=新的Uint8Array(缓冲区长度);
canvasCtx.clearRect(0,0,宽度,高度);
函数绘图(){
drawVisual=requestAnimationFrame(绘制);
分析仪。GetByTefFrequencyData(数据阵列);
canvasCtx.fillStyle='rgb(0,0,0)';
canvasCtx.fillRect(0,0,宽度,高度);
变量barWidth=(宽度/缓冲长度)*2.5;
高度;
var x=0;
对于(变量i=0;i
只是不要使用分析仪计算的较高频率。实现这一点的简单方法是将bufferLength设置为比Analyzer.frequencyBinCount更小的值。分析仪将为您提供尽可能多的数据,并将其余数据丢弃


箱子的间隔均匀,从零到采样率的一半,因此在典型采样率(44kHz)下,您需要大约一半的箱子。更一般地说,
Math.ceil(analyzer.frequencyBinCount*10000/(audioCtx.sampleRate/2))
应该给出您想要的数字。

您需要计算频率分辨率:sampleRate/fftSize。这将为您提供
getByteFrequencyData
提供的每个数字的频率范围。当然,如果您依赖默认的采样器,那么很难知道这个比率。将其覆盖为:

let audio_context = new AudioContext({
    sampleRate: 44000,
});

我解释了@mehmet关于

频率分辨率:sampleRate/fftSize

这意味着,总计被划分为显示的均衡器频带

calcFreqs(sampleRate, fftSize) {
    const bands = fftSize/2; // bands are half the fftSize
    const fqRange = sampleRate / bands;
    let allocated = [];

    for ( let i = 0, j = bands; i < j; i++ ) {
        sampleRate = Math.round(sampleRate - fqRange);
        allocated.push(sampleRate);
    }
    // console.log(allocated.slice().reverse());
    return allocated.slice().reverse();
}
calcFreqs(采样器,fftSize){
const bands=fftSize/2;//频带是fftSize的一半
常数fqRange=采样率/波段;
设分配=[];
for(设i=0,j=bands;i
因此,对于48000Hz以上的16个频带,样本:

[0,3000,6000,9000,12000,15000,18000,21000,24000,27000,30000,33000,36000,39000,42000,45000]

我想请专家澄清一下,但这里有一种方法可以做到这一点。
我的项目在

我要试试这个。谢谢