Last active
April 29, 2019 01:03
-
-
Save J3698/ecbdcda0531d0186a044b9c147a9e6e4 to your computer and use it in GitHub Desktop.
A very simple visualizer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stdbool.h> | |
#include <errno.h> | |
#include <unistd.h> | |
#include <math.h> | |
#include <getopt.h> | |
#include <string.h> | |
#include <wchar.h> | |
#include <locale.h> | |
#include <jack/jack.h> | |
#include <jack/transport.h> | |
// the datatype for audio (should be a double) | |
typedef jack_default_audio_sample_t sample_t; | |
// the name of this program | |
char *client_name = "Visualizer"; | |
// what client that interacts with jack | |
jack_client_t *client; | |
// ports for left and right audio sent to speaker | |
jack_port_t *output_port_l; | |
jack_port_t *output_port_r; | |
// ports for left and right audio coming from system (e.g. a connected phone) | |
jack_port_t *input_port_l; | |
jack_port_t *input_port_r; | |
/* this method does all of the processing and heavylifting in the program. | |
* In this case, it just routes input data to output data, and prints 1s | |
* if a chunk of audio is above a certain volume, and 0s if it is not. | |
*/ | |
int process(jack_nframes_t nframes, void *arg) { | |
sample_t *outBufferLeft = (sample_t *) jack_port_get_buffer(output_port_l, nframes); | |
sample_t *outBufferRight = (sample_t *) jack_port_get_buffer(output_port_r, nframes); | |
sample_t *inBufferLeft = (sample_t *) jack_port_get_buffer(input_port_l, nframes); | |
sample_t *inBufferRight = (sample_t *) jack_port_get_buffer(input_port_r, nframes); | |
// copy input audio to output | |
memcpy(outBufferLeft, inBufferLeft, sizeof(sample_t) * nframes); | |
memcpy(outBufferRight, inBufferRight, sizeof(sample_t) * nframes); | |
// calculate an estimate for the volume of the data | |
double total = 0; | |
for (int i = 0; i < nframes; i++) { | |
total += pow(outBufferLeft[i], 2); | |
total += pow(outBufferRight[i], 2); | |
} | |
// print to the console based on the volume estimate | |
if (total > 0.3) { | |
printf("\n111111111111111111"); | |
} else { | |
printf("\n000000000000000000"); | |
} | |
// uncomment the following line for debugging | |
// printf("%f\n", total); | |
return 0; | |
} | |
// boilerplate code to start a connection to jack | |
bool startClient() { | |
jack_status_t status; | |
while ((client = jack_client_open(client_name, 0, &status)) == 0) { | |
fprintf(stderr, "jack server not running?\n"); | |
return false; | |
} | |
printf("Client started\n"); | |
return true; | |
} | |
// create ports in order to read and write audio data (possibly extraneous) | |
void createPorts() { | |
output_port_l = jack_port_register(client, "lag_out_l", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |
output_port_r = jack_port_register(client, "lag_out_r", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |
input_port_l = jack_port_register(client, "lag_in_l", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |
input_port_r = jack_port_register(client, "lag_in_r", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |
printf("Ports created\n"); | |
} | |
// connect ports from the system and the speakers to our ports | |
void connectPorts() { | |
jack_connect(client, "PulseAudio JACK Sink:front-left", jack_port_name(input_port_l)); | |
jack_connect(client, "PulseAudio JACK Sink:front-right", jack_port_name(input_port_r)); | |
jack_connect(client, jack_port_name(output_port_l), "system:playback_1"); | |
jack_connect(client, jack_port_name(output_port_r), "system:playback_2"); | |
printf("Ports connected\n"); | |
} | |
/** | |
* In the main method jack gets started, ports get created and connected, | |
* and jack is told to call the process function when more work is to be done. | |
* A list of port names is also printed, for debugging purposes. | |
*/ | |
int main(int argc, char *argv[]) { | |
if (!startClient()) { | |
return -1; | |
} | |
createPorts(); | |
jack_set_process_callback(client, process, 0); | |
if (jack_activate(client)) { | |
fprintf(stderr, "cannot activate client"); | |
return 1; | |
} | |
printf("Jack activated\n"); | |
connectPorts(); | |
const char **port_names = jack_get_ports(client, NULL, NULL, 0); | |
for (int j = 0; port_names[j] != NULL; j++) { | |
printf("%s\n", port_names[j]); | |
} | |
while (true) { | |
sleep(1); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment