Use a range of values for ASIO buffer sizes if provided by driver

This has been tested on four devices:

- A RME HDSP Multiface
- A Yamaha AG06
- A Focusrite 2i2
- A built-in soundcard running ASIO4ALL

The HDSP and the AG06 only return one buffer size when queried so the preferred
size is used as before.

The Focusrite returns a min corresponding to the position of the slider in the
control dialog and the max is 1024. The granularity is 1 so this means that the
number of values needs to be reduced for the current UI design with a combo
box so the granularity is increased until there are around 8-9 buffer sizes to
choose from evenly spaced between min and max(but we could easily change this
if the UI changes etc).

The ASIO4ALL driver returns a min of 64 and a max of 2048 and a granularity of
8. So where the minimum buffer size and granularity is a power of 2 use only
buffer sizes that are power of 2.

If the driver returns different values for min and max it is not currently
possible to indicate which is the driver preferred value. A checkbox or other
UI element could be added to the AudioSetup dialog to only use the preferred
value but that is more work and perhaps not necessary.
This commit is contained in:
Tim Mayberry 2015-11-02 15:22:43 +10:00
parent f1b336b01e
commit ac301b998a
2 changed files with 51 additions and 15 deletions

View File

@ -204,8 +204,17 @@ PortAudioIO::get_asio_buffer_properties (int device_id,
return true;
}
static
bool
PortAudioIO::get_asio_buffer_sizes (int device_id, std::vector<uint32_t>& buffer_sizes)
is_power_of_two (uint32_t v)
{
return ((v != 0) && !(v & (v - 1)));
}
bool
PortAudioIO::get_asio_buffer_sizes(int device_id,
std::vector<uint32_t>& buffer_sizes,
bool preferred_only)
{
long min_size_frames = 0;
long max_size_frames = 0;
@ -231,26 +240,51 @@ PortAudioIO::get_asio_buffer_sizes (int device_id, std::vector<uint32_t>& buffer
preferred_size_frames,
granularity));
#ifdef USE_ASIO_MIN_MAX_BUFFER_SIZES
if (min_size_frames >= max_size_frames) {
buffer_sizes.push_back (preferred_size_frames);
bool driver_returns_one_size = (min_size_frames == max_size_frames) &&
(min_size_frames == preferred_size_frames);
if (preferred_only || driver_returns_one_size) {
buffer_sizes.push_back(preferred_size_frames);
return true;
}
long buffer_size = min_size_frames;
while (buffer_size <= max_size_frames) {
buffer_sizes.push_back (buffer_size);
if (granularity <= 0) {
// buffer sizes are power of 2
buffer_size = buffer_size * 2;
} else {
// If min size and granularity are power of two then just use values that
// are power of 2 even if the granularity allows for more values
bool use_power_of_two =
is_power_of_two(min_size_frames) && is_power_of_two(granularity);
if (granularity <= 0 || use_power_of_two) {
// driver uses buffer sizes that are power of 2
while (buffer_size <= max_size_frames) {
buffer_sizes.push_back(buffer_size);
buffer_size *= 2;
}
} else {
if (min_size_frames == max_size_frames) {
// The devices I have tested either return the same values for
// min/max/preferred and changing buffer size is intended to only be
// done via the control dialog or they return a range where min != max
// but I guess min == max could happen if a driver only supports a single
// buffer size
buffer_sizes.push_back(min_size_frames);
return true;
}
// If min_size_frames is not power of 2 use at most 8 of the possible
// buffer sizes spread evenly between min and max
long max_values = 8;
while (((max_size_frames - min_size_frames) / granularity) > max_values) {
granularity *= 2;
}
while (buffer_size < max_size_frames) {
buffer_sizes.push_back(buffer_size);
buffer_size += granularity;
}
buffer_sizes.push_back(max_size_frames);
}
#else
buffer_sizes.push_back (preferred_size_frames);
#endif
return true;
}
#endif
@ -272,7 +306,7 @@ PortAudioIO::available_buffer_sizes(int device_id, std::vector<uint32_t>& buffer
{
#ifdef WITH_ASIO
if (get_current_host_api_type() == paASIO) {
if (get_asio_buffer_sizes (device_id, buffer_sizes)) {
if (get_asio_buffer_sizes (device_id, buffer_sizes, false)) {
return 0;
}
}

View File

@ -63,7 +63,9 @@ public:
long& preferred_size_frames,
long& granularity);
bool get_asio_buffer_sizes (int device_id, std::vector<uint32_t>& buffer_size);
bool get_asio_buffer_sizes(int device_id,
std::vector<uint32_t>& buffer_size,
bool preferred_only);
#endif
std::string control_app_name (int device_id) const;