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), fAudioInBuf2(nullptr),
fAudioOutBuf1(nullptr), fAudioOutBuf1(nullptr),
fAudioOutBuf2(nullptr), fAudioOutBuf2(nullptr),
fMidiIn(getMatchedAudioMidiAPi(api)),
fMidiOut(getMatchedAudioMidiAPi(api))
fMidiIn(getMatchedAudioMidiAPi(api), "CarlaIn"),
fMidiOut(getMatchedAudioMidiAPi(api), "CarlaOut")
{ {
carla_debug("CarlaEngineRtAudio::CarlaEngineRtAudio(%i)", api); carla_debug("CarlaEngineRtAudio::CarlaEngineRtAudio(%i)", api);


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


if (fAudio.getDeviceCount() == 0) if (fAudio.getDeviceCount() == 0)
{ {
@@ -145,7 +146,13 @@ public:
} }
catch (RtError& e) 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; return false;
} }


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


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


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


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


fMidiIn.cancelCallback(); fMidiIn.cancelCallback();
fMidiIn.closePort(); fMidiIn.closePort();
@@ -259,9 +278,10 @@ protected:
CARLA_ASSERT(insPtr != nullptr); CARLA_ASSERT(insPtr != nullptr);
CARLA_ASSERT(outsPtr != 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; return;
} }


@@ -280,21 +300,102 @@ protected:
{ {
std::memcpy(fAudioInBuf1, insPtr, sizeof(float)*nframes); std::memcpy(fAudioInBuf1, insPtr, sizeof(float)*nframes);
std::memcpy(fAudioInBuf2, insPtr+nframes, 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 // initialize audio output
carla_zeroFloat(fAudioOutBuf1, fBufferSize); carla_zeroFloat(fAudioOutBuf1, fBufferSize);
carla_zeroFloat(fAudioOutBuf2, 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 // create audio buffers
@@ -318,11 +419,6 @@ protected:
{ {
std::memcpy(outsPtr, fAudioOutBuf1, sizeof(float)*nframes); std::memcpy(outsPtr, fAudioOutBuf1, sizeof(float)*nframes);
std::memcpy(outsPtr+nframes, fAudioOutBuf2, 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 // output events
@@ -331,37 +427,61 @@ protected:
//fMidiOut.sendMessage(); //fMidiOut.sendMessage();
} }


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

proccessPendingEvents();

return;

// unused
(void)streamTime; (void)streamTime;
(void)status; (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(); const size_t messageSize = message->size();
static uint32_t lastTime = 0;


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


timeStamp /= 2;

if (timeStamp > 0.95)
timeStamp = 0.95;

RtMidiEvent midiEvent; 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) if (messageSize == 1)
{ {
midiEvent.data[0] = message->at(0); midiEvent.data[0] = message->at(0);
midiEvent.data[1] = 0; midiEvent.data[1] = 0;
midiEvent.data[2] = 0; midiEvent.data[2] = 0;
midiEvent.size = 1;
} }
else if (messageSize == 2) else if (messageSize == 2)
{ {
midiEvent.data[0] = message->at(0); midiEvent.data[0] = message->at(0);
midiEvent.data[1] = message->at(1); midiEvent.data[1] = message->at(1);
midiEvent.data[2] = 0; midiEvent.data[2] = 0;
midiEvent.size = 2;
} }
else else
{ {
midiEvent.data[0] = message->at(0); midiEvent.data[0] = message->at(0);
midiEvent.data[1] = message->at(1); midiEvent.data[1] = message->at(1);
midiEvent.data[2] = message->at(2); midiEvent.data[2] = message->at(2);
midiEvent.size = 3;
} }


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


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


struct RtMidiEvents { struct RtMidiEvents {
@@ -417,13 +538,9 @@ private:
mutex.unlock(); 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) ifeq ($(HAVE_AF_DEPS),true)
AF_CXX_FLAGS = $(BUILD_CXX_FLAGS) 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 endif


ifeq ($(HAVE_ZYN_DEPS),true) 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 else
{ {
standalone.lastError = standalone.engine->getLastError();
delete standalone.engine; delete standalone.engine;
standalone.engine = nullptr; standalone.engine = nullptr;
} }


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

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


ifeq ($(HAVE_AF_DEPS),true) 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 endif


ifeq ($(HAVE_ZYN_DEPS),true) ifeq ($(HAVE_ZYN_DEPS),true)
LINK_FLAGS += $(shell pkg-config --libs fftw3 mxml) -lpthread
LINK_FLAGS += $(shell pkg-config --libs fftw3 mxml)
endif 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 += -I. -I../backend -I../includes -I../utils
BUILD_CXX_FLAGS += $(shell pkg-config --cflags liblo QtCore QtXml) 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) ifeq ($(CARLA_PLUGIN_SUPPORT),true)
BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI 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()) audioError = cString(Carla.host.get_last_error())


if audioError: 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: else:
QMessageBox.critical(self, self.tr("Error"), self.tr("Could not connect to Audio backend '%s'" % audioDriver)) QMessageBox.critical(self, self.tr("Error"), self.tr("Could not connect to Audio backend '%s'" % audioDriver))
return return
@@ -1179,8 +1179,10 @@ class CarlaMainW(QMainWindow):


self.saveSettings() 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() self.stopEngine()


QMainWindow.closeEvent(self, event) QMainWindow.closeEvent(self, event)


Loading…
Cancel
Save