first ncurses commit

master
karlstav 11 years ago
parent 6f3251124d
commit ffbd04c728
  1. 5
      README.md
  2. 271
      cava.c
  3. 2
      makefile

@ -39,15 +39,18 @@ Build requirements
* [ALSA dev files](http://alsa-project.org/)
* [FFTW](http://www.fftw.org/)
* ncursesw dev files
Debian/Raspbian users can install this with:
apt-get install libfftw3-dev libasound2-dev
apt-get install libfftw3-dev libasound2-dev libncursesw5-dev
ArchLinux users can install this with:
pacman -S base-devel fftw
Unfortunately I don't know how to install ncursesw in arch, will figure it out soon!
Getting started
---------------

271
cava.c

@ -1,6 +1,8 @@
#define _XOPEN_SOURCE_EXTENDED
#include <alloca.h>
#include <locale.h>
#include <stdio.h>
#include <stddef.h>
#include <stdbool.h>
#include <termios.h>
#include <math.h>
@ -19,6 +21,9 @@
#include <time.h>
#include <getopt.h>
#include <pthread.h>
#include "ncursesw/curses.h"
#include <wchar.h>
#ifdef __GNUC__
// curses.h or other sources may already define
@ -41,11 +46,11 @@ int rc;
// general: cleanup
void cleanup()
{
printf("\033[0m\n");
system("setfont /usr/share/consolefonts/Lat2-Fixed16.psf.gz >/dev/null 2>&1");
system("setterm -cursor on");
system("setterm -blank 10");
system("clear");
endwin();
rc = tcsetattr(0, TCSAFLUSH, &oldtio);
}
@ -250,28 +255,25 @@ int main(int argc, char **argv)
float fc[200];
float fr[200];
int lcf[200], hcf[200];
float f[200];
float fmem[200];
int f[200];
int fmem[200];
int flast[200];
int flastd[200];
float peak[201];
int y[M / 2 + 1];
long int lpeak, hpeak;
int bands = 25;
int sleep = 0;
int i, n, o, bw, width, height, c, rest, virt, fixedbands;
int i, n, o, bw, width, height, h, w, hs, ws, c, rest, virt, fixedbands, q;
int autoband = 1;
float temp;
struct winsize w;
double in[2 * (M / 2 + 1)];
fftw_complex out[M / 2 + 1][2];
fftw_plan p;
char *color;
int col = 36;
int col = 6;
int bgcol = 0;
int sens = 100;
#ifndef DEBUG
int move = 0;
#endif
int fall[200];
float fpeak[200];
float k[200];
@ -280,6 +282,7 @@ int main(int argc, char **argv)
float smooth[64] = {5, 4.5, 4, 3, 2, 1.5, 1.25, 1.5, 1.5, 1.25, 1.25, 1.5, 1.25, 1.25, 1.5, 2, 2, 1.75, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.75, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
float sm = 1.25; //min val from the above array
struct timespec req = { .tv_sec = 0, .tv_nsec = 0 };
const wchar_t* bars[] = {L"\u2581", L"\u2582", L"\u2583", L"\u2584", L"\u2585", L"\u2586", L"\u2587", L"\u2588"};
char *usage = "\n\
Usage : " PACKAGE " [options]\n\
Visualize audio input in terminal. \n\
@ -302,12 +305,7 @@ Options:\n\
setlocale(LC_ALL, "");
for (i = 0; i < 200; i++) {
flast[i] = 0;
fall[i] = 0;
fpeak[i] = 0;
fmem[i] = 0;
}
for (i = 0; i < M; i++)shared[i] = 0;
// general: handle command-line arguments
@ -358,14 +356,14 @@ Options:\n\
case 'c': // argument: foreground color
col = 0;
color = optarg;
if (strcmp(color, "black") == 0) col = 30;
if (strcmp(color, "red") == 0) col = 31;
if (strcmp(color, "green") == 0) col = 32;
if (strcmp(color, "yellow") == 0) col = 33;
if (strcmp(color, "blue") == 0) col = 34;
if (strcmp(color, "magenta") == 0) col = 35;
if (strcmp(color, "cyan") == 0) col = 36;
if (strcmp(color, "white") == 0) col = 37;
if (strcmp(color, "black") == 0) col = 0;
if (strcmp(color, "red") == 0) col = 1;
if (strcmp(color, "green") == 0) col = 2;
if (strcmp(color, "yellow") == 0) col = 3;
if (strcmp(color, "blue") == 0) col = 4;
if (strcmp(color, "magenta") == 0) col = 5;
if (strcmp(color, "cyan") == 0) col = 6;
if (strcmp(color, "white") == 0) col = 7;
if (col == 0) {
cleanup();
fprintf(stderr, "color %s not supported\n", color);
@ -375,14 +373,14 @@ Options:\n\
case 'C': // argument: background color
bgcol = 0;
color = optarg;
if (strcmp(color, "black") == 0) bgcol = 40;
if (strcmp(color, "red") == 0) bgcol = 41;
if (strcmp(color, "green") == 0) bgcol = 42;
if (strcmp(color, "yellow") == 0) bgcol = 43;
if (strcmp(color, "blue") == 0) bgcol = 44;
if (strcmp(color, "magenta") == 0) bgcol = 45;
if (strcmp(color, "cyan") == 0) bgcol = 46;
if (strcmp(color, "white") == 0) bgcol = 47;
if (strcmp(color, "black") == 0) bgcol = 0;
if (strcmp(color, "red") == 0) bgcol = 1;
if (strcmp(color, "green") == 0) bgcol = 2;
if (strcmp(color, "yellow") == 0) bgcol = 3;
if (strcmp(color, "blue") == 0) bgcol = 4;
if (strcmp(color, "magenta") == 0) bgcol = 5;
if (strcmp(color, "cyan") == 0) bgcol = 6;
if (strcmp(color, "white") == 0) bgcol = 7;
if (bgcol == 0) {
cleanup();
fprintf(stderr, "color %s not supported\n", color);
@ -454,45 +452,54 @@ Options:\n\
p = fftw_plan_dft_r2c_1d(M, in, *out, FFTW_MEASURE); //planning to rock
// output: get terminal's geometry
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
initscr();
timeout(0);
while (1) {//jumbing back to this loop means that you resized the screen
for (i = 0; i < 200; i++) {
flast[i] = 0;
flastd[i] = 0;
fall[i] = 0;
fpeak[i] = 0;
fmem[i] = 0;
}
clear();
//getting orignial numbers of bands incase of resize
if (autoband == 1) {
bands = 25;
} else bands = fixedbands;
getmaxyx(stdscr,hs,ws);
if (bands > (int)w.ws_col / 2 - 1)bands = (int)w.ws_col / 2 -
1; //handle for user setting to many bars
height = (int)w.ws_row - 1;
width = (int)w.ws_col - bands - 1;
#ifndef DEBUG
int matrix[width][height];
for (i = 0; i < width; i++) {
for (n = 0; n < height; n++) {
matrix[i][n] = 0;
}
}
#endif
if (bands > ws / 2 - 1)bands = ws / 2 -
1; //handle for user setting to many bars
height = hs - 1;
width = ws - bands - 1;
bw = width / bands;
// process [smoothing]: calculate gravity
g = ((float)height / 1000) * pow((60 / (float)framerate), 2.5);
g = ((float)height / 400) * pow((60 / (float)framerate), 2.5);
//if no bands are selected it tries to padd the default 20 if there is extra room
if (autoband == 1) bands = bands + (((w.ws_col) - (bw * bands + bands - 1)) /
if (autoband == 1) bands = bands + ((ws - (bw * bands + bands - 1)) /
(bw + 1));
width = (int)w.ws_col - bands - 1;
width = width - bands - 1;
//checks if there is stil extra room, will use this to center
rest = (((w.ws_col) - (bw * bands + bands - 1)));
rest = (((ws) - (bw * bands + bands - 1)) / 2) - 1;
if (rest < 0)rest = 0;
#ifdef DEBUG
printf("hoyde: %d bredde: %d bands:%d bandbredde: %d rest: %d\n",
(int)w.ws_row,
(int)w.ws_col, bands, bw, rest);
wh,
ws, bands, bw, rest);
#endif
// process: calculate cutoff frequencies
@ -521,7 +528,8 @@ Options:\n\
// process: weigh signal to frequencies
for (n = 0; n < bands;
n++)k[n] = pow(fc[n],0.62) * (float)height/(M*2000);
n++)k[n] = pow(fc[n],0.62) * ((float)height/(M*2000)) * 8 * ((float)sens /
100);
// output: prepare screen
virt = system("setfont cava.psf >/dev/null 2>&1");
@ -529,26 +537,10 @@ Options:\n\
system("setterm -cursor off");
system("setterm -blank 0");
// output: reset console
printf("\033[0m\n");
system("clear");
printf("\033[%dm", col); //setting color
printf("\033[1m"); //setting "bright" color mode, looks cooler... I think
if (bgcol != 0)
printf("\033[%dm", bgcol);
{
for (n = (height); n >= 0; n--) {
for (i = 0; i < width + bands; i++) {
printf(" ");//setting backround color
}
printf("\n");
}
printf("\033[%dA", height); //moving cursor back up
}
start_color();
init_pair(1, col, bgcol);
bkgd(COLOR_PAIR(1));
attron(COLOR_PAIR(1));
#endif
@ -556,7 +548,7 @@ Options:\n\
while (1) {
// general: keyboard controls
if ((ch = getchar()) != EOF) {
if ((ch = getch()) != EOF) {
switch (ch) {
case 's':
scientificMode = !scientificMode;
@ -567,12 +559,13 @@ Options:\n\
}
}
// output: check if terminal has been resized
if (virt != 0) {
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
if ( ((int)w.ws_row - 1) != height || ((int)w.ws_col - bands - 1) != width) {
break;
}
getmaxyx(stdscr,h,w);
if ( h != hs || w != ws) {
break;
}
}
#ifdef DEBUG
@ -609,38 +602,11 @@ Options:\n\
peak[o] += y[i]; //adding upp band
}
peak[o] = peak[o] / (hcf[o]-lcf[o]+1); //getting average
temp = peak[o] * k[o] * ((float)sens /
100); //multiplying with k and adjusting to sens settings
if (temp > height)temp = height; //just in case
temp = peak[o] * k[o]; //multiplying with k and adjusting to sens settings
if (temp > height * 8)temp = height * 8; //just in case
f[o] = temp;
//**falloff function**//
if (!scientificMode) {
if (temp < flast[o]) {
f[o] = fpeak[o] - (g * fall[o] * fall[o]);
fall[o]++;
} else if (temp >= flast[o]) {
f[o] = temp;
fpeak[o] = f[o];
fall[o] = 0;
}
// process [smoothing]
fmem[o] += f[o];
fmem[o] = fmem[o] * 0.55;
f[o] = fmem[o];
flast[o] = f[o]; //memmory for falloff func
}
if (f[o] < 0.125)f[o] = 0.125;
#ifdef DEBUG
printf("%d: f:%f->%f (%d->%d)peak:%f adjpeak: %f \n", o, fc[o], fc[o + 1],
lcf[o], hcf[o], peak[o], f[o]);
#endif
}
} else { //**if in sleep mode wait and continiue**//
@ -654,6 +620,7 @@ Options:\n\
continue;
}
// process [smoothing]
if (!scientificMode)
{
// process [smoothing]: monstercat-style "average"
@ -669,61 +636,73 @@ Options:\n\
f[m_y] = max(f[z] / pow(2, m_y - z), f[m_y]);
}
}
for (o = 0; o < bands; o++) {
temp = f[o];
if (temp < flast[o]) {
f[o] = fpeak[o] - (g * fall[o] * fall[o]);
fall[o]++;
} else if (temp >= flast[o]) {
f[o] = temp;
fpeak[o] = f[o];
fall[o] = 0;
}
fmem[o] += f[o];
fmem[o] = fmem[o] * 0.55;
f[o] = fmem[o];
if (f[o] < 1)f[o] = 1;
flast[o] = f[o];
#ifdef DEBUG
printf("%d: f:%f->%f (%d->%d)peak:%f adjpeak: %f \n", o, fc[o], fc[o + 1],
lcf[o], hcf[o], peak[o], f[o]);
#endif
}
}
// output: draw processed input
#ifndef DEBUG
switch (om) {
case 1:
for (n = (height - 1); n >= 0; n--) {
o = 0;
move = rest / 2; //center adjustment
for (i = 0; i < width; i++) {
// output: check if we're already at the next bar
if (i != 0 && i % bw == 0) {
o++;
if (o < bands)move++;
case 1:
for (i = rest; i < bands; i++) {
if(f[i] > flastd[i]){//higher then last one
for (n = flastd[i] / 8; n < f[i] / 8; n++) for (q = 0; q < bw; q++) mvaddwstr((height - n), (i * bw) + q + i, bars[7]);
if (f[i] % 8 != 0) {
if (virt == 0) for (q = 0; q < bw; q++) mvprintw( (height - n), (i*bw) + q + i, "%d",(f[i] % 8) );
else for (q = 0; q < bw; q++) mvaddwstr( (height - n), (i*bw) + q + i, bars[(f[i] % 8) - 1]);
}
// output: draw and move to another one, check whether we're not too far
if (o < bands) {
if (f[o] - n < 0.125) { //blank
if (matrix[i][n] != 0) { //change?
if (move != 0)printf("\033[%dC", move);
move = 0;
printf(" ");
} else move++; //no change, moving along
matrix[i][n] = 0;
} else if (f[o] - n > 1) { //color
if (matrix[i][n] != 1) { //change?
if (move != 0)printf("\033[%dC", move);
move = 0;
printf("\u2588");
} else move++; //no change, moving along
matrix[i][n] = 1;
} else { //top color, finding fraction
if (move != 0)printf("\033[%dC", move);
move = 0;
c = ((((f[o] - (float)n) - 0.125) / 0.875 * 7) + 1);
if (0 < c && c < 8) {
if (virt == 0)printf("%d", c);
else printf("%lc", L'\u2580' + c);
} else printf(" ");
matrix[i][n] = 2;
}
}else if(f[i] < flastd[i]){//lower then last one
for (n = f[i] / 8; n < flastd[i]/8 + 1; n++) for (q = 0; q < bw; q++) mvaddstr( (height - n), (i*bw) + q + i, " ");
if (f[i] % 8 != 0) {
if (virt == 0) for (q = 0; q < bw; q++) mvprintw((height - f[i] / 8), (i * bw) + q + i, "%d",(f[i] % 8) );
else for (q = 0; q < bw; q++) mvaddwstr((height - f[i] / 8), (i * bw) + q + i, bars[(f[i] % 8) - 1]);
}
}
printf("\n");
flastd[i] = f[i]; //memmory for falloff func
}
printf("\033[%dA", height);
refresh();
break;
}
req.tv_sec = 0;
req.tv_nsec = (1 / (float)framerate) * 1000000000; //sleeping for set us
nanosleep (&req, NULL);

@ -5,7 +5,7 @@ CC = gcc
CFLAGS = -std=c99 -Wall -Wextra
CPPFLAGS = -DPACKAGE=\"$(PACKAGE)\" -DVERSION=\"$(VERSION)\" \
-D_POSIX_SOURCE -D _POSIX_C_SOURCE=200809L
LDLIBS = -lasound -lm -lfftw3 -lpthread
LDLIBS = -lasound -lm -lfftw3 -lpthread -lncursesw
INSTALL = install
INSTALL_BIN = $(INSTALL) -D -m 755

Loading…
Cancel
Save