xlib, alsa, kissfft, prog compiles but don't work?
Hello, I've written this small prog to display the audio spectrum of the default alsa input. The program starts and closes ok, resizing works, but there's no graphics in the window.
Code:
/* gcc kissfft_xlib_spectrum_v1.c kiss_fft.c -O2 -Wall -o xkissfft_alsa -lm -lX11 -lasound
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <alsa/asoundlib.h> // For audio capture
#include <X11/X.h> // For X11 graphics
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include "kiss_fft.h" // For FFT calculations
#define FFT_SIZE 1024 // Adjust as needed
// Map magnitudes to visual representation (lines and bars)
void draw_spectrum(Display *display, Window window, double *magnitudes)
{
// Get window dimensions
int width, height;
XWindowAttributes wa;
XGetWindowAttributes(display, window, &wa);
width = wa.width;
height = wa.height;
// Calculate bar width and spacing
int bar_width = width / (FFT_SIZE / 2 + 1);
int bar_spacing = 1; // Adjust spacing as needed
GC gc = XCreateGC(display, window, 0, NULL); // Create a graphics context
// Clear the window (optional)
XSetForeground(display, gc, WhitePixel(display, DefaultScreen(display)));
XFillRectangle(display, window, gc, 0, 0, width, height);
// Set drawing color for the bars
XSetForeground(display, gc, BlackPixel(display, DefaultScreen(display)));
// Draw bars for each magnitude value
for (int i = 0; i < FFT_SIZE / 2 + 1; i++)
{
int bar_height = (int)(magnitudes[i] *height / 256); // Scale magnitude to screen height
XFillRectangle(display, window, gc, i *(bar_width + bar_spacing), height - bar_height, bar_width, bar_height);
}
XFreeGC(display, gc); // Release the graphics context
// Handle events and refresh display
XEvent xevent;
XNextEvent(display, &xevent);
XFlush(display);
// Handle events
if (xevent.type == ClientMessage) /*how is this wrong? */
{
if (xevent.xclient.message_type == XInternAtom(display, "WM_PROTOCOLS", False) && (Atom) xevent.xclient.data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False))
{
XCloseDisplay(display);
exit(0);
}
}
}
int main(int argc, char *argv[])
{
//Start of program code
double *magnitudes = (double*) malloc(sizeof(double) *(FFT_SIZE / 2 + 1));
/// Initialize audio capture and X11 display:
// Open audio device
snd_pcm_t * pcm_handle;
snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_CAPTURE, 0);
// Set audio parameters (sample rate, channels, etc.)
snd_pcm_set_params(pcm_handle, SND_PCM_FORMAT_U8, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 48000, 1, 500000);
// Open X11 display
Display *display = XOpenDisplay(NULL);
// Window window = XCreateSimpleWindow(display, window, 100, 100, 800, 600, 1, BlackPixel(display, DefaultScreen(display)), WhitePixel(display, DefaultScreen(display))); //display, parent, x, y, width, height, border_width, border, background
Window window = XCreateSimpleWindow(display, RootWindow(display, DefaultScreen(display)), 100, 100, 1080, 240, 1, BlackPixel(display, DefaultScreen(display)), WhitePixel(display, DefaultScreen(display)));
XStoreName(display, window, "kissfft_alsa-spectrum");
XSelectInput(display, window, ExposureMask | StructureNotifyMask | KeyPressMask); // Set event mask for exposure, resize, and key press
XEvent xevent;
XMapWindow(display, window);
/// Create buffers for audio samples and FFT output:
kiss_fft_cfg cfg = kiss_fft_alloc(FFT_SIZE, 0, 0, 0);
kiss_fft_cpx in[FFT_SIZE];
kiss_fft_cpx out[FFT_SIZE];
/// Main loop:
while (1)
{
// Check for events
XNextEvent(display, &xevent);
// Capture audio samples
snd_pcm_readi(pcm_handle, in, FFT_SIZE);
// Apply window function (Hann window)
for (int i = 0; i < FFT_SIZE; i++)
{
in[i].r *= 0.5 *(1 - cos(2 *M_PI *i / (FFT_SIZE - 1)));
}
// Perform FFT
kiss_fft(cfg, in, out);
// Calculate magnitudes
double magnitudes[FFT_SIZE / 2 + 1];
for (int i = 0; i < FFT_SIZE / 2 + 1; i++)
{
magnitudes[i] = sqrt(out[i].r *out[i].r + out[i].i *out[i].i);
}
// Map magnitudes to visual representation (lines and bars)
draw_spectrum(display, window, magnitudes);
}
/// Clean up:
free(magnitudes);
// Close audio device
snd_pcm_close(pcm_handle);
// Close X11 display
XDestroyWindow(display, window);
XCloseDisplay(display);
return 0;
}