2016-05-24 2 views
2

Я делаю программу визуализации музыки в 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 (длину кадра), чтобы звук синхронизировался со спектром. Звук двухканальный, будет ли этот алгоритм работать на это?

+0

Просто стрельба из бедра, но почему бы не использовать катящееся окно, чтобы окно преобразования двигалось вперед с той же скоростью, что и поток аудиопотока? Оптимизация может заключаться в повторном использовании вычислений, которые «перекрываются», т. Е. Вычислений кеша, которые вы делали в последний раз, перед перемещением окна. –

+0

IMO, используя 'glutIdleFunc()' не так просто в такой синхронизации. 'glutTimerFunc()', возможно, был бы лучшим выбором. Другая возможность была бы, если бы ваш код использовал обратный вызов для генерации спектров, чтобы вызвать 'glutPostRedisplay()' в конце каждого цикла рендеринга обратного вызова, для начала. – user3078414

+0

@ user3078414 Я не очень хорошо разбираюсь в OpenGL. Я использовал этот график из 'https: // en.wikibooks.org/wiki/OpenGL_Programming/Scientific_OpenGL_Tutorial_02' для построения спектра. – Indra

ответ

1

Начните с определения того, как часто вы хотите обновлять визуализатор. Предположим, мы хотим, чтобы он обновлялся 25 раз в секунду (аналогично частоте кадров ТВ или видео). Это означает каждые 1/25 секунд или каждые 40 мс. При частоте дискретизации 44,1 кГц это соответствует 44100/25 = 1764 выборкам. Поскольку мы, как правило, хотим иметь мощность 2 БПФ, тогда давайте перейдем к N = 2048.

Это дает разрешение по частотной оси 44100/2048 = 21,5 Гц. Если вы хотите получить более высокое разрешение, вы можете перекрывать последовательные окна FFT, например. сохраняя одну и ту же скорость обновления и перекрываясь на 50%, тогда вы можете иметь N = 4096 для разрешения 10,75 Гц.

+0

Когда 'N 2048', музыка заканчивается на' Framepointer = 2942976' в общей сложности '10460160 образцов'. – Indra

+0

@Indrajith: похоже, что ваш код на самом деле не синхронизирует визуализатор с воспроизведением звука - вам нужно добавить некоторый временной код, чтобы гарантировать, что кадр, который вы обрабатываете, соответствует кадру, который воспроизводится. –

+0

@Paule Я думаю, из-за сложности алгоритма, если взять N как '2048'. Больше всего он может обрабатывать фреймы '2942976'. Как мы можем увеличить время обработки. Можем ли мы уменьшить время обработки аудио без воспроизведения воспроизводимой музыки? – Indra