2002-11-01 15:07:39 +00:00
|
|
|
/**
|
|
|
|
|
* @file MidiStore.cpp
|
|
|
|
|
*
|
|
|
|
|
* @author Matthijs Hollemans
|
|
|
|
|
* @author Jerome Leveque
|
|
|
|
|
* @author Paul Stadler
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
2002-07-09 12:24:59 +00:00
|
|
|
#include <Entry.h>
|
|
|
|
|
#include <Path.h>
|
2002-11-01 15:07:39 +00:00
|
|
|
#include <List.h>
|
|
|
|
|
|
|
|
|
|
#include "debug.h"
|
2002-07-09 12:24:59 +00:00
|
|
|
#include "MidiEvent.h"
|
2002-11-01 15:07:39 +00:00
|
|
|
#include "MidiStore.h"
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
BMidiStore::BMidiStore()
|
|
|
|
|
{
|
|
|
|
|
events = new BList();
|
|
|
|
|
tempo = 60;
|
|
|
|
|
curEvent = 0;
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
BMidiStore::~BMidiStore()
|
|
|
|
|
{
|
|
|
|
|
int32 count = events->CountItems();
|
|
|
|
|
|
|
|
|
|
for (int i = count - 1; i >= 0; i--)
|
|
|
|
|
{
|
|
|
|
|
delete (BMidiEvent*) events->RemoveItem(i);
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
delete events;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void BMidiStore::NoteOff(
|
|
|
|
|
uchar channel, uchar note, uchar velocity, uint32 time)
|
|
|
|
|
{
|
|
|
|
|
BMidiEvent* event = new BMidiEvent;
|
|
|
|
|
event->opcode = BMidiEvent::OP_NOTE_OFF;
|
|
|
|
|
event->time = B_NOW;
|
|
|
|
|
event->noteOff.channel = channel;
|
|
|
|
|
event->noteOff.note = note;
|
|
|
|
|
event->noteOff.velocity = velocity;
|
|
|
|
|
events->AddItem(event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void BMidiStore::NoteOn(
|
|
|
|
|
uchar channel, uchar note, uchar velocity, uint32 time)
|
|
|
|
|
{
|
|
|
|
|
BMidiEvent* event = new BMidiEvent;
|
|
|
|
|
event->opcode = BMidiEvent::OP_NOTE_ON;
|
|
|
|
|
event->time = B_NOW;
|
|
|
|
|
event->noteOn.channel = channel;
|
|
|
|
|
event->noteOn.note = note;
|
|
|
|
|
event->noteOn.velocity = velocity;
|
|
|
|
|
events->AddItem(event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void BMidiStore::KeyPressure(
|
|
|
|
|
uchar channel, uchar note, uchar pressure, uint32 time)
|
|
|
|
|
{
|
|
|
|
|
BMidiEvent* event = new BMidiEvent;
|
|
|
|
|
event->opcode = BMidiEvent::OP_KEY_PRESSURE;
|
|
|
|
|
event->time = B_NOW;
|
|
|
|
|
event->keyPressure.channel = channel;
|
|
|
|
|
event->keyPressure.note = note;
|
|
|
|
|
event->keyPressure.pressure = pressure;
|
|
|
|
|
events->AddItem(event);
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
void BMidiStore::ControlChange(
|
|
|
|
|
uchar channel, uchar controlNumber, uchar controlValue, uint32 time)
|
|
|
|
|
{
|
|
|
|
|
BMidiEvent* event = new BMidiEvent;
|
|
|
|
|
event->opcode = BMidiEvent::OP_CONTROL_CHANGE;
|
|
|
|
|
event->time = B_NOW;
|
|
|
|
|
event->controlChange.channel = channel;
|
|
|
|
|
event->controlChange.controlNumber = controlNumber;
|
|
|
|
|
event->controlChange.controlValue = controlValue;
|
|
|
|
|
events->AddItem(event);
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
void BMidiStore::ProgramChange(
|
|
|
|
|
uchar channel, uchar programNumber, uint32 time)
|
|
|
|
|
{
|
|
|
|
|
BMidiEvent* event = new BMidiEvent;
|
|
|
|
|
event->opcode = BMidiEvent::OP_PROGRAM_CHANGE;
|
|
|
|
|
event->time = B_NOW;
|
|
|
|
|
event->programChange.channel = channel;
|
|
|
|
|
event->programChange.programNumber = programNumber;
|
|
|
|
|
events->AddItem(event);
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void BMidiStore::ChannelPressure(uchar channel, uchar pressure, uint32 time)
|
|
|
|
|
{
|
|
|
|
|
BMidiEvent* event = new BMidiEvent;
|
|
|
|
|
event->opcode = BMidiEvent::OP_CHANNEL_PRESSURE;
|
|
|
|
|
event->time = B_NOW;
|
|
|
|
|
event->channelPressure.channel = channel;
|
|
|
|
|
event->channelPressure.pressure = pressure;
|
|
|
|
|
events->AddItem(event);
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void BMidiStore::PitchBend(uchar channel, uchar lsb, uchar msb, uint32 time)
|
|
|
|
|
{
|
|
|
|
|
BMidiEvent* event = new BMidiEvent;
|
|
|
|
|
event->opcode = BMidiEvent::OP_PITCH_BEND;
|
|
|
|
|
event->time = B_NOW;
|
|
|
|
|
event->pitchBend.channel = channel;
|
|
|
|
|
event->pitchBend.lsb = lsb;
|
|
|
|
|
event->pitchBend.msb = msb;
|
|
|
|
|
events->AddItem(event);
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void BMidiStore::SystemExclusive(void* data, size_t dataLength, uint32 time)
|
|
|
|
|
{
|
|
|
|
|
BMidiEvent* event = new BMidiEvent;
|
|
|
|
|
event->opcode = BMidiEvent::OP_SYSTEM_EXCLUSIVE;
|
|
|
|
|
event->time = B_NOW;
|
|
|
|
|
event->systemExclusive.data = (uint8*) data;
|
|
|
|
|
event->systemExclusive.dataLength = dataLength;
|
|
|
|
|
events->AddItem(event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void BMidiStore::SystemCommon(
|
|
|
|
|
uchar status, uchar data1, uchar data2, uint32 time)
|
|
|
|
|
{
|
|
|
|
|
BMidiEvent* event = new BMidiEvent;
|
|
|
|
|
event->opcode = BMidiEvent::OP_SYSTEM_COMMON;
|
|
|
|
|
event->time = B_NOW;
|
|
|
|
|
event->systemCommon.status = status;
|
|
|
|
|
event->systemCommon.data1 = data1;
|
|
|
|
|
event->systemCommon.data2 = data2;
|
|
|
|
|
events->AddItem(event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void BMidiStore::SystemRealTime(uchar status, uint32 time)
|
|
|
|
|
{
|
|
|
|
|
BMidiEvent* event = new BMidiEvent;
|
|
|
|
|
event->opcode = BMidiEvent::OP_SYSTEM_REAL_TIME;
|
|
|
|
|
event->time = B_NOW;
|
|
|
|
|
event->systemRealTime.status = status;
|
|
|
|
|
events->AddItem(event);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void BMidiStore::TempoChange(int32 beatsPerMinute, uint32 time)
|
|
|
|
|
{
|
|
|
|
|
BMidiEvent* event = new BMidiEvent;
|
|
|
|
|
event->opcode = BMidiEvent::OP_TEMPO_CHANGE;
|
|
|
|
|
event->time = B_NOW;
|
|
|
|
|
event->tempoChange.beatsPerMinute = beatsPerMinute;
|
|
|
|
|
events->AddItem(event);
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void BMidiStore::AllNotesOff(bool justChannel, uint32 time)
|
|
|
|
|
{
|
|
|
|
|
BMidiEvent* event = new BMidiEvent;
|
|
|
|
|
event->opcode = BMidiEvent::OP_ALL_NOTES_OFF;
|
|
|
|
|
event->time = B_NOW;
|
|
|
|
|
event->allNotesOff.justChannel = justChannel;
|
|
|
|
|
events->AddItem(event);
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
status_t BMidiStore::Import(const entry_ref* ref)
|
|
|
|
|
{
|
2002-07-09 12:24:59 +00:00
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
status_t BMidiStore::Export(const entry_ref* ref, int32 format)
|
|
|
|
|
{
|
2002-07-09 12:24:59 +00:00
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
void BMidiStore::SortEvents(bool force)
|
|
|
|
|
{
|
|
|
|
|
events->SortItems(CompareEvents);
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
uint32 BMidiStore::CountEvents() const
|
|
|
|
|
{
|
|
|
|
|
return events->CountItems();
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
uint32 BMidiStore::CurrentEvent() const
|
|
|
|
|
{
|
|
|
|
|
return curEvent;
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
void BMidiStore::SetCurrentEvent(uint32 eventNumber)
|
|
|
|
|
{
|
|
|
|
|
curEvent = eventNumber;
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
uint32 BMidiStore::DeltaOfEvent(uint32 eventNumber) const
|
|
|
|
|
{
|
|
|
|
|
BMidiEvent* first = EventAt(0);
|
|
|
|
|
|
|
|
|
|
if (first == NULL) { return 0; }
|
|
|
|
|
|
|
|
|
|
BMidiEvent* event = EventAt(eventNumber);
|
|
|
|
|
|
|
|
|
|
if (event == NULL) { return 0; }
|
|
|
|
|
|
|
|
|
|
return event->time - first->time;
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
uint32 BMidiStore::EventAtDelta(uint32 time) const
|
|
|
|
|
{
|
|
|
|
|
uint32 count = CountEvents();
|
|
|
|
|
uint32 delta = 0;
|
|
|
|
|
|
|
|
|
|
for (uint32 t = 0; t < count; ++t)
|
|
|
|
|
{
|
|
|
|
|
if (delta >= time)
|
|
|
|
|
{
|
|
|
|
|
return t;
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
2002-11-01 15:07:39 +00:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
delta += EventAt(t)->time;
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
}
|
2002-11-01 15:07:39 +00:00
|
|
|
|
|
|
|
|
return 0;
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
uint32 BMidiStore::BeginTime() const
|
|
|
|
|
{
|
|
|
|
|
return startTime;
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
void BMidiStore::SetTempo(int32 beatsPerMinute)
|
|
|
|
|
{
|
|
|
|
|
tempo = beatsPerMinute;
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
int32 BMidiStore::Tempo() const
|
|
|
|
|
{
|
|
|
|
|
return tempo;
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
void BMidiStore::_ReservedMidiStore1() { }
|
|
|
|
|
void BMidiStore::_ReservedMidiStore2() { }
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
void BMidiStore::Run()
|
|
|
|
|
{
|
|
|
|
|
startTime = B_NOW;
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
while (KeepRunning())
|
|
|
|
|
{
|
|
|
|
|
BMidiEvent* event = EventAt(curEvent);
|
|
|
|
|
|
|
|
|
|
if (event == NULL) { return; }
|
|
|
|
|
|
|
|
|
|
uint32 oldTime = event->time;
|
|
|
|
|
event->time += startTime;
|
|
|
|
|
SprayMidiEvent(event);
|
|
|
|
|
event->time = oldTime;
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
++curEvent;
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
2002-07-09 12:24:59 +00:00
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
BMidiEvent* BMidiStore::EventAt(uint32 index) const
|
|
|
|
|
{
|
|
|
|
|
return (BMidiEvent*) events->ItemAt(index);
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
|
|
|
|
|
2002-11-01 15:07:39 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
int BMidiStore::CompareEvents(const void* event1, const void* event2)
|
|
|
|
|
{
|
|
|
|
|
return ((BMidiEvent*) event1)->time - ((BMidiEvent*) event2)->time;
|
2002-07-09 12:24:59 +00:00
|
|
|
}
|
2002-11-01 15:07:39 +00:00
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|