您如何使用 Web Audio API 测量两种声音之间的差异?
How do you measure the difference between two sounds using the Web Audio API?
我正在尝试使用分析器节点和 getByteFrequencyData() 测量两种声音之间的差异。我认为通过对每个频率区间的差异求和,我可以得出一个数字来表示这两种声音的差异程度。然后我就可以改变声音并再次测量数字,看看新声音是否与以前有或多或少的不同。
getByteFrequencyData() 是否完全包含声音的表示,或者我是否需要包含其他数据来限定声音?
这是我使用的代码:
var Spectrogram = (function(){
function Spectrogram(ctx) {
this.analyser = ctx.createAnalyser();
this.analyser.fftSize = 2048;
this.sampleRate = 512;
this.scriptNode = ctx.createScriptProcessor(this.sampleRate, 1, 1);
this.scriptNode.onaudioprocess = this.process.bind(this);
this.analyser.connect(this.scriptNode);
this.startNode = this.analyser;
this.endNode = this.scriptNode;
this.data = [];
}
Spectrogram.prototype.process = function(e) {
var d = new Uint8Array(this.analyser.frequencyBinCount);
this.analyser.getByteFrequencyData(d);
this.data.push(d);
var inputBuffer = e.inputBuffer;
var outputBuffer = e.outputBuffer;
for(var channel = 0; channel < outputBuffer.numberOfChannels; channel++) {
var inputData = inputBuffer.getChannelData(channel);
var outputData = outputBuffer.getChannelData(channel);
for(var sample = 0; sample < inputBuffer.length; sample++) {
outputData[sample] = inputData[sample];
}
}
};
Spectrogram.prototype.compare = function(other) {
var fitness = 0;
for(var i=0; i<this.data.length; i++) {
if(other.data[i]) {
for(var k=0; k<this.data[i].length; k++) {
fitness += Math.abs(this.data[i][k] - other.data[i][k]);
}
}
}
return fitness;
}
return Spectrogram;
})();
您可以使用 Meyda 包提供的 spectralFlux 函数来比较两个信号。根据维基百科,光谱通量是 "usually calculated as the 2-norm (also known as the Euclidean distance) between the two normalised spectra."
在 运行ninng npm install --save meyda
之后,你会做这样的事情:
const spectralFlux = require('meyda/src/extractors/spectralFlux');
const difference = spectralFlux({
signal: [your first signal],
previousSignal: [your second signal]
});
随意复制 here 中的代码,这样您就不必处理依赖项,代码库已获得适当许可。
它将 return 两个信号听起来如何 "different" 的系数。您可以在时域或频域中执行此操作。你会得到不同的数字,但两者都会与 "different" 声音彼此之间的关系相关。
但是 "difference" 可能无法足够准确地描述您的用例的差异。例如,您可能非常关心音量差异,而不是非常关心音色差异,但频谱通量指标并未考虑到这一点。您可能希望 运行 每个信号首先通过特征提取器,找到关于它们属性的其他统计信息,例如它们的感知量、它们的亮度等,然后在这些数据之间取一个加权欧几里得距离,这将提供一个更有针对性的"difference" 衡量您的目的所需的指标。
很高兴进一步阐述,但这对于 SO 答案来说已经很长了。
我正在尝试使用分析器节点和 getByteFrequencyData() 测量两种声音之间的差异。我认为通过对每个频率区间的差异求和,我可以得出一个数字来表示这两种声音的差异程度。然后我就可以改变声音并再次测量数字,看看新声音是否与以前有或多或少的不同。
getByteFrequencyData() 是否完全包含声音的表示,或者我是否需要包含其他数据来限定声音?
这是我使用的代码:
var Spectrogram = (function(){
function Spectrogram(ctx) {
this.analyser = ctx.createAnalyser();
this.analyser.fftSize = 2048;
this.sampleRate = 512;
this.scriptNode = ctx.createScriptProcessor(this.sampleRate, 1, 1);
this.scriptNode.onaudioprocess = this.process.bind(this);
this.analyser.connect(this.scriptNode);
this.startNode = this.analyser;
this.endNode = this.scriptNode;
this.data = [];
}
Spectrogram.prototype.process = function(e) {
var d = new Uint8Array(this.analyser.frequencyBinCount);
this.analyser.getByteFrequencyData(d);
this.data.push(d);
var inputBuffer = e.inputBuffer;
var outputBuffer = e.outputBuffer;
for(var channel = 0; channel < outputBuffer.numberOfChannels; channel++) {
var inputData = inputBuffer.getChannelData(channel);
var outputData = outputBuffer.getChannelData(channel);
for(var sample = 0; sample < inputBuffer.length; sample++) {
outputData[sample] = inputData[sample];
}
}
};
Spectrogram.prototype.compare = function(other) {
var fitness = 0;
for(var i=0; i<this.data.length; i++) {
if(other.data[i]) {
for(var k=0; k<this.data[i].length; k++) {
fitness += Math.abs(this.data[i][k] - other.data[i][k]);
}
}
}
return fitness;
}
return Spectrogram;
})();
您可以使用 Meyda 包提供的 spectralFlux 函数来比较两个信号。根据维基百科,光谱通量是 "usually calculated as the 2-norm (also known as the Euclidean distance) between the two normalised spectra."
在 运行ninng npm install --save meyda
之后,你会做这样的事情:
const spectralFlux = require('meyda/src/extractors/spectralFlux');
const difference = spectralFlux({
signal: [your first signal],
previousSignal: [your second signal]
});
随意复制 here 中的代码,这样您就不必处理依赖项,代码库已获得适当许可。
它将 return 两个信号听起来如何 "different" 的系数。您可以在时域或频域中执行此操作。你会得到不同的数字,但两者都会与 "different" 声音彼此之间的关系相关。
但是 "difference" 可能无法足够准确地描述您的用例的差异。例如,您可能非常关心音量差异,而不是非常关心音色差异,但频谱通量指标并未考虑到这一点。您可能希望 运行 每个信号首先通过特征提取器,找到关于它们属性的其他统计信息,例如它们的感知量、它们的亮度等,然后在这些数据之间取一个加权欧几里得距离,这将提供一个更有针对性的"difference" 衡量您的目的所需的指标。
很高兴进一步阐述,但这对于 SO 答案来说已经很长了。