Browse Source

Split `audio::Port::offset` to inputOffset and outputOffset, and `audio::Port::maxChannels` to maxInputs and maxOutputs.

tags/v2.0.0
Andrew Belt 3 years ago
parent
commit
54fbe407af
4 changed files with 58 additions and 83 deletions
  1. +4
    -15
      include/audio.hpp
  2. +38
    -10
      src/app/AudioWidget.cpp
  3. +14
    -57
      src/audio.cpp
  4. +2
    -1
      src/core/AudioInterface.cpp

+ 4
- 15
include/audio.hpp View File

@@ -46,11 +46,6 @@ struct Driver {
virtual int getDeviceNumOutputs(int deviceId) { virtual int getDeviceNumOutputs(int deviceId) {
return 0; return 0;
} }
/** Returns a detailed description of the device without obtaining it.
`offset` specifies the first channel (zero-indexed).
E.g. "MySoundcard (1-2 in, 1-2 out)"
*/
std::string getDeviceDetail(int deviceId, int offset, int maxChannels);


/** Adds the given port as a reference holder of a device and returns the it. /** Adds the given port as a reference holder of a device and returns the it.
Creates the Device if no ports are subscribed before calling. Creates the Device if no ports are subscribed before calling.
@@ -90,11 +85,6 @@ struct Device {
virtual int getNumOutputs() { virtual int getNumOutputs() {
return 0; return 0;
} }
/** Returns a detailed description of the device.
`offset` specifies the first channel (zero-indexed).
E.g. "MySoundcard (1-2 in, 1-2 out)"
*/
std::string getDetail(int offset, int maxChannels);


/** 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.
@@ -139,9 +129,11 @@ That is, if the active Device throws a `rack::Exception`, it is caught and logge
*/ */
struct Port { struct Port {
/** The first channel index of the device to process. */ /** The first channel index of the device to process. */
int offset = 0;
int inputOffset = 0;
int outputOffset = 0;
/** Maximum number of channels to process. */ /** Maximum number of channels to process. */
int maxChannels = 8;
int maxInputs = 8;
int maxOutputs = 8;


// private // private
int driverId = -1; int driverId = -1;
@@ -177,9 +169,6 @@ struct Port {
int getBlockSize(); int getBlockSize();
void setBlockSize(int blockSize); void setBlockSize(int blockSize);


int getOffset();
void setOffset(int offset);

int getNumInputs(); int getNumInputs();
int getNumOutputs(); int getNumOutputs();




+ 38
- 10
src/app/AudioWidget.cpp View File

@@ -8,6 +8,23 @@ namespace rack {
namespace app { namespace app {




static std::string getDetailTemplate(std::string name, int numInputs, int inputOffset, int maxInputs, int numOutputs, int outputOffset, int maxOutputs) {
std::string text = name;
text += " (";
if (inputOffset < numInputs) {
text += string::f("%d-%d in", inputOffset + 1, std::min(inputOffset + maxInputs, numInputs));
}
if (inputOffset < numInputs && outputOffset < numOutputs) {
text += ", ";
}
if (outputOffset < numOutputs) {
text += string::f("%d-%d out", outputOffset + 1, std::min(outputOffset + maxOutputs, numOutputs));
}
text += ")";
return text;
}


struct AudioDriverValueItem : ui::MenuItem { struct AudioDriverValueItem : ui::MenuItem {
audio::Port* port; audio::Port* port;
int driverId; int driverId;
@@ -67,10 +84,12 @@ struct AudioDriverItem : ui::MenuItem {
struct AudioDeviceValueItem : ui::MenuItem { struct AudioDeviceValueItem : ui::MenuItem {
audio::Port* port; audio::Port* port;
int deviceId; int deviceId;
int offset;
int inputOffset;
int outputOffset;
void onAction(const event::Action& e) override { void onAction(const event::Action& e) override {
port->setDeviceId(deviceId); port->setDeviceId(deviceId);
port->setOffset(offset);
port->inputOffset = inputOffset;
port->outputOffset = outputOffset;
} }
}; };


@@ -88,18 +107,24 @@ static void appendAudioDeviceMenu(ui::Menu* menu, audio::Port* port) {
} }


for (int deviceId : port->getDeviceIds()) { for (int deviceId : port->getDeviceIds()) {
int channels = std::max(port->getDeviceNumInputs(deviceId), port->getDeviceNumOutputs(deviceId));
int numInputs = port->getDeviceNumInputs(deviceId);
int numOutputs = port->getDeviceNumOutputs(deviceId);
std::string name = port->getDeviceName(deviceId);

// Prevents devices with a ridiculous number of channels from being displayed // Prevents devices with a ridiculous number of channels from being displayed
const int maxTotalChannels = port->maxChannels * 16;
channels = std::min(maxTotalChannels, channels);
for (int i = 0; i < 8; i++) {
int inputOffset = i * port->maxInputs;
int outputOffset = i * port->maxOutputs;
if (inputOffset >= numInputs && outputOffset >= numOutputs)
break;


for (int offset = 0; offset < channels; offset += port->maxChannels) {
AudioDeviceValueItem* item = new AudioDeviceValueItem; AudioDeviceValueItem* item = new AudioDeviceValueItem;
item->port = port; item->port = port;
item->deviceId = deviceId; item->deviceId = deviceId;
item->offset = offset;
item->text = port->getDeviceDetail(deviceId, offset);
item->rightText = CHECKMARK(item->deviceId == port->getDeviceId() && item->offset == port->getOffset());
item->inputOffset = inputOffset;
item->outputOffset = outputOffset;
item->text = getDetailTemplate(name, numInputs, inputOffset, port->maxInputs, numOutputs, outputOffset, port->maxOutputs);
item->rightText = CHECKMARK(item->deviceId == port->getDeviceId() && inputOffset == port->inputOffset && outputOffset == port->outputOffset);
menu->addChild(item); menu->addChild(item);
} }
} }
@@ -117,7 +142,10 @@ struct AudioDeviceChoice : LedDisplayChoice {
text = ""; text = "";
if (box.size.x >= 200.0) if (box.size.x >= 200.0)
text += "Device: "; text += "Device: ";
std::string detail = (port && port->device) ? port->device->getDetail(port->getOffset(), port->maxChannels) : "";
std::string detail = "";
if (port && port->device)
detail = getDetailTemplate(port->device->getName(), port->getNumInputs(), port->inputOffset, port->maxInputs, port->getNumOutputs(), port->outputOffset, port->maxOutputs);

if (detail != "") { if (detail != "") {
text += detail; text += detail;
color.a = 1.0; color.a = 1.0;


+ 14
- 57
src/audio.cpp View File

@@ -8,31 +8,10 @@ namespace audio {


static std::vector<std::pair<int, Driver*>> drivers; static std::vector<std::pair<int, Driver*>> drivers;


static std::string getDetailTemplate(std::string name, int numInputs, int numOutputs, int offset, int maxChannels) {
std::string text = name;
text += " (";
if (offset < numInputs) {
text += string::f("%d-%d in", offset + 1, std::min(offset + maxChannels, numInputs));
}
if (offset < numInputs && offset < numOutputs) {
text += ", ";
}
if (offset < numOutputs) {
text += string::f("%d-%d out", offset + 1, std::min(offset + maxChannels, numOutputs));
}
text += ")";
return text;
}

//////////////////// ////////////////////
// Driver // Driver
//////////////////// ////////////////////


std::string Driver::getDeviceDetail(int deviceId, int offset, int maxChannels) {
if (deviceId < 0)
return "";
return getDetailTemplate(getDeviceName(deviceId), getDeviceNumInputs(deviceId), getDeviceNumOutputs(deviceId), offset, maxChannels);
}


//////////////////// ////////////////////
// Device // Device
@@ -48,10 +27,6 @@ void Device::unsubscribe(Port* port) {
subscribed.erase(it); subscribed.erase(it);
} }


std::string Device::getDetail(int offset, int maxChannels) {
return getDetailTemplate(getName(), getNumInputs(), getNumOutputs(), offset, maxChannels);
}

void Device::processBuffer(const float* input, int inputStride, float* output, int outputStride, int frames) { void Device::processBuffer(const float* input, int inputStride, float* output, int outputStride, int frames) {
// Zero output in case no Port writes values to it. // Zero output in case no Port writes values to it.
std::memset(output, 0, frames * outputStride * sizeof(float)); std::memset(output, 0, frames * outputStride * sizeof(float));
@@ -59,15 +34,15 @@ void Device::processBuffer(const float* input, int inputStride, float* output, i
for (Port* port : subscribed) { for (Port* port : subscribed) {
// Setting the thread context should probably be the responsibility of Port, but because processInput() etc are overridden, this is the only good place for it. // Setting the thread context should probably be the responsibility of Port, but because processInput() etc are overridden, this is the only good place for it.
contextSet(port->context); contextSet(port->context);
port->processInput(input + port->getOffset(), inputStride, frames);
port->processInput(input + port->inputOffset, inputStride, frames);
} }
for (Port* port : subscribed) { for (Port* port : subscribed) {
contextSet(port->context); contextSet(port->context);
port->processBuffer(input + port->getOffset(), inputStride, output + port->getOffset(), outputStride, frames);
port->processBuffer(input + port->inputOffset, inputStride, output + port->outputOffset, outputStride, frames);
} }
for (Port* port : subscribed) { for (Port* port : subscribed) {
contextSet(port->context); contextSet(port->context);
port->processOutput(output + port->getOffset(), outputStride, frames);
port->processOutput(output + port->outputOffset, outputStride, frames);
} }
} }


@@ -106,7 +81,6 @@ void Port::reset() {
firstDriverId = driverIds[0]; firstDriverId = driverIds[0];


setDriverId(firstDriverId); setDriverId(firstDriverId);
setOffset(0);
} }


Driver* Port::getDriver() { Driver* Port::getDriver() {
@@ -236,19 +210,6 @@ std::string Port::getDeviceName(int deviceId) {
} }
} }


std::string Port::getDeviceDetail(int deviceId, int offset) {
if (!driver)
return "";
try {
// Use maxChannels from Port.
return driver->getDeviceDetail(deviceId, offset, maxChannels);
}
catch (Exception& e) {
WARN("Audio port could not get device detail: %s", e.what());
return 0;
}
}

std::set<float> Port::getSampleRates() { std::set<float> Port::getSampleRates() {
if (!device) if (!device)
return {}; return {};
@@ -319,20 +280,11 @@ void Port::setBlockSize(int blockSize) {
} }
} }


int Port::getOffset() {
return offset;
}

void Port::setOffset(int offset) {
this->offset = offset;
}


int Port::getNumInputs() { int Port::getNumInputs() {
if (!device) if (!device)
return 0; return 0;
try { try {
return std::min(device->getNumInputs() - getOffset(), maxChannels);
return std::min(device->getNumInputs() - inputOffset, maxInputs);
} }
catch (Exception& e) { catch (Exception& e) {
WARN("Audio port could not get device number of inputs: %s", e.what()); WARN("Audio port could not get device number of inputs: %s", e.what());
@@ -344,7 +296,7 @@ int Port::getNumOutputs() {
if (!device) if (!device)
return 0; return 0;
try { try {
return std::min(device->getNumOutputs() - getOffset(), maxChannels);
return std::min(device->getNumOutputs() - outputOffset, maxOutputs);
} }
catch (Exception& e) { catch (Exception& e) {
WARN("Audio port could not get device number of outputs: %s", e.what()); WARN("Audio port could not get device number of outputs: %s", e.what());
@@ -363,7 +315,8 @@ json_t* Port::toJson() {


json_object_set_new(rootJ, "sampleRate", json_real(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(getOffset()));
json_object_set_new(rootJ, "inputOffset", json_integer(inputOffset));
json_object_set_new(rootJ, "outputOffset", json_integer(outputOffset));
return rootJ; return rootJ;
} }


@@ -397,9 +350,13 @@ void Port::fromJson(json_t* rootJ) {
if (blockSizeJ) if (blockSizeJ)
setBlockSize(json_integer_value(blockSizeJ)); setBlockSize(json_integer_value(blockSizeJ));


json_t* offsetJ = json_object_get(rootJ, "offset");
if (offsetJ)
setOffset(json_integer_value(offsetJ));
json_t* inputOffsetJ = json_object_get(rootJ, "inputOffset");
if (inputOffsetJ)
inputOffset = json_integer_value(inputOffsetJ);

json_t* outputOffsetJ = json_object_get(rootJ, "outputOffset");
if (outputOffsetJ)
outputOffset = json_integer_value(outputOffsetJ);
} }


//////////////////// ////////////////////


+ 2
- 1
src/core/AudioInterface.cpp View File

@@ -71,7 +71,8 @@ struct AudioInterface : Module, audio::Port {
configLight(OUTPUT_LIGHTS + 2 * i, string::f("Device input %d/%d status", 2 * i + 1, 2 * i + 2)); configLight(OUTPUT_LIGHTS + 2 * i, string::f("Device input %d/%d status", 2 * i + 1, 2 * i + 2));


lightDivider.setDivision(512); lightDivider.setDivision(512);
maxChannels = std::max(NUM_AUDIO_INPUTS, NUM_AUDIO_OUTPUTS);
maxOutputs = NUM_AUDIO_INPUTS;
maxInputs = NUM_AUDIO_OUTPUTS;
inputSrc.setQuality(6); inputSrc.setQuality(6);
outputSrc.setQuality(6); outputSrc.setQuality(6);




Loading…
Cancel
Save