diff options
| author | Aleksa Vuckovic <aleksa@vuckovic.cc> | 2023-11-18 11:32:43 +0100 |
|---|---|---|
| committer | Aleksa Vuckovic <aleksa@vuckovic.cc> | 2023-11-18 11:32:43 +0100 |
| commit | 45d8de6c22a51efe7e76e71424693c18b93e83e3 (patch) | |
| tree | d21e1e8cfc8c8c06d2de3cd92bfbe92dad9678d5 | |
| parent | 68a4257f117fd55287e589a62168cb9d35a362d9 (diff) | |
Support multiple channels
| -rw-r--r-- | src/main.c | 86 |
1 files changed, 52 insertions, 34 deletions
@@ -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); |
