1
Fork 0

added channel volume command (V)

This commit is contained in:
Leonard Ritter 2010-03-21 16:31:24 +01:00
parent 05a3013858
commit 1ee424c467
5 changed files with 96 additions and 54 deletions

5
commands.txt Normal file
View File

@ -0,0 +1,5 @@
Jacker Pattern Channel Commands
===============================
V xx: change channel volume to xx

View File

@ -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];

View File

@ -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:

View File

@ -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);
}
}

View File

@ -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();