2 Epichord - a midi sequencer
3 Copyright (C) 2008 Evan Rinehart
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to
18 The Free Software Foundation, Inc.
19 51 Franklin Street, Fifth Floor
20 Boston, MA 02110-1301, USA
28 #include <fltk/TextDisplay.h>
35 std::vector
<track
*> tracks
;
37 std::list
<Command
*> undo_stack
;
38 std::list
<Command
*>::iterator undo_ptr
;
39 std::list
<int> undo_number
;
40 std::list
<int>::iterator undo_nptr
;
49 total_event(mevent
* ze
, int zt
, seqpat
* zs
){
55 total_event(const total_event
& zte
){
60 int operator<(const total_event
& zte
){
61 return e
->tick
+s
->tick
< zte
.e
->tick
+zte
.s
->tick
;
63 void operator=(const total_event
& zte
){
69 std::list
<total_event
> dispatch_queue
;
75 static float default_hsv_value
= 0.8;
81 int play_seq(int cur_tick
){
89 dispatch_queue
.clear();
91 /* start at skip s, and skip e
92 if e is in the past, dispatch event and set new skip
93 if next e is past pattern dur, switch patseq
94 if next e is null, switch patseq
95 switch patseq sets skip s
96 do the above until e is in the future and not past end
97 then go to next track and start over
100 //printf("playing. cur_tick = %d\n",cur_tick);
102 for(int i
=0; i
<tracks
.size(); i
++){
103 //if(tracks[i]->alive == 0){continue;}
109 if(!e
){ goto switchblock
; }//no more events in this seqpat
113 if(e
->tick
+s
->tick
<= cur_tick
&& e
->tick
<= s
->dur
){//should have happened
115 if(e
->tick
!= s
->dur
|| e
->type
== MIDI_NOTE_OFF
)
116 if(tracks
[i
]->mute
== 0)
117 if((get_solo() && tracks
[i
]->solo
!= 0) || !get_solo()){
118 //dispatch_event(e, i, s->tick);
119 dispatch_queue
.push_back(total_event(e
,i
,s
));
124 if(!e
){//no more events in this seqpat
128 else if(e
->tick
> s
->dur
){//went past the end
131 else{//no more events on this track right now
134 goto again
;//try to play next event
138 //TODO auto off all playing notes on track because end of block
143 if(!s
){continue;}//no more seqpats
145 if(!p
){continue;}//this shouldnt happen anymore
147 if(!e
){continue;}//...means this pattern has played already...
149 goto again
;//play some or all of the next seqpat
154 dispatch_queue
.sort();
156 std::list
<total_event
>::iterator i
= dispatch_queue
.begin();
157 while(i
!= dispatch_queue
.end()){
158 OnBitArray
* oba
= &(tracks
[i
->t
]->onbits
);
159 if(i
->e
->type
== MIDI_NOTE_ON
){
160 if(!oba
->get(i
->e
->value1
)){
161 tracks
[i
->t
]->onbits
.set(i
->e
->value1
, 1);
165 eoff
.type
= MIDI_NOTE_OFF
;
167 //dispatch_event(&eoff, i->t, i->s->tick);
170 else if(i
->e
->type
== MIDI_NOTE_OFF
){
171 tracks
[i
->t
]->onbits
.set(i
->e
->value1
, 0);
174 if(i
->e
->type
== MIDI_CONTROLLER_CHANGE
){
175 int V
= i
->e
->value2
;
176 int B
= tracks
[i
->t
]->bank
;
177 tracks
[i
->t
]->contr
[i
->e
->value1
] = V
;
179 tracks
[i
->t
]->bank
= B
%128 + V
*128;
182 tracks
[i
->t
]->bank
= B
/128*128 + V
;
185 if(i
->e
->type
== MIDI_PROGRAM_CHANGE
){
186 tracks
[i
->t
]->prog
= i
->e
->value1
;
189 dispatch_event(i
->e
, i
->t
, i
->s
->tick
);
196 int set_seq_pos(int new_tick
){
203 for(int i
=0; i
<tracks
.size(); i
++){
209 s
->skip
= s
->p
->events
;
215 if(s
->tick
+s
->dur
<= new_tick
){
226 tracks
[i
]->skip
= NULL
;
238 else if(e
->tick
>= new_tick
- s
->tick
){
247 void set_rec_track(int t
){
255 int set_default_hsv_value(float v
){
256 default_hsv_value
= v
;
265 CreateSeqpat::CreateSeqpat(int track
, int tick
, seqpat
* zs
, int copy
){
269 s
->p
= new pattern(zs
->p
);
270 s
->skip
= s
->p
->events
;
275 s
->prev
= tfind
<seqpat
>(tracks
[track
]->head
,tick
);
276 s
->next
= s
->prev
->next
;
279 void CreateSeqpat::redo(){
280 tinsert
<seqpat
>(s
->prev
, s
);
283 void CreateSeqpat::undo(){
287 CreateSeqpatBlank::CreateSeqpatBlank(int track
, int tick
, int len
){
288 s
= new seqpat(track
, tick
, len
, new pattern());
293 p
->h
= ((track
%16) / 16.0) * 360;
294 p
->v
= default_hsv_value
;
300 s
->prev
= tfind
<seqpat
>(tracks
[track
]->head
,tick
);
301 s
->next
= s
->prev
->next
;
302 s
->skip
= s
->p
->events
;
306 void DeleteSeqpat::redo(){
308 int pos
= get_play_position();
309 if(pos
>= s
->tick
&& pos
<= s
->tick
+s
->dur
){
310 tracks
[s
->track
]->skip
= s
->next
;
316 void DeleteSeqpat::undo(){
317 tinsert
<seqpat
>(s
->prev
, s
);
321 void ResizeSeqpat::redo(){
323 tinsert
<seqpat
>(s1
->prev
,s2
);
328 void ResizeSeqpat::undo(){
330 tinsert
<seqpat
>(s1
->prev
,s1
);
333 MoveSeqpat::MoveSeqpat(seqpat
* zs
, int track
, int tick
){
340 targ2
= tfind
<seqpat
>(tracks
[track2
]->head
,tick
);
341 if(targ2
== zs
){//dont put it after itself
346 void MoveSeqpat::redo(){
351 int play_pos
= get_play_position();
352 if(play_pos
>= s
->tick
&& play_pos
<= s
->tick
+s
->dur
){//no entry into s by cb
353 tracks
[track1
]->skip
= s
->next
;
356 track
* t
= tracks
[track2
];
358 //here possibly wait a few ms for the audio to leave s if it was in
360 //perform nitty gritty
365 s
->skip
= tfind
<mevent
>(s
->p
->events
, play_pos
- s
->tick
)->next
;
366 tinsert
<seqpat
>(targ2
,s
);
369 void MoveSeqpat::undo(){
373 int play_pos
= get_play_position();
374 if(play_pos
>= s
->tick
&& play_pos
<= s
->tick
+s
->dur
){
375 tracks
[track2
]->skip
= s
->next
;
381 s
->skip
= tfind
<mevent
>(s
->p
->events
, play_pos
- s
->tick
)->next
;
383 tinsert
<seqpat
>(targ1
,s
);
387 SplitSeqpat::SplitSeqpat(seqpat
* zs
, int tick
){
390 int w1
= tick
- s
->tick
;
391 int w2
= s
->tick
+s
->dur
- tick
;
393 pattern
* p1
= new pattern();
394 pattern
* p2
= new pattern();
403 p2
->v
= randf(0.2,0.8);
407 //split the events into two groups
408 mevent
* e
= s
->p
->events
->next
;
410 mevent
* f
= new mevent(e
);
412 if(e
->tick
< tick
-s
->tick
){//group 1
415 else if(e
->tick
== tick
-s
->tick
){//depends, maybe one, maybe other
416 if(e
->type
== MIDI_NOTE_OFF
){
431 s1
= new seqpat(zs
,p1
);
435 s2
= new seqpat(zs
,p2
);
436 s2
->tick
= s1
->tick
+ w1
;
443 void SplitSeqpat::redo(){
445 tinsert
<seqpat
>(s
->prev
,s1
);
446 tinsert
<seqpat
>(s1
,s2
);
449 void SplitSeqpat::undo(){
452 tinsert
<seqpat
>(s
->prev
,s
);
457 JoinSeqpat::JoinSeqpat(seqpat
* zs1
, seqpat
* zs2
){
461 pattern
* p
= new pattern();
467 mevent
* e
= s1
->p
->events
->next
;
469 mevent
* f
= new mevent(e
);
475 e
=s2
->p
->events
->next
;
477 mevent
* f
= new mevent(e
);
484 s
= new seqpat(s1
,p
);
486 s
->dur
= s1
->dur
+ s2
->dur
;
489 void JoinSeqpat::redo(){
492 tinsert
<seqpat
>(s
->prev
,s
);
495 void JoinSeqpat::undo(){
497 tinsert
<seqpat
>(s
->prev
,s1
);
498 tinsert
<seqpat
>(s1
,s2
);
502 void ClearSeqpat::redo(){
506 void ClearSeqpat::undo(){
510 void LayerSeqpat::redo(){
511 if(s
->layers
== NULL
){
512 s
->layers
= new layerstack(s
->p
);
518 void LayerSeqpat::undo(){
519 s
->p
= s
->layers
->pop();
520 printf("ok...%d\n",s
->layers
->total
);
521 if(s
->layers
->total
== 1){
522 printf("deleting layers\n");
529 void CreateNote::redo(){
530 mevent
* targ
= tfind
<mevent
>(p
->events
, e1
->tick
);
531 tinsert
<mevent
>(targ
, e1
);
532 targ
= tfind
<mevent
>(p
->events
, e2
->tick
);
533 tinsert
<mevent
>(targ
, e2
);
536 void CreateNote::undo(){
541 void CreateNoteOn::redo(){
542 mevent
* targ
= tfind
<mevent
>(p
->events
, e1
->tick
);
543 tinsert
<mevent
>(targ
, e1
);
544 //targ = tfind<mevent>(p->events, e2->tick);
545 //tinsert<mevent>(targ, e2);
548 void CreateNoteOn::undo(){
550 //tremove<mevent>(e2);
554 CreateNoteOff::CreateNoteOff(pattern
* zp
, int note
, int vel
, int tick
){
557 mevent
* ptr
= tfind
<mevent
>(zp
->events
,tick
);
559 if(ptr
->type
== MIDI_NOTE_ON
&& ptr
->value1
== note
){
561 dur2
= tick
- ptr
->tick
;
565 if(ptr
->type
== MIDI_NOTE_OFF
&& ptr
->value1
== note
){
570 e2
= new mevent(MIDI_NOTE_OFF
, tick
, note
);
574 void CreateNoteOff::redo(){
575 //mevent* targ = tfind<mevent>(p->events, e1->tick);
576 //tinsert<mevent>(targ, e1);
578 targ
= tfind
<mevent
>(p
->events
, e2
->tick
);
579 tinsert
<mevent
>(targ
, e2
);
585 void CreateNoteOff::undo(){
586 //tremove<mevent>(e1);
593 void DeleteNote::redo(){
600 void DeleteNote::undo(){
601 tinsert
<mevent
>(e1
->prev
,e1
);
603 tinsert
<mevent
>(e2
->prev
,e2
);
609 void MoveNote::arrive(int t
){
610 mevent
* targ
= tfind
<mevent
>(p
->events
, t
);
611 tinsert
<mevent
>(targ
, e1
);
613 targ
= tfind
<mevent
>(p
->events
, t
+e1
->dur
);
614 tinsert
<mevent
>(targ
, e2
);
618 void MoveNote::redo(){
624 e2
->tick
= t2
+e1
->dur
;
630 void MoveNote::undo(){
636 e2
->tick
= t1
+e1
->dur
;
645 ResizeNote::ResizeNote(pattern
* zp
, mevent
* ze
, int dur
){
656 r2
->prev
= tfind
<mevent
>(p
->events
, ze
->tick
+ dur
);
657 r2
->next
= r2
->prev
->next
;
659 if(r2
->prev
== r1
){//prev fix up
664 if(r2
->next
== r1
){//next fix up
668 r2
->tick
= ze
->tick
+ dur
;
672 void ResizeNote::redo(){
673 //tremove<mevent>(l1);
676 tinsert
<mevent
>(r2
->prev
, r2
);
679 //tinsert<mevent>(l2->prev, l2);
681 // tinsert<mevent>(r2->prev, r2);
687 void ResizeNote::undo(){
690 tinsert
<mevent
>(r1
->prev
, r1
);
692 //tremove<mevent>(l2);
694 //tinsert<mevent>(l1->prev, l1);
696 // tinsert<mevent>(r1->prev, r1);
705 void CreateEvent::redo(){
706 tinsert
<mevent
>(e
->prev
, e
);
709 void CreateEvent::undo(){
713 void DeleteEvent::redo(){
717 void DeleteEvent::undo(){
718 tinsert
<mevent
>(e
->prev
, e
);
721 void ChangeEvent::redo(){
722 tswap
<mevent
>(e1
,e2
);
725 void ChangeEvent::undo(){
726 tswap
<mevent
>(e2
,e1
);
733 mevent
* find_off(mevent
* e
){
736 if(ptr
->type
== MIDI_NOTE_OFF
&& ptr
->value1
== e
->value1
&&
737 ptr
->tick
!= e
->tick
){
753 events
= new mevent();//dummy
775 pattern::pattern(pattern
* p
){
776 mevent
* ptr
= p
->events
;
778 events
= new mevent(ptr
);
782 ptr2
->next
= new mevent(ptr
);
783 ptr2
->next
->prev
= ptr2
;
798 void pattern::regen_colors(){
800 while(h
>360){h
-=360;}
804 if(v
< 0.2){v
= 0.2;}
805 if(v
> 0.8){v
= 0.8;}
807 hsv_to_rgb(h
,s
,v
,&r1
,&g1
,&b1
);
808 hsv_to_rgb(h
,s
,v
/2,&r2
,&g2
,&b2
);
809 hsv_to_rgb(h
,s
,v
+0.2 > 1 ? 1 : v
+0.2,&r3
,&g3
,&b3
);
811 hsv_to_rgb(h
,s
,v
-0.3,&rx
,&gx
,&bx
);
814 hsv_to_rgb(h
,s
,0.7,&rx
,&gx
,&bx
);
819 void pattern::append(mevent
* ze
){
828 void pattern::insert(mevent
* ze
, int tick
){
829 mevent
* ptr
= events
;
831 if(ptr
->next
->tick
> tick
){
832 ze
->next
= ptr
->next
;
845 void pattern::fixdur(){
849 if(e
->type
== MIDI_NOTE_ON
){
851 if(f
){e
->dur
= f
->tick
- e
->tick
;}
857 //used when the sequence is changed in such a way
858 //that the sequencer state needs to be updated
859 void track::restate(){
860 int pos
= get_play_position();
861 seqpat
* s
= head
->next
;
866 //printf("trying block: pos %d, tick %d, t2 %d\n",pos,s->tick,s->tick+s->dur);
867 if(pointfound
){//we are past the point, reset up coming blocks
868 //printf("future block\n");
869 s
->skip
= s
->p
->events
->next
;
872 else if(s
->tick
+s
->dur
< pos
){//we are past this block
873 //printf("past block\n");
877 else if(s
->tick
+s
->dur
> pos
&& s
->tick
<= pos
){//we are inside this block, point found
878 //printf("inside block\n");
882 mevent
* e
= s
->p
->events
->next
;
884 if(e
->tick
+s
->tick
>= pos
){
897 else{//we are not in a block, point found
898 //printf("pointfound outside block\n");
907 if(snullflag
){skip
= NULL
;}
911 void seqpat::restate(){
912 mevent
* e
= p
->events
->next
;
913 int pos
= get_play_position();
915 if(e
->tick
+tick
>= pos
){
926 void seqpat::apply_erase(){
930 c
= new ClearSeqpat(this);
935 //create new pattern and make it current
936 void seqpat::apply_layer(){
937 Command
* c
= new LayerSeqpat(this);
942 void seqpat::next_layer(){
948 void seqpat::prev_layer(){
954 int seqpat::layer_index(){
956 return layers
->index
;
963 int seqpat::layer_total(){
965 return layers
->total
;
972 void seqpat::record_check(int mode
){
974 if(mode
==1 || mode
==2){
975 autocomplete();//end stuck notes
976 if(mode
== 1){apply_erase();}
977 else if(mode
== 2){apply_layer();}
978 tracks
[track
]->restate();
984 //sends note off if it determines that
985 //we are in between two notes
986 void seqpat::autocomplete(){
988 mevent
* e
= p
->events
->next
;
991 int pos
= get_play_position()-tick
;
993 int chan
= tracks
[track
]->chan
;
994 int port
= tracks
[track
]->port
;
995 printf("use of deprecated function seqpat::autocomplete\n");
997 if(e
->type
== MIDI_NOTE_ON
&& e
->tick
< pos
){
1000 if(eoff
->tick
> pos
){
1001 midi_note_off(e
->value1
,chan
,port
);
1015 pattern
* layerstack::push_new(){
1020 array
[total
-1] = new pattern();
1021 array
[total
-1]->h
= array
[0]->h
;
1022 array
[total
-1]->s
= array
[0]->s
;
1023 array
[total
-1]->v
= array
[0]->v
;
1024 array
[total
-1]->regen_colors();
1026 return array
[index
];
1029 void layerstack::push(pattern
* p
){
1040 void layerstack::reallocate(){
1041 pattern
** ptmp
= new pattern
*[memsize
*2];
1042 for(int i
=0; i
<memsize
; i
++){
1050 pattern
* layerstack::pop(){
1054 if(index
== total
-1){
1057 array
[total
-1]=NULL
;
1059 return array
[index
];
1062 void layerstack::remove(int n
){
1066 void layerstack::insert(pattern
* p
, int n
){
1071 pattern
* layerstack::next(){
1078 return array
[index
];
1081 pattern
* layerstack::prev(){
1088 return array
[index
];
1091 layerstack::layerstack(pattern
* p
){
1094 array
= new pattern
*[16];
1101 layerstack::~layerstack(){
1102 for(int i
=0; i
<total
; i
++){
1104 if(array
[i
]->ref_c
== 0){
1112 void reset_record_flags(){
1113 for(int i
=0; i
<tracks
.size(); i
++){
1114 seqpat
* s
= tracks
[i
]->head
->next
;
1116 if(s
->record_flag
== 1){
1127 void set_undo(Command
* c
){
1128 if(undo_ptr
!= undo_stack
.end()){
1129 //printf("changing the past, need to erase the future\n");
1130 std::list
<int>::iterator nptr
= undo_number
.end();
1132 while(nptr
!= undo_nptr
){
1134 //printf("deleting %d commands\n",N);
1135 for(int i
=0; i
<N
; i
++){
1136 //delete this command
1137 undo_stack
.pop_back();
1140 undo_number
.pop_back();
1143 //printf("pushing command\n");
1144 undo_stack
.push_back(c
);
1145 undo_ptr
= undo_stack
.end();
1149 void undo_push(int n
){
1151 //printf("pushing number of commands %d\n",n);
1152 undo_number
.push_back(n
);
1157 if(undo_ptr
==undo_stack
.begin()){
1158 printf("no more to undo!\n");
1161 //printf("undoing\n");
1164 for(int i
=0; i
<N
; i
++){
1166 (*undo_ptr
)->undo();
1171 if(undo_ptr
==undo_stack
.end()){
1172 printf("no more to redo!\n");
1175 //printf("redoing\n");
1178 for(int i
=0; i
<N
; i
++){
1179 (*undo_ptr
)->redo();
1185 //printf("undo reset\n");
1186 int N
= undo_stack
.size();
1187 for(int i
=0; i
<N
; i
++){
1188 std::list
<Command
*>::iterator c
= undo_stack
.end();
1191 undo_stack
.pop_back();
1194 N
= undo_number
.size();
1195 for(int i
=0; i
<N
; i
++){
1196 undo_number
.pop_back();
1199 undo_nptr
= undo_number
.begin();
1200 undo_ptr
= undo_stack
.begin();
1204 OnBitArray::OnBitArray(){
1205 for(int i
=0; i
<16; i
++){
1212 int OnBitArray::get(int note
){
1213 //note/8 = note >> 3
1214 //note%8 = note & 0x7
1215 return bytes
[note
>> 3] & (1 << (note
& 0x7));
1218 void OnBitArray::set(int note
, int value
){
1219 //note/8 = note >> 3
1220 //note%8 = note & 0x3
1223 bytes
[note
>> 3] |= (1 << (note
& 0x7));
1226 bytes
[note
>> 3] &= ~(1 << (note
& 0x7));
1230 void OnBitArray::search_init(){
1235 int OnBitArray::search_next(){
1237 for(int i
=spos
; i
<16; i
++){
1241 for(int j
=jpos
; j
<8; j
++){
1252 //bytes[i] &= ~(1<<j);
1262 void OnBitArray::clear(){
1263 for(int i
=0; i
<16; i
++){