| @@ -99,15 +99,15 @@ struct Device { | |||
| /** Returns a list of all valid (user-selectable) sample rates. | |||
| The device may accept sample rates not in this list, but it *must* accept sample rates in the list. | |||
| */ | |||
| virtual std::set<int> getSampleRates() { | |||
| virtual std::set<float> getSampleRates() { | |||
| return {}; | |||
| } | |||
| /** Returns the current sample rate. */ | |||
| virtual int getSampleRate() { | |||
| virtual float getSampleRate() { | |||
| return 0; | |||
| } | |||
| /** Sets the sample rate of the device, re-opening it if needed. */ | |||
| virtual void setSampleRate(int sampleRate) {} | |||
| virtual void setSampleRate(float sampleRate) {} | |||
| /** Returns a list of all valid (user-selectable) block sizes. | |||
| The device may accept block sizes not in this list, but it *must* accept block sizes in the list. | |||
| @@ -169,9 +169,9 @@ struct Port { | |||
| std::string getDeviceName(int deviceId); | |||
| std::string getDeviceDetail(int deviceId, int offset); | |||
| std::set<int> getSampleRates(); | |||
| int getSampleRate(); | |||
| void setSampleRate(int sampleRate); | |||
| std::set<float> getSampleRates(); | |||
| float getSampleRate(); | |||
| void setSampleRate(float sampleRate); | |||
| std::set<int> getBlockSizes(); | |||
| int getBlockSize(); | |||
| @@ -144,7 +144,7 @@ struct AudioDeviceItem : ui::MenuItem { | |||
| struct AudioSampleRateValueItem : ui::MenuItem { | |||
| audio::Port* port; | |||
| int sampleRate; | |||
| float sampleRate; | |||
| void onAction(const event::Action& e) override { | |||
| port->setSampleRate(sampleRate); | |||
| } | |||
| @@ -154,14 +154,14 @@ static void appendAudioSampleRateMenu(ui::Menu* menu, audio::Port* port) { | |||
| if (!port) | |||
| return; | |||
| std::set<int> sampleRates = port->getSampleRates(); | |||
| std::set<float> sampleRates = port->getSampleRates(); | |||
| // Add current sample rate in case it's not in the list | |||
| sampleRates.insert(port->getSampleRate()); | |||
| if (sampleRates.empty()) { | |||
| menu->addChild(createMenuLabel("(Locked by device)")); | |||
| } | |||
| for (int sampleRate : sampleRates) { | |||
| for (float sampleRate : sampleRates) { | |||
| if (sampleRate <= 0) | |||
| continue; | |||
| AudioSampleRateValueItem* item = new AudioSampleRateValueItem; | |||
| @@ -184,9 +184,9 @@ struct AudioSampleRateChoice : LedDisplayChoice { | |||
| text = ""; | |||
| if (box.size.x >= 100.0) | |||
| text += "Rate: "; | |||
| int sampleRate = port ? port->getSampleRate() : 0; | |||
| float sampleRate = port ? port->getSampleRate() : 0; | |||
| if (sampleRate > 0) { | |||
| text += string::f("%g", sampleRate / 1000.0); | |||
| text += string::f("%g", sampleRate / 1000.f); | |||
| color.a = 1.0; | |||
| } | |||
| else { | |||
| @@ -242,7 +242,7 @@ std::string Port::getDeviceDetail(int deviceId, int offset) { | |||
| } | |||
| } | |||
| std::set<int> Port::getSampleRates() { | |||
| std::set<float> Port::getSampleRates() { | |||
| if (!device) | |||
| return {}; | |||
| try { | |||
| @@ -254,7 +254,7 @@ std::set<int> Port::getSampleRates() { | |||
| } | |||
| } | |||
| int Port::getSampleRate() { | |||
| float Port::getSampleRate() { | |||
| if (!device) | |||
| return 0; | |||
| try { | |||
| @@ -266,7 +266,7 @@ int Port::getSampleRate() { | |||
| } | |||
| } | |||
| void Port::setSampleRate(int sampleRate) { | |||
| void Port::setSampleRate(float sampleRate) { | |||
| if (!device) | |||
| return; | |||
| try { | |||
| @@ -345,7 +345,7 @@ json_t* Port::toJson() { | |||
| json_object_set_new(rootJ, "deviceName", json_string(deviceName.c_str())); | |||
| } | |||
| json_object_set_new(rootJ, "sampleRate", json_integer(getSampleRate())); | |||
| json_object_set_new(rootJ, "sampleRate", json_real(getSampleRate())); | |||
| json_object_set_new(rootJ, "blockSize", json_integer(getBlockSize())); | |||
| json_object_set_new(rootJ, "offset", json_integer(offset)); | |||
| return rootJ; | |||
| @@ -377,7 +377,7 @@ void Port::fromJson(json_t* rootJ) { | |||
| json_t* sampleRateJ = json_object_get(rootJ, "sampleRate"); | |||
| if (sampleRateJ) | |||
| setSampleRate(json_integer_value(sampleRateJ)); | |||
| setSampleRate(json_number_value(sampleRateJ)); | |||
| json_t* blockSizeJ = json_object_get(rootJ, "blockSize"); | |||
| if (blockSizeJ) | |||
| @@ -205,7 +205,7 @@ struct AudioInterface : Module, audio::Port { | |||
| // Initialize sample rate converters | |||
| int numInputs = getNumInputs(); | |||
| int engineSampleRate = (int) APP->engine->getSampleRate(); | |||
| int sampleRate = getSampleRate(); | |||
| float sampleRate = getSampleRate(); | |||
| double sampleRateRatio = (double) engineSampleRate / sampleRate; | |||
| outputSrc.setRates(sampleRate, engineSampleRate); | |||
| outputSrc.setChannels(numInputs); | |||
| @@ -253,7 +253,7 @@ struct AudioInterface : Module, audio::Port { | |||
| bool isPrimary = (APP->engine->getPrimaryModule() == this); | |||
| int numOutputs = getNumOutputs(); | |||
| int engineSampleRate = (int) APP->engine->getSampleRate(); | |||
| int sampleRate = getSampleRate(); | |||
| float sampleRate = getSampleRate(); | |||
| inputSrc.setRates(engineSampleRate, sampleRate); | |||
| inputSrc.setChannels(numOutputs); | |||
| @@ -19,14 +19,14 @@ namespace rack { | |||
| struct RtAudioDevice : audio::Device { | |||
| RtAudio *rtAudio; | |||
| RtAudio* rtAudio; | |||
| int deviceId; | |||
| RtAudio::DeviceInfo deviceInfo; | |||
| RtAudio::StreamParameters inputParameters; | |||
| RtAudio::StreamParameters outputParameters; | |||
| RtAudio::StreamOptions options; | |||
| int blockSize = 0; | |||
| int sampleRate = 44100; | |||
| float sampleRate = 44100; | |||
| RtAudioDevice(RtAudio::Api api, int deviceId) { | |||
| rtAudio = new RtAudio(api); | |||
| @@ -73,11 +73,11 @@ struct RtAudioDevice : audio::Device { | |||
| options.numberOfBuffers = 2; | |||
| options.streamName = "VCV Rack"; | |||
| int closestSampleRate = deviceInfo.preferredSampleRate; | |||
| float closestSampleRate = deviceInfo.preferredSampleRate; | |||
| if (sampleRate > 0) { | |||
| // Find the closest sample rate to the requested one. | |||
| for (int sr : deviceInfo.sampleRates) { | |||
| if (std::abs(sr - sampleRate) < std::abs(closestSampleRate - sampleRate)) { | |||
| for (float sr : deviceInfo.sampleRates) { | |||
| if (std::fabs(sr - sampleRate) < std::fabs(closestSampleRate - sampleRate)) { | |||
| closestSampleRate = sr; | |||
| } | |||
| } | |||
| @@ -87,7 +87,7 @@ struct RtAudioDevice : audio::Device { | |||
| blockSize = 256; | |||
| } | |||
| INFO("Opening audio RtAudio device %d with %d in %d out, %d sample rate %d block size", deviceId, inputParameters.nChannels, outputParameters.nChannels, closestSampleRate, blockSize); | |||
| INFO("Opening audio RtAudio device %d with %d in %d out, %f sample rate %d block size", deviceId, inputParameters.nChannels, outputParameters.nChannels, closestSampleRate, blockSize); | |||
| try { | |||
| rtAudio->openStream( | |||
| outputParameters.nChannels > 0 ? &outputParameters : NULL, | |||
| @@ -146,14 +146,14 @@ struct RtAudioDevice : audio::Device { | |||
| return outputParameters.nChannels; | |||
| } | |||
| std::set<int> getSampleRates() override { | |||
| std::set<int> sampleRates(deviceInfo.sampleRates.begin(), deviceInfo.sampleRates.end()); | |||
| std::set<float> getSampleRates() override { | |||
| std::set<float> sampleRates(deviceInfo.sampleRates.begin(), deviceInfo.sampleRates.end()); | |||
| return sampleRates; | |||
| } | |||
| int getSampleRate() override { | |||
| float getSampleRate() override { | |||
| return sampleRate; | |||
| } | |||
| void setSampleRate(int sampleRate) override { | |||
| void setSampleRate(float sampleRate) override { | |||
| closeStream(); | |||
| this->sampleRate = sampleRate; | |||
| openStream(); | |||
| @@ -190,7 +190,7 @@ struct RtAudioDevice : audio::Device { | |||
| struct RtAudioDriver : audio::Driver { | |||
| // Just for querying device IDs names | |||
| RtAudio *rtAudio; | |||
| RtAudio* rtAudio; | |||
| // deviceId -> Device | |||
| std::map<int, RtAudioDevice*> devices; | |||