summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorTim Mayberry <mojofunk@gmail.com>2015-11-02 15:22:43 +1000
committerTim Mayberry <mojofunk@gmail.com>2015-11-19 10:23:26 +1000
commitac301b998a66ef081e5f164f3ee49df900a498f8 (patch)
tree20de1a41da0b70126d95ae8d4f09c6d4b6c07fc3 /libs
parentf1b336b01e28f499dcd73a1fd65236efe118eb7d (diff)
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.
Diffstat (limited to 'libs')
-rw-r--r--libs/backends/portaudio/portaudio_io.cc62
-rw-r--r--libs/backends/portaudio/portaudio_io.h4
2 files changed, 51 insertions, 15 deletions
diff --git a/libs/backends/portaudio/portaudio_io.cc b/libs/backends/portaudio/portaudio_io.cc
index f3276cc7ea..22314f84cd 100644
--- a/libs/backends/portaudio/portaudio_io.cc
+++ b/libs/backends/portaudio/portaudio_io.cc
@@ -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;
}
}
diff --git a/libs/backends/portaudio/portaudio_io.h b/libs/backends/portaudio/portaudio_io.h
index e08490d0b5..c67fdc1b19 100644
--- a/libs/backends/portaudio/portaudio_io.h
+++ b/libs/backends/portaudio/portaudio_io.h
@@ -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;