我正在用C++做一個音樂可視化程序。它給出了音頻輸入的頻譜。我使用Aquila-dsp獲取音頻樣本,Kiss-fft用於執行FFT,SMFL用於播放音頻。輸入格式爲(.wav)格式。 OpenGL用於繪製圖形。如何將音頻與功率譜同步並選擇幀長度N(做fft)?
算法應用於:
1. *framePointer = 0, N = 10000;*
2. Load audio file and play it using SFML.
3. For *i* = framePointer to --> *framePointer* + *N* < *total_samples_count*
Collect audio samples.
4. Apply Window Function (Hann window)
5. Apply *FFT*
6. Calculate magnitude of first N/2 *FFT* data
*Magnitude* = sqrt(re * re + im * im)
7. Convert to dB(log) scale (optional)
10*log(magnitude)
8. Plot N/2, log(magnitude) values
9. If *framaPointer* >= *toatl_samples_count - N*
Exit
Else go to step 3.
#define N 10000
int framePointer = 0;
void getData()
{
int i,j,x;
Aquila::WaveFile wav(fileName);
double mag[N/2];
double roof = wav.getSamplesCount();
//Get first N samples
for(i = framePointer, j = 0; i < (framePointer + N)
&& framePointer < roof - N ; i++,j++ ){
//Apply window function on the sample
double multiplier = 0.5 * (1 - cos(2*M_PI*j/(N-1)));
in[j].r = multiplier * wav.sample(i);
in[j].i = 0; //stores N samples
}
if(framePointer < roof-N -1){
framePointer = i;
}
else {
printf("Frame pointer > roof - N \n");
printf("Framepointer = %d\n",framePointer);
//get total time and exit
timestamp_t t1 = get_timestamp();
double secs = (t1 - tmain)/1000000.0L;
std::cout<<"Program exit.\nTotal time: "<<secs<<std::endl;
exit(0);
}
// Apply FFT
getFft(in,out);
// calculate magnitude of first N/2 FFT
for(i = 0; i < N/2; i++){
mag[i] = sqrt((out[i].r * out[i].r) + (out[i].i * out[i].i));
graph[i] = log(mag[i]) *10;
}
}
我繪製使用OpenGL圖形。 Full source code
我得到的問題是在選擇幀長度(N值)。
對於具有音頻的一定長度:
Length: 237191 ms
Sample frequency: 44100 Hz
Channels: 2
Byte rate: 172 kB/s
Bits per sample: 16b
該圖與音頻如果我選擇N = 10000或同步的至少它而音頻兩端停止。
如何選擇N(幀長),使音頻與頻譜同步。 音頻是雙通道的,這個算法能工作嗎?
剛剛從臀部拍攝,但爲什麼不使用滾動窗口,因此轉換窗口以與音頻採樣流相同的速率向前移動?優化可以是在移動窗口之前重新使用「重疊」的計算,即上次進行的高速緩存計算。 –
IMO在這種同步中使用'glutIdleFunc()'並不容易。 'glutTimerFunc()'也許是更好的選擇。另一種可能性是,如果您的代碼使用回調來生成譜圖,則在每個回調的呈現週期結束時調用'glutPostRedisplay()'以開始。 – user3078414
@ user3078414我不擅長OpenGL。我用'https:// en.wikibooks.org/wiki/OpenGL_Programming/Scientific_OpenGL_Tutorial_02'中的這個圖來繪製頻譜圖。 – Indra