18
18
namespace rack {
19
19
20
20
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 ;
32
92
};
33
93
34
94
35
95
struct RtAudioDevice : audio::Device {
36
- RtAudio::Api api ;
96
+ RtAudioDriver* driver ;
37
97
int deviceId;
38
98
RtAudio* rtAudio;
39
99
RtAudio::DeviceInfo deviceInfo;
@@ -43,13 +103,13 @@ struct RtAudioDevice : audio::Device {
43
103
int blockSize = 0 ;
44
104
float sampleRate = 0 ;
45
105
46
- RtAudioDevice (RtAudio::Api api , int deviceId) {
47
- this ->api = api ;
106
+ RtAudioDevice (RtAudioDriver* driver , int deviceId) {
107
+ this ->driver = driver ;
48
108
this ->deviceId = deviceId;
49
109
50
110
// 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) {
53
113
WARN (" RtAudio error %d: %s" , type, errorText.c_str ());
54
114
});
55
115
@@ -59,7 +119,7 @@ struct RtAudioDevice : audio::Device {
59
119
// Query device ID
60
120
deviceInfo = rtAudio->getDeviceInfo (deviceId);
61
121
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);
63
123
64
124
openStream ();
65
125
}
@@ -78,7 +138,7 @@ struct RtAudioDevice : audio::Device {
78
138
void openStream () {
79
139
// Open new device
80
140
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);
82
142
}
83
143
84
144
inputParameters = RtAudio::StreamParameters ();
@@ -109,25 +169,25 @@ struct RtAudioDevice : audio::Device {
109
169
110
170
if (blockSize <= 0 ) {
111
171
// DirectSound should use a higher default block size
112
- if (api == RtAudio::WINDOWS_DS)
172
+ if (driver-> api == RtAudio::WINDOWS_DS)
113
173
blockSize = 1024 ;
114
174
else
115
175
blockSize = 256 ;
116
176
}
117
177
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);
119
179
if (rtAudio->openStream (
120
180
outputParameters.nChannels > 0 ? &outputParameters : NULL ,
121
181
inputParameters.nChannels > 0 ? &inputParameters : NULL ,
122
182
RTAUDIO_FLOAT32, closestSampleRate, (unsigned int *) &blockSize,
123
183
&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);
125
185
}
126
186
127
187
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);
129
189
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);
131
191
}
132
192
133
193
// Update sample rate to actual value
@@ -143,11 +203,11 @@ struct RtAudioDevice : audio::Device {
143
203
144
204
void closeStream () {
145
205
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);
147
207
rtAudio->stopStream ();
148
208
}
149
209
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);
151
211
rtAudio->closeStream ();
152
212
}
153
213
@@ -220,126 +280,72 @@ struct RtAudioDevice : audio::Device {
220
280
};
221
281
222
282
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" );
231
290
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;
238
294
}
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 ;
258
297
}
259
298
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
+ }
277
302
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
- }
286
303
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);
302
310
303
- device->subscribe (port);
304
- return device;
311
+ if (device->subscribed .empty ()) {
312
+ devices.erase (it);
313
+ delete device;
305
314
}
315
+ }
306
316
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);
313
317
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" },
319
334
};
320
335
321
336
322
337
void rtaudioInit () {
338
+ // Get RtAudio's driver list
323
339
std::vector<RtAudio::Api> apis;
324
340
RtAudio::getCompiledApi (apis);
325
341
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);
343
349
}
344
350
}
345
351
0 commit comments