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
30 #include <fltk/TextDisplay.h>
35 std::vector
<track
*> tracks
;
37 std::list
<Command
*> undo_stack
;
38 std::list
<int> undo_number
;
39 std::list
<Command
*>::iterator undo_ptr
;
45 static float default_hsv_value
= 0.8;
51 int play_seq(int cur_tick
, void (*dispatch_event
)(mevent
*, int port
, int tick
)){
58 /* start at skip s, and skip e
59 if e is in the past, dispatch event and set new skip
60 if next e is past pattern dur, switch patseq
61 if next e is null, switch patseq
62 switch patseq sets skip s
63 do the above until e is in the future and not past end
64 then go to next track and start over
67 //printf("playing. cur_tick = %d\n",cur_tick);
69 for(int i
=0; i
<tracks
.size(); i
++){
70 //if(tracks[i]->alive == 0){continue;}
76 if(!e
){ goto switchpatseq
; }//no more events in this seqpat
80 if(e
->tick
+s
->tick
<= cur_tick
&& e
->tick
<= s
->dur
){//should have happened
82 if(e
->tick
!= s
->dur
|| e
->type
== MIDI_NOTE_OFF
)
83 if(tracks
[i
]->mute
== 0)
84 if((get_solo() && tracks
[i
]->solo
!= 0) || !get_solo())
85 dispatch_event(e
, i
, s
->tick
);
89 if(!e
){//no more events in this seqpat
93 else if(e
->tick
> s
->dur
){//went past the end
96 else{//no more events on this track right now
99 goto again
;//try to play next event
104 if(!s
){continue;}//no more seqpats
106 if(!p
){continue;}//this shouldnt happen anymore
108 if(!e
){continue;}//...means this pattern has played already...
110 goto again
;//play some or all of the next seqpat
114 int set_seq_pos(int new_tick
){
121 for(int i
=0; i
<tracks
.size(); i
++){
127 s
->skip
= s
->p
->events
;
133 if(s
->tick
+s
->dur
<= new_tick
){
144 tracks
[i
]->skip
= NULL
;
156 else if(e
->tick
>= new_tick
- s
->tick
){
165 void set_rec_track(int t
){
173 int set_default_hsv_value(float v
){
174 default_hsv_value
= v
;
177 void set_undo(Command
* c
){
178 if(undo_ptr
!= undo_stack
.end()){
179 //then we need to clean house
180 //delete everything at and after undo_ptr (for real);
183 undo_stack
.push_back(c
);
184 undo_ptr
= undo_stack
.end();
188 void undo_push(int n
){
189 undo_number
.push_back(n
);
208 CreateSeqpat::CreateSeqpat(int track
, int tick
, seqpat
* zs
, int copy
){
211 s
->p
= new pattern(zs
->p
);
212 s
->skip
= s
->p
->events
;
217 s
->prev
= tfind
<seqpat
>(tracks
[track
]->head
,tick
);
218 s
->next
= s
->prev
->next
;
221 void CreateSeqpat::redo(){
222 tinsert
<seqpat
>(s
->prev
, s
);
225 void CreateSeqpat::undo(){
229 CreateSeqpatBlank::CreateSeqpatBlank(int track
, int tick
, int len
){
230 s
= new seqpat(track
, tick
, len
, new pattern());
235 p
->h
= ((track
%16) / 16.0) * 360;
236 p
->v
= default_hsv_value
;
242 s
->prev
= tfind
<seqpat
>(tracks
[track
]->head
,tick
);
243 s
->next
= s
->prev
->next
;
244 s
->skip
= s
->p
->events
;
248 void DeleteSeqpat::redo(){
250 int pos
= get_play_position();
251 if(pos
>= s
->tick
&& pos
<= s
->tick
+s
->dur
){
252 tracks
[s
->track
]->skip
= s
->next
;
258 void DeleteSeqpat::undo(){
259 tinsert
<seqpat
>(s
->prev
, s
);
263 void ResizeSeqpat::redo(){
265 tinsert
<seqpat
>(s1
->prev
,s2
);
270 void ResizeSeqpat::undo(){
272 tinsert
<seqpat
>(s1
->prev
,s1
);
275 MoveSeqpat::MoveSeqpat(seqpat
* zs
, int track
, int tick
){
282 targ2
= tfind
<seqpat
>(tracks
[track2
]->head
,tick
);
283 if(targ2
== zs
){//dont put it after itself
288 void MoveSeqpat::redo(){
293 int play_pos
= get_play_position();
294 if(play_pos
>= s
->tick
&& play_pos
<= s
->tick
+s
->dur
){//no entry into s by cb
295 tracks
[track1
]->skip
= s
->next
;
298 track
* t
= tracks
[track2
];
300 //here possibly wait a few ms for the audio to leave s if it was in
302 //perform nitty gritty
307 s
->skip
= tfind
<mevent
>(s
->p
->events
, play_pos
- s
->tick
)->next
;
308 tinsert
<seqpat
>(targ2
,s
);
311 void MoveSeqpat::undo(){
315 int play_pos
= get_play_position();
316 if(play_pos
>= s
->tick
&& play_pos
<= s
->tick
+s
->dur
){
317 tracks
[track2
]->skip
= s
->next
;
323 s
->skip
= tfind
<mevent
>(s
->p
->events
, play_pos
- s
->tick
)->next
;
325 tinsert
<seqpat
>(targ1
,s
);
328 void SplitSeqpat::redo(){
332 void SplitSeqpat::undo(){
339 void CreateNote::redo(){
340 mevent
* targ
= tfind
<mevent
>(p
->events
, e1
->tick
);
341 tinsert
<mevent
>(targ
, e1
);
342 targ
= tfind
<mevent
>(p
->events
, e2
->tick
);
343 tinsert
<mevent
>(targ
, e2
);
346 void CreateNote::undo(){
351 void CreateNoteOn::redo(){
352 mevent
* targ
= tfind
<mevent
>(p
->events
, e1
->tick
);
353 tinsert
<mevent
>(targ
, e1
);
354 //targ = tfind<mevent>(p->events, e2->tick);
355 //tinsert<mevent>(targ, e2);
358 void CreateNoteOn::undo(){
360 //tremove<mevent>(e2);
364 CreateNoteOff::CreateNoteOff(pattern
* zp
, int note
, int vel
, int tick
){
367 mevent
* ptr
= tfind
<mevent
>(zp
->events
,tick
);
369 if(ptr
->type
== MIDI_NOTE_ON
&& ptr
->value1
== note
){
371 dur2
= tick
- ptr
->tick
;
375 if(ptr
->type
== MIDI_NOTE_OFF
&& ptr
->value1
== note
){
380 e2
= new mevent(MIDI_NOTE_OFF
, tick
, note
);
384 void CreateNoteOff::redo(){
385 //mevent* targ = tfind<mevent>(p->events, e1->tick);
386 //tinsert<mevent>(targ, e1);
388 targ
= tfind
<mevent
>(p
->events
, e2
->tick
);
389 tinsert
<mevent
>(targ
, e2
);
395 void CreateNoteOff::undo(){
396 //tremove<mevent>(e1);
403 void DeleteNote::redo(){
410 void DeleteNote::undo(){
411 tinsert
<mevent
>(e1
->prev
,e1
);
413 tinsert
<mevent
>(e2
->prev
,e2
);
419 void MoveNote::arrive(int t
){
420 mevent
* targ
= tfind
<mevent
>(p
->events
, t
);
421 tinsert
<mevent
>(targ
, e1
);
423 targ
= tfind
<mevent
>(p
->events
, t
+e1
->dur
);
424 tinsert
<mevent
>(targ
, e2
);
428 void MoveNote::redo(){
434 e2
->tick
= t2
+e1
->dur
;
440 void MoveNote::undo(){
446 e2
->tick
= t1
+e1
->dur
;
455 ResizeNote::ResizeNote(pattern
* zp
, mevent
* ze
, int dur
){
465 r2
->prev
= tfind
<mevent
>(p
->events
, ze
->tick
+ dur
);
466 if(r2
->prev
== r1
|| r2
->prev
== l1
){
469 r2
->tick
= ze
->tick
+ dur
;
473 void ResizeNote::redo(){
479 tinsert
<mevent
>(l2
->prev
, l2
);
481 tinsert
<mevent
>(r2
->prev
, r2
);
485 void ResizeNote::undo(){
491 tinsert
<mevent
>(l1
->prev
, l1
);
493 tinsert
<mevent
>(r1
->prev
, r1
);
500 void CreateEvent::redo(){
501 tinsert
<mevent
>(e
->prev
, e
);
504 void CreateEvent::undo(){
508 void DeleteEvent::redo(){
512 void DeleteEvent::undo(){
513 tinsert
<mevent
>(e
->prev
, e
);
516 void ChangeEvent::redo(){
517 tswap
<mevent
>(e1
,e2
);
520 void ChangeEvent::undo(){
521 tswap
<mevent
>(e2
,e1
);
528 mevent
* find_off(mevent
* e
){
531 if(ptr
->type
== MIDI_NOTE_OFF
&& ptr
->value1
== e
->value1
){
547 events
= new mevent();//dummy
569 pattern::pattern(pattern
* p
){
570 mevent
* ptr
= p
->events
;
572 events
= new mevent(ptr
);
576 ptr2
->next
= new mevent(ptr
);
577 ptr2
->next
->prev
= ptr2
;
592 void pattern::regen_colors(){
594 while(h
>360){h
-=360;}
598 if(v
< 0.2){v
= 0.2;}
599 if(v
> 0.8){v
= 0.8;}
601 hsv_to_rgb(h
,s
,v
,&r1
,&g1
,&b1
);
602 hsv_to_rgb(h
,s
,v
/2,&r2
,&g2
,&b2
);
603 hsv_to_rgb(h
,s
,v
+0.2 > 1 ? 1 : v
+0.2,&r3
,&g3
,&b3
);
605 hsv_to_rgb(h
,s
,v
-0.3,&rx
,&gx
,&bx
);
608 hsv_to_rgb(h
,s
,0.7,&rx
,&gx
,&bx
);
613 void pattern::append(mevent
* ze
){
622 void pattern::insert(mevent
* ze
, int tick
){
623 mevent
* ptr
= events
;
625 if(ptr
->next
->tick
> tick
){
626 ze
->next
= ptr
->next
;
639 void pattern::fixdur(){
643 if(e
->type
== MIDI_NOTE_ON
){
645 if(f
){e
->dur
= f
->tick
- e
->tick
;}
653 //used when the sequence is changed in such a way
654 //that the sequencer state needs to be updated
655 void track::restate(){
656 int pos
= get_play_position();
657 seqpat
* s
= head
->next
;
662 //printf("trying block: pos %d, tick %d, t2 %d\n",pos,s->tick,s->tick+s->dur);
663 if(pointfound
){//we are past the point, reset up coming blocks
664 //printf("future block\n");
665 s
->skip
= s
->p
->events
->next
;
668 else if(s
->tick
+s
->dur
< pos
){//we are past this block
669 //printf("past block\n");
673 else if(s
->tick
+s
->dur
> pos
&& s
->tick
<= pos
){//we are inside this block, point found
674 //printf("inside block\n");
678 mevent
* e
= s
->p
->events
->next
;
680 if(e
->tick
+s
->tick
>= pos
){
693 else{//we are not in a block, point found
694 //printf("pointfound outside block\n");
703 if(snullflag
){skip
= NULL
;}
707 void seqpat::restate(){
708 mevent
* e
= p
->events
->next
;
709 int pos
= get_play_position();
711 if(e
->tick
+tick
>= pos
){
722 void seqpat::apply_erase(){
725 if(layers
->ref_c
== 0){
731 pattern
* ptmp
= new pattern();
736 ptmp
->regen_colors();
739 if(--(p
->ref_c
) == 0){
747 //create new pattern and make it current
748 void seqpat::apply_layer(){
750 p
= layers
->push_new();
753 layers
= new layerstack(p
);
755 p
= layers
->push_new();
759 void seqpat::next_layer(){
765 void seqpat::prev_layer(){
771 int seqpat::layer_index(){
773 return layers
->index
;
780 int seqpat::layer_total(){
782 return layers
->total
;
789 void seqpat::record_check(int mode
){
791 if(mode
==1 || mode
==2){
792 autocomplete();//end stuck notes
793 if(mode
== 1){apply_erase();}
794 else if(mode
== 2){apply_layer();}
795 tracks
[track
]->restate();
801 //sends note off if it determines that
802 //we are in between two notes
803 void seqpat::autocomplete(){
805 mevent
* e
= p
->events
->next
;
808 int pos
= get_play_position()-tick
;
810 int chan
= tracks
[track
]->chan
;
811 int port
= tracks
[track
]->port
;
814 if(e
->type
== MIDI_NOTE_ON
&& e
->tick
< pos
){
817 if(eoff
->tick
> pos
){
818 midi_note_off(e
->value1
,chan
,port
);
832 pattern
* layerstack::push_new(){
837 array
[total
-1] = new pattern();
838 array
[total
-1]->h
= array
[0]->h
;
839 array
[total
-1]->s
= array
[0]->s
;
840 array
[total
-1]->v
= array
[0]->v
;
841 array
[total
-1]->regen_colors();
846 void layerstack::push_new(pattern
* p
){
857 void layerstack::reallocate(){
858 pattern
** ptmp
= new pattern
*[memsize
*2];
859 for(int i
=0; i
<memsize
; i
++){
868 pattern
* layerstack::next(){
878 pattern
* layerstack::prev(){
888 layerstack::layerstack(pattern
* p
){
891 array
= new pattern
*[16];
898 layerstack::~layerstack(){
899 for(int i
=0; i
<total
; i
++){
901 if(array
[i
]->ref_c
== 0){
909 void reset_record_flags(){
910 for(int i
=0; i
<tracks
.size(); i
++){
911 seqpat
* s
= tracks
[i
]->head
->next
;
913 if(s
->record_flag
== 1){