Browse Source

Bridge server progress

tags/v0.6.0
Andrew Belt 7 years ago
parent
commit
04ba73454c
4 changed files with 71 additions and 50 deletions
  1. +2
    -2
      include/audio.hpp
  2. +9
    -2
      src/app/AudioWidget.cpp
  3. +31
    -27
      src/audio.cpp
  4. +29
    -19
      src/bridge.cpp

+ 2
- 2
include/audio.hpp View File

@@ -40,7 +40,9 @@ struct AudioIO {
std::string getDeviceDetail(int device, int offset); std::string getDeviceDetail(int device, int offset);
void setDevice(int device, int offset); void setDevice(int device, int offset);


std::vector<int> getSampleRates();
void setSampleRate(int sampleRate); void setSampleRate(int sampleRate);
std::vector<int> getBlockSizes();
void setBlockSize(int blockSize); void setBlockSize(int blockSize);


void setChannels(int numOutputs, int numInputs); void setChannels(int numOutputs, int numInputs);
@@ -49,8 +51,6 @@ struct AudioIO {
void openStream(); void openStream();
void closeStream(); void closeStream();


std::vector<int> getSampleRates();

virtual void processStream(const float *input, float *output, int frames) {} virtual void processStream(const float *input, float *output, int frames) {}
virtual void onCloseStream() {} virtual void onCloseStream() {}
virtual void onOpenStream() {} virtual void onOpenStream() {}


+ 9
- 2
src/app/AudioWidget.cpp View File

@@ -98,7 +98,11 @@ struct AudioSampleRateChoice : LedDisplayChoice {
void onAction(EventAction &e) override { void onAction(EventAction &e) override {
Menu *menu = gScene->createMenu(); Menu *menu = gScene->createMenu();
menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Sample rate")); menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Sample rate"));
for (int sampleRate : audioWidget->audioIO->getSampleRates()) {
std::vector<int> sampleRates = audioWidget->audioIO->getSampleRates();
if (sampleRates.empty()) {
menu->addChild(construct<MenuLabel>(&MenuLabel::text, "(None available)"));
}
for (int sampleRate : sampleRates) {
AudioSampleRateItem *item = new AudioSampleRateItem(); AudioSampleRateItem *item = new AudioSampleRateItem();
item->audioIO = audioWidget->audioIO; item->audioIO = audioWidget->audioIO;
item->sampleRate = sampleRate; item->sampleRate = sampleRate;
@@ -126,7 +130,10 @@ struct AudioBlockSizeChoice : LedDisplayChoice {
void onAction(EventAction &e) override { void onAction(EventAction &e) override {
Menu *menu = gScene->createMenu(); Menu *menu = gScene->createMenu();
menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Block size")); menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Block size"));
std::vector<int> blockSizes = {64, 128, 256, 512, 1024, 2048, 4096};
std::vector<int> blockSizes = audioWidget->audioIO->getBlockSizes();
if (blockSizes.empty()) {
menu->addChild(construct<MenuLabel>(&MenuLabel::text, "(None available)"));
}
for (int blockSize : blockSizes) { for (int blockSize : blockSizes) {
AudioBlockSizeItem *item = new AudioBlockSizeItem(); AudioBlockSizeItem *item = new AudioBlockSizeItem();
item->audioIO = audioWidget->audioIO; item->audioIO = audioWidget->audioIO;


+ 31
- 27
src/audio.cpp View File

@@ -70,7 +70,7 @@ int AudioIO::getDeviceCount() {
if (rtAudio) { if (rtAudio) {
return rtAudio->getDeviceCount(); return rtAudio->getDeviceCount();
} }
if (driver == BRIDGE_DRIVER) {
else if (driver == BRIDGE_DRIVER) {
return BRIDGE_NUM_PORTS; return BRIDGE_NUM_PORTS;
} }
return 0; return 0;
@@ -108,7 +108,7 @@ int AudioIO::getDeviceChannels(int device) {
if (getDeviceInfo(device, &deviceInfo)) if (getDeviceInfo(device, &deviceInfo))
return max((int) deviceInfo.inputChannels, (int) deviceInfo.outputChannels); return max((int) deviceInfo.inputChannels, (int) deviceInfo.outputChannels);
} }
if (driver == BRIDGE_DRIVER) {
else if (driver == BRIDGE_DRIVER) {
return 2; return 2;
} }
return 0; return 0;
@@ -123,7 +123,7 @@ std::string AudioIO::getDeviceName(int device) {
if (getDeviceInfo(device, &deviceInfo)) if (getDeviceInfo(device, &deviceInfo))
return deviceInfo.name; return deviceInfo.name;
} }
if (driver == BRIDGE_DRIVER) {
else if (driver == BRIDGE_DRIVER) {
return stringf("%d", device + 1); return stringf("%d", device + 1);
} }
return ""; return "";
@@ -147,7 +147,7 @@ std::string AudioIO::getDeviceDetail(int device, int offset) {
return deviceDetail; return deviceDetail;
} }
} }
if (driver == BRIDGE_DRIVER) {
else if (driver == BRIDGE_DRIVER) {
return stringf("Port %d", device + 1); return stringf("Port %d", device + 1);
} }
return ""; return "";
@@ -160,13 +160,38 @@ void AudioIO::setDevice(int device, int offset) {
openStream(); openStream();
} }


std::vector<int> AudioIO::getSampleRates() {
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());
}
}
return {};
}

void AudioIO::setSampleRate(int sampleRate) { void AudioIO::setSampleRate(int sampleRate) {
if (sampleRate == this->sampleRate)
return;
closeStream(); closeStream();
this->sampleRate = sampleRate; this->sampleRate = sampleRate;
openStream(); openStream();
} }


std::vector<int> AudioIO::getBlockSizes() {
if (rtAudio) {
return {64, 128, 256, 512, 1024, 2048, 4096};
}
return {};
}

void AudioIO::setBlockSize(int blockSize) { void AudioIO::setBlockSize(int blockSize) {
if (blockSize == this->blockSize)
return;
closeStream(); closeStream();
this->blockSize = blockSize; this->blockSize = blockSize;
openStream(); openStream();
@@ -256,11 +281,8 @@ void AudioIO::openStream() {
this->sampleRate = rtAudio->getStreamSampleRate(); this->sampleRate = rtAudio->getStreamSampleRate();
onOpenStream(); onOpenStream();
} }
if (driver == BRIDGE_DRIVER) {
else if (driver == BRIDGE_DRIVER) {
setChannels(0, 0); setChannels(0, 0);
// TEMP
sampleRate = 44100;
blockSize = 256;
bridgeAudioSubscribe(device, this); bridgeAudioSubscribe(device, this);
} }
} }
@@ -289,31 +311,13 @@ void AudioIO::closeStream() {
} }
deviceInfo = RtAudio::DeviceInfo(); deviceInfo = RtAudio::DeviceInfo();
} }
if (driver == BRIDGE_DRIVER) {
else if (driver == BRIDGE_DRIVER) {
bridgeAudioUnsubscribe(device, this); bridgeAudioUnsubscribe(device, this);
} }


onCloseStream(); onCloseStream();
} }


std::vector<int> AudioIO::getSampleRates() {
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 == BRIDGE_DRIVER) {
return {44100, 48000, 88200, 96000, 176400, 192000};
}

return {};
}

json_t *AudioIO::toJson() { json_t *AudioIO::toJson() {
json_t *rootJ = json_object(); json_t *rootJ = json_object();
json_object_set_new(rootJ, "driver", json_integer(driver)); json_object_set_new(rootJ, "driver", json_integer(driver));


+ 29
- 19
src/bridge.cpp View File

@@ -21,14 +21,11 @@
namespace rack { namespace rack {




static const int RECV_BUFFER_SIZE = (1<<13);
static const int RECV_QUEUE_SIZE = (1<<17);

struct BridgeClientConnection; struct BridgeClientConnection;
static BridgeClientConnection *connections[BRIDGE_NUM_PORTS] = {}; static BridgeClientConnection *connections[BRIDGE_NUM_PORTS] = {};
static AudioIO *audioListeners[BRIDGE_NUM_PORTS] = {}; static AudioIO *audioListeners[BRIDGE_NUM_PORTS] = {};
static std::thread serverThread; static std::thread serverThread;
static bool running;
static bool serverRunning = false;




struct BridgeClientConnection { struct BridgeClientConnection {
@@ -138,7 +135,7 @@ struct BridgeClientConnection {


case QUIT_COMMAND: { case QUIT_COMMAND: {
debug("Bridge client quitting"); debug("Bridge client quitting");
ready = true;
ready = false;
} break; } break;


case PORT_SET_COMMAND: { case PORT_SET_COMMAND: {
@@ -150,7 +147,7 @@ struct BridgeClientConnection {
case MIDI_MESSAGE_SEND_COMMAND: { case MIDI_MESSAGE_SEND_COMMAND: {
uint8_t midiBuffer[3]; uint8_t midiBuffer[3];
recv(&midiBuffer, 3); recv(&midiBuffer, 3);
// debug("MIDI: %02x %02x %02x", midiBuffer[0], midiBuffer[1], midiBuffer[2]);
debug("MIDI: %02x %02x %02x", midiBuffer[0], midiBuffer[1], midiBuffer[2]);
} break; } break;


case AUDIO_SAMPLE_RATE_SET_COMMAND: { case AUDIO_SAMPLE_RATE_SET_COMMAND: {
@@ -174,9 +171,13 @@ struct BridgeClientConnection {
} }


float input[length]; float input[length];
recv(&input, length * sizeof(float));
if (!recv(&input, length * sizeof(float))) {
ready = false;
return;
}
float output[length]; float output[length];
int frames = length / 2; int frames = length / 2;
memset(&output, 0, sizeof(output));
processStream(input, output, frames); processStream(input, output, frames);
send(&output, length * sizeof(float)); send(&output, length * sizeof(float));
flush(); flush();
@@ -184,12 +185,12 @@ struct BridgeClientConnection {


case AUDIO_ACTIVATE: { case AUDIO_ACTIVATE: {
audioActive = true; audioActive = true;
refreshAudioActive();
refreshAudio();
} break; } break;


case AUDIO_DEACTIVATE: { case AUDIO_DEACTIVATE: {
audioActive = false; audioActive = false;
refreshAudioActive();
refreshAudio();
} break; } break;
} }
} }
@@ -206,7 +207,7 @@ struct BridgeClientConnection {
if ((0 <= port && port < BRIDGE_NUM_PORTS) && !connections[port]) { if ((0 <= port && port < BRIDGE_NUM_PORTS) && !connections[port]) {
this->port = port; this->port = port;
connections[this->port] = this; connections[this->port] = this;
refreshAudioActive();
refreshAudio();
} }
else { else {
this->port = -1; this->port = -1;
@@ -214,8 +215,8 @@ struct BridgeClientConnection {
} }


void setSampleRate(int sampleRate) { void setSampleRate(int sampleRate) {
// TODO
this->sampleRate = sampleRate; this->sampleRate = sampleRate;
refreshAudio();
} }


void processStream(const float *input, float *output, int frames) { void processStream(const float *input, float *output, int frames) {
@@ -223,19 +224,22 @@ struct BridgeClientConnection {
return; return;
if (!audioListeners[port]) if (!audioListeners[port])
return; return;
audioListeners[port]->setBlockSize(frames);
audioListeners[port]->processStream(input, output, frames); audioListeners[port]->processStream(input, output, frames);
debug("%d frames", frames);
} }


void refreshAudioActive() {
void refreshAudio() {
if (!(0 <= port && port < BRIDGE_NUM_PORTS)) if (!(0 <= port && port < BRIDGE_NUM_PORTS))
return; return;
if (connections[port] != this)
return;
if (!audioListeners[port]) if (!audioListeners[port])
return; return;
if (audioActive) if (audioActive)
audioListeners[port]->setChannels(2, 2); audioListeners[port]->setChannels(2, 2);
else else
audioListeners[port]->setChannels(0, 0); audioListeners[port]->setChannels(0, 0);
audioListeners[port]->setSampleRate(sampleRate);
} }
}; };


@@ -267,13 +271,13 @@ static void clientRun(int client) {
} }




static void serverRun() {
static void serverConnect() {
int err; int err;


// Initialize sockets // Initialize sockets
#ifdef ARCH_WIN #ifdef ARCH_WIN
WSADATA wsaData; WSADATA wsaData;
err = WSAStartup(MAKEWORD(2,2), &wsaData);
err = WSAStartup(MAKEWORD(2, 2), &wsaData);
defer({ defer({
WSACleanup(); WSACleanup();
}); });
@@ -352,8 +356,7 @@ static void serverRun() {
#endif #endif


// Accept clients // Accept clients
running = true;
while (running) {
while (serverRunning) {
int client = accept(server, NULL, NULL); int client = accept(server, NULL, NULL);
if (client < 0) { if (client < 0) {
// Wait a bit before attempting to accept another client // Wait a bit before attempting to accept another client
@@ -369,13 +372,20 @@ static void serverRun() {
info("Bridge server closed"); info("Bridge server closed");
} }


static void serverRun() {
while (serverRunning) {
std::this_thread::sleep_for(std::chrono::duration<double>(0.1));
serverConnect();
}
}


void bridgeInit() { void bridgeInit() {
serverRunning = true;
serverThread = std::thread(serverRun); serverThread = std::thread(serverRun);
} }


void bridgeDestroy() { void bridgeDestroy() {
running = false;
serverRunning = false;
serverThread.join(); serverThread.join();
} }


@@ -387,7 +397,7 @@ void bridgeAudioSubscribe(int port, AudioIO *audio) {
return; return;
audioListeners[port] = audio; audioListeners[port] = audio;
if (connections[port]) if (connections[port])
connections[port]->refreshAudioActive();
connections[port]->refreshAudio();
} }


void bridgeAudioUnsubscribe(int port, AudioIO *audio) { void bridgeAudioUnsubscribe(int port, AudioIO *audio) {


Loading…
Cancel
Save