|
- #include "util.hpp"
- #include "math.hpp"
- #include "audio.hpp"
-
-
- #define DRIVER_BRIDGE -1
-
-
- namespace rack {
-
-
- AudioIO::AudioIO() {
- setDriver(RtAudio::UNSPECIFIED);
- }
-
- AudioIO::~AudioIO() {
- closeStream();
- }
-
- std::vector<int> AudioIO::listDrivers() {
- std::vector<RtAudio::Api> apis;
- RtAudio::getCompiledApi(apis);
- std::vector<int> drivers;
- for (RtAudio::Api api : apis)
- drivers.push_back((int) api);
- // Add Bridge fake driver
- // drivers.push_back(DRIVER_BRIDGE);
- return drivers;
- }
-
- std::string AudioIO::getDriverName(int driver) {
- switch (driver) {
- case RtAudio::UNSPECIFIED: return "Unspecified";
- case RtAudio::LINUX_ALSA: return "ALSA";
- case RtAudio::LINUX_PULSE: return "PulseAudio";
- case RtAudio::LINUX_OSS: return "OSS";
- case RtAudio::UNIX_JACK: return "JACK";
- case RtAudio::MACOSX_CORE: return "Core Audio";
- case RtAudio::WINDOWS_WASAPI: return "WASAPI";
- case RtAudio::WINDOWS_ASIO: return "ASIO";
- case RtAudio::WINDOWS_DS: return "DirectSound";
- case RtAudio::RTAUDIO_DUMMY: return "Dummy";
- case DRIVER_BRIDGE: return "VCV Bridge";
- default: return "Unknown";
- }
- }
-
- void AudioIO::setDriver(int driver) {
- // Close driver
- closeStream();
- if (rtAudio) {
- delete rtAudio;
- rtAudio = NULL;
- }
- this->driver = 0;
-
- // Open driver
- if (driver >= 0) {
- rtAudio = new RtAudio((RtAudio::Api) driver);
- this->driver = (int) rtAudio->getCurrentApi();
- }
- else if (driver == DRIVER_BRIDGE) {
- // TODO Connect to Bridge
- this->driver = DRIVER_BRIDGE;
- }
- }
-
- int AudioIO::getDeviceCount() {
- if (rtAudio) {
- return rtAudio->getDeviceCount();
- }
- if (driver == DRIVER_BRIDGE) {
- return 16;
- }
- return 0;
- }
-
- std::string AudioIO::getDeviceName(int device) {
- if (rtAudio) {
- try {
- RtAudio::DeviceInfo deviceInfo = rtAudio->getDeviceInfo(device);
- return deviceInfo.name;
- }
- catch (RtAudioError &e) {
- warn("Failed to query RtAudio device: %s", e.what());
- }
- }
- if (driver == DRIVER_BRIDGE) {
- return stringf("%d", device + 1);
- }
- return "";
- }
-
- std::string AudioIO::getDeviceDetail(int device) {
- if (rtAudio) {
- try {
- RtAudio::DeviceInfo deviceInfo = rtAudio->getDeviceInfo(device);
- return stringf("%s (%d in, %d out)", deviceInfo.name.c_str(), deviceInfo.inputChannels, deviceInfo.outputChannels);
- }
- catch (RtAudioError &e) {
- warn("Failed to query RtAudio device: %s", e.what());
- }
- }
- if (driver == DRIVER_BRIDGE) {
- return stringf("Channel %d", device + 1);
- }
- return "";
- }
-
- static int rtCallback(void *outputBuffer, void *inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status, void *userData) {
- AudioIO *audioIO = (AudioIO*) userData;
- assert(audioIO);
- audioIO->processStream((const float *) inputBuffer, (float *) outputBuffer, nFrames);
- return 0;
- }
-
- void AudioIO::openStream() {
- // Close device but remember the current device number
- int device = this->device;
- closeStream();
-
- if (device < 0)
- return;
-
- if (rtAudio) {
- // Open new device
- RtAudio::DeviceInfo deviceInfo;
- try {
- deviceInfo = rtAudio->getDeviceInfo(device);
- }
- catch (RtAudioError &e) {
- warn("Failed to query RtAudio device: %s", e.what());
- return;
- }
-
- numOutputs = mini(deviceInfo.outputChannels, maxOutputs);
- numInputs = mini(deviceInfo.inputChannels, maxInputs);
-
- if (numOutputs == 0 && numInputs == 0) {
- warn("RtAudio device %d has 0 inputs and 0 outputs");
- return;
- }
-
- RtAudio::StreamParameters outParameters;
- outParameters.deviceId = device;
- outParameters.nChannels = numOutputs;
-
- RtAudio::StreamParameters inParameters;
- inParameters.deviceId = device;
- inParameters.nChannels = numInputs;
-
- RtAudio::StreamOptions options;
- // options.flags |= RTAUDIO_SCHEDULE_REALTIME;
-
- int closestSampleRate = deviceInfo.preferredSampleRate;
- for (int sr : deviceInfo.sampleRates) {
- if (abs(sr - sampleRate) < abs(closestSampleRate - sampleRate)) {
- closestSampleRate = sr;
- }
- }
-
- try {
- debug("Opening audio RtAudio device %d", device);
- rtAudio->openStream(
- numOutputs == 0 ? NULL : &outParameters,
- numInputs == 0 ? NULL : &inParameters,
- RTAUDIO_FLOAT32, closestSampleRate, (unsigned int*) &blockSize, &rtCallback, this, &options, NULL);
- }
- catch (RtAudioError &e) {
- warn("Failed to open RtAudio stream: %s", e.what());
- return;
- }
-
- try {
- debug("Starting RtAudio stream %d", device);
- rtAudio->startStream();
- }
- catch (RtAudioError &e) {
- warn("Failed to start RtAudio stream: %s", e.what());
- return;
- }
-
- // Update sample rate because this may have changed
- this->sampleRate = rtAudio->getStreamSampleRate();
- this->device = device;
- onOpenStream();
- }
- }
-
- void AudioIO::closeStream() {
- if (rtAudio) {
- if (rtAudio->isStreamRunning()) {
- debug("Stopping RtAudio stream %d", device);
- try {
- rtAudio->stopStream();
- }
- catch (RtAudioError &e) {
- warn("Failed to stop RtAudio stream %s", e.what());
- }
- }
- if (rtAudio->isStreamOpen()) {
- debug("Closing RtAudio stream %d", device);
- try {
- rtAudio->closeStream();
- }
- catch (RtAudioError &e) {
- warn("Failed to close RtAudio stream %s", e.what());
- }
- }
- }
-
- // Reset rtAudio settings
- device = -1;
- numOutputs = 0;
- numInputs = 0;
- onCloseStream();
- }
-
- std::vector<int> AudioIO::listSampleRates() {
- if (rtAudio) {
- try {
- RtAudio::DeviceInfo deviceInfo = rtAudio->getDeviceInfo(device);
- std::vector<int> sampleRates(deviceInfo.sampleRates.begin(), deviceInfo.sampleRates.end());
- return sampleRates;
- }
- catch (RtAudioError &e) {
- warn("Failed to query RtAudio device: %s", e.what());
- }
- }
- if (driver == DRIVER_BRIDGE) {
- return {44100, 48000, 88200, 96000, 176400, 192000};
- }
-
- return {};
- }
-
- json_t *AudioIO::toJson() {
- json_t *rootJ = json_object();
- json_object_set_new(rootJ, "driver", json_integer(driver));
- std::string deviceName = getDeviceName(device);
- json_object_set_new(rootJ, "deviceName", json_string(deviceName.c_str()));
- json_object_set_new(rootJ, "sampleRate", json_integer(sampleRate));
- json_object_set_new(rootJ, "blockSize", json_integer(blockSize));
- return rootJ;
- }
-
- void AudioIO::fromJson(json_t *rootJ) {
- json_t *driverJ = json_object_get(rootJ, "driver");
- if (driverJ)
- setDriver(json_number_value(driverJ));
-
- json_t *deviceNameJ = json_object_get(rootJ, "deviceName");
- if (deviceNameJ) {
- std::string deviceName = json_string_value(deviceNameJ);
- // Search for device ID with equal name
- for (int device = 0; device < getDeviceCount(); device++) {
- if (getDeviceName(device) == deviceName) {
- this->device = device;
- break;
- }
- }
- }
-
- json_t *sampleRateJ = json_object_get(rootJ, "sampleRate");
- if (sampleRateJ)
- sampleRate = json_integer_value(sampleRateJ);
-
- json_t *blockSizeJ = json_object_get(rootJ, "blockSize");
- if (blockSizeJ)
- blockSize = json_integer_value(blockSizeJ);
-
- openStream();
- }
-
-
- } // namespace rack
|