From c49a2164155882f27d3310c77b37a44ae1107d6e Mon Sep 17 00:00:00 2001 From: Ramesh Date: Mon, 29 Nov 2021 00:03:38 -0500 Subject: [PATCH] portaudio realtime playback works --- libbluos_ssc_ipc.c | 2 - meson.build | 3 +- samples/sndfile_portaudio.c | 110 +++++++++++++++++++++++++----------- 3 files changed, 78 insertions(+), 37 deletions(-) diff --git a/libbluos_ssc_ipc.c b/libbluos_ssc_ipc.c index ba79cb9..a9ae5f5 100755 --- a/libbluos_ssc_ipc.c +++ b/libbluos_ssc_ipc.c @@ -80,8 +80,6 @@ ipc_mqa_struct *bluos_ssc_ipc_init(SF_INFO in_file_info, // We block until the decoder has put the initial details required into the // shared_mqa_struct, and then return the handle. while (shared_mqa_struct->turn != AMDREAD) { - printf("turn value %d\n", shared_mqa_struct->turn); - printf("frame value %d\n", shared_mqa_struct->get_samples_var.frame_size); } // TODO fork mqaplay_ipc here using a config file diff --git a/meson.build b/meson.build index c981ddf..7eed6e0 100644 --- a/meson.build +++ b/meson.build @@ -2,6 +2,7 @@ project('libbluos_ssc_ipc', 'c') sndfile = dependency('sndfile') gmp = dependency('gmp') +portaudio = dependency('portaudio-2.0') bits = static_library('bits', 'mqa-files/bits.c') mqa_common = static_library('mqa-common', 'mqa-files/mqa-common.c') @@ -12,4 +13,4 @@ mqascan = static_library('mqascan', 'mqa-files/mqascan.c', dependencies: bluos_ssc_ipc = library('bluos_ssc_ipc', 'libbluos_ssc_ipc.c', dependencies: sndfile, link_with: mqascan) -executable('sndfile_portaudio', 'samples/sndfile_portaudio.c', dependencies: sndfile, link_with: bluos_ssc_ipc ) +executable('sndfile_portaudio', 'samples/sndfile_portaudio.c', dependencies: [sndfile, portaudio], link_with: bluos_ssc_ipc ) diff --git a/samples/sndfile_portaudio.c b/samples/sndfile_portaudio.c index bc82e84..474be63 100644 --- a/samples/sndfile_portaudio.c +++ b/samples/sndfile_portaudio.c @@ -1,19 +1,27 @@ #include "../libbluos_ssc_ipc.h" #include "ipc_structs.h" #include "mqa-files/mqascan.h" +#include +#include #include #include -int main(int argc, char **argv) { - // lol help +// code partially stolen from +// https://github.com/hosackm/wavplayer/blob/master/src/wavplay.c + +static int portaudio_callback(const void *input, void *output, + ulong frame_count, + const PaStreamCallbackTimeInfo *time_info, + PaStreamCallbackFlags status_flags, + void *user_data); +static ipc_mqa_struct *handle; +static SNDFILE *in_file; - ipc_mqa_struct *handle; +int main(int argc, char **argv) { mqa_sample_rates rates; int num_folds; - SNDFILE *in_file; - SNDFILE *out_file; SF_INFO in_file_info; - SF_INFO out_file_info; + PaStream *stream; memset(&in_file_info, 0, sizeof(in_file_info)); in_file = sf_open(argv[1], SFM_READ, &in_file_info); @@ -26,39 +34,73 @@ int main(int argc, char **argv) { num_folds = (rates.original_rate / rates.compressed_rate) / 2; printf("initialising decoder with %d folds\n", num_folds); - // Set up outfile - out_file_info.samplerate = rates.original_rate; // infmt.samplerate << rs; - out_file_info.channels = in_file_info.channels; - out_file_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24; - out_file = sf_open(argv[2], SFM_WRITE, &out_file_info); - if (!out_file) { - // printf("sf_open (out) failed!\n"); + // TODO convert rates into number of folds + handle = bluos_ssc_ipc_init(in_file_info, num_folds); + + // PASTART + int error = Pa_Initialize(); + if (error != paNoError) { + printf("Pa_Initialise failed!\n"); + return 1; + } + error = Pa_OpenDefaultStream( + &stream, 0, in_file_info.channels, paInt32, rates.original_rate, + BUF_SIZE * handle->number_of_folds, portaudio_callback, NULL); + if (error != paNoError) { + printf("Pa_OpenDefaultStream failed!\n"); return 1; } - // TODO convert rates into number of folds - handle = bluos_ssc_ipc_init(in_file_info, num_folds); + error = Pa_StartStream(stream); + if (error != paNoError) { + printf("Pa_StartStream failed!\n"); + return 1; + } + + while (Pa_IsStreamActive(stream)) { + Pa_Sleep(100); + } + + sf_close(in_file); + + error = Pa_Terminate(); + if (error != paNoError) { + printf("Pa_Terminate failed!\n"); + return 1; + } + // PAEND + return 0; +} + +static int portaudio_callback(const void *input, void *output, + ulong frame_count, + const PaStreamCallbackTimeInfo *time_info, + PaStreamCallbackFlags status_flags, + void *user_data) { - out_file_info.samplerate = rates.original_rate; // infmt.samplerate << rs; - out_file_info.channels = in_file_info.channels; - out_file_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24; + int *out = (int *)output; - while (handle->turn != FINISHED) { - switch (handle->turn) { - case AMDREAD: - // read; - bluos_ssc_sndfile_read_samples_shm(handle, in_file); - goto handoff_point; - case AMDWRITE: - // write - sf_writef_int(out_file, handle->output_buffer, - handle->write_samples_var.len * num_folds); - goto handoff_point; - handoff_point: - bluos_ssc_ipc_handoff(handle); - break; - default: - continue; + if (handle->turn != FINISHED) { + while (true) { + switch (handle->turn) { + case AMDREAD: + // read; + bluos_ssc_sndfile_read_samples_shm(handle, in_file); + bluos_ssc_ipc_handoff(handle); + break; + case AMDWRITE: + // write + memcpy(out, handle->output_buffer, + sizeof(int) * handle->write_samples_var.len * + handle->audio_info.channels * handle->number_of_folds); + bluos_ssc_ipc_handoff(handle); + // we're done with this execution of the function + return paContinue; + default: + continue; + } } + } else { + return paComplete; } }