Browse Source

RtMidi input working (experimental); misc fixes

tags/1.9.4
falkTX 12 years ago
parent
commit
e83db451ae
7 changed files with 161 additions and 40 deletions
  1. +3
    -2
      source/backend/Makefile.mk
  2. +146
    -29
      source/backend/engine/CarlaEngineRtAudio.cpp
  3. +2
    -2
      source/backend/native/Makefile
  4. +1
    -0
      source/backend/standalone/CarlaStandalone.cpp
  5. +2
    -2
      source/backend/standalone/Makefile
  6. +2
    -2
      source/bridges/Makefile
  7. +5
    -3
      source/carla.py

+ 3
- 2
source/backend/Makefile.mk View File

@@ -8,8 +8,9 @@ include ../../Makefile.mk

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

BUILD_C_FLAGS += -fvisibility=hidden -fPIC -I. -I.. -I../../includes
BUILD_CXX_FLAGS += -fvisibility=hidden -fPIC -I. -I.. -I../../includes -I../../libs -I../../utils
BUILD_C_FLAGS += -pthread -fvisibility=hidden -fPIC -I. -I.. -I../../includes
BUILD_CXX_FLAGS += -pthread -fvisibility=hidden -fPIC -I. -I.. -I../../includes -I../../libs -I../../utils
LINK_FLAGS += -lpthread

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



+ 146
- 29
source/backend/engine/CarlaEngineRtAudio.cpp View File

@@ -77,8 +77,8 @@ public:
fAudioInBuf2(nullptr),
fAudioOutBuf1(nullptr),
fAudioOutBuf2(nullptr),
fMidiIn(getMatchedAudioMidiAPi(api)),
fMidiOut(getMatchedAudioMidiAPi(api))
fMidiIn(getMatchedAudioMidiAPi(api), "CarlaIn"),
fMidiOut(getMatchedAudioMidiAPi(api), "CarlaOut")
{
carla_debug("CarlaEngineRtAudio::CarlaEngineRtAudio(%i)", api);

@@ -106,6 +106,7 @@ public:
CARLA_ASSERT(fAudioInBuf2 == nullptr);
CARLA_ASSERT(fAudioOutBuf1 == nullptr);
CARLA_ASSERT(fAudioOutBuf2 == nullptr);
CARLA_ASSERT(clientName != nullptr);

if (fAudio.getDeviceCount() == 0)
{
@@ -145,7 +146,13 @@ public:
}
catch (RtError& e)
{
setLastError(e.what());
carla_stderr2("RtAudio::openStream() failed");
if (e.getType() == RtError::SYSTEM_ERROR)
setLastError("Stream cannot be opened with the specified parameters");
else if (e.getType() == RtError::INVALID_USE)
setLastError("Invalid device ID");
else
setLastError("Unknown error");
return false;
}

@@ -154,7 +161,9 @@ public:
}
catch (RtError& e)
{
carla_stderr2("RtAudio::startStream() failed");
setLastError(e.what());
fAudio.closeStream();
return false;
}

@@ -192,10 +201,20 @@ public:
fAudioIsReady = false;

if (fAudio.isStreamRunning())
fAudio.stopStream();
{
try {
fAudio.stopStream();
}
catch (...) {}
}

if (fAudio.isStreamOpen())
fAudio.closeStream();
{
try {
fAudio.closeStream();
}
catch (...) {}
}

fMidiIn.cancelCallback();
fMidiIn.closePort();
@@ -259,9 +278,10 @@ protected:
CARLA_ASSERT(insPtr != nullptr);
CARLA_ASSERT(outsPtr != nullptr);

if (currentPluginCount() == 0 || ! fAudioIsReady)
if (! fAudioIsReady)
{
carla_zeroFloat(outsPtr, sizeof(float)*nframes*2);
carla_zeroFloat(outsPtr, nframes*2);
proccessPendingEvents();
return;
}

@@ -280,21 +300,102 @@ protected:
{
std::memcpy(fAudioInBuf1, insPtr, sizeof(float)*nframes);
std::memcpy(fAudioInBuf2, insPtr+nframes, sizeof(float)*nframes);

//for (unsigned int i=0; i < nframes; i++)
// fAudioInBuf1[i] = insPtr[i];
//for (unsigned int i=0, j=nframes; i < nframes; i++, j++)
// fAudioInBuf2[i] = insPtr[j];
}

// initialize audio output
carla_zeroFloat(fAudioOutBuf1, fBufferSize);
carla_zeroFloat(fAudioOutBuf2, fBufferSize);

// initialize events input
//memset(rackEventsIn, 0, sizeof(EngineEvent)*MAX_EVENTS);
// initialize input events
carla_zeroMem(kData->rack.in, sizeof(EngineEvent)*RACK_EVENT_COUNT);

if (fMidiInEvents.mutex.tryLock())
{
// TODO
uint32_t engineEventIndex = 0;
fMidiInEvents.splice();

while (! fMidiInEvents.data.isEmpty())
{
const RtMidiEvent& midiEvent = fMidiInEvents.data.getLast(true);

EngineEvent* const engineEvent = &kData->rack.in[engineEventIndex++];
engineEvent->clear();

const uint8_t midiStatus = MIDI_GET_STATUS_FROM_DATA(midiEvent.data);
const uint8_t midiChannel = MIDI_GET_CHANNEL_FROM_DATA(midiEvent.data);

engineEvent->channel = midiChannel;

if (midiEvent.time < fTimeInfo.frame)
engineEvent->time = 0;
else if (midiEvent.time >= fTimeInfo.frame + nframes)
{
engineEvent->time = fTimeInfo.frame + nframes-1;
carla_stderr("MIDI Event in the future!, %i vs %i", engineEvent->time, fTimeInfo.frame);
}
else
engineEvent->time = midiEvent.time - fTimeInfo.frame;

//carla_stdout("Got midi, time %f vs %i", midiEvent.time, engineEvent->time);

if (MIDI_IS_STATUS_CONTROL_CHANGE(midiStatus))
{
const uint8_t midiControl = midiEvent.data[1];
engineEvent->type = kEngineEventTypeControl;

if (MIDI_IS_CONTROL_BANK_SELECT(midiControl))
{
const uint8_t midiBank = midiEvent.data[2];

engineEvent->ctrl.type = kEngineControlEventTypeMidiBank;
engineEvent->ctrl.param = midiBank;
engineEvent->ctrl.value = 0.0;
}
else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF)
{
engineEvent->ctrl.type = kEngineControlEventTypeAllSoundOff;
engineEvent->ctrl.param = 0;
engineEvent->ctrl.value = 0.0;
}
else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF)
{
engineEvent->ctrl.type = kEngineControlEventTypeAllNotesOff;
engineEvent->ctrl.param = 0;
engineEvent->ctrl.value = 0.0;
}
else
{
const uint8_t midiValue = midiEvent.data[2];

engineEvent->ctrl.type = kEngineControlEventTypeParameter;
engineEvent->ctrl.param = midiControl;
engineEvent->ctrl.value = double(midiValue)/127.0;
}
}
else if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus))
{
const uint8_t midiProgram = midiEvent.data[1];
engineEvent->type = kEngineEventTypeControl;

engineEvent->ctrl.type = kEngineControlEventTypeMidiProgram;
engineEvent->ctrl.param = midiProgram;
engineEvent->ctrl.value = 0.0;
}
else
{
engineEvent->type = kEngineEventTypeMidi;

engineEvent->midi.data[0] = midiStatus;
engineEvent->midi.data[1] = midiEvent.data[1];
engineEvent->midi.data[2] = midiEvent.data[2];
engineEvent->midi.size = midiEvent.size;
}

if (engineEventIndex >= RACK_EVENT_COUNT)
break;
}

fMidiInEvents.mutex.unlock();
}

// create audio buffers
@@ -318,11 +419,6 @@ protected:
{
std::memcpy(outsPtr, fAudioOutBuf1, sizeof(float)*nframes);
std::memcpy(outsPtr+nframes, fAudioOutBuf2, sizeof(float)*nframes);

//for (unsigned int i=0; i < nframes; i++)
// outsPtr[i] = fAudioOutBuf1[i];
//for (unsigned int i=0, j=nframes; i < nframes; i++, j++)
// outsPtr[j] = fAudioOutBuf2[i];
}

// output events
@@ -331,37 +427,61 @@ protected:
//fMidiOut.sendMessage();
}

// TESTING
fTimeInfo.playing = true;
fTimeInfo.frame += nframes;

proccessPendingEvents();

return;

// unused
(void)streamTime;
(void)status;
}

void handleMidiCallback(const double timeStamp, std::vector<unsigned char>* const message)
void handleMidiCallback(double timeStamp, std::vector<unsigned char>* const message)
{
const size_t messageSize = message->size();
static uint32_t lastTime = 0;

if (messageSize == 0 || messageSize > 3)
return;

timeStamp /= 2;

if (timeStamp > 0.95)
timeStamp = 0.95;

RtMidiEvent midiEvent;
midiEvent.time = timeStamp;
midiEvent.time = fTimeInfo.frame + (timeStamp*(double)fBufferSize);
carla_stdout("Put midi, frame:%09i/%09i, stamp:%g", fTimeInfo.frame, midiEvent.time, timeStamp);

if (midiEvent.time < lastTime)
midiEvent.time = lastTime;
else
lastTime = midiEvent.time;

if (messageSize == 1)
{
midiEvent.data[0] = message->at(0);
midiEvent.data[1] = 0;
midiEvent.data[2] = 0;
midiEvent.size = 1;
}
else if (messageSize == 2)
{
midiEvent.data[0] = message->at(0);
midiEvent.data[1] = message->at(1);
midiEvent.data[2] = 0;
midiEvent.size = 2;
}
else
{
midiEvent.data[0] = message->at(0);
midiEvent.data[1] = message->at(1);
midiEvent.data[2] = message->at(2);
midiEvent.size = 3;
}

fMidiInEvents.append(midiEvent);
@@ -382,8 +502,9 @@ private:
RtMidiOut fMidiOut;

struct RtMidiEvent {
double time;
uint32_t time;
unsigned char data[3];
unsigned char size;
};

struct RtMidiEvents {
@@ -417,13 +538,9 @@ private:
mutex.unlock();
}

void trySplice()
void splice()
{
if (mutex.tryLock())
{
dataPending.splice(data, true);
mutex.unlock();
}
dataPending.splice(data, true);
}
};



+ 2
- 2
source/backend/native/Makefile View File

@@ -14,8 +14,8 @@ LINK_FLAGS += $(shell pkg-config --libs QtGui gl)

ifeq ($(HAVE_AF_DEPS),true)
AF_CXX_FLAGS = $(BUILD_CXX_FLAGS)
AF_CXX_FLAGS += $(shell pkg-config --cflags libavcodec libavformat sndfile) -pthread
LINK_FLAGS += $(shell pkg-config --libs libavcodec libavformat sndfile) -lpthread
AF_CXX_FLAGS += $(shell pkg-config --cflags libavcodec libavformat sndfile)
LINK_FLAGS += $(shell pkg-config --libs libavcodec libavformat sndfile)
endif

ifeq ($(HAVE_ZYN_DEPS),true)


+ 1
- 0
source/backend/standalone/CarlaStandalone.cpp View File

@@ -266,6 +266,7 @@ bool carla_engine_init(const char* driverName, const char* clientName)
}
else
{
standalone.lastError = standalone.engine->getLastError();
delete standalone.engine;
standalone.engine = nullptr;
}


+ 2
- 2
source/backend/standalone/Makefile View File

@@ -43,11 +43,11 @@ endif
LINK_FLAGS += $(shell pkg-config --libs gl)

ifeq ($(HAVE_AF_DEPS),true)
LINK_FLAGS += $(shell pkg-config --libs libavcodec libavformat sndfile) -lpthread
LINK_FLAGS += $(shell pkg-config --libs libavcodec libavformat sndfile)
endif

ifeq ($(HAVE_ZYN_DEPS),true)
LINK_FLAGS += $(shell pkg-config --libs fftw3 mxml) -lpthread
LINK_FLAGS += $(shell pkg-config --libs fftw3 mxml)
endif

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


+ 2
- 2
source/bridges/Makefile View File

@@ -13,10 +13,10 @@ HAVE_GTK3 = $(shell pkg-config --exists gtk+-3.0 && echo true)

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

BUILD_CXX_FLAGS += -DBUILD_BRIDGE
BUILD_CXX_FLAGS += -DBUILD_BRIDGE -pthread
BUILD_CXX_FLAGS += -I. -I../backend -I../includes -I../utils
BUILD_CXX_FLAGS += $(shell pkg-config --cflags liblo QtCore QtXml)
LINK_FLAGS += $(shell pkg-config --libs liblo QtCore QtXml)
LINK_FLAGS += $(shell pkg-config --libs liblo QtCore QtXml) -lpthread

ifeq ($(CARLA_PLUGIN_SUPPORT),true)
BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI


+ 5
- 3
source/carla.py View File

@@ -649,7 +649,7 @@ class CarlaMainW(QMainWindow):
audioError = cString(Carla.host.get_last_error())

if audioError:
QMessageBox.critical(self, self.tr("Error"), self.tr("Could not connect to Audio backend '%s', possible reasons: %s" % (audioDriver, audioError)))
QMessageBox.critical(self, self.tr("Error"), self.tr("Could not connect to Audio backend '%s', possible reasons:\n%s" % (audioDriver, audioError)))
else:
QMessageBox.critical(self, self.tr("Error"), self.tr("Could not connect to Audio backend '%s'" % audioDriver))
return
@@ -1179,8 +1179,10 @@ class CarlaMainW(QMainWindow):

self.saveSettings()

Carla.host.set_engine_about_to_close()
self.removeAllPlugins()
if Carla.host.is_engine_running():
Carla.host.set_engine_about_to_close()
self.removeAllPlugins()

self.stopEngine()

QMainWindow.closeEvent(self, event)


Loading…
Cancel
Save