aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksa Vuckovic <aleksa@vuckovic.cc>2023-11-18 11:32:43 +0100
committerAleksa Vuckovic <aleksa@vuckovic.cc>2023-11-18 11:32:43 +0100
commit45d8de6c22a51efe7e76e71424693c18b93e83e3 (patch)
treed21e1e8cfc8c8c06d2de3cd92bfbe92dad9678d5
parent68a4257f117fd55287e589a62168cb9d35a362d9 (diff)
Support multiple channels
-rw-r--r--src/main.c86
1 files changed, 52 insertions, 34 deletions
diff --git a/src/main.c b/src/main.c
index f5db2de..10d00eb 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2,19 +2,17 @@
#include <cairo/cairo.h>
#include <portaudio.h>
-int device = -1;
-
typedef struct {
- float left;
- float right;
+ int device_num;
+ int chanel_cnt;
+ float *chanels;
} AudioData;
-AudioData audiodata;
-
-struct data {
+typedef struct {
int device_num;
-};
+} SelectedDevice;
+AudioData audiodata;
PaStream *stream = NULL;
GtkWidget *drawing_area;
@@ -25,17 +23,16 @@ int patestCallback(const void *inputBuffer, void *outputBuffer, unsigned long fr
AudioData *data = (AudioData *)userData;
float *in = (float *)inputBuffer;
- if (data->left > 0) {
- data->left -= 0.005;
- }
-
- if (data->right > 0) {
- data->right -= 0.005;
+ for (int i = 0; i < data->chanel_cnt; i++) {
+ if (data->chanels[i] > 0) {
+ data->chanels[i] -= 0.005;
+ }
}
- for (unsigned long i = 0; i < framesPerBuffer * 2; i += 2) {
- data->left = MAX(data->left, fabs(in[i]));
- data->right = MAX(data->right, fabs(in[i + 1]));
+ for (unsigned long i = 0; i < framesPerBuffer * data->chanel_cnt; i += data->chanel_cnt) {
+ for (int j = 0; j < data->chanel_cnt; j++) {
+ data->chanels[j] = MAX(data->chanels[j], fabs(in[i + j]));
+ }
}
if (drawing_area) {
@@ -53,27 +50,47 @@ static void select_device(GtkWidget *widget, gpointer data)
stream = NULL;
}
- struct data *d = (struct data *)data;
- device = d->device_num;
- printf("Device %d selected\n", d->device_num);
+ int device_num = ((SelectedDevice *)data)->device_num;
+ printf("Device %d selected\n", device_num);
PaStreamParameters inputParameters;
memset(&inputParameters, 0, sizeof(inputParameters));
- inputParameters.channelCount = 2;
- inputParameters.device = device;
+ inputParameters.channelCount = Pa_GetDeviceInfo(device_num)->maxInputChannels;
+ inputParameters.device = device_num;
inputParameters.hostApiSpecificStreamInfo = NULL;
inputParameters.sampleFormat = paFloat32;
- inputParameters.suggestedLatency = Pa_GetDeviceInfo(device)->defaultLowInputLatency;
+ inputParameters.suggestedLatency = Pa_GetDeviceInfo(device_num)->defaultLowInputLatency;
+
+ audiodata.device_num = device_num;
+ audiodata.chanel_cnt = inputParameters.channelCount;
+ audiodata.chanels = (float *)calloc(audiodata.chanel_cnt, sizeof(float));
- Pa_OpenStream(&stream, &inputParameters, NULL, Pa_GetDeviceInfo(device)->defaultSampleRate, FRAMES_PER_BUFFER, paNoFlag, patestCallback, &audiodata);
+ Pa_OpenStream(&stream, &inputParameters, NULL, Pa_GetDeviceInfo(device_num)->defaultSampleRate, FRAMES_PER_BUFFER, paNoFlag, patestCallback, &audiodata);
Pa_StartStream(stream);
}
static void draw(cairo_t *cr, GtkWidget *area)
{
+ float window_width = 900;
+ float window_height = 900;
+ float radius = 200;
+ float space = 50;
+ float delta, x, y;
+
+ delta = 2 * M_PI / audiodata.chanel_cnt;
+
+ cairo_set_source_rgba(cr, 1, 1, 1, 1);
+ cairo_arc(cr, window_width / 2, window_height / 2, space, 0, 2 * M_PI);
+ cairo_fill(cr);
+
cairo_set_source_rgba(cr, 1, 0, 0, 1);
- cairo_arc(cr, 250, 250, audiodata.left * 250, 0, 2 * M_PI);
- cairo_arc(cr, 800, 250, audiodata.right * 250, 0, 2 * M_PI);
+ for (int i = 0; i < audiodata.chanel_cnt; i += 2) {
+ x = (radius + space) * cos(i * delta / 2);
+ y = (radius + space) * sin(i * delta / 2);
+
+ cairo_arc(cr, window_width / 2 - x, window_height / 2 - y, audiodata.chanels[i] * radius, 0, 2 * M_PI);
+ cairo_arc(cr, window_width / 2 + x, window_height / 2 + y, audiodata.chanels[i + 1] * radius, 0, 2 * M_PI);
+ }
cairo_fill(cr);
gtk_widget_queue_draw(area);
@@ -82,14 +99,13 @@ static void draw(cairo_t *cr, GtkWidget *area)
static void draw_cb(GtkDrawingArea *drawing_area, cairo_t *cr, int width, int height, gpointer data)
{
cairo_paint(cr);
- draw(cr, (GtkWidget*)data);
+ draw(cr, (GtkWidget *)data);
}
-static void refresh(GtkWidget* grid)
+static void refresh(GtkWidget *grid)
{
Pa_Terminate();
Pa_Initialize();
- GtkWidget *button;
int numDevices = Pa_GetDeviceCount();
if (numDevices < 0) {
@@ -100,19 +116,21 @@ static void refresh(GtkWidget* grid)
exit(EXIT_SUCCESS);
}
+ GtkWidget *button;
+
for (int i = 0; i < numDevices; i++) {
const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(i);
- struct data *d = (struct data*)malloc(sizeof(struct data));
- d->device_num = i;
+ SelectedDevice *sel_dev = (SelectedDevice *)malloc(sizeof(SelectedDevice));
+ sel_dev->device_num = i;
button = gtk_button_new_with_label(deviceInfo->name);
- g_signal_connect(button, "clicked", G_CALLBACK(select_device), d);
+ g_signal_connect(button, "clicked", G_CALLBACK(select_device), sel_dev);
gtk_grid_attach(GTK_GRID(grid), button, 0, numDevices - i - 1, 1, 1);
}
gtk_widget_queue_draw(grid);
}
-static void close_window(GtkWindow* window)
+static void close_window(GtkWindow *window)
{
if (stream != NULL) {
Pa_StopStream(stream);
@@ -141,7 +159,7 @@ static void activate(GtkApplication *app, gpointer user_data)
// init drawing_area
drawing_area = gtk_drawing_area_new();
- gtk_widget_set_size_request(drawing_area, 1050, 500);
+ gtk_widget_set_size_request(drawing_area, 900, 900);
gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(drawing_area), draw_cb, drawing_area, NULL);
gtk_grid_attach(GTK_GRID(grid), drawing_area, 1, 2, 100, 100);