mirror of
https://github.com/ggerganov/ggwave.git
synced 2026-03-29 00:19:01 +08:00
spectrogram : add simple spectrogram tool (#17)
This commit is contained in:
91
examples/spectrogram/fft.h
Normal file
91
examples/spectrogram/fft.h
Normal file
@@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// FFT routines taken from https://stackoverflow.com/a/37729648/4039976
|
||||
|
||||
constexpr auto kMaxSamplesPerFrame = 1024;
|
||||
|
||||
int log2(int N) {
|
||||
int k = N, i = 0;
|
||||
while(k) {
|
||||
k >>= 1;
|
||||
i++;
|
||||
}
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
int reverse(int N, int n) {
|
||||
int j, p = 0;
|
||||
for(j = 1; j <= log2(N); j++) {
|
||||
if(n & (1 << (log2(N) - j)))
|
||||
p |= 1 << (j - 1);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void ordina(float * f1, int N) {
|
||||
float f2[2*kMaxSamplesPerFrame];
|
||||
for (int i = 0; i < N; i++) {
|
||||
int ir = reverse(N, i);
|
||||
f2[2*i + 0] = f1[2*ir + 0];
|
||||
f2[2*i + 1] = f1[2*ir + 1];
|
||||
}
|
||||
for (int j = 0; j < N; j++) {
|
||||
f1[2*j + 0] = f2[2*j + 0];
|
||||
f1[2*j + 1] = f2[2*j + 1];
|
||||
}
|
||||
}
|
||||
|
||||
void transform(float * f, int N) {
|
||||
ordina(f, N); //first: reverse order
|
||||
float * W;
|
||||
W = (float *)malloc(N*sizeof(float));
|
||||
W[2*1 + 0] = cos(-2.*M_PI/N);
|
||||
W[2*1 + 1] = sin(-2.*M_PI/N);
|
||||
W[2*0 + 0] = 1;
|
||||
W[2*0 + 1] = 0;
|
||||
for (int i = 2; i < N / 2; i++) {
|
||||
W[2*i + 0] = cos(-2.*i*M_PI/N);
|
||||
W[2*i + 1] = sin(-2.*i*M_PI/N);
|
||||
}
|
||||
int n = 1;
|
||||
int a = N / 2;
|
||||
for(int j = 0; j < log2(N); j++) {
|
||||
for(int i = 0; i < N; i++) {
|
||||
if(!(i & n)) {
|
||||
int wi = (i * a) % (n * a);
|
||||
int fi = i + n;
|
||||
float a = W[2*wi + 0];
|
||||
float b = W[2*wi + 1];
|
||||
float c = f[2*fi + 0];
|
||||
float d = f[2*fi + 1];
|
||||
float temp[2] = { f[2*i + 0], f[2*i + 1] };
|
||||
float Temp[2] = { a*c - b*d, b*c + a*d };
|
||||
f[2*i + 0] = temp[0] + Temp[0];
|
||||
f[2*i + 1] = temp[1] + Temp[1];
|
||||
f[2*fi + 0] = temp[0] - Temp[0];
|
||||
f[2*fi + 1] = temp[1] - Temp[1];
|
||||
}
|
||||
}
|
||||
n *= 2;
|
||||
a = a / 2;
|
||||
}
|
||||
free(W);
|
||||
}
|
||||
|
||||
void FFT(float * f, int N, float d) {
|
||||
transform(f, N);
|
||||
for (int i = 0; i < N; i++) {
|
||||
f[2*i + 0] *= d;
|
||||
f[2*i + 1] *= d;
|
||||
}
|
||||
}
|
||||
|
||||
void FFT(float * src, float * dst, int N, float d) {
|
||||
for (int i = 0; i < N; ++i) {
|
||||
dst[2*i + 0] = src[i];
|
||||
dst[2*i + 1] = 0.0f;
|
||||
}
|
||||
FFT(dst, N, d);
|
||||
}
|
||||
Reference in New Issue
Block a user