Browse Source

Audio Interface: add timed sleep lock to output buffer, adjust widgets

on panel
tags/v0.5.0
Andrew Belt 7 years ago
parent
commit
91d414376c
1 changed files with 78 additions and 81 deletions
  1. +78
    -81
      src/core/AudioInterface.cpp

+ 78
- 81
src/core/AudioInterface.cpp View File

@@ -31,7 +31,7 @@ struct AudioInterface : Module {


RtAudio *stream = NULL; RtAudio *stream = NULL;
// Stream properties // Stream properties
int deviceId = -1;
int device = -1;
float sampleRate = 44100.0; float sampleRate = 44100.0;
int blockSize = 256; int blockSize = 256;
int numOutputs = 0; int numOutputs = 0;
@@ -57,7 +57,7 @@ struct AudioInterface : Module {
void stepStream(const float *input, float *output, int numFrames); void stepStream(const float *input, float *output, int numFrames);


int getDeviceCount(); int getDeviceCount();
std::string getDeviceName(int deviceId);
std::string getDeviceName(int device);


void openStream(); void openStream();
void closeStream(); void closeStream();
@@ -101,36 +101,29 @@ struct AudioInterface : Module {


json_t *toJson() override { json_t *toJson() override {
json_t *rootJ = json_object(); json_t *rootJ = json_object();
if (deviceId >= 0) {
std::string deviceName = getDeviceName(deviceId);
json_object_set_new(rootJ, "deviceName", json_string(deviceName.c_str()));
json_object_set_new(rootJ, "sampleRate", json_real(sampleRate));
json_object_set_new(rootJ, "blockSize", json_integer(blockSize));
}
json_object_set_new(rootJ, "driver", json_integer(getDriver()));
json_object_set_new(rootJ, "device", json_integer(device));
json_object_set_new(rootJ, "sampleRate", json_real(sampleRate));
json_object_set_new(rootJ, "blockSize", json_integer(blockSize));
return rootJ; return rootJ;
} }


void fromJson(json_t *rootJ) override { void fromJson(json_t *rootJ) override {
json_t *deviceNameJ = json_object_get(rootJ, "deviceName");
if (deviceNameJ) {
std::string deviceName = json_string_value(deviceNameJ);
for (int i = 0; i < getDeviceCount(); i++) {
if (deviceName == getDeviceName(i)) {
deviceId = i;
break;
}
}
}
json_t *driverJ = json_object_get(rootJ, "driver");
if (driverJ)
setDriver(json_number_value(driverJ));

json_t *deviceJ = json_object_get(rootJ, "device");
if (deviceJ)
device = json_number_value(deviceJ);


json_t *sampleRateJ = json_object_get(rootJ, "sampleRate"); json_t *sampleRateJ = json_object_get(rootJ, "sampleRate");
if (sampleRateJ) {
if (sampleRateJ)
sampleRate = json_number_value(sampleRateJ); sampleRate = json_number_value(sampleRateJ);
}


json_t *blockSizeJ = json_object_get(rootJ, "blockSize"); json_t *blockSizeJ = json_object_get(rootJ, "blockSize");
if (blockSizeJ) {
if (blockSizeJ)
blockSize = json_integer_value(blockSizeJ); blockSize = json_integer_value(blockSizeJ);
}


openStream(); openStream();
} }
@@ -154,6 +147,7 @@ struct AudioInterface : Module {




void AudioInterface::step() { void AudioInterface::step() {
// debug("inputBuffer %d inputSrcBuffer %d outputBuffer %d", inputBuffer.size(), inputSrcBuffer.size(), outputBuffer.size());
// Read/write stream if we have enough input, OR the output buffer is empty if we have no input // Read/write stream if we have enough input, OR the output buffer is empty if we have no input
if (numOutputs > 0) { if (numOutputs > 0) {
TIMED_SLEEP_LOCK(inputSrcBuffer.size() < blockSize, 100e-6, 0.2); TIMED_SLEEP_LOCK(inputSrcBuffer.size() < blockSize, 100e-6, 0.2);
@@ -203,6 +197,9 @@ void AudioInterface::stepStream(const float *input, float *output, int numFrames
// Wait for enough input before proceeding // Wait for enough input before proceeding
TIMED_SLEEP_LOCK(inputSrcBuffer.size() >= numFrames, 100e-6, 0.2); TIMED_SLEEP_LOCK(inputSrcBuffer.size() >= numFrames, 100e-6, 0.2);
} }
else if (numInputs > 0) {
TIMED_SLEEP_LOCK(outputBuffer.empty(), 100e-6, 0.2);
}


// input stream -> output buffer // input stream -> output buffer
if (numInputs > 0) { if (numInputs > 0) {
@@ -244,12 +241,12 @@ int AudioInterface::getDeviceCount() {
return stream->getDeviceCount(); return stream->getDeviceCount();
} }


std::string AudioInterface::getDeviceName(int deviceId) {
if (!stream || deviceId < 0)
std::string AudioInterface::getDeviceName(int device) {
if (!stream || device < 0)
return ""; return "";


try { try {
RtAudio::DeviceInfo deviceInfo = stream->getDeviceInfo(deviceId);
RtAudio::DeviceInfo deviceInfo = stream->getDeviceInfo(device);
return stringf("%s (%d in, %d out)", deviceInfo.name.c_str(), deviceInfo.inputChannels, deviceInfo.outputChannels); return stringf("%s (%d in, %d out)", deviceInfo.name.c_str(), deviceInfo.inputChannels, deviceInfo.outputChannels);
} }
catch (RtAudioError &e) { catch (RtAudioError &e) {
@@ -266,16 +263,16 @@ static int rtCallback(void *outputBuffer, void *inputBuffer, unsigned int nFrame
} }


void AudioInterface::openStream() { void AudioInterface::openStream() {
int deviceId = this->deviceId;
int device = this->device;
closeStream(); closeStream();
if (!stream) if (!stream)
return; return;


// Open new device // Open new device
if (deviceId >= 0) {
if (device >= 0) {
RtAudio::DeviceInfo deviceInfo; RtAudio::DeviceInfo deviceInfo;
try { try {
deviceInfo = stream->getDeviceInfo(deviceId);
deviceInfo = stream->getDeviceInfo(device);
} }
catch (RtAudioError &e) { catch (RtAudioError &e) {
warn("Failed to query audio device: %s", e.what()); warn("Failed to query audio device: %s", e.what());
@@ -291,11 +288,11 @@ void AudioInterface::openStream() {
} }


RtAudio::StreamParameters outParameters; RtAudio::StreamParameters outParameters;
outParameters.deviceId = deviceId;
outParameters.deviceId = device;
outParameters.nChannels = numOutputs; outParameters.nChannels = numOutputs;


RtAudio::StreamParameters inParameters; RtAudio::StreamParameters inParameters;
inParameters.deviceId = deviceId;
inParameters.deviceId = device;
inParameters.nChannels = numInputs; inParameters.nChannels = numInputs;


RtAudio::StreamOptions options; RtAudio::StreamOptions options;
@@ -311,7 +308,7 @@ void AudioInterface::openStream() {


try { try {
// Don't use stream parameters if 0 input or output channels // Don't use stream parameters if 0 input or output channels
debug("Opening audio stream %d", deviceId);
debug("Opening audio stream %d", device);
stream->openStream( stream->openStream(
numOutputs == 0 ? NULL : &outParameters, numOutputs == 0 ? NULL : &outParameters,
numInputs == 0 ? NULL : &inParameters, numInputs == 0 ? NULL : &inParameters,
@@ -323,7 +320,7 @@ void AudioInterface::openStream() {
} }


try { try {
debug("Starting audio stream %d", deviceId);
debug("Starting audio stream %d", device);
stream->startStream(); stream->startStream();
} }
catch (RtAudioError &e) { catch (RtAudioError &e) {
@@ -333,14 +330,14 @@ void AudioInterface::openStream() {


// Update sample rate because this may have changed // Update sample rate because this may have changed
this->sampleRate = stream->getStreamSampleRate(); this->sampleRate = stream->getStreamSampleRate();
this->deviceId = deviceId;
this->device = device;
} }
} }


void AudioInterface::closeStream() { void AudioInterface::closeStream() {
if (stream) { if (stream) {
if (stream->isStreamRunning()) { if (stream->isStreamRunning()) {
debug("Aborting audio stream %d", deviceId);
debug("Aborting audio stream %d", device);
try { try {
stream->abortStream(); stream->abortStream();
} }
@@ -349,7 +346,7 @@ void AudioInterface::closeStream() {
} }
} }
if (stream->isStreamOpen()) { if (stream->isStreamOpen()) {
debug("Closing audio stream %d", deviceId);
debug("Closing audio stream %d", device);
try { try {
stream->closeStream(); stream->closeStream();
} }
@@ -360,7 +357,7 @@ void AudioInterface::closeStream() {
} }


// Reset stream settings // Reset stream settings
deviceId = -1;
device = -1;
numOutputs = 0; numOutputs = 0;
numInputs = 0; numInputs = 0;


@@ -374,12 +371,12 @@ void AudioInterface::closeStream() {


std::vector<float> AudioInterface::getSampleRates() { std::vector<float> AudioInterface::getSampleRates() {
std::vector<float> allowedSampleRates = {44100, 48000, 88200, 96000, 176400, 192000}; std::vector<float> allowedSampleRates = {44100, 48000, 88200, 96000, 176400, 192000};
if (!stream || deviceId < 0)
if (!stream || device < 0)
return allowedSampleRates; return allowedSampleRates;


try { try {
std::vector<float> sampleRates; std::vector<float> sampleRates;
RtAudio::DeviceInfo deviceInfo = stream->getDeviceInfo(deviceId);
RtAudio::DeviceInfo deviceInfo = stream->getDeviceInfo(device);
for (int sr : deviceInfo.sampleRates) { for (int sr : deviceInfo.sampleRates) {
float sampleRate = sr; float sampleRate = sr;
auto allowedIt = std::find(allowedSampleRates.begin(), allowedSampleRates.end(), sampleRate); auto allowedIt = std::find(allowedSampleRates.begin(), allowedSampleRates.end(), sampleRate);
@@ -428,9 +425,9 @@ struct AudioDriverChoice : ChoiceButton {


struct AudioDeviceItem : MenuItem { struct AudioDeviceItem : MenuItem {
AudioInterface *audioInterface; AudioInterface *audioInterface;
int deviceId;
int device;
void onAction(EventAction &e) override { void onAction(EventAction &e) override {
audioInterface->deviceId = deviceId;
audioInterface->device = device;
audioInterface->openStream(); audioInterface->openStream();
} }
}; };
@@ -447,23 +444,23 @@ struct AudioDeviceChoice : ChoiceButton {
{ {
AudioDeviceItem *audioItem = new AudioDeviceItem(); AudioDeviceItem *audioItem = new AudioDeviceItem();
audioItem->audioInterface = audioInterface; audioItem->audioInterface = audioInterface;
audioItem->deviceId = -1;
audioItem->device = -1;
audioItem->text = "No device"; audioItem->text = "No device";
menu->pushChild(audioItem); menu->pushChild(audioItem);
} }
for (int deviceId = 0; deviceId < deviceCount; deviceId++) {
for (int device = 0; device < deviceCount; device++) {
AudioDeviceItem *audioItem = new AudioDeviceItem(); AudioDeviceItem *audioItem = new AudioDeviceItem();
audioItem->audioInterface = audioInterface; audioItem->audioInterface = audioInterface;
audioItem->deviceId = deviceId;
audioItem->text = audioInterface->getDeviceName(deviceId);
audioItem->device = device;
audioItem->text = audioInterface->getDeviceName(device);
menu->pushChild(audioItem); menu->pushChild(audioItem);
} }
} }
void step() override { void step() override {
if (lastDeviceId != audioInterface->deviceId) {
std::string name = audioInterface->getDeviceName(audioInterface->deviceId);
if (lastDeviceId != audioInterface->device) {
std::string name = audioInterface->getDeviceName(audioInterface->device);
text = ellipsize(name, 24); text = ellipsize(name, 24);
lastDeviceId = audioInterface->deviceId;
lastDeviceId = audioInterface->device;
} }
} }
}; };
@@ -546,77 +543,77 @@ AudioInterfaceWidget::AudioInterfaceWidget() {
// addChild(createScrew<ScrewSilver>(Vec(15, 365))); // addChild(createScrew<ScrewSilver>(Vec(15, 365)));
// addChild(createScrew<ScrewSilver>(Vec(box.size.x-30, 365))); // addChild(createScrew<ScrewSilver>(Vec(box.size.x-30, 365)));


float margin = 5;
Vec margin = Vec(5, 2);
float labelHeight = 15; float labelHeight = 15;
float yPos = margin;
float yPos = margin.y;
float xPos; float xPos;


{ {
Label *label = new Label(); Label *label = new Label();
label->box.pos = Vec(margin, yPos);
label->box.pos = Vec(margin.x, yPos);
label->text = "Audio driver"; label->text = "Audio driver";
addChild(label); addChild(label);
yPos += labelHeight + margin;
yPos += labelHeight + margin.y;


AudioDriverChoice *choice = new AudioDriverChoice(); AudioDriverChoice *choice = new AudioDriverChoice();
choice->audioInterface = module; choice->audioInterface = module;
choice->box.pos = Vec(margin, yPos);
choice->box.size.x = box.size.x - 2*margin;
choice->box.pos = Vec(margin.x, yPos);
choice->box.size.x = box.size.x - 2*margin.x;
addChild(choice); addChild(choice);
yPos += choice->box.size.y + margin;
yPos += choice->box.size.y + margin.y;
} }


{ {
Label *label = new Label(); Label *label = new Label();
label->box.pos = Vec(margin, yPos);
label->box.pos = Vec(margin.x, yPos);
label->text = "Audio device"; label->text = "Audio device";
addChild(label); addChild(label);
yPos += labelHeight + margin;
yPos += labelHeight + margin.y;


AudioDeviceChoice *choice = new AudioDeviceChoice(); AudioDeviceChoice *choice = new AudioDeviceChoice();
choice->audioInterface = module; choice->audioInterface = module;
choice->box.pos = Vec(margin, yPos);
choice->box.size.x = box.size.x - 2*margin;
choice->box.pos = Vec(margin.x, yPos);
choice->box.size.x = box.size.x - 2*margin.x;
addChild(choice); addChild(choice);
yPos += choice->box.size.y + margin;
yPos += choice->box.size.y + margin.y;
} }


{ {
Label *label = new Label(); Label *label = new Label();
label->box.pos = Vec(margin, yPos);
label->box.pos = Vec(margin.x, yPos);
label->text = "Sample rate"; label->text = "Sample rate";
addChild(label); addChild(label);
yPos += labelHeight + margin;
yPos += labelHeight + margin.y;


SampleRateChoice *choice = new SampleRateChoice(); SampleRateChoice *choice = new SampleRateChoice();
choice->audioInterface = module; choice->audioInterface = module;
choice->box.pos = Vec(margin, yPos);
choice->box.size.x = box.size.x - 2*margin;
choice->box.pos = Vec(margin.x, yPos);
choice->box.size.x = box.size.x - 2*margin.x;
addChild(choice); addChild(choice);
yPos += choice->box.size.y + margin;
yPos += choice->box.size.y + margin.y;
} }


{ {
Label *label = new Label(); Label *label = new Label();
label->box.pos = Vec(margin, yPos);
label->box.pos = Vec(margin.x, yPos);
label->text = "Block size"; label->text = "Block size";
addChild(label); addChild(label);
yPos += labelHeight + margin;
yPos += labelHeight + margin.y;


BlockSizeChoice *choice = new BlockSizeChoice(); BlockSizeChoice *choice = new BlockSizeChoice();
choice->audioInterface = module; choice->audioInterface = module;
choice->box.pos = Vec(margin, yPos);
choice->box.size.x = box.size.x - 2*margin;
choice->box.pos = Vec(margin.x, yPos);
choice->box.size.x = box.size.x - 2*margin.x;
addChild(choice); addChild(choice);
yPos += choice->box.size.y + margin;
yPos += choice->box.size.y + margin.y;
} }


{ {
Label *label = new Label(); Label *label = new Label();
label->box.pos = Vec(margin, yPos);
label->box.pos = Vec(margin.x, yPos);
label->text = "Outputs"; label->text = "Outputs";
addChild(label); addChild(label);
yPos += labelHeight + margin;
yPos += labelHeight + margin.y;
} }


yPos += 5; yPos += 5;
@@ -628,9 +625,9 @@ AudioInterfaceWidget::AudioInterfaceWidget() {
label->text = stringf("%d", i + 1); label->text = stringf("%d", i + 1);
addChild(label); addChild(label);


xPos += 37 + margin;
xPos += 37 + margin.x;
} }
yPos += 35 + margin;
yPos += 35 + margin.y;


yPos += 5; yPos += 5;
xPos = 10; xPos = 10;
@@ -641,16 +638,16 @@ AudioInterfaceWidget::AudioInterfaceWidget() {
label->text = stringf("%d", i + 1); label->text = stringf("%d", i + 1);
addChild(label); addChild(label);


xPos += 37 + margin;
xPos += 37 + margin.x;
} }
yPos += 35 + margin;
yPos += 35 + margin.y;


{ {
Label *label = new Label(); Label *label = new Label();
label->box.pos = Vec(margin, yPos);
label->box.pos = Vec(margin.x, yPos);
label->text = "Inputs"; label->text = "Inputs";
addChild(label); addChild(label);
yPos += labelHeight + margin;
yPos += labelHeight + margin.y;
} }


yPos += 5; yPos += 5;
@@ -662,9 +659,9 @@ AudioInterfaceWidget::AudioInterfaceWidget() {
label->text = stringf("%d", i + 1); label->text = stringf("%d", i + 1);
addChild(label); addChild(label);


xPos += 37 + margin;
xPos += 37 + margin.x;
} }
yPos += 35 + margin;
yPos += 35 + margin.y;


yPos += 5; yPos += 5;
xPos = 10; xPos = 10;
@@ -675,7 +672,7 @@ AudioInterfaceWidget::AudioInterfaceWidget() {
label->text = stringf("%d", i + 1); label->text = stringf("%d", i + 1);
addChild(label); addChild(label);


xPos += 37 + margin;
xPos += 37 + margin.x;
} }
yPos += 35 + margin;
yPos += 35 + margin.y;
} }

Loading…
Cancel
Save