@@ -1,14 +1,18 @@ | |||
#pragma once | |||
#include "audio.hpp" | |||
#define BRIDGE_CHANNELS 16 | |||
namespace rack { | |||
namespace rack { | |||
static const int BRIDGE_CHANNELS = 16; | |||
void bridgeInit(); | |||
void bridgeDestroy(); | |||
void bridgeAudioSubscribe(int channel, AudioIO *audio); | |||
void bridgeAudioUnsubscribe(int channel, AudioIO *audio); | |||
bool bridgeAudioIsSubscribed(int channel, AudioIO *audio); | |||
} // namespace rack |
@@ -18,8 +18,6 @@ | |||
#define OUTPUTS 8 | |||
#define INPUTS 8 | |||
static const auto audioTimeout = std::chrono::milliseconds(100); | |||
using namespace rack; | |||
@@ -60,7 +58,8 @@ struct AudioInterfaceIO : AudioIO { | |||
auto cond = [&] { | |||
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 | |||
for (int i = 0; i < length; i++) { | |||
Frame<OUTPUTS> f = outputBuffer.shift(); | |||
@@ -189,7 +188,8 @@ void AudioInterface::step() { | |||
auto cond = [&] { | |||
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 | |||
int inLen = outputBuffer.size(); | |||
int outLen = audioIO.outputBuffer.capacity(); | |||
@@ -3,7 +3,7 @@ | |||
#include "bridge.hpp" | |||
#define BRIDGE_DRIVER -1 | |||
#define BRIDGE_DRIVER -5000 | |||
namespace rack { | |||
@@ -60,7 +60,6 @@ void AudioIO::setDriver(int driver) { | |||
this->driver = (int) rtAudio->getCurrentApi(); | |||
} | |||
else if (driver == BRIDGE_DRIVER) { | |||
// TODO Connect to Bridge | |||
this->driver = BRIDGE_DRIVER; | |||
} | |||
} | |||
@@ -253,13 +252,19 @@ void AudioIO::openStream() { | |||
onOpenStream(); | |||
} | |||
if (driver == BRIDGE_DRIVER) { | |||
if (device < BRIDGE_CHANNELS) { | |||
// TODO | |||
} | |||
numOutputs = 2; | |||
numInputs = 2; | |||
// TEMP | |||
sampleRate = 44100; | |||
blockSize = 256; | |||
bridgeAudioSubscribe(device, this); | |||
} | |||
} | |||
void AudioIO::closeStream() { | |||
numOutputs = 0; | |||
numInputs = 0; | |||
if (rtAudio) { | |||
if (rtAudio->isStreamRunning()) { | |||
info("Stopping RtAudio stream %d", device); | |||
@@ -281,14 +286,20 @@ void AudioIO::closeStream() { | |||
} | |||
deviceInfo = RtAudio::DeviceInfo(); | |||
} | |||
if (driver == BRIDGE_DRIVER) { | |||
bridgeAudioUnsubscribe(device, this); | |||
} | |||
onCloseStream(); | |||
} | |||
bool AudioIO::isActive() { | |||
if (rtAudio) | |||
if (rtAudio) { | |||
return rtAudio->isStreamRunning(); | |||
// TODO Bridge | |||
} | |||
if (driver == BRIDGE_DRIVER) { | |||
bridgeAudioIsSubscribed(device, this); | |||
} | |||
return false; | |||
} | |||
@@ -2,8 +2,6 @@ | |||
#include "util/common.hpp" | |||
#include "dsp/ringbuffer.hpp" | |||
#include <thread> | |||
#include <unistd.h> | |||
#include <sys/socket.h> | |||
#include <netinet/in.h> | |||
@@ -11,12 +9,12 @@ | |||
#include <netinet/tcp.h> | |||
#include <fcntl.h> | |||
#include <thread> | |||
namespace rack { | |||
enum BridgeCommand { | |||
NO_COMMAND = 0, | |||
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 bool serverQuit; | |||
#define RECV_BUFFER_SIZE (1<<13) | |||
#define RECV_QUEUE_SIZE (1<<17) | |||
struct BridgeClientConnection { | |||
RingBuffer<uint8_t, RECV_QUEUE_SIZE> recvQueue; | |||
BridgeCommand currentCommand = START_COMMAND; | |||
@@ -46,19 +44,10 @@ struct BridgeClientConnection { | |||
int sampleRate = -1; | |||
int audioChannels = 0; | |||
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> | |||
T shift() { | |||
T x; | |||
@@ -173,7 +162,7 @@ struct BridgeClientConnection { | |||
} | |||
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 we can't accept it, future messages will be incomplete | |||
closeRequested = true; | |||
@@ -272,7 +261,7 @@ static void serverRun() { | |||
int client = accept(server, NULL, NULL); | |||
if (client < 0) { | |||
// 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; | |||
} | |||
@@ -298,6 +287,27 @@ void bridgeDestroy() { | |||
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 |