Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pcm_capabilities.hpp
Go to the documentation of this file.
1#pragma once
2
9
10#include <algorithm>
11#include <array>
12#include <cstdint>
13#include <iterator>
14#include <optional>
15#include <vector>
16
17namespace pulp::audio {
18
21 unsigned rate_min = 0;
22 unsigned rate_max = 0;
25 std::vector<unsigned> accepted_rates;
26 bool rates_tested = false;
27
28 unsigned channels_min = 0;
29 unsigned channels_max = 0;
30
32 unsigned long period_min = 0;
33 unsigned long period_max = 0;
35 unsigned long buffer_max = 0;
36};
37
39inline const std::array<unsigned, 13>& standard_sample_rates() {
40 static const std::array<unsigned, 13> rates{8000, 11025, 16000, 22050, 32000, 44100, 48000,
41 88200, 96000, 176400, 192000, 352800, 384000};
42 return rates;
43}
44
49inline std::vector<double> sample_rates_from(const PcmCapabilities& caps) {
50 std::vector<double> out;
51 if (caps.rate_min == 0 || caps.rate_max < caps.rate_min)
52 return out;
53 auto in_range = [&](unsigned r) { return r >= caps.rate_min && r <= caps.rate_max; };
54
55 std::vector<unsigned> picked;
56 if (caps.rates_tested) {
57 for (unsigned r : caps.accepted_rates) {
58 if (in_range(r))
59 picked.push_back(r);
60 }
61 } else {
62 for (unsigned r : standard_sample_rates()) {
63 if (in_range(r))
64 picked.push_back(r);
65 }
66 }
67 if (picked.empty() && caps.rate_min == caps.rate_max)
68 picked.push_back(caps.rate_min);
69
70 std::sort(picked.begin(), picked.end());
71 picked.erase(std::unique(picked.begin(), picked.end()), picked.end());
72 out.reserve(picked.size());
73 for (unsigned r : picked)
74 out.push_back(static_cast<double>(r));
75 return out;
76}
77
81inline std::vector<int> buffer_sizes_from(const PcmCapabilities& caps,
82 unsigned periods_per_buffer = 2) {
83 std::vector<int> out;
84 if (caps.period_min == 0 || caps.period_max < caps.period_min)
85 return out;
86 if (periods_per_buffer == 0)
87 periods_per_buffer = 1;
88 auto fits = [&](unsigned long p) {
89 if (p < caps.period_min || p > caps.period_max)
90 return false;
91 if (p > 0x7FFFFFFFul)
92 return false;
93 return caps.buffer_max == 0 || p * periods_per_buffer <= caps.buffer_max;
94 };
95 for (unsigned long p = 16; p <= 16384; p *= 2) {
96 if (fits(p))
97 out.push_back(static_cast<int>(p));
98 }
99 if (out.empty() && fits(caps.period_min))
100 out.push_back(static_cast<int>(caps.period_min));
101 return out;
102}
103
104namespace detail {
105template <typename T>
106std::vector<T> intersect_sorted(const std::vector<T>& a, const std::vector<T>& b) {
107 std::vector<T> out;
108 std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(out));
109 return out;
110}
111} // namespace detail
112
115 std::vector<double> sample_rates;
116 std::vector<int> buffer_sizes;
119};
120
126inline PcmDeviceSummary summarize_pcm_capabilities(const std::optional<PcmCapabilities>& playback,
127 const std::optional<PcmCapabilities>& capture) {
128 auto usable = [](const std::optional<PcmCapabilities>& c) {
129 return c && c->channels_max > 0 && c->channels_min <= c->channels_max;
130 };
131 const bool has_play = usable(playback);
132 const bool has_cap = usable(capture);
133
135 if (!has_play && !has_cap) {
136 out.max_output_channels = 2;
137 out.max_input_channels = 2;
138 out.sample_rates = {44100, 48000, 88200, 96000};
139 out.buffer_sizes = {64, 128, 256, 512, 1024, 2048, 4096};
140 return out;
141 }
142
143 out.max_output_channels = has_play ? static_cast<int>(playback->channels_max) : 0;
144 out.max_input_channels = has_cap ? static_cast<int>(capture->channels_max) : 0;
145
146 if (has_play && has_cap) {
147 out.sample_rates =
149 out.buffer_sizes =
151 } else {
152 const auto& only = has_play ? *playback : *capture;
155 }
156 return out;
157}
158
159} // namespace pulp::audio
std::vector< T > intersect_sorted(const std::vector< T > &a, const std::vector< T > &b)
Definition pcm_capabilities.hpp:106
Definition analyzer_provider.hpp:12
std::vector< int > buffer_sizes_from(const PcmCapabilities &caps, unsigned periods_per_buffer=2)
Callback buffer sizes (frames), ascending: the powers of two inside the driver's period range such th...
Definition pcm_capabilities.hpp:81
std::vector< double > sample_rates_from(const PcmCapabilities &caps)
Sample rates the device supports, ascending.
Definition pcm_capabilities.hpp:49
PcmDeviceSummary summarize_pcm_capabilities(const std::optional< PcmCapabilities > &playback, const std::optional< PcmCapabilities > &capture)
Summarise the probed directions.
Definition pcm_capabilities.hpp:126
const std::array< unsigned, 13 > & standard_sample_rates()
Rates worth offering when a driver reports a continuous range.
Definition pcm_capabilities.hpp:39
Definition audio_renderer.hpp:20
What one direction (playback or capture) of a device can do.
Definition pcm_capabilities.hpp:20
unsigned channels_min
Definition pcm_capabilities.hpp:28
std::vector< unsigned > accepted_rates
Rates the driver confirmed one by one.
Definition pcm_capabilities.hpp:25
unsigned rate_max
Definition pcm_capabilities.hpp:22
unsigned long period_max
Definition pcm_capabilities.hpp:33
unsigned long period_min
Frames per callback the driver will accept.
Definition pcm_capabilities.hpp:32
unsigned long buffer_max
Largest total buffer in frames; 0 when the driver gives no bound.
Definition pcm_capabilities.hpp:35
unsigned rate_min
Definition pcm_capabilities.hpp:21
bool rates_tested
Definition pcm_capabilities.hpp:26
unsigned channels_max
Definition pcm_capabilities.hpp:29
The lists and channel counts a DeviceInfo carries for one device.
Definition pcm_capabilities.hpp:114
std::vector< double > sample_rates
Definition pcm_capabilities.hpp:115
std::vector< int > buffer_sizes
Definition pcm_capabilities.hpp:116
int max_input_channels
Definition pcm_capabilities.hpp:117
int max_output_channels
Definition pcm_capabilities.hpp:118