Я делаю программу визуализации музыки в 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