@@ -1,14 +1,18 @@ | |||||
#pragma once | #pragma once | ||||
#include "audio.hpp" | |||||
#define BRIDGE_CHANNELS 16 | |||||
namespace rack { | |||||
namespace rack { | |||||
static const int BRIDGE_CHANNELS = 16; | |||||
void bridgeInit(); | void bridgeInit(); | ||||
void bridgeDestroy(); | void bridgeDestroy(); | ||||
void bridgeAudioSubscribe(int channel, AudioIO *audio); | |||||
void bridgeAudioUnsubscribe(int channel, AudioIO *audio); | |||||
bool bridgeAudioIsSubscribed(int channel, AudioIO *audio); | |||||
} // namespace rack | } // namespace rack |
@@ -18,8 +18,6 @@ | |||||
#define OUTPUTS 8 | #define OUTPUTS 8 | ||||
#define INPUTS 8 | #define INPUTS 8 | ||||
static const auto audioTimeout = std::chrono::milliseconds(100); | |||||
using namespace rack; | using namespace rack; | ||||
@@ -60,7 +58,8 @@ struct AudioInterfaceIO : AudioIO { | |||||
auto cond = [&] { | auto cond = [&] { | ||||
return (outputBuffer.size() >= (size_t) length); | return (outputBuffer.size() >= (size_t) length); | ||||
}; | }; | ||||
if (audioCv.wait_for(lock, audioTimeout, cond)) { | |||||
auto timeout = std::chrono::duration<float>(0.1); | |||||
if (audioCv.wait_for(lock, timeout, cond)) { | |||||
// Consume audio block | // Consume audio block | ||||
for (int i = 0; i < length; i++) { | for (int i = 0; i < length; i++) { | ||||
Frame<OUTPUTS> f = outputBuffer.shift(); | Frame<OUTPUTS> f = outputBuffer.shift(); | ||||
@@ -189,7 +188,8 @@ void AudioInterface::step() { | |||||
auto cond = [&] { | auto cond = [&] { | ||||
return (audioIO.outputBuffer.size() < (size_t) audioIO.blockSize); | return (audioIO.outputBuffer.size() < (size_t) audioIO.blockSize); | ||||
}; | }; | ||||
if (audioIO.engineCv.wait_for(lock, audioTimeout, cond)) { | |||||
auto timeout = std::chrono::duration<float>(0.1); | |||||
if (audioIO.engineCv.wait_for(lock, timeout, cond)) { | |||||
// Push converted output | // Push converted output | ||||
int inLen = outputBuffer.size(); | int inLen = outputBuffer.size(); | ||||
int outLen = audioIO.outputBuffer.capacity(); | int outLen = audioIO.outputBuffer.capacity(); | ||||
@@ -3,7 +3,7 @@ | |||||
#include "bridge.hpp" | #include "bridge.hpp" | ||||
#define BRIDGE_DRIVER -1 | |||||
#define BRIDGE_DRIVER -5000 | |||||
namespace rack { | namespace rack { | ||||
@@ -60,7 +60,6 @@ void AudioIO::setDriver(int driver) { | |||||
this->driver = (int) rtAudio->getCurrentApi(); | this->driver = (int) rtAudio->getCurrentApi(); | ||||
} | } | ||||
else if (driver == BRIDGE_DRIVER) { | else if (driver == BRIDGE_DRIVER) { | ||||
// TODO Connect to Bridge | |||||
this->driver = BRIDGE_DRIVER; | this->driver = BRIDGE_DRIVER; | ||||
} | } | ||||
} | } | ||||
@@ -253,13 +252,19 @@ void AudioIO::openStream() { | |||||
onOpenStream(); | onOpenStream(); | ||||
} | } | ||||
if (driver == BRIDGE_DRIVER) { | if (driver == BRIDGE_DRIVER) { | ||||
if (device < BRIDGE_CHANNELS) { | |||||
// TODO | |||||
} | |||||
numOutputs = 2; | |||||
numInputs = 2; | |||||
// TEMP | |||||
sampleRate = 44100; | |||||
blockSize = 256; | |||||
bridgeAudioSubscribe(device, this); | |||||
} | } | ||||
} | } | ||||
void AudioIO::closeStream() { | void AudioIO::closeStream() { | ||||
numOutputs = 0; | |||||
numInputs = 0; | |||||
if (rtAudio) { | if (rtAudio) { | ||||
if (rtAudio->isStreamRunning()) { | if (rtAudio->isStreamRunning()) { | ||||
info("Stopping RtAudio stream %d", device); | info("Stopping RtAudio stream %d", device); | ||||
@@ -281,14 +286,20 @@ void AudioIO::closeStream() { | |||||
} | } | ||||
deviceInfo = RtAudio::DeviceInfo(); | deviceInfo = RtAudio::DeviceInfo(); | ||||
} | } | ||||
if (driver == BRIDGE_DRIVER) { | |||||
bridgeAudioUnsubscribe(device, this); | |||||
} | |||||
onCloseStream(); | onCloseStream(); | ||||
} | } | ||||
bool AudioIO::isActive() { | bool AudioIO::isActive() { | ||||
if (rtAudio) | |||||
if (rtAudio) { | |||||
return rtAudio->isStreamRunning(); | return rtAudio->isStreamRunning(); | ||||
// TODO Bridge | |||||
} | |||||
if (driver == BRIDGE_DRIVER) { | |||||
bridgeAudioIsSubscribed(device, this); | |||||
} | |||||
return false; | return false; | ||||
} | } | ||||
@@ -2,8 +2,6 @@ | |||||
#include "util/common.hpp" | #include "util/common.hpp" | ||||
#include "dsp/ringbuffer.hpp" | #include "dsp/ringbuffer.hpp" | ||||
#include <thread> | |||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
@@ -11,12 +9,12 @@ | |||||
#include <netinet/tcp.h> | #include <netinet/tcp.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <thread> | |||||
namespace rack { | namespace rack { | ||||
enum BridgeCommand { | enum BridgeCommand { | ||||
NO_COMMAND = 0, | NO_COMMAND = 0, | ||||
START_COMMAND, | START_COMMAND, | ||||
@@ -30,14 +28,14 @@ enum BridgeCommand { | |||||
}; | }; | ||||
static const int RECV_BUFFER_SIZE = (1<<13); | |||||
static const int RECV_QUEUE_SIZE = (1<<17); | |||||
static AudioIO *audioListeners[BRIDGE_CHANNELS]; | |||||
static std::thread serverThread; | static std::thread serverThread; | ||||
static bool serverQuit; | static bool serverQuit; | ||||
#define RECV_BUFFER_SIZE (1<<13) | |||||
#define RECV_QUEUE_SIZE (1<<17) | |||||
struct BridgeClientConnection { | struct BridgeClientConnection { | ||||
RingBuffer<uint8_t, RECV_QUEUE_SIZE> recvQueue; | RingBuffer<uint8_t, RECV_QUEUE_SIZE> recvQueue; | ||||
BridgeCommand currentCommand = START_COMMAND; | BridgeCommand currentCommand = START_COMMAND; | ||||
@@ -46,19 +44,10 @@ struct BridgeClientConnection { | |||||
int sampleRate = -1; | int sampleRate = -1; | ||||
int audioChannels = 0; | int audioChannels = 0; | ||||
int audioBufferLength = -1; | int audioBufferLength = -1; | ||||
// TEMP | |||||
// FILE *audioOutputFile; | |||||
BridgeClientConnection() { | |||||
// audioOutputFile = fopen("out.f32", "w"); | |||||
// assert(audioOutputFile); | |||||
} | |||||
~BridgeClientConnection() { | |||||
// fclose(audioOutputFile); | |||||
} | |||||
/** Does not check if the queue has enough data. You must do that yourself. */ | |||||
/** Does not check if the queue has enough data. | |||||
You must do that yourself before calling this method. | |||||
*/ | |||||
template <typename T> | template <typename T> | ||||
T shift() { | T shift() { | ||||
T x; | T x; | ||||
@@ -173,7 +162,7 @@ struct BridgeClientConnection { | |||||
} | } | ||||
void recv(uint8_t *buffer, int length) { | void recv(uint8_t *buffer, int length) { | ||||
// Make sure we can fill the buffer before filling it | |||||
// Make sure we can fill the buffer | |||||
if (recvQueue.capacity() < (size_t) length) { | if (recvQueue.capacity() < (size_t) length) { | ||||
// If we can't accept it, future messages will be incomplete | // If we can't accept it, future messages will be incomplete | ||||
closeRequested = true; | closeRequested = true; | ||||
@@ -272,7 +261,7 @@ static void serverRun() { | |||||
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 | ||||
std::this_thread::sleep_for(std::chrono::duration<double>(0.1)); | |||||
std::this_thread::sleep_for(std::chrono::duration<float>(0.1)); | |||||
continue; | continue; | ||||
} | } | ||||
@@ -298,6 +287,27 @@ void bridgeDestroy() { | |||||
serverThread.join(); | serverThread.join(); | ||||
} | } | ||||
void bridgeAudioSubscribe(int channel, AudioIO *audio) { | |||||
if (!(0 <= channel && channel < BRIDGE_CHANNELS)) | |||||
return; | |||||
if (audioListeners[channel]) | |||||
return; | |||||
audioListeners[channel] = audio; | |||||
} | |||||
void bridgeAudioUnsubscribe(int channel, AudioIO *audio) { | |||||
if (!(0 <= channel && channel < BRIDGE_CHANNELS)) | |||||
return; | |||||
if (audioListeners[channel] != audio) | |||||
return; | |||||
audioListeners[channel] = NULL; | |||||
} | |||||
bool bridgeAudioIsSubscribed(int channel, AudioIO *audio) { | |||||
if (!(0 <= channel && channel < BRIDGE_CHANNELS)) | |||||
return false; | |||||
return (audioListeners[channel] == audio); | |||||
} | |||||
} // namespace rack | } // namespace rack |