added own dft implementation (to slow for daily use)

This commit is contained in:
Steffen Vogel 2011-02-02 12:33:20 +01:00
parent 53f03bbeac
commit 388ac49d39
3 changed files with 69 additions and 54 deletions

27
lib/dft.c Normal file
View 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
View 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

View file

@ -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;
}