我知道之前被问了一千次,但我仍然找不到解决方案。搜索SO,我确实找到了它的算法,但缺乏真正理解它所需的数学知识,我无助地迷失了!
首先,我的目标是计算整个频谱图并将其保存到图像中,以便将其用于可视化器。
我尝试使用 Sound.computeSpectrum,但这需要播放声音并等待它结束,我想以比聆听所有歌曲所需的时间更短的方式计算频谱图。我有 2 小时长的 mp3。
我现在正在做的是从 Sound 对象中读取字节,分成两个 Vectors(.); 然后使用计时器,每 100 毫秒我调用一个函数(步骤 1),其中我有算法的实现,如下所示:
- 对于每个向量(每个向量),我将 hann 函数应用于元素;
- 对于每个向量,我都会取消虚部(我有一个辅助向量)
- 对于每个向量,我应用 FFT
- 对于每个向量,我找到前 N / 2 个元素的大小
- 对于每个向量,我将平方幅度转换为 dB 比例
- 结尾。
但我只得到负值,只有 30% 的结果可能有用(其余部分相同)
我将只发布一个频道的代码,以摆脱“每个矢量”部分。
private var N:Number = 512;
private function step1() : void
{
var xReLeft:Vector.<Number> = new Vector.<Number>(N);
var xImLeft:Vector.<Number> = new Vector.<Number>(N);
var leftA:Vector.<Number> = new Vector.<Number>(N);
// getting sample range
leftA = this.channels.left.slice(step * N, step * (N) + (N));
if (leftA.length < N)
{
stepper.removeEventListener(TimerEvent.TIMER, getFreq100ms);
return;
}
else if (leftA.length == 0)
{
stepper.removeEventListener(TimerEvent.TIMER, getFreq100ms);
return;
}
var i:int;
// hann window function init
m_win = new Vector.<Number>(N);
for ( var i:int = 0; i < N; i++ )
m_win[i] = (4.0 / N) * 0.5 * (1 - Math.cos(2 * Math.PI * i / N));
// applying hann window function
for ( i = 0; i < N; i++ )
{
xReLeft[i] = m_win[i]*leftA[i];
//xReRight[i] = m_win[i]*rightA[i];
}
// nullify the imaginary part
for ( i = 0; i < N; i++ )
{
xImLeft[i] = 0.0;
//xImRight[i] = 0.0;
}
var magnitutel:Vector.<Number> = new Vector.<Number>(N);
fftl.run( xReLeft, xImLeft );
current = xReLeft;
currf = xImLeft;
for ( i = 0; i < N / 2; i++ )
{
var re:Number = xReLeft[i];
var im:Number = xImLeft[i];
magnitutel[i] = Math.sqrt(re * re + im * im);
}
const SCALE:Number = 20 / Math.LN10;
var l:uint = this.total.length;
for ( i = 0; i < N / 2; i++ )
{
magnitutel[i] = SCALE * Math.log( magnitutel[i] + Number.MIN_VALUE );
}
var bufferl:Vector.<Number> = new Vector.<Number>();
for (i = 0; i < N / 2 ; i++)
{
bufferl[i] = magnitutel[i];
}
var complete:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
complete[0] = bufferl;
this.total[step] = complete;
this.step++;
}
该函数在定时器(步进器)调度的事件中执行。显然我做错了什么,正如我所说的,我只有负值,而且更多的值在 1 到 7000 之间(至少)。
我要提前感谢您的帮助。
怀着敬意,保罗