Skip to content

Commit

Permalink
miniaudio: Support for selecting input device
Browse files Browse the repository at this point in the history
  • Loading branch information
ideoforms committed Oct 22, 2024
1 parent 5474da3 commit f10d489
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 9 deletions.
4 changes: 3 additions & 1 deletion source/include/signalflow/node/io/output/miniaudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ class AudioOut : public AudioOut_Abstract
static std::list<std::string> get_input_device_names(std::string backend_name = "");
static std::list<std::string> get_backend_names();

private:
/*--------------------------------------------------------------------------------
* Initialise a new miniaudio context, using the specified backend name if
* present, or the default backend otherwise.
*
* Public because AudioIn also uses this method.
*-------------------------------------------------------------------------------*/
static void init_context(ma_context *context, std::string backend_name = "");

private:
std::string backend_name;
std::string device_name;
ma_context context;
Expand Down
43 changes: 42 additions & 1 deletion source/src/node/io/input/miniaudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,55 @@ AudioIn::~AudioIn()

void AudioIn::init()
{
ma_result rv;
ma_device_config config = ma_device_config_init(ma_device_type_capture);
config.capture.format = ma_format_f32;
config.capture.channels = this->num_channels;
config.periodSizeInFrames = this->get_graph()->get_output_buffer_size();
config.sampleRate = this->get_graph()->get_sample_rate();
config.dataCallback = read_callback;

ma_result rv = ma_device_init(NULL, &config, &device);
ma_device_info *capture_devices;
ma_uint32 capture_device_count;

// TODO: Add get_input_backend_name
AudioOut::init_context(&this->context, this->get_graph()->get_config().get_output_backend_name());

rv = ma_context_get_devices(&this->context,
NULL,
NULL,
&capture_devices,
&capture_device_count);
int selected_device_index = -1;
std::string device_name = this->get_graph()->get_config().get_input_device_name();

if (!device_name.empty())
{
for (unsigned int i = 0; i < capture_device_count; i++)
{
/*-----------------------------------------------------------------------*
* For ease of use, SignalFlow allows for partial matches so that only
* the first part of the device names needs to be specified. However,
* an errors is thrown if the match is ambiguous.
*-----------------------------------------------------------------------*/
if (strncmp(capture_devices[i].name, device_name.c_str(), strlen(device_name.c_str())) == 0)
{
if (selected_device_index != -1)
{
throw audio_io_exception("More than one audio device found matching name '" + device_name + "'");
}
selected_device_index = i;
}
}
if (selected_device_index == -1)
{
throw audio_io_exception("No audio device found matching name '" + device_name + "'");
}

config.capture.pDeviceID = &capture_devices[selected_device_index].id;
}

rv = ma_device_init(NULL, &config, &device);
if (rv != MA_SUCCESS)
{
throw audio_io_exception("miniaudio: Error initialising input device");
Expand Down
14 changes: 7 additions & 7 deletions source/src/node/io/output/miniaudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,22 +98,25 @@ void AudioOut::init()

ma_device_info *playback_devices;
ma_uint32 playback_device_count;
ma_device_info *capture_devices;
ma_uint32 capture_device_count;
ma_result rv;

AudioOut::init_context(&this->context, this->backend_name);

rv = ma_context_get_devices(&this->context,
&playback_devices,
&playback_device_count,
&capture_devices,
&capture_device_count);
NULL,
NULL);
int selected_device_index = -1;
if (!this->device_name.empty())
{
for (unsigned int i = 0; i < playback_device_count; i++)
{
/*-----------------------------------------------------------------------*
* For ease of use, SignalFlow allows for partial matches so that only
* the first part of the device names needs to be specified. However,
* an errors is thrown if the match is ambiguous.
*-----------------------------------------------------------------------*/
if (strncmp(playback_devices[i].name, device_name.c_str(), strlen(device_name.c_str())) == 0)
{
if (selected_device_index != -1)
Expand Down Expand Up @@ -145,9 +148,6 @@ void AudioOut::init()
config.sampleRate = this->sample_rate;
config.dataCallback = data_callback;

// Buffer blocks into a fixed number of frames
config.noFixedSizedCallback = 1;

// On Core Audio, let the application select a preferred sample rate.
config.coreaudio.allowNominalSampleRateChange = 1;

Expand Down

0 comments on commit f10d489

Please sign in to comment.