added channel volume command (V)
This commit is contained in:
parent
05a3013858
commit
1ee424c467
|
@ -0,0 +1,5 @@
|
|||
|
||||
Jacker Pattern Channel Commands
|
||||
===============================
|
||||
|
||||
V xx: change channel volume to xx
|
2
midi.hpp
2
midi.hpp
|
@ -57,7 +57,7 @@ struct Message {
|
|||
};
|
||||
unsigned char data1;
|
||||
unsigned char data2;
|
||||
unsigned char rest;
|
||||
unsigned char data3; // usually unused
|
||||
};
|
||||
long data;
|
||||
unsigned char bytes[4];
|
||||
|
|
|
@ -99,6 +99,9 @@ void PatternEvent::sanitize_value() {
|
|||
value = std::min(std::max(value,0x21),0x7f);
|
||||
} break;
|
||||
case ParamValue:
|
||||
{
|
||||
value = std::min(std::max(value,0),0xff);
|
||||
} break;
|
||||
case ParamVolume:
|
||||
case ParamCCIndex:
|
||||
case ParamCCValue:
|
||||
|
|
132
player.cpp
132
player.cpp
|
@ -60,7 +60,25 @@ void MessageQueue::on_cc(int bus, int ccindex, int ccvalue) {
|
|||
push(msg);
|
||||
}
|
||||
|
||||
void MessageQueue::on_note(int bus, int channel, int note, int velocity/*=0x7f*/) {
|
||||
void MessageQueue::on_command(int bus, Message::Type command, int value, int value2, int value3) {
|
||||
if (value == ValueNone)
|
||||
return;
|
||||
if (value2 == ValueNone)
|
||||
value2 = 0;
|
||||
if (value3 == ValueNone)
|
||||
value3 = 0;
|
||||
assert(model);
|
||||
Message msg;
|
||||
init_message(bus,msg);
|
||||
msg.type = command;
|
||||
msg.bus = bus;
|
||||
msg.status = value;
|
||||
msg.data1 = value2;
|
||||
msg.data2 = value3;
|
||||
push(msg);
|
||||
}
|
||||
|
||||
void MessageQueue::on_note(int bus, int channel, int note, int velocity) {
|
||||
if (note == ValueNone)
|
||||
return;
|
||||
if (velocity == ValueNone)
|
||||
|
@ -99,7 +117,7 @@ void MessageQueue::status_msg() {
|
|||
|
||||
Player::Channel::Channel() {
|
||||
note = ValueNone;
|
||||
volume = 0x7f;
|
||||
volume = 1.0f;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -210,7 +228,7 @@ void Player::play_event(int track, const class PatternEvent &event) {
|
|||
int note = event.value;
|
||||
if (note == ValueNone)
|
||||
return;
|
||||
rt_messages.on_note(track, event.channel, note);
|
||||
rt_messages.on_note(track, event.channel, note, ValueNone);
|
||||
}
|
||||
|
||||
void Player::mix_events(MessageQueue &queue, int samples) {
|
||||
|
@ -256,8 +274,14 @@ void Player::mix_frame(MessageQueue &queue) {
|
|||
|
||||
// first run: process all cc events
|
||||
for (int channel = 0; channel < pattern.get_channel_count(); ++channel) {
|
||||
queue.on_cc(event.track, row.get_value(channel, ParamCCIndex),
|
||||
row.get_value(channel, ParamCCValue));
|
||||
int command = row.get_value(channel, ParamCommand);
|
||||
int ccindex = row.get_value(channel, ParamCCIndex);
|
||||
int ccvalue = row.get_value(channel, ParamCCValue);
|
||||
if (command != ValueNone) {
|
||||
queue.on_command(event.track, (Message::Type)command,
|
||||
row.get_value(channel, ParamValue), ccindex, ccvalue);
|
||||
}
|
||||
queue.on_cc(event.track, ccindex, ccvalue);
|
||||
}
|
||||
|
||||
// second run: process volume and notes
|
||||
|
@ -279,52 +303,58 @@ void Player::handle_message(Message msg) {
|
|||
Bus &bus = buses[msg.bus];
|
||||
Channel &values = bus.channels[msg.bus_channel];
|
||||
|
||||
if (msg.command == MIDI::CommandControlChange) {
|
||||
switch(msg.data1) {
|
||||
case MIDI::ControllerAllNotesOff:
|
||||
{
|
||||
for (NoteArray::iterator iter = bus.notes.begin();
|
||||
iter != bus.notes.end(); ++iter) {
|
||||
*iter = -1;
|
||||
}
|
||||
on_message(msg);
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
on_message(msg);
|
||||
} break;
|
||||
}
|
||||
return;
|
||||
} else if (msg.command == MIDI::CommandNoteOff) {
|
||||
if (values.note != ValueNone) {
|
||||
int note = values.note;
|
||||
values.note = ValueNone;
|
||||
// see if that note is actually being played
|
||||
// on our channel, if yes, kill it.
|
||||
if (bus.notes[note] == msg.bus_channel) {
|
||||
bus.notes[note] = -1;
|
||||
msg.data1 = note;
|
||||
msg.data2 = 0;
|
||||
on_message(msg);
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (msg.command == MIDI::CommandNoteOn) {
|
||||
if (values.note != ValueNone) {
|
||||
int note = values.note;
|
||||
values.note = ValueNone;
|
||||
// no matter where the note is played, kill it.
|
||||
bus.notes[note] = -1;
|
||||
Message off_msg(msg);
|
||||
off_msg.command = MIDI::CommandNoteOff;
|
||||
off_msg.data1 = note;
|
||||
off_msg.data2 = 0;
|
||||
on_message(off_msg);
|
||||
}
|
||||
values.note = msg.data1;
|
||||
bus.notes[values.note] = msg.bus_channel;
|
||||
on_message(msg);
|
||||
return;
|
||||
if (msg.type == Message::TypeMIDI) {
|
||||
if (msg.command == MIDI::CommandControlChange) {
|
||||
switch(msg.data1) {
|
||||
case MIDI::ControllerAllNotesOff:
|
||||
{
|
||||
for (NoteArray::iterator iter = bus.notes.begin();
|
||||
iter != bus.notes.end(); ++iter) {
|
||||
*iter = -1;
|
||||
}
|
||||
on_message(msg);
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
on_message(msg);
|
||||
} break;
|
||||
}
|
||||
return;
|
||||
} else if (msg.command == MIDI::CommandNoteOff) {
|
||||
if (values.note != ValueNone) {
|
||||
int note = values.note;
|
||||
values.note = ValueNone;
|
||||
// see if that note is actually being played
|
||||
// on our channel, if yes, kill it.
|
||||
if (bus.notes[note] == msg.bus_channel) {
|
||||
bus.notes[note] = -1;
|
||||
msg.data1 = note;
|
||||
msg.data2 = 0;
|
||||
on_message(msg);
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (msg.command == MIDI::CommandNoteOn) {
|
||||
if (values.note != ValueNone) {
|
||||
int note = values.note;
|
||||
values.note = ValueNone;
|
||||
// no matter where the note is played, kill it.
|
||||
bus.notes[note] = -1;
|
||||
Message off_msg(msg);
|
||||
off_msg.command = MIDI::CommandNoteOff;
|
||||
off_msg.data1 = note;
|
||||
off_msg.data2 = 0;
|
||||
on_message(off_msg);
|
||||
}
|
||||
values.note = msg.data1;
|
||||
int volume = std::min((int)((float)(msg.data2) * values.volume), 0x7f);
|
||||
msg.data2 = volume;
|
||||
bus.notes[values.note] = msg.bus_channel;
|
||||
on_message(msg);
|
||||
return;
|
||||
}
|
||||
} else if (msg.type == Message::TypeCommandChannelVolume) {
|
||||
values.volume = std::min((float)(msg.status) / 0x7f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,9 @@ struct Message : MIDI::Message {
|
|||
TypeEmpty = 0,
|
||||
// midi package
|
||||
TypeMIDI = 1,
|
||||
|
||||
// command
|
||||
TypeCommandChannelVolume = 'V',
|
||||
};
|
||||
|
||||
Type type;
|
||||
|
@ -33,8 +36,9 @@ public:
|
|||
volatile int position; // in frames
|
||||
volatile long long read_samples;
|
||||
|
||||
void on_note(int bus, int channel, int value, int velocity=0x7f);
|
||||
void on_note(int bus, int channel, int value, int velocity);
|
||||
void on_cc(int bus, int ccindex, int ccvalue);
|
||||
void on_command(int bus, Message::Type command, int value, int value2, int value3);
|
||||
void all_notes_off(int bus);
|
||||
|
||||
void status_msg();
|
||||
|
@ -55,7 +59,7 @@ public:
|
|||
};
|
||||
|
||||
struct Channel {
|
||||
int volume;
|
||||
float volume;
|
||||
int note;
|
||||
|
||||
Channel();
|
||||
|
|
Loading…
Reference in New Issue