13
0
livetrax/libs/backends/portaudio/portaudio_io.h
Tim Mayberry ac301b998a 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.
2015-11-19 10:23:26 +10:00

174 lines
5.5 KiB
C++

/*
* Copyright (C) 2015 Robin Gareus <robin@gareus.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __libbackend_portaudio_pcmio_h__
#define __libbackend_portaudio_pcmio_h__
#include <map>
#include <vector>
#include <string>
#include <boost/shared_ptr.hpp>
#include <stdint.h>
#include <portaudio.h>
namespace ARDOUR {
class PortAudioIO {
public:
PortAudioIO (void);
~PortAudioIO (void);
enum StandardDevices {
DeviceNone = -2,
DeviceDefault = -1
};
void host_api_list (std::vector<std::string>&);
bool set_host_api (const std::string& host_api_name);
std::string get_host_api () const { return _host_api_name; }
PaHostApiTypeId get_current_host_api_type () const;
PaHostApiIndex get_host_api_index_from_name (const std::string& name);
PaDeviceIndex get_default_input_device () const;
PaDeviceIndex get_default_output_device () const;
bool update_devices();
void input_device_list (std::map<int, std::string> &devices) const;
void output_device_list (std::map<int, std::string> &devices) const;
int available_sample_rates (int device_id, std::vector<float>& sample_rates);
int available_buffer_sizes (int device_id, std::vector<uint32_t>& buffer_sizes);
#ifdef WITH_ASIO
bool get_asio_buffer_properties (int device_id,
long& min_size_frames,
long& max_size_frames,
long& preferred_size_frames,
long& granularity);
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;
void launch_control_app (int device_id);
PaErrorCode open_blocking_stream(int device_input,
int device_output,
double sample_rate,
uint32_t samples_per_period);
PaErrorCode open_callback_stream(int device_input,
int device_output,
double sample_rate,
uint32_t samples_per_period,
PaStreamCallback* callback,
void* data);
PaErrorCode start_stream(void);
PaErrorCode close_stream(void);
uint32_t n_playback_channels (void) const { return _playback_channels; }
uint32_t n_capture_channels (void) const { return _capture_channels; }
std::string get_input_channel_name (int device_id, uint32_t channel) const;
std::string get_output_channel_name (int device_id, uint32_t channel) const;
double sample_rate (void) const { return _cur_sample_rate; }
uint32_t capture_latency (void) const { return _cur_input_latency; }
uint32_t playback_latency (void) const { return _cur_output_latency; }
double stream_time(void) const { if (_stream) return Pa_GetStreamTime (_stream); return 0; }
int next_cycle(uint32_t n_samples);
int get_capture_channel (uint32_t chn, float *input, uint32_t n_samples);
int set_playback_channel (uint32_t chn, const float *input, uint32_t n_samples);
float* get_capture_buffer () { return _input_buffer; }
float* get_playback_buffer () { return _output_buffer; }
private: // Methods
static bool pa_initialize();
static bool pa_deinitialize();
static bool& pa_initialized();
void clear_device_lists ();
void add_none_devices ();
void add_default_devices ();
void add_devices ();
std::string get_host_api_name_from_index (PaHostApiIndex index);
bool get_output_stream_params(int device_output,
PaStreamParameters& outputParam) const;
bool get_input_stream_params(int device_input,
PaStreamParameters& inputParam) const;
bool set_sample_rate_and_latency_from_stream();
bool allocate_buffers_for_blocking_api (uint32_t samples_per_period);
PaErrorCode pre_stream_open(int device_input,
PaStreamParameters& inputParam,
int device_output,
PaStreamParameters& outputParam);
void reset_stream_dependents ();
static void get_default_sample_rates(std::vector<float>&);
static void get_default_buffer_sizes(std::vector<uint32_t>&);
private: // Data
uint32_t _capture_channels;
uint32_t _playback_channels;
PaStream *_stream;
float *_input_buffer;
float *_output_buffer;
double _cur_sample_rate;
uint32_t _cur_input_latency;
uint32_t _cur_output_latency;
struct paDevice {
std::string name;
uint32_t n_inputs;
uint32_t n_outputs;
paDevice (std::string n, uint32_t i, uint32_t o)
: name (n)
, n_inputs (i)
, n_outputs (o)
{}
};
std::map<int, paDevice *> _input_devices;
std::map<int, paDevice *> _output_devices;
PaHostApiIndex _host_api_index;
std::string _host_api_name;
};
} // namespace
#endif /* __libbackend_portaudio_pcmio_h__ */