diff options
| author | alexander.pickering <alexander.pickering@anondomain.site90.net> | 2014-09-16 15:51:04 -0400 |
|---|---|---|
| committer | alexander.pickering <alexander.pickering@anondomain.site90.net> | 2014-09-16 15:51:04 -0400 |
| commit | 5615d00be87bc2263ffa759a877a942c013a31ef (patch) | |
| tree | ba2b9450f70e5b420e269f1f44012770a7fee360 | |
| download | vaud-5615d00be87bc2263ffa759a877a942c013a31ef.tar.gz vaud-5615d00be87bc2263ffa759a877a942c013a31ef.tar.bz2 vaud-5615d00be87bc2263ffa759a877a942c013a31ef.zip | |
Initial commit
| -rw-r--r-- | config.h | 88 | ||||
| -rw-r--r-- | makefile | 18 | ||||
| -rw-r--r-- | vaud.c | 370 |
3 files changed, 476 insertions, 0 deletions
diff --git a/config.h b/config.h new file mode 100644 index 0000000..bdfa4b3 --- /dev/null +++ b/config.h @@ -0,0 +1,88 @@ +/*Settings for customization*/ +#define BLANK " " //Blank space in the graph +#define BAR "|" //Character to use for the bar +#define COLORFUL false //Use custom colors? +/* + *Use Ncurses colors, valid colors are: + * COLOR_BLACK + * COLOR_RED + * COLOR_GREEN + * COLOR_YELLOW + * COLOR_BLUE + * COLOR_MAGENTA + * COLOR_CYAN + * COLOR_WHITE + */ +#define BORCOLORBG COLOR_BLACK //Border color background +#define BORCOLORFG COLOR_RED //Border color forground +#define BARCOLORBG COLOR_GREEN //Bar color background +#define BARCOLORFG COLOR_YELLOW //Bar color forground +#define BLANKCOLORBG COLOR_BLUE //Blank color background +#define BLANKCOLORFG COLOR_MAGENTA //Blank color forground + + +/******************************************************** + * STOP CHANGEING HERE UNLESS YOU KNOW WHAT YOU'RE DOING* + ********************************************************/ + +/* Define to 1 if you have the `atexit' function. */ +#define HAVE_ATEXIT 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `usleep' function. */ +#define HAVE_USLEEP 1 + +/* Name of package */ +#define PACKAGE "vaud" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "alexander.pickering@anondomain.site90.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "visual-audio" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "vaud 0.5" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "vaud" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.5" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "0.5" + + diff --git a/makefile b/makefile new file mode 100644 index 0000000..2d89131 --- /dev/null +++ b/makefile @@ -0,0 +1,18 @@ +# the compiler: gcc for C program, define as g++ for C++ +CC = g++ + +# compiler flags: +PREFLAGS = +POSTFLAGS = -lncurses -ljack + +# the build target executable: +TARGET = vaud + + +all: $(TARGET) + +$(TARGET): $(TARGET).c + $(CC) $(PREFLAGS) -o $(TARGET) $(TARGET).c $(POSTFLAGS) + +clean: + $(RM) $(TARGET) @@ -0,0 +1,370 @@ +/* + vaud.c + A console based audio visualizer for JACK + Copyright (C) 2014 Alexander M. Pickering + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + A big thank you goes to Nicholas J. Humfrey, whos jack meter + was modified to make this. You can view the project here: + http://www.aelius.com/njh/jackmeter/ +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <ncurses.h> +#include <jack/jack.h> +#include <getopt.h> +#include "config.h" + +/*Stuff to get from the settings file*/ + +float bias = 1.0f; +float peak = 0.0f; +jack_default_audio_sample_t *data; +jack_nframes_t dframes; +int dpeak = 0; +int dtime = 0; +int decay_len; +int set = 0; +jack_port_t *input_port = NULL; +jack_client_t *client = NULL; + +WINDOW *create_newwin(int height, int width, int starty, int startx); + +/* Read and reset the recent peak sample */ +static float read_peak() +{ + float tmp = peak; + peak = 0.0f; + + return tmp; +} +/* Callback called by JACK when audio is available. + Stores value of peak sample */ +static int process_peak(jack_nframes_t nframes, void *arg) +{ + dframes = nframes; + jack_default_audio_sample_t *in; + unsigned int i; + + + /* just incase the port isn't registered yet */ + if (input_port == NULL) { + return 0; + } + + + /* get the audio samples, and find the peak sample */ + in = (jack_default_audio_sample_t *) jack_port_get_buffer(input_port, nframes); + for (i = 0; i < nframes; i++) { + const float s = fabs(in[i]); + if (s > peak) { + peak = s; + } + } + data = in; + + return 0; +} + + +/* Close down JACK when exiting */ +static void cleanup() +{ + const char **all_ports; + unsigned int i; + + fprintf(stderr,"cleanup()\n"); + + if (input_port != NULL ) { + + all_ports = jack_port_get_all_connections(client, input_port); + + for (i=0; all_ports && all_ports[i]; i++) { + jack_disconnect(client, all_ports[i], jack_port_name(input_port)); + } + } + + /* Leave the jack graph */ + jack_client_close(client); + +} + + +/* Connect the chosen port to ours */ +static void connect_port(jack_client_t *client, char *port_name) +{ + jack_port_t *port; + + // Get the port we are connecting to + port = jack_port_by_name(client, port_name); + if (port == NULL) { + fprintf(stderr, "Can't find port '%s'\n", port_name); + exit(1); + } + + // Connect the port to our input port + fprintf(stderr,"Connecting '%s' to '%s'...\n", jack_port_name(port), jack_port_name(input_port)); + if (jack_connect(client, jack_port_name(port), jack_port_name(input_port))) { + fprintf(stderr, "Cannot connect port '%s' to '%s'\n", jack_port_name(port), jack_port_name(input_port)); + exit(1); + } +} + + +/* Sleep for a fraction of a second */ +static int fsleep( float secs ) +{ + +//#ifdef HAVE_USLEEP + return usleep( secs * 1000000 ); +//#endif +} + + +/* Display how to use this program */ +static int usage( const char * progname ) +{ + fprintf(stderr, "Visual Audio Version - %s\n\n", VERSION); + fprintf(stderr, "Usage %s [-f freqency] [-m meter] [-n] [<port>, ...]\n\n", progname); + fprintf(stderr, "where -f is how often to update the meter per second [8]\n"); + fprintf(stderr, " -g is the number of the meter (1-2)\n"); + fprintf(stderr, " -n changes mode to output meter level as number in decibels\n"); + fprintf(stderr, " <port> the port(s) to monitor (multiple ports are mixed)\n"); + exit(1); +} + +/*Start the ncurses stuff + */ +void start_ncurses() +{ + if(COLORFUL && !has_colors) //Settings tell us to be colorful, + //but terminal does not support colors. + { + printf("Your terminal does not support colors! Chage \"COLORFUL\" in config.h to 0 and rebuild."); + exit(1); + } + initscr(); //Start ncurses + curs_set(0); //Hide cursor + if(COLORFUL) + { + start_color(); //Tell ncurses to be colorufl! + init_pair(1, BORCOLORFG, BORCOLORBG); //Color the border + init_pair(2, BARCOLORFG, BARCOLORBG); //Color the bars + init_pair(3, BLANKCOLORBG, BLANKCOLORFG); //Color the blank space + } +} + +/* Creates a new NCurses window + *int height : the height of the window to make + *int width : the width of the window to make + *int startx : the column to start the window on + *int starty : the row to start the window on + */ +WINDOW *create_newwin(int height, int width, int startx, int starty) +{ WINDOW *local_win; + if(COLORFUL) + attron(COLOR_PAIR(1)); + local_win = newwin(height, width, starty, startx); + box(local_win, 0 , 0); + wrefresh(local_win); + if(COLORFUL) + attroff(COLOR_PAIR(1)); + + return local_win; +} + +void display_centerBars() +{ + int width,height,startx,starty,i=0; + WINDOW *my_win; + + /*Get width and height of console, make border*/ + getmaxyx(stdscr,height,width); + my_win = create_newwin(height,width,startx,starty); + + /*Figure out how which nodes we can safely get*/ + int space = ((unsigned int) dframes) / width; + + for(i=0;i<space;i+=1) + { + float samp = fabs(data[space * i]); //get the waveform data + float dec; + mvprintw(height/2,i,BAR); + int j; + for(j=0;j<samp*height;j++) + { + mvprintw((height/2)+j,i,BAR); + mvprintw((height/2)-j,i,BAR); + } + } +} + +/* Displays the graph + */ +void display_meter() +{ + /*Some variables to keep track of stuff*/ + int i; + int width,height; + int startx,starty = 0; + int space = 1; + WINDOW *my_win; + + /*Get width and height of console, make border*/ + getmaxyx(stdscr,height,width); + my_win = create_newwin(height,width,startx,starty); + + /*Figure out how far inbetween the samples that are "safe" to get are*/ + int samples = ((unsigned int) dframes) / width; + + /*For every sample we can safely get*/ + for(i=0;i<dframes;i+=samples) + { + /*Get the value*/ + float samp = fabs(data[i]); + float dec; //The percentage up the graph + if(COLORFUL) + attron(COLOR_PAIR(2)); + /*Draw whitespace from the ground up*/ + for(dec = height+2;dec > samp;dec-=(1.0/height)) + { + if(dec*height<height-1 && dec*height>=1) + mvprintw(dec*height,space,BLANK); + } + if(COLORFUL) + attroff(COLOR_PAIR(2)); + attron(COLOR_PAIR(3)); + /*And draw bars the rest of the way*/ + for(;dec>0;dec-=(1.0/height)) + { + if(dec*height >= 1) + mvprintw(dec*height,space,BAR); + } + if(COLORFUL) + attroff(COLOR_PAIR(3)); + /*Makes sure we don't draw over the frame*/ + if(space < width-2) + { + space++; + } + } + refresh(); //And refresh the screen +} + + +int main(int argc, char *argv[]) +{ + int console_width = 79; + jack_status_t status; + int running = 1; + float ref_lev; + int decibels_mode = 0; + int rate = 8; + int opt; + int graph = 1; + + // Make STDOUT unbuffered + setbuf(stdout, NULL); + + while ((opt = getopt(argc, argv, "f:g:n")) != -1) { + switch (opt) { + case 'g': + graph = atoi(optarg); + break; + case 'f': + rate = atoi(optarg); + fprintf(stderr,"Updates per second: %d\n", rate); + break; + case 'n': + decibels_mode = 1; + break; + default: + /* Show usage/version information */ + usage( argv[0] ); + break; + } + } + + + + // Register with Jack + if ((client = jack_client_open("meter", JackNullOption, &status)) == 0) { + fprintf(stderr, "Failed to start jack client: %d\n", status); + exit(1); + } + fprintf(stderr,"Registering as '%s'.\n", jack_get_client_name( client ) ); + + // Create our input port + if (!(input_port = jack_port_register(client, "in", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0))) { + fprintf(stderr, "Cannot register input port 'meter'.\n"); + exit(1); + } + + // Register the cleanup function to be called when program exits + atexit( cleanup ); + + // Register the peak signal callback + jack_set_process_callback(client, process_peak, 0); + + + if (jack_activate(client)) { + fprintf(stderr, "Cannot activate client.\n"); + exit(1); + } + + + // Connect our port to specified port(s) + if (argc > optind) { + while (argc > optind) { + connect_port( client, argv[ optind ] ); + optind++; + } + } else { + fprintf(stderr,"Meter is not connected to a port.\n"); + } + + // Calculate the decay length (should be 1600ms) + decay_len = (int)(1.6f / (1.0f/rate)); + + + // Display the scale + if (decibels_mode==0) { + start_ncurses(); + } + while (running) { + float db = 20.0f * log10f(read_peak() * bias); + + if (decibels_mode==1) { + printf("%1.1f\n", db); + } else { + switch(graph) + { + case 1 : display_meter();break; + case 2 : display_centerBars();break; + } + } + + fsleep( 1.0f/rate ); + } + endwin(); + return 0; +} + |
