Browse Source

Small changes to midi-base internal class, in preparation for midiseq

tags/1.9.6
falkTX 9 years ago
parent
commit
81f9a28fa4
3 changed files with 92 additions and 49 deletions
  1. +81
    -40
      source/native-plugins/midi-base.hpp
  2. +5
    -5
      source/native-plugins/midi-file.cpp
  3. +6
    -4
      source/native-plugins/midi-sequencer.cpp

+ 81
- 40
source/native-plugins/midi-base.hpp View File

@@ -1,6 +1,6 @@
/* /*
* Carla Native Plugins * Carla Native Plugins
* Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
@@ -25,10 +25,14 @@
#include "CarlaJuceUtils.hpp" #include "CarlaJuceUtils.hpp"
#include "CarlaMathUtils.hpp" #include "CarlaMathUtils.hpp"


// -----------------------------------------------------------------------

#define MAX_EVENT_DATA_SIZE 4 #define MAX_EVENT_DATA_SIZE 4
#define MIN_PREALLOCATED_EVENT_COUNT 100 #define MIN_PREALLOCATED_EVENT_COUNT 100
#define MAX_PREALLOCATED_EVENT_COUNT 1000 #define MAX_PREALLOCATED_EVENT_COUNT 1000


// -----------------------------------------------------------------------

struct RawMidiEvent { struct RawMidiEvent {
uint64_t time; uint64_t time;
uint8_t size; uint8_t size;
@@ -42,53 +46,60 @@ struct RawMidiEvent {
} }
}; };


// -----------------------------------------------------------------------

class AbstractMidiPlayer class AbstractMidiPlayer
{ {
public: public:
virtual ~AbstractMidiPlayer() {} virtual ~AbstractMidiPlayer() {}
virtual void writeMidiEvent(const uint64_t timePosFrame, const RawMidiEvent* const event) = 0;
virtual void writeMidiEvent(const uint8_t port, const uint64_t timePosFrame, const RawMidiEvent* const event) = 0;
}; };


// -----------------------------------------------------------------------

class MidiPattern class MidiPattern
{ {
public: public:
MidiPattern(AbstractMidiPlayer* const player)
MidiPattern(AbstractMidiPlayer* const player) noexcept
: kPlayer(player), : kPlayer(player),
fMidiPort(0),
fStartTime(0),
fMutex(), fMutex(),
fData(), fData(),
leakDetector_MidiPattern() leakDetector_MidiPattern()
//fStartTime(0),
//fDuration(0)
{ {
CARLA_ASSERT(kPlayer != nullptr);
CARLA_SAFE_ASSERT(kPlayer != nullptr);
} }


~MidiPattern()
~MidiPattern() noexcept
{ {
fData.clear();
clear();
} }


// -------------------------------------------------------------------
// add data, time always counts from 0

void addControl(const uint64_t time, const uint8_t channel, const uint8_t control, const uint8_t value) void addControl(const uint64_t time, const uint8_t channel, const uint8_t control, const uint8_t value)
{ {
RawMidiEvent* ctrlEvent(new RawMidiEvent());
RawMidiEvent* const ctrlEvent(new RawMidiEvent());
ctrlEvent->time = time; ctrlEvent->time = time;
ctrlEvent->size = 3; ctrlEvent->size = 3;
ctrlEvent->data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (channel & 0x0F)); ctrlEvent->data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (channel & 0x0F));
ctrlEvent->data[1] = control; ctrlEvent->data[1] = control;
ctrlEvent->data[2] = value; ctrlEvent->data[2] = value;


append(ctrlEvent);
appendSorted(ctrlEvent);
} }


void addChannelPressure(const uint64_t time, const uint8_t channel, const uint8_t pressure) void addChannelPressure(const uint64_t time, const uint8_t channel, const uint8_t pressure)
{ {
RawMidiEvent* pressureEvent(new RawMidiEvent());
RawMidiEvent* const pressureEvent(new RawMidiEvent());
pressureEvent->time = time; pressureEvent->time = time;
pressureEvent->size = 2; pressureEvent->size = 2;
pressureEvent->data[0] = uint8_t(MIDI_STATUS_CHANNEL_PRESSURE | (channel & 0x0F)); pressureEvent->data[0] = uint8_t(MIDI_STATUS_CHANNEL_PRESSURE | (channel & 0x0F));
pressureEvent->data[1] = pressure; pressureEvent->data[1] = pressure;


append(pressureEvent);
appendSorted(pressureEvent);
} }


void addNote(const uint64_t time, const uint8_t channel, const uint8_t pitch, const uint8_t velocity, const uint32_t duration) void addNote(const uint64_t time, const uint8_t channel, const uint8_t pitch, const uint8_t velocity, const uint32_t duration)
@@ -99,143 +110,173 @@ public:


void addNoteOn(const uint64_t time, const uint8_t channel, const uint8_t pitch, const uint8_t velocity) void addNoteOn(const uint64_t time, const uint8_t channel, const uint8_t pitch, const uint8_t velocity)
{ {
RawMidiEvent* noteOnEvent(new RawMidiEvent());
RawMidiEvent* const noteOnEvent(new RawMidiEvent());
noteOnEvent->time = time; noteOnEvent->time = time;
noteOnEvent->size = 3; noteOnEvent->size = 3;
noteOnEvent->data[0] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & 0x0F)); noteOnEvent->data[0] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & 0x0F));
noteOnEvent->data[1] = pitch; noteOnEvent->data[1] = pitch;
noteOnEvent->data[2] = velocity; noteOnEvent->data[2] = velocity;


append(noteOnEvent);
appendSorted(noteOnEvent);
} }


void addNoteOff(const uint64_t time, const uint8_t channel, const uint8_t pitch, const uint8_t velocity = 0) void addNoteOff(const uint64_t time, const uint8_t channel, const uint8_t pitch, const uint8_t velocity = 0)
{ {
RawMidiEvent* noteOffEvent(new RawMidiEvent());
RawMidiEvent* const noteOffEvent(new RawMidiEvent());
noteOffEvent->time = time; noteOffEvent->time = time;
noteOffEvent->size = 3; noteOffEvent->size = 3;
noteOffEvent->data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (channel & 0x0F)); noteOffEvent->data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (channel & 0x0F));
noteOffEvent->data[1] = pitch; noteOffEvent->data[1] = pitch;
noteOffEvent->data[2] = velocity; noteOffEvent->data[2] = velocity;


append(noteOffEvent);
appendSorted(noteOffEvent);
} }


void addNoteAftertouch(const uint64_t time, const uint8_t channel, const uint8_t pitch, const uint8_t pressure) void addNoteAftertouch(const uint64_t time, const uint8_t channel, const uint8_t pitch, const uint8_t pressure)
{ {
RawMidiEvent* noteAfterEvent(new RawMidiEvent());
RawMidiEvent* const noteAfterEvent(new RawMidiEvent());
noteAfterEvent->time = time; noteAfterEvent->time = time;
noteAfterEvent->size = 3; noteAfterEvent->size = 3;
noteAfterEvent->data[0] = uint8_t(MIDI_STATUS_POLYPHONIC_AFTERTOUCH | (channel & 0x0F)); noteAfterEvent->data[0] = uint8_t(MIDI_STATUS_POLYPHONIC_AFTERTOUCH | (channel & 0x0F));
noteAfterEvent->data[1] = pitch; noteAfterEvent->data[1] = pitch;
noteAfterEvent->data[2] = pressure; noteAfterEvent->data[2] = pressure;


append(noteAfterEvent);
appendSorted(noteAfterEvent);
} }


void addProgram(const uint64_t time, const uint8_t channel, const uint8_t bank, const uint8_t program) void addProgram(const uint64_t time, const uint8_t channel, const uint8_t bank, const uint8_t program)
{ {
RawMidiEvent* bankEvent(new RawMidiEvent());
RawMidiEvent* const bankEvent(new RawMidiEvent());
bankEvent->time = time; bankEvent->time = time;
bankEvent->size = 3; bankEvent->size = 3;
bankEvent->data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (channel & 0x0F)); bankEvent->data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (channel & 0x0F));
bankEvent->data[1] = MIDI_CONTROL_BANK_SELECT; bankEvent->data[1] = MIDI_CONTROL_BANK_SELECT;
bankEvent->data[2] = bank; bankEvent->data[2] = bank;


RawMidiEvent* programEvent(new RawMidiEvent());
RawMidiEvent* const programEvent(new RawMidiEvent());
programEvent->time = time; programEvent->time = time;
programEvent->size = 2; programEvent->size = 2;
programEvent->data[0] = uint8_t(MIDI_STATUS_PROGRAM_CHANGE | (channel & 0x0F)); programEvent->data[0] = uint8_t(MIDI_STATUS_PROGRAM_CHANGE | (channel & 0x0F));
programEvent->data[1] = program; programEvent->data[1] = program;


append(bankEvent);
append(programEvent);
appendSorted(bankEvent);
appendSorted(programEvent);
} }


void addPitchbend(const uint64_t time, const uint8_t channel, const uint8_t lsb, const uint8_t msb) void addPitchbend(const uint64_t time, const uint8_t channel, const uint8_t lsb, const uint8_t msb)
{ {
RawMidiEvent* pressureEvent(new RawMidiEvent());
RawMidiEvent* const pressureEvent(new RawMidiEvent());
pressureEvent->time = time; pressureEvent->time = time;
pressureEvent->size = 3; pressureEvent->size = 3;
pressureEvent->data[0] = uint8_t(MIDI_STATUS_PITCH_WHEEL_CONTROL | (channel & 0x0F)); pressureEvent->data[0] = uint8_t(MIDI_STATUS_PITCH_WHEEL_CONTROL | (channel & 0x0F));
pressureEvent->data[1] = lsb; pressureEvent->data[1] = lsb;
pressureEvent->data[2] = msb; pressureEvent->data[2] = msb;


append(pressureEvent);
appendSorted(pressureEvent);
} }


void addRaw(const uint64_t time, const uint8_t* data, const uint8_t size)
void addRaw(const uint64_t time, const uint8_t* const data, const uint8_t size)
{ {
RawMidiEvent* rawEvent(new RawMidiEvent());
RawMidiEvent* const rawEvent(new RawMidiEvent());
rawEvent->time = time; rawEvent->time = time;
rawEvent->size = size; rawEvent->size = size;


carla_copy<uint8_t>(rawEvent->data, data, size); carla_copy<uint8_t>(rawEvent->data, data, size);


append(rawEvent);
appendSorted(rawEvent);
}

// -------------------------------------------------------------------
// clear

void clear() noexcept
{
const CarlaMutexLocker sl(fMutex);

for (LinkedList<const RawMidiEvent*>::Itenerator it = fData.begin(); it.valid(); it.next())
delete it.getValue(nullptr);

fData.clear();
} }


void play(uint64_t timePosFrame, uint32_t frames)
// -------------------------------------------------------------------
// play on time

void play(uint64_t timePosFrame, const uint32_t frames)
{ {
if (! fMutex.tryLock()) if (! fMutex.tryLock())
return; return;


timePosFrame += fStartTime;

for (LinkedList<const RawMidiEvent*>::Itenerator it = fData.begin(); it.valid(); it.next()) for (LinkedList<const RawMidiEvent*>::Itenerator it = fData.begin(); it.valid(); it.next())
{ {
const RawMidiEvent* const rawMidiEvent(it.getValue());
const RawMidiEvent* const rawMidiEvent(it.getValue(nullptr));
CARLA_SAFE_ASSERT_CONTINUE(rawMidiEvent != nullptr);


if (timePosFrame > rawMidiEvent->time) if (timePosFrame > rawMidiEvent->time)
continue; continue;
if (timePosFrame + frames <= rawMidiEvent->time) if (timePosFrame + frames <= rawMidiEvent->time)
continue; continue;


kPlayer->writeMidiEvent(timePosFrame, rawMidiEvent);
kPlayer->writeMidiEvent(fMidiPort, timePosFrame, rawMidiEvent);
} }


fMutex.unlock(); fMutex.unlock();
} }


void clear()
// -------------------------------------------------------------------
// configure

void setMidiPort(const uint8_t port) noexcept
{ {
const CarlaMutexLocker sl(fMutex);
fData.clear();
fMidiPort = port;
}

void setStartTime(const uint64_t time) noexcept
{
fStartTime = time;
} }


// -------------------------------------------------------------------

private: private:
AbstractMidiPlayer* const kPlayer; AbstractMidiPlayer* const kPlayer;


//uint32_t fStartTime; // unused
//uint32_t fDuration; // unused
uint8_t fMidiPort;
uint64_t fStartTime;


CarlaMutex fMutex; CarlaMutex fMutex;
LinkedList<const RawMidiEvent*> fData; LinkedList<const RawMidiEvent*> fData;


void append(const RawMidiEvent* const event)
void appendSorted(const RawMidiEvent* const event)
{ {
const CarlaMutexLocker sl(fMutex);

if (fData.isEmpty()) if (fData.isEmpty())
{ {
const CarlaMutexLocker sl(fMutex);
fData.append(event); fData.append(event);
return; return;
} }


for (LinkedList<const RawMidiEvent*>::Itenerator it = fData.begin(); it.valid(); it.next()) for (LinkedList<const RawMidiEvent*>::Itenerator it = fData.begin(); it.valid(); it.next())
{ {
const RawMidiEvent* const oldEvent(it.getValue());
const RawMidiEvent* const oldEvent(it.getValue(nullptr));
CARLA_SAFE_ASSERT_CONTINUE(oldEvent != nullptr);


if (event->time >= oldEvent->time) if (event->time >= oldEvent->time)
continue; continue;


const CarlaMutexLocker sl(fMutex);
fData.insertAt(event, it); fData.insertAt(event, it);
return; return;
} }


const CarlaMutexLocker sl(fMutex);
fData.append(event); fData.append(event);
} }


CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MidiPattern) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MidiPattern)
}; };


// -----------------------------------------------------------------------

#endif // MIDI_BASE_HPP_INCLUDED #endif // MIDI_BASE_HPP_INCLUDED

+ 5
- 5
source/native-plugins/midi-file.cpp View File

@@ -1,6 +1,6 @@
/* /*
* Carla Native Plugins * Carla Native Plugins
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
@@ -91,9 +91,7 @@ protected:
return; return;


if (const char* const filename = uiOpenFile(false, "Open Audio File", "MIDI Files *.mid;*.midi;;")) if (const char* const filename = uiOpenFile(false, "Open Audio File", "MIDI Files *.mid;*.midi;;"))
{
uiCustomDataChanged("file", filename); uiCustomDataChanged("file", filename);
}


uiClosed(); uiClosed();
} }
@@ -101,11 +99,11 @@ protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// AbstractMidiPlayer calls // AbstractMidiPlayer calls


void writeMidiEvent(const uint64_t timePosFrame, const RawMidiEvent* const event) override
void writeMidiEvent(const uint8_t port, const uint64_t timePosFrame, const RawMidiEvent* const event) override
{ {
NativeMidiEvent midiEvent; NativeMidiEvent midiEvent;


midiEvent.port = 0;
midiEvent.port = port;
midiEvent.time = uint32_t(event->time-timePosFrame); midiEvent.time = uint32_t(event->time-timePosFrame);
midiEvent.size = event->size; midiEvent.size = event->size;
midiEvent.data[0] = event->data[0]; midiEvent.data[0] = event->data[0];
@@ -116,6 +114,8 @@ protected:
NativePluginClass::writeMidiEvent(&midiEvent); NativePluginClass::writeMidiEvent(&midiEvent);
} }


// -------------------------------------------------------------------

private: private:
MidiPattern fMidiOut; MidiPattern fMidiOut;
bool fWasPlayingBefore; bool fWasPlayingBefore;


+ 6
- 4
source/native-plugins/midi-sequencer.cpp View File

@@ -1,6 +1,6 @@
/* /*
* Carla Native Plugins * Carla Native Plugins
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
@@ -18,6 +18,8 @@
#include "CarlaNative.hpp" #include "CarlaNative.hpp"
#include "midi-base.hpp" #include "midi-base.hpp"


// -----------------------------------------------------------------------

class MidiSequencerPlugin : public NativePluginClass, class MidiSequencerPlugin : public NativePluginClass,
public AbstractMidiPlayer public AbstractMidiPlayer
{ {
@@ -172,12 +174,12 @@ protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Plugin process calls // Plugin process calls


void writeMidiEvent(const uint32_t timePosFrame, const RawMidiEvent* const event) override
void writeMidiEvent(const uint8_t port, const uint32_t timePosFrame, const RawMidiEvent* const event) override
{ {
NativeMidiEvent midiEvent; NativeMidiEvent midiEvent;


midiEvent.port = 0;
midiEvent.time = event->time-timePosFrame;
midiEvent.port = port;
midiEvent.time = uint32_t(event->time-timePosFrame);
midiEvent.data[0] = event->data[0]; midiEvent.data[0] = event->data[0];
midiEvent.data[1] = event->data[1]; midiEvent.data[1] = event->data[1];
midiEvent.data[2] = event->data[2]; midiEvent.data[2] = event->data[2];


Loading…
Cancel
Save