Browse Source

libjack: implement midi out channel buffer mixdown

tags/v2.1-rc1
falkTX 6 years ago
parent
commit
b511d21006
2 changed files with 70 additions and 5 deletions
  1. +2
    -0
      source/backend/plugin/CarlaPluginJack.cpp
  2. +68
    -5
      source/libjack/libjack.cpp

+ 2
- 0
source/backend/plugin/CarlaPluginJack.cpp View File

@@ -31,6 +31,8 @@

#ifdef HAVE_LIBLO
# include "CarlaOscUtils.hpp"
#else
# warning No liblo support, NSM (session state) will not be available
#endif

#include "water/files/File.h"


+ 68
- 5
source/libjack/libjack.cpp View File

@@ -187,6 +187,9 @@ public:
fSessionManager = static_cast<uint>(libjackSetup[4] - '0');
fSetupHints = static_cast<uint>(libjackSetup[5] - '0');

if (fSetupHints & LIBJACK_FLAG_MIDI_OUTPUT_CHANNEL_MIXDOWN)
fServer.numMidiOuts = 16;

jack_carla_interposed_action(LIBJACK_INTERPOSER_ACTION_SET_HINTS_AND_CALLBACK,
fSetupHints,
(void*)carla_interposed_callback);
@@ -655,7 +658,9 @@ bool CarlaJackAppClient::handleRtData()
CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr);

// mixdown is default, do buffer addition (for multiple clients) if requested
const bool doBufferAddition = fSetupHints & 0x10;
const bool doBufferAddition = fSetupHints & LIBJACK_FLAG_AUDIO_BUFFERS_ADDITION;
// mixdown midi outputs based on channel if requested
const bool doMidiChanMixdown = fSetupHints & LIBJACK_FLAG_MIDI_OUTPUT_CHANNEL_MIXDOWN;

// location to start of audio outputs (shm buffer)
float* const fdataRealOuts = fShmAudioPool.data+(fServer.bufferSize*fServer.numAudioIns);
@@ -668,6 +673,9 @@ bool CarlaJackAppClient::handleRtData()
// save transport for all clients
const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);

const bool transportChanged = fServer.playing != bridgeTimeInfo.playing ||
(bridgeTimeInfo.playing && fServer.position.frame + frames != bridgeTimeInfo.frame);

fServer.playing = bridgeTimeInfo.playing;
fServer.position.frame = static_cast<jack_nframes_t>(bridgeTimeInfo.frame);
fServer.position.usecs = bridgeTimeInfo.usecs;
@@ -702,8 +710,7 @@ bool CarlaJackAppClient::handleRtData()
JackClientState* const jclient(it.getValue(nullptr));
CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);

// FIXME - lock if offline
const CarlaMutexTryLocker cmtl2(jclient->mutex);
const CarlaMutexTryLocker cmtl2(jclient->mutex, fIsOffline);

// check if we can process
if (cmtl2.wasNotLocked() || jclient->processCb == nullptr || ! jclient->activated)
@@ -716,6 +723,14 @@ bool CarlaJackAppClient::handleRtData()
}
else
{
// report transport sync changes if needed
if (transportChanged && jclient->syncCb != nullptr)
{
jclient->syncCb(fServer.playing ? JackTransportRolling : JackTransportStopped,
&fServer.position,
jclient->syncCbPtr);
}

uint8_t i;
// direct access to shm buffer, used only for inputs
float* fdataReal = fShmAudioPool.data;
@@ -871,7 +886,7 @@ bool CarlaJackAppClient::handleRtData()

if (fServer.numMidiOuts > 0)
{
uint8_t* midiData(fShmRtClientControl.data->midiOut);
uint8_t* midiData = fShmRtClientControl.data->midiOut;
carla_zeroBytes(midiData, kBridgeBaseMidiOutHeaderSize);
std::size_t curMidiDataPos = 0;

@@ -886,12 +901,16 @@ bool CarlaJackAppClient::handleRtData()
if (curMidiDataPos + kBridgeBaseMidiOutHeaderSize + jmevent.size >= kBridgeRtClientDataMidiOutSize)
break;

if (doMidiChanMixdown && MIDI_IS_CHANNEL_MESSAGE(jmevent.buffer[0]))
jmevent.buffer[0] = static_cast<jack_midi_data_t>(
(jmevent.buffer[0] & MIDI_STATUS_BIT) | (i & MIDI_CHANNEL_BIT));

// set time
*(uint32_t*)midiData = jmevent.time;
midiData += 4;

// set port
*midiData++ = i;
*midiData++ = doMidiChanMixdown ? 0 : i;

// set size
*midiData++ = static_cast<uint8_t>(jmevent.size);
@@ -904,10 +923,54 @@ bool CarlaJackAppClient::handleRtData()
}
}

// make last event null, so server stops when reaching it
if (curMidiDataPos != 0 &&
curMidiDataPos + kBridgeBaseMidiOutHeaderSize < kBridgeRtClientDataMidiOutSize)
{
carla_zeroBytes(midiData, kBridgeBaseMidiOutHeaderSize);

// sort events in case of mixdown
if (doMidiChanMixdown)
{
uint32_t time;
uint8_t size, *midiDataPtr = fShmRtClientControl.data->midiOut;
uint8_t tmp[kBridgeBaseMidiOutHeaderSize + JackMidiPortBufferBase::kMaxEventSize];
bool wasSorted = true;

for (; wasSorted;)
{
uint8_t prevSize, *prevData = midiDataPtr;
uint32_t prevTime = *(uint32_t*)midiDataPtr;
wasSorted = false;

for (;;)
{
time = *(uint32_t*)midiDataPtr;
size = *(midiDataPtr + 5); // time and port

if (size == 0)
break;

if (prevTime > time)
{
// copy previous data to a temporary place
std::memcpy(tmp, prevData, kBridgeBaseMidiOutHeaderSize + prevSize);
// override previous data with new one (shifting left)
std::memcpy(prevData, midiDataPtr, kBridgeBaseMidiOutHeaderSize + size);
// override new data with old one
std::memcpy(midiDataPtr, tmp, kBridgeBaseMidiOutHeaderSize + prevSize);
// done swapping, flag it
wasSorted = true;
}

prevTime = time;
prevSize = size;
prevData = midiDataPtr;
midiDataPtr += 6 + size;
}
}
}
}
}
}
else


Loading…
Cancel
Save