Browse Source

libjack: mixdown streams of multiple clients. neat :)

tags/1.9.8
falkTX 7 years ago
parent
commit
5814441c1a
5 changed files with 73 additions and 30 deletions
  1. +4
    -4
      resources/ui/carla_add_jack.ui
  2. +2
    -0
      source/libjack/Makefile
  3. +64
    -23
      source/libjack/libjack.cpp
  4. +1
    -1
      source/libjack/libjack.hpp
  5. +2
    -2
      source/libjack/libjack_ports.cpp

+ 4
- 4
resources/ui/carla_add_jack.ui View File

@@ -315,7 +315,7 @@
<item row="0" column="6"> <item row="0" column="6">
<widget class="QLabel" name="label_7"> <widget class="QLabel" name="label_7">
<property name="enabled"> <property name="enabled">
<bool>true</bool>
<bool>false</bool>
</property> </property>
<property name="text"> <property name="text">
<string>MIDI inputs:</string> <string>MIDI inputs:</string>
@@ -328,7 +328,7 @@
<item row="0" column="7"> <item row="0" column="7">
<widget class="QSpinBox" name="sb_midi_ins"> <widget class="QSpinBox" name="sb_midi_ins">
<property name="enabled"> <property name="enabled">
<bool>true</bool>
<bool>false</bool>
</property> </property>
<property name="maximum"> <property name="maximum">
<number>1</number> <number>1</number>
@@ -358,7 +358,7 @@
<item row="1" column="6"> <item row="1" column="6">
<widget class="QLabel" name="label_8"> <widget class="QLabel" name="label_8">
<property name="enabled"> <property name="enabled">
<bool>true</bool>
<bool>false</bool>
</property> </property>
<property name="text"> <property name="text">
<string>MIDI outputs:</string> <string>MIDI outputs:</string>
@@ -371,7 +371,7 @@
<item row="1" column="7"> <item row="1" column="7">
<widget class="QSpinBox" name="sb_midi_outs"> <widget class="QSpinBox" name="sb_midi_outs">
<property name="enabled"> <property name="enabled">
<bool>true</bool>
<bool>false</bool>
</property> </property>
<property name="maximum"> <property name="maximum">
<number>1</number> <number>1</number>


+ 2
- 0
source/libjack/Makefile View File

@@ -24,6 +24,8 @@ endif
BUILD_C_FLAGS += -I$(CWD) -I$(CWD)/includes BUILD_C_FLAGS += -I$(CWD) -I$(CWD)/includes
BUILD_CXX_FLAGS += -I$(CWD) -I$(CWD)/backend -I$(CWD)/includes -I$(CWD)/modules -I$(CWD)/utils BUILD_CXX_FLAGS += -I$(CWD) -I$(CWD)/backend -I$(CWD)/includes -I$(CWD)/modules -I$(CWD)/utils
LINK_FLAGS += $(MODULEDIR)/juce_core.a LINK_FLAGS += $(MODULEDIR)/juce_core.a
LINK_FLAGS += $(MODULEDIR)/juce_audio_basics.a
LINK_FLAGS += $(JUCE_AUDIO_BASICS_LIBS)
LINK_FLAGS += $(JUCE_CORE_LIBS) LINK_FLAGS += $(JUCE_CORE_LIBS)


# ---------------------------------------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------------------------------------


+ 64
- 23
source/libjack/libjack.cpp View File

@@ -19,6 +19,7 @@
#include "libjack.hpp" #include "libjack.hpp"


using juce::File; using juce::File;
using juce::FloatVectorOperations;
using juce::MemoryBlock; using juce::MemoryBlock;
using juce::String; using juce::String;
using juce::Time; using juce::Time;
@@ -37,6 +38,7 @@ public:
CarlaJackAppClient() CarlaJackAppClient()
: Thread("CarlaJackAppClient"), : Thread("CarlaJackAppClient"),
fServer(), fServer(),
fAudioPoolCopy(nullptr),
fIsValid(false), fIsValid(false),
fIsOffline(false), fIsOffline(false),
fLastPingTime(-1) fLastPingTime(-1)
@@ -130,6 +132,8 @@ private:
BridgeNonRtClientControl fShmNonRtClientControl; BridgeNonRtClientControl fShmNonRtClientControl;
BridgeNonRtServerControl fShmNonRtServerControl; BridgeNonRtServerControl fShmNonRtServerControl;


float* fAudioPoolCopy;

char fBaseNameAudioPool[6+1]; char fBaseNameAudioPool[6+1];
char fBaseNameRtClientControl[6+1]; char fBaseNameRtClientControl[6+1];
char fBaseNameNonRtClientControl[6+1]; char fBaseNameNonRtClientControl[6+1];
@@ -161,6 +165,12 @@ private:


void CarlaJackAppClient::clear() noexcept void CarlaJackAppClient::clear() noexcept
{ {
if (fAudioPoolCopy != nullptr)
{
delete[] fAudioPoolCopy;
fAudioPoolCopy = nullptr;
}

fShmAudioPool.clear(); fShmAudioPool.clear();
fShmRtClientControl.clear(); fShmRtClientControl.clear();
fShmNonRtClientControl.clear(); fShmNonRtClientControl.clear();
@@ -420,9 +430,15 @@ void CarlaJackAppClient::run()
jackbridge_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data); jackbridge_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data);
fShmAudioPool.data = nullptr; fShmAudioPool.data = nullptr;
} }
if (fAudioPoolCopy != nullptr)
{
delete[] fAudioPoolCopy;
fAudioPoolCopy = nullptr;
}
const uint64_t poolSize(fShmRtClientControl.readULong()); const uint64_t poolSize(fShmRtClientControl.readULong());
CARLA_SAFE_ASSERT_BREAK(poolSize > 0); CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast<size_t>(poolSize)); fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast<size_t>(poolSize));
fAudioPoolCopy = new float[poolSize];
break; break;
} }


@@ -441,11 +457,17 @@ void CarlaJackAppClient::run()


if (cmtl.wasLocked()) if (cmtl.wasLocked())
{ {
float* fdata = fShmAudioPool.data;
// location to start of audio outputs (shm buffer)
float* const fdataRealOuts = fShmAudioPool.data+(fServer.bufferSize*fNumPorts.audioIns);


// silence outputs first
if (fNumPorts.audioOuts > 0)
FloatVectorOperations::clear(fdataRealOuts, fServer.bufferSize*fNumPorts.audioOuts);

// see if there's any clients
if (! fClients.isEmpty()) if (! fClients.isEmpty())
{ {
// tranport for all clients
// save tranport for all clients
const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo); const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);


fServer.playing = bridgeTimeInfo.playing; fServer.playing = bridgeTimeInfo.playing;
@@ -472,21 +494,19 @@ void CarlaJackAppClient::run()
fServer.position.valid = static_cast<jack_position_bits_t>(0); fServer.position.valid = static_cast<jack_position_bits_t>(0);
} }


// now go through each client
for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next()) for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
{ {
JackClientState* const jclient(it.getValue(nullptr)); JackClientState* const jclient(it.getValue(nullptr));
CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr); CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);


int numClientOutputsProcessed = 0;

const CarlaMutexTryLocker cmtl2(jclient->mutex); const CarlaMutexTryLocker cmtl2(jclient->mutex);


// check if we can process
if (cmtl2.wasNotLocked() || jclient->processCb == nullptr || ! jclient->activated) if (cmtl2.wasNotLocked() || jclient->processCb == nullptr || ! jclient->activated)
{ {
if (fNumPorts.audioIns > 0)
fdata += fServer.bufferSize*fNumPorts.audioIns;

if (fNumPorts.audioOuts > 0)
carla_zeroFloats(fdata, fServer.bufferSize*fNumPorts.audioOuts);

if (jclient->deactivated) if (jclient->deactivated)
{ {
fShmRtClientControl.data->procFlags = 1; fShmRtClientControl.data->procFlags = 1;
@@ -495,43 +515,64 @@ void CarlaJackAppClient::run()
else else
{ {
uint32_t i; uint32_t i;
// direct access to shm buffer, used only for inputs
float* fdataReal = fShmAudioPool.data;
// safe temp location for output, mixed down to shm buffer later on
float* fdataCopy = fAudioPoolCopy;


// set inputs
i = 0; i = 0;
for (LinkedList<JackPortState*>::Itenerator it = jclient->audioIns.begin2(); it.valid(); it.next()) for (LinkedList<JackPortState*>::Itenerator it = jclient->audioIns.begin2(); it.valid(); it.next())
{ {
CARLA_SAFE_ASSERT_BREAK(i++ < fNumPorts.audioIns); CARLA_SAFE_ASSERT_BREAK(i++ < fNumPorts.audioIns);
if (JackPortState* const jport = it.getValue(nullptr)) if (JackPortState* const jport = it.getValue(nullptr))
jport->buffer = fdata;
fdata += fServer.bufferSize;
jport->buffer = fdataReal;
fdataReal += fServer.bufferSize;
fdataCopy += fServer.bufferSize;
} }
// FIXME one single "if"
for (; i++ < fNumPorts.audioIns;) for (; i++ < fNumPorts.audioIns;)
fdata += fServer.bufferSize;
{
fdataReal += fServer.bufferSize;
fdataCopy += fServer.bufferSize;
}

// location to start of audio outputs
float* const fdataCopyOuts = fdataCopy;


// set ouputs
i = 0; i = 0;
for (LinkedList<JackPortState*>::Itenerator it = jclient->audioOuts.begin2(); it.valid(); it.next()) for (LinkedList<JackPortState*>::Itenerator it = jclient->audioOuts.begin2(); it.valid(); it.next())
{ {
CARLA_SAFE_ASSERT_BREAK(i++ < fNumPorts.audioOuts); CARLA_SAFE_ASSERT_BREAK(i++ < fNumPorts.audioOuts);
if (JackPortState* const jport = it.getValue(nullptr)) if (JackPortState* const jport = it.getValue(nullptr))
jport->buffer = fdata;
fdata += fServer.bufferSize;
jport->buffer = fdataCopy;
fdataCopy += fServer.bufferSize;
} }
// FIXME one single "if"
for (; i++ < fNumPorts.audioOuts;) for (; i++ < fNumPorts.audioOuts;)
{ {
carla_zeroFloats(fdata, fServer.bufferSize);
fdata += fServer.bufferSize;
FloatVectorOperations::clear(fdataCopy, fServer.bufferSize);
fdataCopy += fServer.bufferSize;
} }


jclient->processCb(fServer.bufferSize, jclient->processCbPtr); jclient->processCb(fServer.bufferSize, jclient->processCbPtr);

if (fNumPorts.audioOuts > 0)
{
++numClientOutputsProcessed;
FloatVectorOperations::add(fdataRealOuts, fdataCopyOuts,
fServer.bufferSize*fNumPorts.audioOuts);
}
} }
}
}
else
{
if (fNumPorts.audioIns > 0)
fdata += fServer.bufferSize*fNumPorts.audioIns;


if (fNumPorts.audioOuts > 0)
carla_zeroFloats(fdata, fServer.bufferSize*fNumPorts.audioOuts);
if (numClientOutputsProcessed > 1)
{
FloatVectorOperations::multiply(fdataRealOuts,
1.0f/static_cast<float>(numClientOutputsProcessed),
fServer.bufferSize*fNumPorts.audioOuts);
}
}
} }
} }
else else


+ 1
- 1
source/libjack/libjack.hpp View File

@@ -29,7 +29,7 @@
#include "LinkedList.hpp" #include "LinkedList.hpp"


#include "AppConfig.h" #include "AppConfig.h"
#include "juce_core/juce_core.h"
#include "juce_audio_basics/juce_audio_basics.h"


#if 0 #if 0
#include <jack/jack.h> #include <jack/jack.h>


+ 2
- 2
source/libjack/libjack_ports.cpp View File

@@ -77,13 +77,13 @@ int jack_port_unregister(jack_client_t* client, jack_port_t* port)


if (jport->flags & JackPortIsInput) if (jport->flags & JackPortIsInput)
{ {
CARLA_SAFE_ASSERT_RETURN(jclient->audioOuts.removeOne(jport), 1);
CARLA_SAFE_ASSERT_RETURN(jclient->audioIns.removeOne(jport), 1);
return 0; return 0;
} }


if (jport->flags & JackPortIsOutput) if (jport->flags & JackPortIsOutput)
{ {
CARLA_SAFE_ASSERT_RETURN(jclient->audioIns.removeOne(jport), 1);
CARLA_SAFE_ASSERT_RETURN(jclient->audioOuts.removeOne(jport), 1);
return 0; return 0;
} }




Loading…
Cancel
Save