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