added own dft implementation (to slow for daily use)
This commit is contained in:
parent
53f03bbeac
commit
388ac49d39
3 changed files with 69 additions and 54 deletions
27
lib/dft.c
Normal file
27
lib/dft.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dft.h"
|
||||
|
||||
double complex_abs(complex_t z) {
|
||||
return sqrt(z.imag * z.imag + z.real * z.real);
|
||||
}
|
||||
|
||||
complex_t * dft(int16_t * in, complex_t * out, int16_t n) {
|
||||
uint16_t k, l;
|
||||
|
||||
// clear output
|
||||
memset(out, 0, n * sizeof(complex_t));
|
||||
|
||||
for (k = 0; k < n/2; k++) {
|
||||
for (l = 0; l < n; l++) {
|
||||
double phasor = -2*M_PI*k*l/n;
|
||||
|
||||
out[k].real += in[l] * cos(phasor);
|
||||
out[k].imag += in[l] * sin(phasor);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
12
lib/dft.h
Normal file
12
lib/dft.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef LIBDFT_H
|
||||
#define LIBDFT_H
|
||||
|
||||
typedef struct complex {
|
||||
double real;
|
||||
double imag;
|
||||
} complex_t;
|
||||
|
||||
double complex_abs(complex_t z);
|
||||
complex_t * dft(int16_t * in, complex_t * out, int16_t n);
|
||||
|
||||
#endif
|
84
src/fnvum.c
84
src/fnvum.c
|
@ -3,23 +3,21 @@
|
|||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <complex.h>
|
||||
|
||||
/* third party libs */
|
||||
#include "libfn.h"
|
||||
#include "../lib/libfn.h"
|
||||
#include "../lib/dft.h"
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
#include <pulse/simple.h>
|
||||
#include <pulse/error.h>
|
||||
#include <pulse/gccmacro.h>
|
||||
#include <fftw3.h>
|
||||
|
||||
#define BUFFER_SIZE 1024
|
||||
#define SAMPLING_RATE 44100
|
||||
#define SCREEN_WIDTH (BUFFER_SIZE/2+1)
|
||||
#define SCREEN_HEIGHT (SCREEN_WIDTH / 2)
|
||||
#define SCREEN_WIDTH (BUFFER_SIZE/2)
|
||||
#define SCREEN_HEIGHT (SCREEN_WIDTH/2)
|
||||
#define TITLE "fnordlicht vumeter & spectrum"
|
||||
|
||||
void show_level(SDL_Surface *dst, float level) {
|
||||
|
@ -35,9 +33,8 @@ void show_level(SDL_Surface *dst, float level) {
|
|||
SDL_Flip(dst);
|
||||
}
|
||||
|
||||
void show_spectrum(SDL_Surface * dst, complex * fft_data) {
|
||||
int x, p, start, end;
|
||||
double log_data[BUFFER_SIZE];
|
||||
void show_spectrum(SDL_Surface * dst, complex_t * dft_data) {
|
||||
int k;
|
||||
|
||||
SDL_Rect rect;
|
||||
Uint32 color = SDL_MapRGB(dst->format, 0xff, 0, 0);
|
||||
|
@ -45,15 +42,14 @@ void show_spectrum(SDL_Surface * dst, complex * fft_data) {
|
|||
|
||||
SDL_FillRect(dst, &dst->clip_rect, background);
|
||||
|
||||
double ampl, db;
|
||||
double ampl;
|
||||
rect.w = 1;
|
||||
|
||||
for (x = 0; x < BUFFER_SIZE/2+1; x++) {
|
||||
ampl = cabs(fft_data[x]);
|
||||
|
||||
rect.x = x;
|
||||
// rect.h = (ampl/3000000) * SCREEN_HEIGHT;
|
||||
rect.h = 10 * log10(ampl/300000) * SCREEN_HEIGHT;
|
||||
for (k = 0; k < SCREEN_WIDTH; k++) {
|
||||
ampl = complex_abs(dft_data[k]);
|
||||
|
||||
rect.x = k;
|
||||
rect.h = (ampl / 100000) * SCREEN_HEIGHT;
|
||||
rect.y = SCREEN_HEIGHT - rect.h;
|
||||
|
||||
SDL_FillRect(dst, &rect, color);
|
||||
|
@ -61,9 +57,9 @@ void show_spectrum(SDL_Surface * dst, complex * fft_data) {
|
|||
SDL_Flip(dst);
|
||||
}
|
||||
|
||||
void fade_level(int fd, float level) {
|
||||
void fade_level(int fd, y level) {
|
||||
struct remote_msg_fade_rgb_t fncmd;
|
||||
memset(&fncmd, 0, sizeof (struct remote_msg_t));
|
||||
memset(&fncmd, 0, sizeof(struct remote_msg_t));
|
||||
|
||||
fncmd.color.red = fncmd.color.green = fncmd.color.blue = (uint8_t) 255.0 * level;
|
||||
fncmd.address = 255;
|
||||
|
@ -77,21 +73,18 @@ void fade_level(int fd, float level) {
|
|||
int main(int argc, char *argv[]) {
|
||||
/* The sample type to use */
|
||||
static const pa_sample_spec ss = {
|
||||
.format = PA_SAMPLE_S16LE,
|
||||
.format = PA_SAMPLE_S16NE,
|
||||
.rate = SAMPLING_RATE,
|
||||
.channels = 1
|
||||
};
|
||||
|
||||
|
||||
pa_simple *s = NULL;
|
||||
SDL_Surface *screen = NULL;
|
||||
SDL_Event event;
|
||||
|
||||
int error, counter = 0, fd = -1;
|
||||
uint32_t level;
|
||||
int16_t * pcm_data;
|
||||
complex * fft_data;
|
||||
fftw_plan fft_plan;
|
||||
complex_t * dft_data;
|
||||
|
||||
/* init fnordlichts */
|
||||
if (argc > 1) {
|
||||
|
@ -118,12 +111,11 @@ int main(int argc, char *argv[]) {
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
/* init fftw & get buffers*/
|
||||
pcm_data = (int16_t *) malloc(BUFFER_SIZE);
|
||||
fft_data = (complex *) fftw_malloc(BUFFER_SIZE * sizeof (complex));
|
||||
fft_plan = fftw_plan_dft_1d(BUFFER_SIZE, fft_data, fft_data, FFTW_FORWARD, 0);
|
||||
/* allocate buffers */
|
||||
pcm_data = malloc(BUFFER_SIZE * sizeof(int16_t));
|
||||
dft_data = malloc(BUFFER_SIZE * sizeof(complex_t));
|
||||
|
||||
/* Create the recording stream */
|
||||
/* open the recording stream */
|
||||
if (!(s = pa_simple_new(NULL, TITLE, PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error))) {
|
||||
fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
|
||||
exit(-1);
|
||||
|
@ -142,40 +134,24 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
/* read PCM audio data */
|
||||
if (pa_simple_read(s, pcm_data, BUFFER_SIZE, &error) < 0) {
|
||||
if (pa_simple_read(s, pcm_data, sizeof(pcm_data[0]) * BUFFER_SIZE, &error) < 0) {
|
||||
fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* analyse audio data */
|
||||
uint16_t index, max = 0;
|
||||
uint32_t sum = 0;
|
||||
float level;
|
||||
for (index = 0; index < BUFFER_SIZE; index++) {
|
||||
sum += abs(pcm_data[index]);
|
||||
if (abs(pcm_data[index]) > max) max = pcm_data[index];
|
||||
|
||||
fft_data[index] = (double) pcm_data[index];
|
||||
/* do the dft and show spectrum */
|
||||
dft(pcm_data, dft_data, BUFFER_SIZE);
|
||||
show_spectrum(screen, dft_data);
|
||||
|
||||
/*int i;
|
||||
for (i = 0; i < BUFFER_SIZE; i++) {
|
||||
printf("%d ", pcm_data[i]);
|
||||
}
|
||||
|
||||
/* execute fftw plan */
|
||||
fftw_execute(fft_plan);
|
||||
|
||||
level = (float) sum / (BUFFER_SIZE * 32767);
|
||||
|
||||
show_spectrum(screen, (complex *) fft_data);
|
||||
//show_level(screen, level);
|
||||
//fade_level(fd, level);
|
||||
|
||||
//printf("level: %f \tsum: %d\t max: %d\n", level, sum, max);
|
||||
printf("\n\n");*/
|
||||
}
|
||||
|
||||
/* housekeeping */
|
||||
SDL_Quit();
|
||||
free(pcm_data);
|
||||
fftw_free(fft_data);
|
||||
fftw_destroy(fft_plan);
|
||||
fftw_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue