Skip to content

Commit 16dbaff

Browse files
committed
Refactor RtAudioDriver/Device. Hardcode old RtAudio driverIds to be compatible with Rack <2.6.1 patches.
1 parent 454033d commit 16dbaff

File tree

1 file changed

+134
-128
lines changed

1 file changed

+134
-128
lines changed

src/rtaudio.cpp

Lines changed: 134 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,82 @@
1818
namespace rack {
1919

2020

21-
static const std::map<RtAudio::Api, std::string> RTAUDIO_API_NAMES = {
22-
{RtAudio::LINUX_ALSA, "ALSA"},
23-
{RtAudio::UNIX_JACK, "JACK"},
24-
{RtAudio::LINUX_PULSE, "PulseAudio"},
25-
{RtAudio::LINUX_OSS, "OSS"},
26-
{RtAudio::WINDOWS_WASAPI, "WASAPI"},
27-
{RtAudio::WINDOWS_ASIO, "ASIO"},
28-
{RtAudio::WINDOWS_DS, "DirectSound"},
29-
{RtAudio::MACOSX_CORE, "Core Audio"},
30-
{RtAudio::RTAUDIO_DUMMY, "Dummy"},
31-
{RtAudio::UNSPECIFIED, "Unspecified"},
21+
struct RtAudioDevice;
22+
23+
24+
struct RtAudioDriver : audio::Driver {
25+
RtAudio::Api api;
26+
std::string name;
27+
RtAudio* rtAudio = NULL;
28+
// deviceId -> Device
29+
std::map<int, RtAudioDevice*> devices;
30+
31+
RtAudioDriver(RtAudio::Api api, std::string name) {
32+
this->api = api;
33+
this->name = name;
34+
35+
INFO("Creating RtAudio %s driver", name.c_str());
36+
rtAudio = new RtAudio(api, [](RtAudioErrorType type, const std::string& errorText) {
37+
WARN("RtAudio error %d: %s", type, errorText.c_str());
38+
});
39+
40+
rtAudio->showWarnings(false);
41+
}
42+
43+
~RtAudioDriver() {
44+
assert(devices.empty());
45+
if (rtAudio)
46+
delete rtAudio;
47+
}
48+
49+
std::string getName() override {
50+
return name;
51+
}
52+
53+
std::vector<int> getDeviceIds() override {
54+
std::vector<int> deviceIds;
55+
if (rtAudio) {
56+
for (unsigned int id : rtAudio->getDeviceIds()) {
57+
deviceIds.push_back(id);
58+
}
59+
}
60+
return deviceIds;
61+
}
62+
63+
std::string getDeviceName(int deviceId) override {
64+
if (rtAudio) {
65+
RtAudio::DeviceInfo deviceInfo = rtAudio->getDeviceInfo(deviceId);
66+
if (deviceInfo.ID > 0)
67+
return deviceInfo.name;
68+
}
69+
return "";
70+
}
71+
72+
int getDeviceNumInputs(int deviceId) override {
73+
if (rtAudio) {
74+
RtAudio::DeviceInfo deviceInfo = rtAudio->getDeviceInfo(deviceId);
75+
if (deviceInfo.ID > 0)
76+
return deviceInfo.inputChannels;
77+
}
78+
return 0;
79+
}
80+
81+
int getDeviceNumOutputs(int deviceId) override {
82+
if (rtAudio) {
83+
RtAudio::DeviceInfo deviceInfo = rtAudio->getDeviceInfo(deviceId);
84+
if (deviceInfo.ID > 0)
85+
return deviceInfo.outputChannels;
86+
}
87+
return 0;
88+
}
89+
90+
audio::Device* subscribe(int deviceId, audio::Port* port) override;
91+
void unsubscribe(int deviceId, audio::Port* port) override;
3292
};
3393

3494

3595
struct RtAudioDevice : audio::Device {
36-
RtAudio::Api api;
96+
RtAudioDriver* driver;
3797
int deviceId;
3898
RtAudio* rtAudio;
3999
RtAudio::DeviceInfo deviceInfo;
@@ -43,13 +103,13 @@ struct RtAudioDevice : audio::Device {
43103
int blockSize = 0;
44104
float sampleRate = 0;
45105

46-
RtAudioDevice(RtAudio::Api api, int deviceId) {
47-
this->api = api;
106+
RtAudioDevice(RtAudioDriver* driver, int deviceId) {
107+
this->driver = driver;
48108
this->deviceId = deviceId;
49109

50110
// Create RtAudio object
51-
INFO("Creating RtAudio %s device", RTAUDIO_API_NAMES.at(api).c_str());
52-
rtAudio = new RtAudio(api, [](RtAudioErrorType type, const std::string& errorText) {
111+
INFO("Creating RtAudio %s device", driver->getName().c_str());
112+
rtAudio = new RtAudio(driver->api, [](RtAudioErrorType type, const std::string& errorText) {
53113
WARN("RtAudio error %d: %s", type, errorText.c_str());
54114
});
55115

@@ -59,7 +119,7 @@ struct RtAudioDevice : audio::Device {
59119
// Query device ID
60120
deviceInfo = rtAudio->getDeviceInfo(deviceId);
61121
if (deviceInfo.ID == 0)
62-
throw Exception("Failed to query RtAudio %s device %d", RTAUDIO_API_NAMES.at(api).c_str(), deviceId);
122+
throw Exception("Failed to query RtAudio %s device %d", driver->getName().c_str(), deviceId);
63123

64124
openStream();
65125
}
@@ -78,7 +138,7 @@ struct RtAudioDevice : audio::Device {
78138
void openStream() {
79139
// Open new device
80140
if (deviceInfo.outputChannels == 0 && deviceInfo.inputChannels == 0) {
81-
throw Exception("RtAudio %s device %d has 0 inputs and 0 outputs", RTAUDIO_API_NAMES.at(api).c_str(), deviceId);
141+
throw Exception("RtAudio %s device %d has 0 inputs and 0 outputs", driver->getName().c_str(), deviceId);
82142
}
83143

84144
inputParameters = RtAudio::StreamParameters();
@@ -109,25 +169,25 @@ struct RtAudioDevice : audio::Device {
109169

110170
if (blockSize <= 0) {
111171
// DirectSound should use a higher default block size
112-
if (api == RtAudio::WINDOWS_DS)
172+
if (driver->api == RtAudio::WINDOWS_DS)
113173
blockSize = 1024;
114174
else
115175
blockSize = 256;
116176
}
117177

118-
INFO("Opening RtAudio %s device %d: %s (%d in, %d out, %d sample rate, %d block size)", RTAUDIO_API_NAMES.at(api).c_str(), deviceId, deviceInfo.name.c_str(), inputParameters.nChannels, outputParameters.nChannels, closestSampleRate, blockSize);
178+
INFO("Opening RtAudio %s device %d: %s (%d in, %d out, %d sample rate, %d block size)", driver->getName().c_str(), deviceId, deviceInfo.name.c_str(), inputParameters.nChannels, outputParameters.nChannels, closestSampleRate, blockSize);
119179
if (rtAudio->openStream(
120180
outputParameters.nChannels > 0 ? &outputParameters : NULL,
121181
inputParameters.nChannels > 0 ? &inputParameters : NULL,
122182
RTAUDIO_FLOAT32, closestSampleRate, (unsigned int*) &blockSize,
123183
&rtAudioCallback, this, &options)) {
124-
throw Exception("Failed to open RtAudio %s device %d", RTAUDIO_API_NAMES.at(api).c_str(), deviceId);
184+
throw Exception("Failed to open RtAudio %s device %d", driver->getName().c_str(), deviceId);
125185
}
126186

127187
try {
128-
INFO("Starting RtAudio %s device %d", RTAUDIO_API_NAMES.at(api).c_str(), deviceId);
188+
INFO("Starting RtAudio %s device %d", driver->getName().c_str(), deviceId);
129189
if (rtAudio->startStream()) {
130-
throw Exception("Failed to start RtAudio %s device %d", RTAUDIO_API_NAMES.at(api).c_str(), deviceId);
190+
throw Exception("Failed to start RtAudio %s device %d", driver->getName().c_str(), deviceId);
131191
}
132192

133193
// Update sample rate to actual value
@@ -143,11 +203,11 @@ struct RtAudioDevice : audio::Device {
143203

144204
void closeStream() {
145205
if (rtAudio->isStreamRunning()) {
146-
INFO("Stopping RtAudio %s device %d", RTAUDIO_API_NAMES.at(api).c_str(), deviceId);
206+
INFO("Stopping RtAudio %s device %d", driver->getName().c_str(), deviceId);
147207
rtAudio->stopStream();
148208
}
149209
if (rtAudio->isStreamOpen()) {
150-
INFO("Closing RtAudio %s device %d", RTAUDIO_API_NAMES.at(api).c_str(), deviceId);
210+
INFO("Closing RtAudio %s device %d", driver->getName().c_str(), deviceId);
151211
rtAudio->closeStream();
152212
}
153213

@@ -220,126 +280,72 @@ struct RtAudioDevice : audio::Device {
220280
};
221281

222282

223-
struct RtAudioDriver : audio::Driver {
224-
RtAudio::Api api;
225-
// deviceId -> Device
226-
std::map<int, RtAudioDevice*> devices;
227-
RtAudio* rtAudio = NULL;
228-
229-
RtAudioDriver(RtAudio::Api api) {
230-
this->api = api;
283+
audio::Device* RtAudioDriver::subscribe(int deviceId, audio::Port* port) {
284+
RtAudioDevice* device;
285+
auto it = devices.find(deviceId);
286+
if (it == devices.end()) {
287+
// ASIO only allows one device to be used simultaneously
288+
if (api == RtAudio::WINDOWS_ASIO && devices.size() >= 1)
289+
throw Exception("ASIO driver only allows one audio device to be used simultaneously");
231290

232-
INFO("Creating RtAudio %s driver", RTAUDIO_API_NAMES.at(api).c_str());
233-
rtAudio = new RtAudio(api, [](RtAudioErrorType type, const std::string& errorText) {
234-
WARN("RtAudio error %d: %s", type, errorText.c_str());
235-
});
236-
237-
rtAudio->showWarnings(false);
291+
// Can throw Exception
292+
device = new RtAudioDevice(this, deviceId);
293+
devices[deviceId] = device;
238294
}
239-
240-
~RtAudioDriver() {
241-
assert(devices.empty());
242-
if (rtAudio)
243-
delete rtAudio;
244-
}
245-
246-
std::string getName() override {
247-
return RTAUDIO_API_NAMES.at(api);
248-
}
249-
250-
std::vector<int> getDeviceIds() override {
251-
std::vector<int> deviceIds;
252-
if (rtAudio) {
253-
for (unsigned int id : rtAudio->getDeviceIds()) {
254-
deviceIds.push_back(id);
255-
}
256-
}
257-
return deviceIds;
295+
else {
296+
device = it->second;
258297
}
259298

260-
std::string getDeviceName(int deviceId) override {
261-
if (rtAudio) {
262-
RtAudio::DeviceInfo deviceInfo = rtAudio->getDeviceInfo(deviceId);
263-
if (deviceInfo.ID > 0)
264-
return deviceInfo.name;
265-
}
266-
return "";
267-
}
268-
269-
int getDeviceNumInputs(int deviceId) override {
270-
if (rtAudio) {
271-
RtAudio::DeviceInfo deviceInfo = rtAudio->getDeviceInfo(deviceId);
272-
if (deviceInfo.ID > 0)
273-
return deviceInfo.inputChannels;
274-
}
275-
return 0;
276-
}
299+
device->subscribe(port);
300+
return device;
301+
}
277302

278-
int getDeviceNumOutputs(int deviceId) override {
279-
if (rtAudio) {
280-
RtAudio::DeviceInfo deviceInfo = rtAudio->getDeviceInfo(deviceId);
281-
if (deviceInfo.ID > 0)
282-
return deviceInfo.outputChannels;
283-
}
284-
return 0;
285-
}
286303

287-
audio::Device* subscribe(int deviceId, audio::Port* port) override {
288-
RtAudioDevice* device;
289-
auto it = devices.find(deviceId);
290-
if (it == devices.end()) {
291-
// ASIO only allows one device to be used simultaneously
292-
if (api == RtAudio::WINDOWS_ASIO && devices.size() >= 1)
293-
throw Exception("ASIO driver only allows one audio device to be used simultaneously");
294-
295-
// Can throw Exception
296-
device = new RtAudioDevice(api, deviceId);
297-
devices[deviceId] = device;
298-
}
299-
else {
300-
device = it->second;
301-
}
304+
void RtAudioDriver::unsubscribe(int deviceId, audio::Port* port) {
305+
auto it = devices.find(deviceId);
306+
if (it == devices.end())
307+
return;
308+
RtAudioDevice* device = it->second;
309+
device->unsubscribe(port);
302310

303-
device->subscribe(port);
304-
return device;
311+
if (device->subscribed.empty()) {
312+
devices.erase(it);
313+
delete device;
305314
}
315+
}
306316

307-
void unsubscribe(int deviceId, audio::Port* port) override {
308-
auto it = devices.find(deviceId);
309-
if (it == devices.end())
310-
return;
311-
RtAudioDevice* device = it->second;
312-
device->unsubscribe(port);
313317

314-
if (device->subscribed.empty()) {
315-
devices.erase(it);
316-
delete device;
317-
}
318-
}
318+
struct ApiInfo {
319+
// Should match indices in https://github.com/VCVRack/rtaudio/blob/ece277bd839603648c80c8a5f145678e13bc23f3/RtAudio.cpp#L107-L118
320+
int driverId;
321+
RtAudio::Api rtApi;
322+
// Used instead of RtAudio::getApiName()
323+
std::string name;
324+
};
325+
// The vector order here defines the order in the audio driver menu
326+
static const std::vector<ApiInfo> API_INFOS = {
327+
{1, RtAudio::LINUX_ALSA, "ALSA"},
328+
{2, RtAudio::LINUX_PULSE, "PulseAudio"},
329+
{4, RtAudio::UNIX_JACK, "JACK"},
330+
{5, RtAudio::MACOSX_CORE, "Core Audio"},
331+
{6, RtAudio::WINDOWS_WASAPI, "WASAPI"},
332+
{7, RtAudio::WINDOWS_ASIO, "ASIO"},
333+
{8, RtAudio::WINDOWS_DS, "DirectSound"},
319334
};
320335

321336

322337
void rtaudioInit() {
338+
// Get RtAudio's driver list
323339
std::vector<RtAudio::Api> apis;
324340
RtAudio::getCompiledApi(apis);
325341

326-
// I don't like the order returned by getCompiledApi(), so reorder it here.
327-
std::vector<RtAudio::Api> orderedApis = {
328-
RtAudio::LINUX_ALSA,
329-
RtAudio::LINUX_PULSE,
330-
RtAudio::UNIX_JACK,
331-
RtAudio::LINUX_OSS,
332-
RtAudio::WINDOWS_WASAPI,
333-
RtAudio::WINDOWS_ASIO,
334-
RtAudio::WINDOWS_DS,
335-
RtAudio::MACOSX_CORE,
336-
};
337-
for (RtAudio::Api api : orderedApis) {
338-
auto it = std::find(apis.begin(), apis.end(), api);
339-
if (it != apis.end()) {
340-
RtAudioDriver* driver = new RtAudioDriver(api);
341-
audio::addDriver((int) api, driver);
342-
}
342+
for (const ApiInfo& apiInfo : API_INFOS) {
343+
auto it = std::find(apis.begin(), apis.end(), apiInfo.rtApi);
344+
if (it == apis.end())
345+
continue;
346+
// Create and add driver
347+
RtAudioDriver* driver = new RtAudioDriver(apiInfo.rtApi, apiInfo.name);
348+
audio::addDriver(apiInfo.driverId, driver);
343349
}
344350
}
345351

0 commit comments

Comments
 (0)