Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package cava for openSUSE:Factory checked in at 2022-11-04 17:37:44 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/cava (Old) and /work/SRC/openSUSE:Factory/.cava.new.2275 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "cava" Fri Nov 4 17:37:44 2022 rev:13 rq:1033470 version:0.8.3 Changes: -------- --- /work/SRC/openSUSE:Factory/cava/cava.changes 2022-04-25 23:35:37.682424921 +0200 +++ /work/SRC/openSUSE:Factory/.cava.new.2275/cava.changes 2022-11-04 17:41:32.438871530 +0100 @@ -1,0 +2,15 @@ +Fri Nov 4 09:06:43 UTC 2022 - Michael Vetter <[email protected]> + +- Update to 0.8.3: + bugfixes: + * fix some calculations on x-axis label + * cavacore: channels where sorted wrong according to doc + * fix autosensing sometimes not working + improvements: + * improved response time by decreasing audio buffer size + * add support for alacritty synchronized updates + * brought EQ back by popular demand + * added support for hex colors and gradient in noncurses mode + * add configurable orientation of bars + +------------------------------------------------------------------- Old: ---- 0.8.2.tar.gz New: ---- 0.8.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ cava.spec ++++++ --- /var/tmp/diff_new_pack.JtPcTc/_old 2022-11-04 17:41:32.950874205 +0100 +++ /var/tmp/diff_new_pack.JtPcTc/_new 2022-11-04 17:41:32.954874226 +0100 @@ -17,7 +17,7 @@ Name: cava -Version: 0.8.2 +Version: 0.8.3 Release: 0 Summary: Console-based Audio Visualizer for Alsa License: MIT @@ -33,7 +33,6 @@ BuildRequires: ncurses-devel # Installing the psf in a directory that comes from kbd Requires: kbd -BuildRoot: %{_tmppath}/%{name}-%{version}-build %description C.A.V.A. is a bar spectrum audio visualizer for the Linux terminal using ALSA, pulseaudio or fifo buffer for input. @@ -44,14 +43,14 @@ %configure FONT_DIR="%{_datadir}/kbd/consolefonts" %build -make %{?_smp_mflags} +%make_build %install %make_install %files -%defattr(-,root,root) -%doc README.md LICENSE +%license LICENSE +%doc README.md %{_bindir}/cava %dir %{_datadir}/kbd/ %dir %{_datadir}/kbd/consolefonts/ ++++++ 0.8.2.tar.gz -> 0.8.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/.github/workflows/build-and-test.yml new/cava-0.8.3/.github/workflows/build-and-test.yml --- old/cava-0.8.2/.github/workflows/build-and-test.yml 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/.github/workflows/build-and-test.yml 2022-11-04 09:01:05.000000000 +0100 @@ -23,7 +23,7 @@ - name: Run ./configure run: ./configure - name: Run make - run: make + run: make CFLAGS='-Werror' - name: Prepare tests run: | pulseaudio -D @@ -56,7 +56,7 @@ - name: Run ./configure run: LDFLAGS="-L/usr/local/opt/ncurses/lib" CPPFLAGS="-I/usr/local/opt/ncurses/include" ./configure - name: Run make - run: make + run: make CFLAGS='-Werror' - name: run non zero test run: ./cava -p example_files/test_configs/non_zero_test > /dev/null - name: run portaudio test diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/Makefile.am new/cava-0.8.3/Makefile.am --- old/cava-0.8.2/Makefile.am 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/Makefile.am 2022-11-04 09:01:05.000000000 +0100 @@ -8,7 +8,7 @@ cava_CPPFLAGS = -DPACKAGE=\"$(PACKAGE)\" -DVERSION=\"$(VERSION)\" \ -D_POSIX_SOURCE -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE_EXTENDED \ -DFONTDIR=\"@FONT_DIR@\" -cava_CFLAGS = -std=c99 -Wall -Werror -Wextra -Wno-unused-result -Wno-unknown-warning-option -Wno-maybe-uninitialized -Wno-vla-parameter +cava_CFLAGS = -std=c99 -Wall -Wextra -Wno-unused-result -Wno-unknown-warning-option -Wno-maybe-uninitialized -Wno-vla-parameter if OSX cava_CFLAGS += -DNORT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/README.md new/cava-0.8.3/README.md --- old/cava-0.8.2/README.md 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/README.md 2022-11-04 09:01:05.000000000 +0100 @@ -3,9 +3,7 @@ **C**onsole-based **A**udio **V**isualizer for **A**LSA -also supports audio input from Pulseaudio, fifo (mpd), sndio, squeezelite and portaudio. - -Now with SDL support! +also supports audio input from Pulseaudio, fifo (mpd), sndio, squeezelite and portaudio (macOS). by [Karl Stavestrand](mailto:[email protected]) @@ -13,44 +11,28 @@ [Demo video](https://youtu.be/9PSp8VA6yjU) -<!-- START doctoc generated TOC please keep comment here to allow auto update --> -<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> -**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* - - [What it is](#what-it-is) - [Installing](#installing) - [From Source](#from-source) - - [Installing Build Requirements](#installing-build-requirements) - - [Building](#building) - - [Installing](#installing-1) - - [Uninstalling](#uninstalling) - [Some distro specific pre-made binaries/recipes](#some-distro-specific-pre-made-binariesrecipes) - - [openSUSE](#opensuse) - - [Fedora](#fedora) - - [Arch](#arch) - - [Ubuntu/Debian](#ubuntudebian) - - [macOS](#macos) - [Capturing audio](#capturing-audio) - - [Pulseaudio monitor source (Easy, default if supported)](#pulseaudio-monitor-source-easy-default-if-supported) - - [ALSA-loopback device (Tricky)](#alsa-loopback-device-tricky) - - [mpd's fifo output](#mpds-fifo-output) + - [Pulseaudio](#pulseaudio) + - [ALSA](#alsa) + - [MPD](#mpd) - [sndio](#sndio) - [squeezelite](#squeezelite) - [macOS](#macos) - - [Windows - winscap - WSL](#Windows---winscap---WSL) + - [WSL](#wsl) - [Running via ssh](#running-via-ssh) - - [Raw Output](#raw-output) -- [Font notes](#font-notes) - - [In ttys](#in-ttys) - - [In terminal emulators](#in-terminal-emulators) -- [Latency notes](#latency-notes) +- [Troubleshooting](#troubleshooting) - [Usage](#usage) - [Controls](#controls) - [Configuration](#configuration) - [Using cava in other applications](#using-cava-in-other-applications) + - [cavacore](#cavacore-library) + - [Raw Output](#raw-output) - [Contribution](#contribution) -<!-- END doctoc generated TOC please keep comment here to allow auto update --> What it is @@ -93,7 +75,7 @@ All the requirements can be installed easily in all major distros: -Debian Buster or higher/Ubuntu 18.04 or higher : +Debian Buster or higher/Ubuntu 18.04 or higher: apt install libfftw3-dev libasound2-dev libncursesw5-dev libpulse-dev libtool automake libiniparser-dev libsdl2-2.0-0 libsdl2-dev @@ -219,7 +201,7 @@ Capturing audio --------------- -### Pulseaudio monitor source (Easy, default if supported) +### Pulseaudio Just make sure you have installed pulseaudio dev files and that cava has been built with pulseaudio support (it should be automatically if the dev files are found). @@ -228,7 +210,7 @@ If nothing happens you might have to use a different source than the default. The default might also be your microphone. Look at the [config](#configuration) file for help. -### ALSA-loopback device (Tricky) +### ALSA Set @@ -258,7 +240,7 @@ dtoverlay=i2s-mmap ``` -### mpd's fifo output +### mpd Add these lines in mpd: @@ -330,9 +312,10 @@ source = "Soundflower (2ch)" ``` -### Windows - winscap - WSL +### WSL -@quantum5 has written a handy tool called [winscap](https://github.com/quantum5/winscap) to capture audio from Windows and output it to stdout. Just follow the instructions in the readme on how to set it up with cava. +@quantum5 has written a handy tool called [winscap](https://github.com/quantum5/winscap) to capture audio from Windows and output it to stdout. +This way cava can be used in a terminal running windows subsystem for linux. Just follow the instructions in the readme on how to set it up with cava. Running via ssh @@ -346,44 +329,39 @@ (You must be root to redirect to console. Simple sudo is not enough: Run `sudo su` first.) -### Raw Output -You can also use Cava's output for other programs by using raw output mode, which will write bar data to `STDOUT` that can be piped into other processes. More information on this option is documented in [the example config file](/example_files/config). +## Troubleshooting -A useful starting point example script written in python that consumes raw data can be found [here](https://github.com/karlstav/cava/issues/123#issuecomment-307891020). +### No bars in terminal -Font notes ----------- - -Since the graphics are simply based on characters, performance is dependent on the terminal font. +Most likley issue [#399](https://github.com/karlstav/cava/issues/399). Locale settings need to be set correctly in order for cava to work. -### In ttys +### Visualizer reacts to microphone instead of output -If you run this in a TTY the program will change the font to the included `cava.psf` (actually a slightly modified "unifont"). +This is a known issue with pipewire. Try the workaround described [here](https://github.com/karlstav/cava/issues/422#issuecomment-994270910) -In console fonts it seems that only 256 Unicode characters are supported, probably because they are bitmap fonts. I could not find a font with Unicode characters 2581-2587 (the 1/8 - 7/8 blocks used on the top of each bar to increase resolution). +### Vertical lines in bars -So in `cava.psf`, the characters 1-7 are actually replaced by Unicode characters 2581-2587. When cava exits, it changes the font back. If cava exits abnormally and you notice that 1-7 are replaced by partial blocks, just change the font with `setfont`. +This is either an issue with the font, or line spacing being enabled in the terminal emulator. Try to change font or disable line spacing. -Actually, `setfont` is supposed to return the default font, but this usually isn't set. I haven't found another way to get the current font. So cava sets the font to "Lat2-Fixed16" when interrupted. All major distros should have it. It will revert to your default font at reboot. +### Low resolution -### In terminal emulators +Since the graphics are simply based on characters, try decreasing the font size. -In terminal emulators like `xterm`, the font settings is chosen in the software and cannot be changed by an application. So find your terminal settings and try out different fonts and settings. Also character spacing affects the look of the bar spectrum. +### Low frame rate -Performance is also different, urxvt is the best I found so far, while Gnome-terminal is quite slow. +Some terminal emulators are just slow. Cava will look best in a GPU based terminal like kitty or alacritty. You can also try to increase the font size -Cava also disables the terminal cursor, and turns it back on on exit, but in case it terminates unexpectedly, run `setterm -cursor on` to get it back. +### Font is changed in ttys after exit -Tip: Cava will look much nicer in small font sizes. Use a second terminal emulator for cava and set the font size to 1. Warning, can cause high CPU usage and latency if the terminal window is too large! +If you run cava in a TTY (like ctrl+alt+F2) the program will change the font to the included `cava.psf` (actually a slightly modified "unifont"). +In console fonts it seems that only 256 Unicode characters are supported, probably because they are bitmap fonts. I could not find a font with Unicode characters 2581-2587 (the 1/8 - 7/8 blocks used on the top of each bar to increase resolution). -Latency notes -------------- +So in `cava.psf`, the characters 1-7 are actually replaced by Unicode characters 2581-2587. When cava exits, it changes the font back. If cava exits abnormally and you notice that 1-7 are replaced by partial blocks, just change the font with `setfont`. -If you see latency issues (sound before image) in a terminal emulator, try increasing the font size. This will reduce the number of characters that have to be shown. +Actually, `setfont` is supposed to return the default font, but this usually isn't set. I haven't found another way to get the current font. So cava sets the font to "Lat2-Fixed16" when interrupted. All major distros should have it. It will revert to your default font at reboot. -If your audio device has a huge buffer, you might experience that cava is actually faster than the audio you hear. This reduces the experience of the visualization. To fix this, try decreasing the buffer settings in your audio playing software. Usage ----- @@ -419,9 +397,7 @@ As of version 0.4.0 all options are done in the config file, no more command-line arguments! -By default a configuration file is located in `$XDG_CONFIG_HOME/cava/config` or `$HOME/.config/cava/config`, but cava can also be made to use a different file with the `-p` option. - -If for some reason the config file is not in the config dir, copy the [bundled configuration file](/example_files/config) to the config dir manually. +By default a configuration file is created upon first launch in `$XDG_CONFIG_HOME/cava/config` or `$HOME/.config/cava/config`, but cava can also be made to use a different file with the `-p` option. Sending cava a SIGUSR1 signal, will force cava to reload its configuration file. Thus, it behaves as if the user pressed <kbd>r</kbd> in the terminal. One might send a SIGUSR1 signal using `pkill` or `killall`. For example: @@ -436,8 +412,6 @@ **Examples on how the equalizer works:** -The equalizer is DEPRECATED as of 0.8.0, can be brought back by popular request. - [eq] 1=0 2=1 @@ -460,8 +434,16 @@ Using cava in other applications -------------------------------- +### cavacore library + The core processing engine in cava has been split into a separate library `cavacore`. See CAVACORE.md for details. +### Raw Output + +You can also use Cava's output for other programs by using raw output mode, which will write bar data to `STDOUT` that can be piped into other processes. More information on this option is documented in [the example config file](/example_files/config). + +A useful starting point example script written in python that consumes raw data can be found [here](https://github.com/karlstav/cava/issues/123#issuecomment-307891020). + Contribution ------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/autogen.sh new/cava-0.8.3/autogen.sh --- old/cava-0.8.2/autogen.sh 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/autogen.sh 2022-11-04 09:01:05.000000000 +0100 @@ -3,7 +3,7 @@ if [ -d .git ]; then git describe --always --tags --dirty > version # get version from git else - echo 0.8.2 > version # hard coded versions + echo 0.8.3 > version # hard coded versions fi libtoolize diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/cava.c new/cava-0.8.3/cava.c --- old/cava-0.8.2/cava.c 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/cava.c 2022-11-04 09:01:05.000000000 +0100 @@ -300,20 +300,13 @@ audio.channels = 2; audio.input_buffer_size = BUFFER_SIZE * audio.channels; - audio.cava_buffer_size = audio.input_buffer_size * 4; + audio.cava_buffer_size = audio.input_buffer_size * 8; audio.cava_in = (double *)malloc(audio.cava_buffer_size * sizeof(double)); memset(audio.cava_in, 0, sizeof(int) * audio.cava_buffer_size); audio.terminate = 0; - int *bars_left, *bars_right; - double *cava_out; - - bars_left = (int *)malloc(BUFFER_SIZE * sizeof(int)); - bars_right = (int *)malloc(BUFFER_SIZE * sizeof(int)); - cava_out = (double *)malloc(BUFFER_SIZE * audio.channels * sizeof(double)); - debug("starting audio thread\n"); pthread_t p_thread; @@ -412,10 +405,22 @@ exit(EXIT_FAILURE); } - int bars[BUFFER_SIZE]; - int previous_frame[BUFFER_SIZE]; + int *bars; + int *previous_frame; + + int *bars_left, *bars_right; + double *cava_out; int height, lines, width, remainder, fp; + int *dimension_bar, *dimension_value; + + if (p.orientation == ORIENT_LEFT || p.orientation == ORIENT_RIGHT) { + dimension_bar = &height; + dimension_value = &width; + } else { + dimension_bar = &width; + dimension_value = &height; + } #ifdef SDL // output: start sdl mode @@ -428,12 +433,6 @@ bool reloadConf = false; while (!reloadConf) { // jumping back to this loop means that you resized the screen - for (int n = 0; n < BUFFER_SIZE; n++) { - previous_frame[n] = 0; - bars[n] = 0; - cava_out[n] = 0; - cava_out[n + BUFFER_SIZE] = 0; - } // frequencies on x axis require a bar width of four or more if (p.xaxis == FREQUENCY && p.bar_width < 4) @@ -447,8 +446,9 @@ p.gradient_count, p.gradient_colors, &width, &lines); if (p.xaxis != NONE) lines--; - // we have 8 times as much height due to using 1/8 block characters - height = lines * 8; + height = lines; + *dimension_value *= + 8; // we have 8 times as much height due to using 1/8 block characters break; #endif #ifdef SDL @@ -463,7 +463,9 @@ if (p.xaxis != NONE) lines--; - init_terminal_noncurses(inAtty, p.col, p.bgcol, width, lines, p.bar_width); + init_terminal_noncurses(inAtty, p.color, p.bcolor, p.col, p.bgcol, p.gradient, + p.gradient_count, p.gradient_colors, width, lines, + p.bar_width); height = lines * 8; break; @@ -502,7 +504,7 @@ #endif // width must be hardcoded for raw output. - width = BUFFER_SIZE; + width = 512; if (strcmp(p.data_format, "ascii") != 0) { // "binary" or "noritake" @@ -527,76 +529,99 @@ int number_of_bars = p.fixedbars; if (p.autobars == 1) - number_of_bars = (width + p.bar_spacing) / (p.bar_width + p.bar_spacing); + number_of_bars = (*dimension_bar + p.bar_spacing) / (p.bar_width + p.bar_spacing); - if (number_of_bars < 1) + if (number_of_bars <= 1) { number_of_bars = 1; // must have at least 1 bars - if (number_of_bars > BUFFER_SIZE) - number_of_bars = BUFFER_SIZE; // cant have more than BUFFER_SIZE bars + if (p.stereo) { + number_of_bars = 2; // stereo have at least 2 bars + } + } + if (number_of_bars > 512) + number_of_bars = 512; // cant have more than 512 bars on 44100 rate int output_channels = 1; if (p.stereo) { // stereo must have even numbers of bars + if (audio.channels == 1) { + fprintf(stderr, + "stereo output configured, but only one channel in audio input.\n"); + exit(1); + } output_channels = 2; if (number_of_bars % 2 != 0) number_of_bars--; } // checks if there is stil extra room, will use this to center - remainder = (width - number_of_bars * p.bar_width - number_of_bars * p.bar_spacing + - p.bar_spacing) / + remainder = (*dimension_bar - number_of_bars * p.bar_width - + number_of_bars * p.bar_spacing + p.bar_spacing) / 2; if (remainder < 0) remainder = 0; #ifndef NDEBUG - debug("height: %d width: %d bars:%d bar width: %d remainder: %d\n", height, width, - number_of_bars, p.bar_width, remainder); + debug("height: %d width: %d dimension_bar: %d dimension_value: %d bars:%d bar width: " + "%d remainder: %d\n", + height, width, *dimension_bar, *dimension_value, number_of_bars, p.bar_width, + remainder); #endif + double userEQ_keys_to_bars_ratio; + + if (p.userEQ_enabled && (number_of_bars / output_channels > 0)) { + userEQ_keys_to_bars_ratio = (double)(((double)p.userEQ_keys) / + ((double)(number_of_bars / output_channels))); + } + struct cava_plan *plan = cava_init(number_of_bars / output_channels, audio.rate, audio.channels, p.autosens, p.noise_reduction, p.lower_cut_off, p.upper_cut_off); - double center_frequencies[BUFFER_SIZE]; + if (audio.channels == 2) { + bars_left = (int *)malloc(number_of_bars / output_channels * sizeof(int)); + bars_right = (int *)malloc(number_of_bars / output_channels * sizeof(int)); + memset(bars_left, 0, sizeof(int) * number_of_bars / output_channels); + memset(bars_right, 0, sizeof(int) * number_of_bars / output_channels); + } + bars = (int *)malloc(number_of_bars * sizeof(int)); + previous_frame = (int *)malloc(number_of_bars * sizeof(int)); + cava_out = (double *)malloc(number_of_bars * audio.channels / output_channels * + sizeof(double)); + + memset(bars, 0, sizeof(int) * number_of_bars); + memset(previous_frame, 0, sizeof(int) * number_of_bars); + memset(cava_out, 0, sizeof(double) * number_of_bars * audio.channels / output_channels); // process: calculate x axis values int x_axis_info = 0; if (p.xaxis != NONE) { x_axis_info = 1; - double center_frequency; + double cut_off_frequency; if (output_mode == OUTPUT_NONCURSES) { printf("\r\033[%dB", lines + 1); if (remainder) printf("\033[%dC", remainder); } for (int n = 0; n < number_of_bars; n++) { - float upper_cut_off_frequency = 10000; - - if (n < number_of_bars - 1) { - upper_cut_off_frequency = plan->cut_off_frequency[n + 1]; - } - - center_frequencies[n] = - pow((plan->cut_off_frequency[n] * upper_cut_off_frequency), 0.5); if (p.stereo) { if (n < number_of_bars / 2) - center_frequency = center_frequencies[number_of_bars / 2 - 1 - n]; + cut_off_frequency = plan->cut_off_frequency[number_of_bars / 2 - 1 - n]; else - center_frequency = center_frequencies[n - number_of_bars / 2]; + cut_off_frequency = plan->cut_off_frequency[n - number_of_bars / 2]; } else { - center_frequency = center_frequencies[n]; + cut_off_frequency = plan->cut_off_frequency[n]; } - float freq_kilohz = center_frequency / 1000; - int freq_floor = center_frequency; + float freq_kilohz = cut_off_frequency / 1000; + int freq_floor = cut_off_frequency; if (output_mode == OUTPUT_NCURSES) { #ifdef NCURSES - if (center_frequency < 1000) + if (cut_off_frequency < 1000) mvprintw(lines, n * (p.bar_width + p.bar_spacing) + remainder, "%-4d", freq_floor); - else if (center_frequency > 1000 && center_frequency < 10000) + else if (cut_off_frequency > 1000 && cut_off_frequency < 10000) mvprintw(lines, n * (p.bar_width + p.bar_spacing) + remainder, "%.2f", freq_kilohz); else @@ -604,9 +629,9 @@ freq_kilohz); #endif } else if (output_mode == OUTPUT_NONCURSES) { - if (center_frequency < 1000) + if (cut_off_frequency < 1000) printf("%-4d", freq_floor); - else if (center_frequency > 1000 && center_frequency < 10000) + else if (cut_off_frequency > 1000 && cut_off_frequency < 10000) printf("%.2f", freq_kilohz); else printf("%.1f", freq_kilohz); @@ -756,29 +781,44 @@ } pthread_mutex_unlock(&audio.lock); - for (uint32_t n = 0; n < number_of_bars * audio.channels; n++) { + for (uint32_t n = 0; n < (number_of_bars / output_channels) * audio.channels; n++) { if (p.autosens) - cava_out[n] *= height; + cava_out[n] *= *dimension_value; else cava_out[n] *= p.sens; } - for (uint32_t n = 0; n < number_of_bars * audio.channels / output_channels; n++) { - bars_right[n] = cava_out[n]; - if (audio.channels == 2) - bars_left[n] = cava_out[n + number_of_bars / output_channels]; + if (audio.channels == 2) { + for (int n = 0; n < number_of_bars / output_channels; n++) { + if (p.userEQ_enabled) + cava_out[n] *= + p.userEQ[(int)floor(((double)n) * userEQ_keys_to_bars_ratio)]; + bars_left[n] = cava_out[n]; + } + for (int n = 0; n < number_of_bars / output_channels; n++) { + if (p.userEQ_enabled) + cava_out[n + number_of_bars / output_channels] *= + p.userEQ[(int)floor(((double)n) * userEQ_keys_to_bars_ratio)]; + bars_right[n] = cava_out[n + number_of_bars / output_channels]; + } + } else { + for (int n = 0; n < number_of_bars; n++) { + if (p.userEQ_enabled) + cava_out[n] *= + p.userEQ[(int)floor(((double)n) * userEQ_keys_to_bars_ratio)]; + bars[n] = cava_out[n]; + } } // process [filter] if (p.monstercat) { - if (p.stereo) { + if (audio.channels == 2) { bars_left = monstercat_filter(bars_left, number_of_bars / 2, p.waves, p.monstercat); bars_right = monstercat_filter(bars_right, number_of_bars / 2, p.waves, p.monstercat); } else { - bars_left = - monstercat_filter(bars_left, number_of_bars, p.waves, p.monstercat); + bars = monstercat_filter(bars, number_of_bars, p.waves, p.monstercat); } } if (audio.channels == 2) { @@ -822,12 +862,8 @@ } } } - } else { - // only one input channel - for (int n = 0; n < number_of_bars; n++) { - bars[n] = bars_left[n]; - } } + for (int n = 0; n < number_of_bars; n++) { // zero values causes divided by zero segfault (if not raw) if (output_mode != OUTPUT_RAW && output_mode != OUTPUT_NORITAKE && bars[n] < 1) @@ -865,25 +901,31 @@ // output: draw processed input #ifdef NDEBUG + if (p.sync_updates) { + printf("\033P=1s\033\\"); + fflush(stdout); + } int rc; switch (output_mode) { case OUTPUT_NCURSES: #ifdef NCURSES - rc = draw_terminal_ncurses(inAtty, lines, width, number_of_bars, p.bar_width, - p.bar_spacing, remainder, bars, previous_frame, - p.gradient, x_axis_info); + rc = draw_terminal_ncurses(inAtty, *dimension_value / 8, *dimension_bar, + number_of_bars, p.bar_width, p.bar_spacing, + remainder, bars, previous_frame, p.gradient, + x_axis_info, p.orientation); break; #endif #ifdef SDL case OUTPUT_SDL: - rc = draw_sdl(number_of_bars, p.bar_width, p.bar_spacing, remainder, height, - bars, previous_frame, frame_time_msec); + rc = draw_sdl(number_of_bars, p.bar_width, p.bar_spacing, remainder, + *dimension_value, bars, previous_frame, frame_time_msec, + p.orientation); break; #endif case OUTPUT_NONCURSES: rc = draw_terminal_noncurses(inAtty, lines, width, number_of_bars, p.bar_width, p.bar_spacing, remainder, bars, previous_frame, - x_axis_info); + p.gradient, x_axis_info); break; case OUTPUT_RAW: rc = print_raw_out(number_of_bars, fp, p.raw_format, p.bit_format, @@ -896,7 +938,10 @@ default: exit(EXIT_FAILURE); // Can't happen. } - + if (p.sync_updates) { + printf("\033P=2s\033\\"); + fflush(stdout); + } // terminal has been resized breaking to recalibrating values if (rc == -1) resizeTerminal = true; @@ -909,7 +954,7 @@ #endif - memcpy(previous_frame, bars, BUFFER_SIZE * sizeof(int)); + memcpy(previous_frame, bars, number_of_bars * sizeof(int)); // checking if audio thread has exited unexpectedly if (audio.terminate == 1) { @@ -940,6 +985,13 @@ } // resize terminal cava_destroy(plan); free(plan); + if (audio.channels == 2) { + free(bars_left); + free(bars_right); + } + free(cava_out); + free(bars); + free(previous_frame); } // reloading config //**telling audio thread to terminate**// @@ -951,9 +1003,6 @@ free(audio.source); free(audio.cava_in); - free(cava_out); - free(bars_left); - free(bars_right); cleanup(); if (should_quit) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/cavacore.c new/cava-0.8.3/cavacore.c --- old/cava-0.8.2/cavacore.c 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/cavacore.c 2022-11-04 09:01:05.000000000 +0100 @@ -31,17 +31,17 @@ int treble_buffer_size = 128; if (rate > 8125 && rate <= 16250) - treble_buffer_size = 256; + treble_buffer_size *= 2; else if (rate > 16250 && rate <= 32500) - treble_buffer_size = 512; + treble_buffer_size *= 4; else if (rate > 32500 && rate <= 75000) - treble_buffer_size = 1024; + treble_buffer_size *= 8; else if (rate > 75000 && rate <= 150000) - treble_buffer_size = 2048; + treble_buffer_size *= 16; else if (rate > 150000 && rate <= 300000) - treble_buffer_size = 4096; + treble_buffer_size *= 32; else if (rate > 300000) - treble_buffer_size = 8096; + treble_buffer_size *= 64; if (number_of_bars < 1) { snprintf(p->error_message, 1024, @@ -55,8 +55,7 @@ if (number_of_bars > treble_buffer_size / 2 + 1) { snprintf(p->error_message, 1024, "cava_init called with illegal number of bars: %d, for %d sample rate number of " - "bars can't be more than %d " - "positive integer\n", + "bars can't be more than %d\n", number_of_bars, rate, treble_buffer_size / 2 + 1); p->status = -1; return p; @@ -82,6 +81,7 @@ p->audio_channels = channels; p->rate = rate; p->autosens = 1; + p->sens_init = 1; p->sens = 1; p->autosens = autosens; p->framerate = 75; @@ -91,8 +91,8 @@ p->g = log10((float)p->height) * 0.05; - p->FFTbassbufferSize = treble_buffer_size * 4; - p->FFTmidbufferSize = treble_buffer_size * 2; + p->FFTbassbufferSize = treble_buffer_size * 8; + p->FFTmidbufferSize = treble_buffer_size * 4; p->FFTtreblebufferSize = treble_buffer_size; p->input_buffer_size = p->FFTbassbufferSize * channels; @@ -196,8 +196,8 @@ // process: calculate cutoff frequencies and eq int lower_cut_off = low_cut_off; int upper_cut_off = high_cut_off; - int bass_cut_off = 150; - int treble_cut_off = 2500; + int bass_cut_off = 100; + int treble_cut_off = 500; // calculate frequency constant (used to distribute bars across the frequency band) double frequency_constant = log10((float)lower_cut_off / (float)upper_cut_off) / @@ -234,7 +234,7 @@ // the numbers that come out of the FFT are verry high // the EQ is used to "normalize" them by dividing with this verry huge number - p->eq[n] /= pow(2, 20); + p->eq[n] /= pow(2, 18); p->eq[n] /= log2(p->FFTbassbufferSize); @@ -247,7 +247,6 @@ if (p->bass_cut_off_bar > 0) first_bar = 0; - p->eq[n] *= log2(p->FFTbassbufferSize); if (p->FFTbuffer_lower_cut_off[n] > p->FFTbassbufferSize / 2) { p->FFTbuffer_lower_cut_off[n] = p->FFTbassbufferSize / 2; } @@ -267,7 +266,6 @@ first_bar = 0; } - p->eq[n] *= log2(p->FFTmidbufferSize); if (p->FFTbuffer_lower_cut_off[n] > p->FFTmidbufferSize / 2) { p->FFTbuffer_lower_cut_off[n] = p->FFTmidbufferSize / 2; } @@ -286,7 +284,6 @@ first_bar = 0; } - p->eq[n] *= log2(p->FFTtreblebufferSize); if (p->FFTbuffer_lower_cut_off[n] > p->FFTtreblebufferSize / 2) { p->FFTbuffer_lower_cut_off[n] = p->FFTtreblebufferSize / 2; } @@ -374,24 +371,24 @@ // fill the bass, mid and treble buffers for (uint16_t n = 0; n < p->FFTbassbufferSize; n++) { if (p->audio_channels == 2) { - p->in_bass_l_raw[n] = p->input_buffer[n * 2]; - p->in_bass_r_raw[n] = p->input_buffer[n * 2 + 1]; + p->in_bass_r_raw[n] = p->input_buffer[n * 2]; + p->in_bass_l_raw[n] = p->input_buffer[n * 2 + 1]; } else { p->in_bass_l_raw[n] = p->input_buffer[n]; } } for (uint16_t n = 0; n < p->FFTmidbufferSize; n++) { if (p->audio_channels == 2) { - p->in_mid_l_raw[n] = p->input_buffer[n * 2]; - p->in_mid_r_raw[n] = p->input_buffer[n * 2 + 1]; + p->in_mid_r_raw[n] = p->input_buffer[n * 2]; + p->in_mid_l_raw[n] = p->input_buffer[n * 2 + 1]; } else { p->in_mid_l_raw[n] = p->input_buffer[n]; } } for (uint16_t n = 0; n < p->FFTtreblebufferSize; n++) { if (p->audio_channels == 2) { - p->in_treble_l_raw[n] = p->input_buffer[n * 2]; - p->in_treble_r_raw[n] = p->input_buffer[n * 2 + 1]; + p->in_treble_r_raw[n] = p->input_buffer[n * 2]; + p->in_treble_l_raw[n] = p->input_buffer[n * 2 + 1]; } else { p->in_treble_l_raw[n] = p->input_buffer[n]; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/cavacore.h new/cava-0.8.3/cavacore.h --- old/cava-0.8.2/cavacore.h 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/cavacore.h 2022-11-04 09:01:05.000000000 +0100 @@ -123,7 +123,8 @@ // in case of async reading of data this number is allowed to vary from execution to execution // cava_out, output buffer. Size must be number of bars * number of channels. Bars will -// be sorted from lowest to highest frequency. Feft channel first then right channel. +// be sorted from lowest to highest frequency. If stereo input channels are configured +// then all left channel bars will be first then the right. // plan, the cava_plan struct returned from cava_init diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/cavacore_test.c new/cava-0.8.3/cavacore_test.c --- old/cava-0.8.2/cavacore_test.c 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/cavacore_test.c 2022-11-04 09:01:05.000000000 +0100 @@ -20,8 +20,8 @@ double noise_reduction = 0.77; int low_cut_off = 50; int high_cut_off = 10000; - double blueprint_2000MHz[10] = {0, 0, 0, 0, 0, 0, 0.783, 0.209, 0, 0}; - double blueprint_200MHz[10] = {0, 0.002, 0.980, 0.049, 0.001, 0, 0, 0, 0, 0}; + double blueprint_2000MHz[10] = {0, 0, 0, 0, 0, 0, 0.524, 0.474, 0, 0}; + double blueprint_200MHz[10] = {0, 0, 0.998, 0.009, 0, 0.001, 0, 0, 0, 0}; printf("planning visualization with %d bars per channel, %d rate, %d channels, autosens, " "%.2f noise reduction, %d - %d MHz bandwith.\n", @@ -35,7 +35,7 @@ } printf("got lower cut off frequencies:\n"); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < bars_per_channel; i++) { printf("%.0f \t", plan->cut_off_frequency[i]); } printf("MHz\n\n"); @@ -57,11 +57,11 @@ for (int k = 0; k < 300; k++) { // filling up 512*2 samples at a time, making sure the sinus wave is unbroken - // 200MHz in right channel, 2000MHz in left + // 200MHz in left channel, 2000MHz in right // if we where using a proper audio source this would be replaced by a simple read function for (int n = 0; n < buffer_size / 2; n++) { - cava_in[n * 2] = sin(2 * PI * 200 / rate * (n + (k * buffer_size / 2))) * 10000; - cava_in[n * 2 + 1] = sin(2 * PI * 2000 / rate * (n + (k * buffer_size / 2))) * 10000; + cava_in[n * 2] = sin(2 * PI * 200 / rate * (n + (k * buffer_size / 2))) * 20000; + cava_in[n * 2 + 1] = sin(2 * PI * 2000 / rate * (n + (k * buffer_size / 2))) * 20000; } cava_execute(cava_in, buffer_size, cava_out, plan); @@ -72,13 +72,13 @@ cava_out[i] = (double)round(cava_out[i] * 1000) / 1000; } - printf("\nlast output left, max value should be at 2000Hz:\n"); + printf("\nlast output left, max value should be at 200Hz:\n"); for (int i = 0; i < bars_per_channel; i++) { printf("%.3f \t", cava_out[i]); } printf("MHz\n"); - printf("last output right, max value should be at 200Hz:\n"); + printf("last output right, max value should be at 2000Hz:\n"); for (int i = 0; i < bars_per_channel; i++) { printf("%.3f \t", cava_out[i + bars_per_channel]); } @@ -87,12 +87,12 @@ // checking if within 2% of blueprint int bp_ok = 1; for (int i = 0; i < bars_per_channel; i++) { - if (cava_out[i] > blueprint_2000MHz[i] * 1.02 || cava_out[i] < blueprint_2000MHz[i] * 0.98) + if (cava_out[i] > blueprint_200MHz[i] * 1.02 || cava_out[i] < blueprint_200MHz[i] * 0.98) bp_ok = 0; } for (int i = 0; i < bars_per_channel; i++) { - if (cava_out[i + bars_per_channel] > blueprint_200MHz[i] * 1.02 || - cava_out[i + bars_per_channel] < blueprint_200MHz[i] * 0.98) + if (cava_out[i + bars_per_channel] > blueprint_2000MHz[i] * 1.02 || + cava_out[i + bars_per_channel] < blueprint_2000MHz[i] * 0.98) bp_ok = 0; } cava_destroy(plan); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/config.c new/cava-0.8.3/config.c --- old/cava-0.8.2/config.c 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/config.c 2022-11-04 09:01:05.000000000 +0100 @@ -26,7 +26,7 @@ INPUT_PULSE, }; -char *outputMethod, *channels, *xaxisScale, *monoOption; +char *outputMethod, *orientation, *channels, *xaxisScale, *monoOption; const char *input_method_names[] = { "fifo", "portaudio", "alsa", "pulse", "sndio", "shmem", @@ -61,23 +61,6 @@ struct error_s *error = (struct error_s *)err; int validColor = 0; if (checkColor[0] == '#' && strlen(checkColor) == 7) { - // If the output mode is not ncurses, tell the user to use a named colour instead of hex - // colours. - if (p->output != OUTPUT_NCURSES && p->output != OUTPUT_SDL) { -#if defined(NCURSES) || defined(SDL) - write_errorf(error, - "hex color configured, but ncurses not set. Forcing ncurses mode.\n"); - p->output = OUTPUT_NCURSES; -#else - write_errorf(error, "Only 'ncurses' and sdl output method supports HTML colors " - "(required by gradient). " - "Cava was built without sdl or ncurses support, install ncurses(w) " - "or sdl dev files " - "and rebuild.\n"); - return 0; -#endif - } - // 0 to 9 and a to f for (int i = 1; checkColor[i]; ++i) { if (!isdigit(checkColor[i])) { if (tolower(checkColor[i]) >= 'a' && tolower(checkColor[i]) <= 'f') { @@ -153,6 +136,8 @@ p->col = 6; if (strcmp(p->color, "white") == 0) p->col = 7; + if (p->color[0] == '#') + p->col = 8; // default if invalid // validate: background color @@ -172,6 +157,8 @@ p->bgcol = 6; if (strcmp(p->bcolor, "white") == 0) p->bgcol = 7; + if (p->bcolor[0] == '#') + p->bgcol = 8; // default if invalid return true; @@ -237,21 +224,31 @@ } } if (p->output == OUTPUT_NOT_SUPORTED) { -#ifndef NCURSES - write_errorf( - error, - "output method %s is not supported, supported methods are: 'noncurses' and 'raw'\n", - outputMethod); - return false; -#endif + + char supportedOutput[1024] = "'noncurses', 'raw', 'noritake'"; #ifdef NCURSES - write_errorf(error, - "output method %s is not supported, supported methods are: 'ncurses', " - "'noncurses' and 'raw'\n", - outputMethod); - return false; + strcat(supportedOutput, ", 'ncurses'"); +#endif +#ifdef SDL + strcat(supportedOutput, ", 'sdl'"); #endif + write_errorf(error, "output method %s is not supported, supported methods are: %s\n", + outputMethod, supportedOutput); + return false; + } + + p->orientation = ORIENT_BOTTOM; + if (p->output == OUTPUT_SDL || p->output == OUTPUT_NCURSES) { + if (strcmp(orientation, "top") == 0) { + p->orientation = ORIENT_TOP; + } + if (strcmp(orientation, "left") == 0) { + p->orientation = ORIENT_LEFT; + } + if (strcmp(orientation, "right") == 0) { + p->orientation = ORIENT_RIGHT; + } } p->xaxis = NONE; @@ -468,6 +465,7 @@ outputMethod = (char *)iniparser_getstring(ini, "output:method", "noncurses"); #endif + orientation = (char *)iniparser_getstring(ini, "output:orientation", "bottom"); xaxisScale = (char *)iniparser_getstring(ini, "output:xaxis", "none"); p->monstercat = 1.5 * iniparser_getdouble(ini, "smoothing:monstercat", 0); p->waves = iniparser_getint(ini, "smoothing:waves", 0); @@ -529,6 +527,8 @@ p->bar_spacing = iniparser_getint(ini, "general:bar_spacing", 5); } + p->sync_updates = iniparser_getint(ini, "output:alacritty_sync", 0); + // read & validate: eq p->userEQ_keys = iniparser_getsecnkeys(ini, "eq"); if (p->userEQ_keys > 0) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/config.h new/cava-0.8.3/config.h --- old/cava-0.8.2/config.h 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/config.h 2022-11-04 09:01:05.000000000 +0100 @@ -57,6 +57,8 @@ enum xaxis_scale { NONE, FREQUENCY, NOTE }; +enum orientation { ORIENT_BOTTOM, ORIENT_TOP, ORIENT_LEFT, ORIENT_RIGHT }; + struct config_params { char *color, *bcolor, *raw_target, *audio_source, /**gradient_color_1, *gradient_color_2,*/ **gradient_colors, *data_format; @@ -68,10 +70,11 @@ enum output_method output; enum xaxis_scale xaxis; enum mono_option mono_opt; + enum orientation orientation; int userEQ_keys, userEQ_enabled, col, bgcol, autobars, stereo, raw_format, ascii_range, bit_format, gradient, gradient_count, fixedbars, framerate, bar_width, bar_spacing, bar_height, autosens, overshoot, waves, fifoSample, fifoSampleBits, sleep_timer, sdl_width, - sdl_height, sdl_x, sdl_y, draw_and_quit, zero_test, non_zero_test, reverse; + sdl_height, sdl_x, sdl_y, draw_and_quit, zero_test, non_zero_test, reverse, sync_updates; }; struct error_s { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/example_files/config new/cava-0.8.3/example_files/config --- old/cava-0.8.2/example_files/config 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/example_files/config 2022-11-04 09:01:05.000000000 +0100 @@ -93,6 +93,12 @@ # 'sdl' uses the Simple DirectMedia Layer to render in a graphical context. ; method = ncurses +# Orientation of the visualization. Can be 'bottom', 'top', 'left' or 'right'. +# Default is 'bottom'. Other orientations are only supported on sdl and ncruses +# output. Note: many fonts have weird glyphs for 'top' and 'right' characters, +# which can make ncurses not look right. +; orientation = bottom + # Visual channels. Can be 'stereo' or 'mono'. # 'stereo' mirrors both channels with low frequencies in center. # 'mono' outputs left to right lowest to highest frequencies. @@ -125,12 +131,21 @@ ; sdl_x = -1 ; sdl_y= -1 +# set label on bars on the x-axis. Can be 'frequency' or 'none'. Default: 'none' +# 'frequency' displays the lower cut off frequency of the bar above. +# Only supported on ncurses and noncurses output. +; xaxis = none + +# enable alacritty synchronized updates. 1 = on, 0 = off +# removes flickering in alacritty terminal emeulator. +# defaults to off since the behaviour in other terminal emulators is unknown +; alacritty_sync = 0 + [color] # Colors can be one of seven predefined: black, blue, cyan, green, magenta, red, white, yellow. # Or defined by hex code '#xxxxxx' (hex code must be within ''). User defined colors requires -# ncurses output method and a terminal that can change color definitions such as Gnome-terminal or rxvt. -# if supported, ncurses mode will be forced on if user defined colors are used. +# a terminal that can change color definitions such as Gnome-terminal or rxvt. # default is to keep current terminal color ; background = default ; foreground = default @@ -140,8 +155,8 @@ ; foreground = '#33cccc' -# Gradient mode, only hex defined colors (and thereby ncurses mode) are supported, -# background must also be defined in hex or remain commented out. 1 = on, 0 = off. +# Gradient mode, only hex defined colors are supported, +# background must also be defined in hex or remain commented out. 1 = on, 0 = off. # You can define as many as 8 different colors. They range from bottom to top of screen ; gradient = 0 ; gradient_count = 8 @@ -188,8 +203,6 @@ # This one is tricky. You can have as much keys as you want. # Remember to uncomment more then one key! More keys = more precision. # Look at readme.md on github for further explanations and examples. -# DEPRECATED as of 0.8.0 can be brought back by popular request, open issue at: -# https://github.com/karlstav/cava ; 1 = 1 # bass ; 2 = 1 ; 3 = 1 # midtone diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/input/common.h new/cava-0.8.3/input/common.h --- old/cava-0.8.2/input/common.h 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/input/common.h 2022-11-04 09:01:05.000000000 +0100 @@ -9,11 +9,8 @@ #include <string.h> #include <unistd.h> -// number of bytes to read from audio source x number of channels -// determins the size of all other buffers -// matches the CAVA_TREBLE_BUFFER_SIZE in core.h - -#define BUFFER_SIZE 1024 +// number of samples to read from audio source per channel +#define BUFFER_SIZE 512 struct audio_data { double *cava_in; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/input/portaudio.c new/cava-0.8.3/input/portaudio.c --- old/cava-0.8.2/input/portaudio.c 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/input/portaudio.c 2022-11-04 09:01:05.000000000 +0100 @@ -139,7 +139,7 @@ err = Pa_OpenStream(&stream, &inputParameters, NULL, audio->rate, audio->input_buffer_size / 2, paClipOff, recordCallback, &data); if (err != paNoError) { - fprintf(stderr, "Error: failure in opening stream (%x)\n", err); + fprintf(stderr, "Error: failure in opening stream (%s)\n", Pa_GetErrorText(err)); exit(EXIT_FAILURE); } @@ -149,7 +149,7 @@ data.frameIndex = 0; err = Pa_StartStream(stream); if (err != paNoError) { - fprintf(stderr, "Error: failure in starting stream (%x)\n", err); + fprintf(stderr, "Error: failure in starting stream (%s)\n", Pa_GetErrorText(err)); exit(EXIT_FAILURE); } @@ -161,7 +161,7 @@ } // check for errors if (err < 0) { - fprintf(stderr, "Error: failure in recording audio (%x)\n", err); + fprintf(stderr, "Error: failure in recording audio (%s)\n", Pa_GetErrorText(err)); exit(EXIT_FAILURE); } @@ -171,7 +171,7 @@ } // close stream if ((err = Pa_CloseStream(stream)) != paNoError) { - fprintf(stderr, "Error: failure in closing stream (%x)\n", err); + fprintf(stderr, "Error: failure in closing stream (%s)\n", Pa_GetErrorText(err)); exit(EXIT_FAILURE); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/output/sdl_cava.c new/cava-0.8.3/output/sdl_cava.c --- old/cava-0.8.2/output/sdl_cava.c 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/output/sdl_cava.c 2022-11-04 09:01:05.000000000 +0100 @@ -1,7 +1,7 @@ -#include "output/sdl_cava.h" - #include <SDL2/SDL.h> +#include "output/sdl_cava.h" + #include <stdbool.h> #include <stdlib.h> @@ -63,7 +63,7 @@ } int draw_sdl(int bars_count, int bar_width, int bar_spacing, int remainder, int height, - const int bars[], int previous_frame[], int frame_time) { + const int bars[], int previous_frame[], int frame_time, enum orientation orientation) { bool update = false; int rc = 0; @@ -80,10 +80,33 @@ SDL_SetRenderDrawColor(gRenderer, bg_color.R, bg_color.G, bg_color.B, 0xFF); SDL_RenderClear(gRenderer); for (int bar = 0; bar < bars_count; bar++) { - fillRect.x = bar * (bar_width + bar_spacing) + remainder; - fillRect.y = height - bars[bar]; - fillRect.w = bar_width; - fillRect.h = bars[bar]; + switch (orientation) { + case ORIENT_LEFT: + fillRect.x = 0; + fillRect.y = bar * (bar_width + bar_spacing) + remainder; + fillRect.w = bars[bar]; + fillRect.h = bar_width; + break; + case ORIENT_RIGHT: + fillRect.x = height - bars[bar]; + fillRect.y = bar * (bar_width + bar_spacing) + remainder; + fillRect.w = bars[bar]; + fillRect.h = bar_width; + break; + case ORIENT_TOP: + fillRect.x = bar * (bar_width + bar_spacing) + remainder; + fillRect.y = 0; + fillRect.w = bar_width; + fillRect.h = bars[bar]; + break; + default: + fillRect.x = bar * (bar_width + bar_spacing) + remainder; + fillRect.y = height - bars[bar]; + fillRect.w = bar_width; + fillRect.h = bars[bar]; + break; + } + SDL_SetRenderDrawColor(gRenderer, fg_color.R, fg_color.G, fg_color.B, 0xFF); SDL_RenderFillRect(gRenderer, &fillRect); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/output/sdl_cava.h new/cava-0.8.3/output/sdl_cava.h --- old/cava-0.8.2/output/sdl_cava.h 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/output/sdl_cava.h 2022-11-04 09:01:05.000000000 +0100 @@ -1,6 +1,8 @@ +#include "../config.h" + void init_sdl_window(int width, int height, int x, int y); void init_sdl_surface(int *width, int *height, char *const fg_color_string, char *const bg_color_string); int draw_sdl(int bars_count, int bar_width, int bar_spacing, int remainder, int height, - const int bars[], int previous_frame[], int frame_timer); + const int bars[], int previous_frame[], int frame_timer, enum orientation orientation); void cleanup_sdl(void); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/output/terminal_ncurses.c new/cava-0.8.3/output/terminal_ncurses.c --- old/cava-0.8.2/output/terminal_ncurses.c 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/output/terminal_ncurses.c 2022-11-04 09:01:05.000000000 +0100 @@ -20,9 +20,17 @@ #define MAX_COLOR_REDEFINITION 256 -const wchar_t *bar_heights[] = {L"\u2581", L"\u2582", L"\u2583", L"\u2584", - L"\u2585", L"\u2586", L"\u2587", L"\u2588"}; -int num_bar_heights = (sizeof(bar_heights) / sizeof(bar_heights[0])); +const int num_bar_heights = 8; +const wchar_t *bar_heights_bottom[] = {L"\u2581", L"\u2582", L"\u2583", L"\u2584", + L"\u2585", L"\u2586", L"\u2587", L"\u2588"}; +const wchar_t *bar_heights_top[] = {L"\u2594", L"\U0001FB82", L"\U0001FB83", L"\u2580", + L"\U0001FB84", L"\U0001FB85", L"\U0001FB86", L"\u2588"}; +const wchar_t *bar_heights_left[] = {L"\u258F", L"\u258E", L"\u258D", L"\u258C", + L"\u258B", L"\u258A", L"\u2589", L"\u2588"}; +const wchar_t *bar_heights_right[] = {L"\u2595", L"\U0001FB87", L"\U0001FB88", L"\u2590", + L"\U0001FB89", L"\U0001FB8A", L"\U0001FB8B", L"\u2588"}; +const wchar_t **bar_heights[] = {bar_heights_bottom, bar_heights_top, bar_heights_left, + bar_heights_right}; // static struct colors the_color_redefinitions[MAX_COLOR_REDEFINITION]; @@ -69,6 +77,28 @@ return return_color_number; } +static void get_screen_coords(int val, int col, int max_value, enum orientation orientation, int *x, + int *y) { + switch (orientation) { + case ORIENT_LEFT: + *x = val; + *y = col; + break; + case ORIENT_RIGHT: + *x = max_value - val; + *y = col; + break; + case ORIENT_TOP: + *x = col; + *y = val; + break; + default: + *x = col; + *y = max_value - val; + break; + } +} + void init_terminal_ncurses(char *const fg_color_string, char *const bg_color_string, int predef_fg_color, int predef_bg_color, int gradient, int gradient_count, char **gradient_colors, int *width, int *lines) { @@ -191,33 +221,42 @@ #define TERMINAL_RESIZED -1 -int draw_terminal_ncurses(int is_tty, int terminal_height, int terminal_width, int bars_count, +int draw_terminal_ncurses(int is_tty, int dimension_value, int dimension_bar, int bars_count, int bar_width, int bar_spacing, int rest, const int bars[], - int previous_frame[], int gradient, int x_axis_info) { - const int height = terminal_height - 1; + int previous_frame[], int gradient, int x_axis_info, + enum orientation orientation) { + const int max_value = dimension_value - 1; // output: check if terminal has been resized if (!is_tty) { if (x_axis_info) - terminal_height++; + dimension_value++; + int terminal_width, terminal_height; + if (orientation == ORIENT_LEFT || orientation == ORIENT_RIGHT) { + terminal_width = dimension_value; + terminal_height = dimension_bar; + } else { + terminal_width = dimension_bar; + terminal_height = dimension_value; + } if (LINES != terminal_height || COLS != terminal_width) { return TERMINAL_RESIZED; if (x_axis_info) - terminal_height--; + dimension_value--; } } // Compute how much of the screen we possibly need to update ahead-of-time. - int max_update_y = 0; + int max_update_value = 0; for (int bar = 0; bar < bars_count; bar++) { - max_update_y = max(max_update_y, max(bars[bar], previous_frame[bar])); + max_update_value = max(max_update_value, max(bars[bar], previous_frame[bar])); } - max_update_y = (max_update_y + num_bar_heights) / num_bar_heights; + max_update_value = (max_update_value + num_bar_heights) / num_bar_heights; - for (int y = 0; y < max_update_y; y++) { + for (int val = 0; val < max_update_value; val++) { if (gradient) { - change_colors(y, height); + change_colors(val, max_value); } for (int bar = 0; bar < bars_count; bar++) { @@ -229,14 +268,14 @@ int f_cell = (bars[bar] - 1) / num_bar_heights; int f_last_cell = (previous_frame[bar] - 1) / num_bar_heights; - if (f_cell >= y) { + if (f_cell >= val) { int bar_step; - if (f_cell == y) { - // The "cap" of the bar occurs at this [y]. + if (f_cell == val) { + // The "cap" of the bar occurs at this [val]. bar_step = (bars[bar] - 1) % num_bar_heights; - } else if (f_last_cell <= y) { - // The bar is full at this [y]. + } else if (f_last_cell <= val) { + // The bar is full at this [val]. bar_step = num_bar_heights - 1; } else { // No update necessary since last frame. @@ -244,17 +283,22 @@ } for (int col = cur_col, i = 0; i < bar_width; i++, col++) { + int x, y; + get_screen_coords(val, col, max_value, orientation, &x, &y); + if (is_tty) { - mvaddch(height - y, col, 0x41 + bar_step); + mvaddch(y, x, 0x41 + bar_step); } else { - mvaddwstr(height - y, col, bar_heights[bar_step]); + mvaddwstr(y, x, bar_heights[orientation][bar_step]); } } - } else if (f_last_cell >= y) { + } else if (f_last_cell >= val) { // This bar was taller during the last frame than during this frame, so // clear the excess characters. for (int col = cur_col, i = 0; i < bar_width; i++, col++) { - mvaddch(height - y, col, ' '); + int x, y; + get_screen_coords(val, col, max_value, orientation, &x, &y); + mvaddch(y, x, ' '); } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/output/terminal_ncurses.h new/cava-0.8.3/output/terminal_ncurses.h --- old/cava-0.8.2/output/terminal_ncurses.h 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/output/terminal_ncurses.h 2022-11-04 09:01:05.000000000 +0100 @@ -1,8 +1,11 @@ +#include "../config.h" + void init_terminal_ncurses(char *const fg_color_string, char *const bg_color_string, int predef_fg_color, int predef_bg_color, int gradient, int gradient_count, char **gradient_colors, int *width, int *height); void get_terminal_dim_ncurses(int *width, int *height); int draw_terminal_ncurses(int is_tty, int terminal_height, int terminal_width, int bars_count, int bar_width, int bar_spacing, int rest, const int bars[], - int previous_frame[], int gradient, int x_axis_info); + int previous_frame[], int gradient, int x_axis_info, + enum orientation orientation); void cleanup_terminal_ncurses(void); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/output/terminal_noncurses.c new/cava-0.8.3/output/terminal_noncurses.c --- old/cava-0.8.2/output/terminal_noncurses.c 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/output/terminal_noncurses.c 2022-11-04 09:01:05.000000000 +0100 @@ -35,6 +35,18 @@ return 0; } +struct colors { + short unsigned int rgb[3]; +}; + +struct colors *gradient_colors; + +struct colors parse_color(char *color_string) { + struct colors color; + sscanf(++color_string, "%02hx%02hx%02hx", &color.rgb[0], &color.rgb[1], &color.rgb[2]); + return color; +} + // general: cleanup void free_terminal_noncurses(void) { free(frame_buffer); @@ -45,9 +57,12 @@ free(barstring[i]); free(ttybarstring[i]); } + free(gradient_colors); } -int init_terminal_noncurses(int tty, int col, int bgcol, int width, int lines, int bar_width) { +int init_terminal_noncurses(int tty, char *const fg_color_string, char *const bg_color_string, + int col, int bgcol, int gradient, int gradient_count, + char **gradient_color_strings, int width, int lines, int bar_width) { free_terminal_noncurses(); @@ -114,19 +129,62 @@ printf("\033[0m\n"); system("clear"); - if (col) + if (col == 38) { + struct colors fg_color = parse_color(fg_color_string); + printf("\033[38;2;%d;%d;%dm", fg_color.rgb[0], fg_color.rgb[1], fg_color.rgb[2]); + } else { printf("\033[%dm", col); // setting color + } + + if (gradient) { + struct colors gradient_color_defs[gradient_count]; + for (int i = 0; i < gradient_count; i++) { + gradient_color_defs[i] = parse_color(gradient_color_strings[i]); + } - // printf("\033[1m"); // setting "bright" color mode, looks cooler... I think + gradient_colors = (struct colors *)malloc((lines * 2) * sizeof(struct colors)); + + int individual_size = lines / (gradient_count - 1); + + float rest = lines / (float)(gradient_count - 1) - individual_size; + + float rest_total = 0; + int gradient_lines = 0; + + for (int i = 0; i < gradient_count - 1; i++) { + individual_size = lines / (gradient_count - 1); + if (rest_total > 1.0) { + individual_size++; + rest_total = rest_total - 1.0; + } + for (int n = 0; n < individual_size; n++) { + for (int c = 0; c < 3; c++) { + float next_color = + gradient_color_defs[i + 1].rgb[c] - gradient_color_defs[i].rgb[c]; + next_color *= n / (float)individual_size; + gradient_colors[gradient_lines].rgb[c] = + gradient_color_defs[i].rgb[c] + next_color; + } + gradient_lines++; + } + rest_total = rest_total + rest; + } + gradient_colors[lines - 1] = gradient_color_defs[gradient_count - 1]; + } if (bgcol != 0) { bgcol += 40; - printf("\033[%dm", bgcol); + + if (bgcol == 48) { + struct colors bg_color = parse_color(bg_color_string); + printf("\033[48;2;%d;%d;%dm", bg_color.rgb[0], bg_color.rgb[1], bg_color.rgb[2]); + } else { + printf("\033[%dm", bgcol); + } for (int n = lines; n >= 0; n--) { for (int i = 0; i < width; i++) { - printf(" "); // setting backround color } if (n != 0) @@ -156,7 +214,7 @@ int draw_terminal_noncurses(int tty, int lines, int width, int number_of_bars, int bar_width, int bar_spacing, int rest, int bars[], int previous_frame[], - int x_axis_info) { + int gradient, int x_axis_info) { int current_cell, prev_cell, same_line, new_line, cx; @@ -184,6 +242,20 @@ for (int current_line = lines - 1; current_line >= 0; current_line--) { + if (gradient) { + if (tty) { + cx += snprintf(ttyframe_buffer + cx, ttybuf_length - cx, "\033[38;2;%d;%d;%dm", + gradient_colors[current_line].rgb[0], + gradient_colors[current_line].rgb[1], + gradient_colors[current_line].rgb[2]); + } else if (!tty) { + cx += swprintf(frame_buffer + cx, buf_length - cx, L"\033[38;2;%d;%d;%dm", + gradient_colors[current_line].rgb[0], + gradient_colors[current_line].rgb[1], + gradient_colors[current_line].rgb[2]); + } + } + int same_bar = 0; int center_adjusted = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cava-0.8.2/output/terminal_noncurses.h new/cava-0.8.3/output/terminal_noncurses.h --- old/cava-0.8.2/output/terminal_noncurses.h 2022-04-24 21:36:28.000000000 +0200 +++ new/cava-0.8.3/output/terminal_noncurses.h 2022-11-04 09:01:05.000000000 +0100 @@ -1,6 +1,8 @@ -int init_terminal_noncurses(int inAtty, int col, int bgcol, int w, int h, int bar_width); +int init_terminal_noncurses(int inAtty, char *const fg_color_string, char *const bg_color_string, + int col, int bgcol, int gradient, int gradient_count, + char **gradient_colors, int w, int h, int bar_width); void get_terminal_dim_noncurses(int *w, int *h); int draw_terminal_noncurses(int inAtty, int lines, int width, int number_of_bars, int bar_width, int bar_spacing, int rest, int bars[], int previous_frame[], - int x_axis_info); + int gradient, int x_axis_info); void cleanup_terminal_noncurses(void);
