Давайте попробуем настоящий ответ на этот раз. :-)
Проблема слишком сложна, чтобы дать полное решение со всем кодом в этом пространстве, но я буду использовать псевдокод и предположим, что у вас есть библиотека, которая может окончить блок выборок и вычислять БПФ.
Это похоже на построение отображения формы волны. Когда вы создаете отображение осциллограммы, вы определяете, сколько выборок «вписывается» в один горизонтальный пиксель на текущем уровне масштабирования, где они начинают задавать положение X-прокрутки, вычисляют минимальное и максимальное значение выборки для этого сегмента и дают вам min/max Y для этого пикселя формы сигнала. (На самом деле это немного упрощено, я написал код визуализации формы сигнала в тот же день, но это хорошее приближение.)
Чтобы покрасить волны с частотой, вы хотите предварительно запрограммировать волновые данные с использованием короткого времени FFT с маленькими бункерами, и для каждого бункера определяют, какая преобладающая частота, а затем сопоставлять ее с цветом на спектре от красного до фиолетового.
Скажем, ваши звуковые образцы в массиве под названием samples
, вот псевдокод.
// sample rate
float fS = 44100;
// size of frame for analysis, you may want to play with this
float frameMsec = 10;
// samples in a frame
int frameSamples = (int)(fS/(frameMsec * 1000));
// how much overlap each frame, you may want to play with this one too
int overlapSamples = (frameSamples/2);
// number of samples in the sound file
int numSamples = ...;
// input array of samples
float inSamples[] = ...;
// color to use for each frame
RGB outColors[] = new float[(numSamples/frameOverlap) + 1];
// scratch buffers
float tmpWindow[frameSamples];
float tmpFFT[frameSamples];
// helper function to apply a windowing function to a frame of samples
void calcWindow(float* dst, const float* src, int size);
// helper function to compute FFT
void fft(float* dst, const float* src, int size);
// find the index of array element with the highest absolute value
// probably want to take some kind of moving average of buf[i]^2
// and return the maximum found
int maxFreqIndex(const float* buf, int size);
// map a frequency to a color, red = lower freq -> violet = high freq
RGB freqToColor(int i);
for (int i = 0, outptr = 0; i < numSamples; i += frameOverlap, outptr++)
{
// window another frame for FFT
calcWindow(tmpWindow, &inSamples[i], frameSamples);
// compute the FFT on the next frame
fft(tmpFFT, tmpWindow, frameSamples);
// which frequency is the highest?
int freqIndex = maxFreqIndex(tmpFFT, frameSamples);
// map to color
outColor[outptr] = freqToColor(freqIndex);
}
Это даст вам массив RGB, который вы можете увеличивать и уменьшать масштаб как вы увеличили масштаб дисплея формы сигнала и выход. По мере увеличения вы, вероятно, хотите усреднить значения RGB смежных кадров, чтобы дать вам общий вид.
Надеюсь, это поможет.
Audacity - популярный бесплатный аудиоредактор с открытым исходным кодом для многоплатформенных платформ, включая исходный код, который можно загрузить с http://web.audacityteam.org/download/source. Я уверен, что если вы посмотрите вокруг, найду код, где он рисует осциллограммы. (Если вы используете этот код, ПОЖАЛУЙСТА, обязательно включите все атрибуты с открытым исходным кодом в соответствии с их лицензией с открытым исходным кодом.) –
@RonKuper 1) нет, это не так. В нем есть темы для покраски всей волны определенного цвета. Это не то, о чем я прошу. 2) Вы задумываетесь о том, чтобы опросить этот вопрос с таким забытым ответом. И я довольно долго смотрел на аудио-технические статьи о Serato/Traktor/Comparisonics. – user656028
Я не спустил ваш вопрос, на самом деле я просто поддержал его для вас. –