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
* 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
* modify it under the terms of the GNU General Public License as
@@ -25,10 +25,14 @@
#include "CarlaJuceUtils.hpp"
#include "CarlaMathUtils.hpp"

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

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

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

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

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

class AbstractMidiPlayer
{
public:
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
{
public:
MidiPattern(AbstractMidiPlayer* const player)
MidiPattern(AbstractMidiPlayer* const player) noexcept
: kPlayer(player),
fMidiPort(0),
fStartTime(0),
fMutex(),
fData(),
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)
{
RawMidiEvent* ctrlEvent(new RawMidiEvent());
RawMidiEvent* const ctrlEvent(new RawMidiEvent());
ctrlEvent->time = time;
ctrlEvent->size = 3;
ctrlEvent->data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (channel & 0x0F));
ctrlEvent->data[1] = control;
ctrlEvent->data[2] = value;

append(ctrlEvent);
appendSorted(ctrlEvent);
}

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->size = 2;
pressureEvent->data[0] = uint8_t(MIDI_STATUS_CHANNEL_PRESSURE | (channel & 0x0F));
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)
@@ -99,143 +110,173 @@ public:

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->size = 3;
noteOnEvent->data[0] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & 0x0F));
noteOnEvent->data[1] = pitch;
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)
{
RawMidiEvent* noteOffEvent(new RawMidiEvent());
RawMidiEvent* const noteOffEvent(new RawMidiEvent());
noteOffEvent->time = time;
noteOffEvent->size = 3;
noteOffEvent->data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (channel & 0x0F));
noteOffEvent->data[1] = pitch;
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)
{
RawMidiEvent* noteAfterEvent(new RawMidiEvent());
RawMidiEvent* const noteAfterEvent(new RawMidiEvent());
noteAfterEvent->time = time;
noteAfterEvent->size = 3;
noteAfterEvent->data[0] = uint8_t(MIDI_STATUS_POLYPHONIC_AFTERTOUCH | (channel & 0x0F));
noteAfterEvent->data[1] = pitch;
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)
{
RawMidiEvent* bankEvent(new RawMidiEvent());
RawMidiEvent* const bankEvent(new RawMidiEvent());
bankEvent->time = time;
bankEvent->size = 3;
bankEvent->data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (channel & 0x0F));
bankEvent->data[1] = MIDI_CONTROL_BANK_SELECT;
bankEvent->data[2] = bank;

RawMidiEvent* programEvent(new RawMidiEvent());
RawMidiEvent* const programEvent(new RawMidiEvent());
programEvent->time = time;
programEvent->size = 2;
programEvent->data[0] = uint8_t(MIDI_STATUS_PROGRAM_CHANGE | (channel & 0x0F));
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)
{
RawMidiEvent* pressureEvent(new RawMidiEvent());
RawMidiEvent* const pressureEvent(new RawMidiEvent());
pressureEvent->time = time;
pressureEvent->size = 3;
pressureEvent->data[0] = uint8_t(MIDI_STATUS_PITCH_WHEEL_CONTROL | (channel & 0x0F));
pressureEvent->data[1] = lsb;
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->size = 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())
return;

timePosFrame += fStartTime;

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)
continue;
if (timePosFrame + frames <= rawMidiEvent->time)
continue;

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

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:
AbstractMidiPlayer* const kPlayer;

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

CarlaMutex fMutex;
LinkedList<const RawMidiEvent*> fData;

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

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

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)
continue;

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

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

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MidiPattern)
};

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

#endif // MIDI_BASE_HPP_INCLUDED

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

@@ -1,6 +1,6 @@
/*
* 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
* modify it under the terms of the GNU General Public License as
@@ -91,9 +91,7 @@ protected:
return;

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

uiClosed();
}
@@ -101,11 +99,11 @@ protected:
// -------------------------------------------------------------------
// 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;

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

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

private:
MidiPattern fMidiOut;
bool fWasPlayingBefore;


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

@@ -1,6 +1,6 @@
/*
* 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
* modify it under the terms of the GNU General Public License as
@@ -18,6 +18,8 @@
#include "CarlaNative.hpp"
#include "midi-base.hpp"

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

class MidiSequencerPlugin : public NativePluginClass,
public AbstractMidiPlayer
{
@@ -172,12 +174,12 @@ protected:
// -------------------------------------------------------------------
// 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;

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[1] = event->data[1];
midiEvent.data[2] = event->data[2];


Loading…
Cancel
Save