1
Fork 0

Virtual keyboard experience upgraded.

Keyboard keys light up when you press them.
Hold space bar to enable sustain.
Inserting notes or moving notes plays the keyboard.
Sensor regions were adjusted by 1 pixel. Now it is better.
Horizontal rule at C.
Bright horizontal rule indicates middle C.
This commit is contained in:
EvanR 2008-12-11 21:34:31 -06:00
parent ca0c42881d
commit b952ecad61
6 changed files with 126 additions and 18 deletions

View File

@ -40,7 +40,7 @@ using namespace fltk;
Keyboard::Keyboard(int x, int y, int w, int h, const char* label = 0) : fltk::Widget(x, y, w, h, label) {
sustain = 0;
cur_note = 60;
cur_note = -1;
fltk::add_event_handler(keyboard_handler);
}
@ -51,6 +51,9 @@ int keyboard_handler(int e, fltk::Window* w){
return 0;
}
switch(event_key()){
case fltk::SpaceKey:
ui->keyboard->set_sustain(1);
break;
case '[':
//printf("octave down\n");
break;
@ -76,6 +79,9 @@ int keyboard_handler(int e, fltk::Window* w){
return 1;
case fltk::KEYUP:
switch(event_key()){
case fltk::SpaceKey:
ui->keyboard->set_sustain(0);
break;
case 'q':
//printf("C off\n");
break;
@ -102,17 +108,36 @@ void note_on(int note, int vel, int channel){
}
void Keyboard::set_sustain(int state){
sustain=state;
if(state==0){
for(int i=0; i<128; i++){
if(ons[i]==1 && cur_note!=i){
ons[i]=0;
midi_note_off(i,cur_chan,cur_port);
}
}
redraw();
}
}
int Keyboard::handle(int event){
char buf[16];
int note;
switch(event){
case fltk::FOCUS:
return 1;
case fltk::PUSH:
take_focus();
note = ypix2note(event_y()+scroll, event_x() < w()/2 ? 1 : 0);
play_note(note);
redraw();
return 1;
case fltk::RELEASE:
cur_note=-1;
if(sustain == 0){
cut_notes();
redraw();
}
return 1;
case fltk::DRAG:
@ -122,6 +147,7 @@ int Keyboard::handle(int event){
cut_notes();
}
play_note(note);
redraw();
}
return 1;
}
@ -129,21 +155,26 @@ int Keyboard::handle(int event){
}
void Keyboard::play_note(int note){
if(ons[note]==1){
return;
}
cur_note = note;
char buf[3];
buf[0] = 0x90 | cur_chan;
buf[1] = note;
buf[2] = 0x7f;
send_midi(buf,3,cur_port);
ons[note] = 1;
}
void Keyboard::cut_notes(){
//if sustain needs to cut all playing notes
char buf[3];
buf[0] = 0x80 | cur_chan;
buf[1] = cur_note;
buf[2] = 0x00;
send_midi(buf,3,cur_port);
for(int i=0; i<128; i++){
if(ons[i]){
ons[i] = 0;
midi_note_off(i,cur_chan,cur_port);
}
}
}
@ -153,6 +184,18 @@ void Keyboard::draw(){
fltk::push_clip(0,0,w(),h());
//draw held white notes
int black;
for(int i=0; i<128; i++){
if(ons[i]){
int Y = note2ypix(i,&black)-scroll;
if(!black){
fltk::setcolor(fltk::GRAY50);
fltk::fillrect(0,Y,w(),12);
}
}
}
fltk::setcolor(fltk::BLACK);
for(int i=-scroll; i<h(); i+=12){
fltk::drawline(0,i,w(),i);
@ -171,6 +214,17 @@ void Keyboard::draw(){
}
}
//draw held black notes
for(int i=0; i<128; i++){
if(ons[i]){
int Y = note2ypix(i,&black)-scroll;
if(black){
fltk::setcolor(fltk::GRAY70);
fltk::fillrect(1,Y+1,w()/2 - 2,5);
}
}
}
fltk::pop_clip();
}

View File

@ -29,6 +29,8 @@ class Keyboard : public fltk::Widget {
int cur_note;
int sustain;
char ons[128];
public:
int cur_port;
int cur_chan;
@ -38,7 +40,7 @@ class Keyboard : public fltk::Widget {
void play_note(int note);
void cut_notes();
void set_sustain(int state){sustain = state;}
void set_sustain(int state);
int handle(int event);
void draw();

View File

@ -87,13 +87,20 @@ int PianoRoll::handle(int event){
}
return 0;
case fltk::PUSH:
take_focus();
if(event_button()==1){//left mouse
if(over_note()==NULL){//begin pattern creation
if(over_note()==NULL){//new note init
new_drag = 1;
new_left_t = quantize(xpix2tick(event_x()));
new_orig_t = new_left_t;
new_note = ypix2note(event_y(),1);
new_right_t = new_left_t + q_tick;
last_note = new_note;
if(1){//play on insert
ui->keyboard->play_note(last_note);
ui->keyboard->redraw();
}
}
else{
//if shift, add to selection
@ -106,6 +113,12 @@ int PianoRoll::handle(int event){
move_offset = quantize(xpix2tick(event_x())) - move_t;
//move_track = event_y() / 30;
move_note = ypix2note(event_y(),1);
last_note = move_note;
if(1){//play on move
ui->keyboard->play_note(last_note);
ui->keyboard->redraw();
}
}
redraw();
}
@ -135,12 +148,28 @@ int PianoRoll::handle(int event){
new_left_t = new_orig_t;
}
new_note = ypix2note(event_y(),1);
if(new_note != last_note){
last_note = new_note;
if(1){//play on insert
ui->keyboard->cut_notes();
ui->keyboard->play_note(last_note);
ui->keyboard->redraw();
}
}
redraw();
return 1;
}
else if(move_flag){
move_t = quantize(xpix2tick(event_x())) - move_offset;
move_note = ypix2note(event_y(),1);
if(move_note != last_note){
last_note = move_note;
if(1){//play on move
ui->keyboard->cut_notes();
ui->keyboard->play_note(last_note);
ui->keyboard->redraw();
}
}
redraw();
return 1;
}
@ -151,6 +180,8 @@ int PianoRoll::handle(int event){
c=new CreateNote(p,new_note,new_left_t,new_right_t-new_left_t);
set_undo(c);
undo_push(1);
ui->keyboard->cut_notes();
ui->keyboard->redraw();
}
else if(move_flag && move_note < 128 && move_note >= 0){
int play_pos = get_play_position();
@ -167,6 +198,9 @@ int PianoRoll::handle(int event){
int cur_chan = tracks[cur_seqpat->track]->chan;
int cur_port = tracks[cur_seqpat->track]->port;
midi_note_off(old_note,cur_chan,cur_port);
ui->keyboard->cut_notes();
ui->keyboard->redraw();
}
new_drag=0;
move_flag=0;
@ -198,12 +232,18 @@ void PianoRoll::draw(){
fltk::drawline(i,0,i,h());
}
fltk::setcolor(fltk::GRAY30);
for(int i=12*5; i<h(); i+=12*7){
fltk::drawline(0,i,w(),i);
}
fltk::setcolor(fltk::GRAY50);
for(int i=zoom*4; i<w(); i+=zoom*4){
fltk::drawline(i,0,i,h());
}
fltk::setcolor(fltk::color(128,128,0));
fltk::drawline(0,12*40,w(),12*40);
if(new_drag){
fltk::setcolor(fltk::BLUE);

View File

@ -32,6 +32,8 @@ class PianoRoll : public fltk::Widget {
int wkeyh;
int bkeyh;
int last_note;
int new_left_t;
int new_right_t;
int new_orig_t;

View File

@ -93,20 +93,29 @@ void hsv_to_rgb(float h, float s, float v, unsigned char* r, unsigned char* g, u
int ypix2note(int ypix, int black){
int udy = 900 - ypix + 2;
int udy = 900 - ypix + 1;
int white = udy/12;
int note = 2*white - white/7 - (white+4)/7;
//printf("white %d\n",white);
//printf("wmidi %d\n",note);
//printf("udy%12 = %d\n",udy%12);
if(black){
if(udy%12<3 && white%7!=0 && (white+4)%7!=0){note--;}
else if(udy%12>9 && (white+1)%7!=0 && (white+5)%7!=0){note++;}
if(udy%12<4 && white%7!=0 && (white+4)%7!=0){note--;}
else if(udy%12>8 && (white+1)%7!=0 && (white+5)%7!=0){note++;}
}
//printf("total midi %d\n",note);
return note;
}
int note2ypix(int note, int* black){
int key = (note + (note+7)/12 + note/12)/2;
if((note + (note+7)/12 + note/12)%2 == 0){//white key
*black=0;
return 900 - key*12 - 12;
}
else{//black key
*black=1;
return 900 - key*12 - 12 - 3;
}
}

View File

@ -29,5 +29,6 @@ void load_text(fltk::TextDisplay* o, const char* filename);
void hsv_to_rgb(float h, float s, float v, unsigned char* r, unsigned char* g, unsigned char* b);
int ypix2note(int ypix, int black);
int note2ypix(int note, int* black);
#endif