#include "memory.h" #include #include using namespace std; #include "allegro.h" void seq_print(Alg_seq_ptr seq) { for (int i = 0; i < seq->tracks(); i++) { printf("TRACK %d\n", i); for (int j = 0; j < seq->track(i)->length(); j++) { (*seq->track(i))[j]->show(); } } } Alg_seq_ptr make_simple_score() { Alg_seq_ptr seq = new Alg_seq; Alg_update_ptr update = seq->create_update(0, 0, -1); update->set_real_value("attackr", 0.007); seq->add_event(update, 0); Alg_note_ptr note = seq->create_note(0, 0, 63, 63, 105, 0.8); // at 100bpm, dur will be 1.33 beats seq->add_event(note, 0); // at 100bpm, time = W0.33 beats, dur = 0.66 beats note = seq->create_note(0.8, 0, 65, 65, 107, 0.4); seq->add_event(note, 0); //seq_print(seq); return seq; } void test1() { Alg_seq_ptr seq = make_simple_score(); seq->write(cout, false); } void test2() { Alg_seq_ptr seq = make_simple_score(); seq->convert_to_seconds(); seq->get_time_map()->last_tempo = 120.0 / 60.0; // 120bpm seq->time_sig.insert(0, 3, 4); seq->write(cout, false); } Alg_seq_ptr make_score() { Alg_seq_ptr seq = make_simple_score(); // now we have notes at 0 and 0.8 seconds // add new ones at 1.2 and 1.8 seconds Alg_note_ptr note = seq->create_note(1.2, 0, 67, 67, 107, 0.6); seq->add_event(note, 0); note = seq->create_note(1.8, 0, 69, 69, 109, 0.2); seq->add_event(note, 0); // make the tempo such that notes start at 0, 1, 2, 3 beats seq->convert_to_seconds(); // hold time, change beats seq->get_time_map()->insert_beat(0.8, 1.0); seq->get_time_map()->insert_beat(1.2, 2.0); seq->get_time_map()->insert_beat(1.8, 3.0); seq->get_time_map()->insert_beat(2.0, 4.0); return seq; } void test3() { Alg_seq_ptr seq = make_score(); // show the tempo map: seq->get_time_map()->show(); // write the sequence seq->write(cout, false); // in beats /* score should include 63 @ m 0 = 0s 65 @ m 0.25 = 0.8s 67 @ m 0.5 = 1.2s 69 @ m 0.75 = 1.8s */ seq->write(cout, true); // in seconds } void test4() { Alg_seq_ptr seq = make_score(); seq->write(cout, false); ofstream file("test4.mid", ios::out | ios::binary); if (!file) { printf("could not open test4.mid for writing"); return; } seq->smf_write(file); file.close(); delete seq; ifstream ifile("test4.mid", ios::binary | ios::in); if (ifile.fail()) { printf("could not open test4.mid for reading"); return; } seq = new Alg_seq(ifile, true); // read midi file ifile.close(); seq->write(cout, false); } void test5() { Alg_seq_ptr seq = make_score(); ofstream file("test5.gro"); if (file.is_open()) { printf("could not open test5.gro for writing"); return; } seq->write(cout, true); seq->write(file, true); file.close(); delete seq; ifstream ifile("test5.gro"); if (ifile.fail()) { printf("could not open test5.gro for reading"); return; } seq = new Alg_seq(ifile, false); // read midi file ifile.close(); printf("SCORE AFTER READING\n"); seq->write(cout, true); } void test6() { Alg_seq_ptr seq = make_score(); seq->write(cout, true); long index = seq->seek_time(1.0, 0); printf("seq->get_units_are_seconds() = %d\n", seq->get_units_are_seconds()); printf("seq->seek_time(1.0, 0) returns %ld\n", index); printf("note is:\n"); if ((*seq->track(0))[index]->is_note()) { ((Alg_note_ptr) (*(seq->track(0)))[index])->show(); } else { printf("event is not a note\n"); } } /* # test6() # should print # seq.units_are_seconds t # seq_time(1,0) returns 5 # note is: # Alg_note: time 1.2, chan 0, dur 0.6, key 67, pitch 67, loud 107, attributes nil */ void test7() { Alg_seq_ptr seq = make_score(); seq->write(cout, false); // insert time signature for one bar each of 4/4, 3/4, 5/4, 4/4 and // call quarter_to_measure() on various times seq->convert_to_beats(); // make sure we're talking beats seq->time_sig.insert(0, 4, 4); seq->time_sig.insert(4, 3, 4); seq->time_sig.insert(7, 5, 4); seq->time_sig.insert(12, 4, 4); double qtable[] = {0, 1, 3.999, 4, 4.001, 5, 7, 7.5, 12, 17, 17.25}; for (int i = 0; i < 11; i++) { long m; double b, n, d; seq->beat_to_measure(qtable[i], &m, &b, &n, &d); printf("%g -> %ld + %g (%g/%g)\n", qtable[i], m, b, n, d); } } /* # test7() # should print: # 0 -> [0, 0, 4, 4] # 1 -> [0, 1, 4, 4] # 3.99999 -> [0, 3.99999, 4, 4] # 4 -> [1, 0, 3, 4] # 4.00001 -> [1, 1e-005, 3, 4] # 5 -> [1, 1, 3, 4] # 7 -> [2, 0, 5, 4] # 7.5 -> [2, 0.5, 5, 4] # 12 -> [3, 0, 4, 4] # 17 -> [4, 1, 4, 4] # 17.25 -> [4, 1.25, 4, 4] */ void test8() { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); // just to be sure seq->write(cout, false); seq->get_time_map()->beats.len = 1; seq->get_time_map()->show(); seq->write(cout, false); printf("insert 1 1 returns %d\n", seq->insert_beat(1.0, 1.0)); seq->get_time_map()->show(); printf("insert 5 3 returns %d\n", seq->insert_beat(5.0, 3.0)); seq->get_time_map()->show(); seq->write(cout, false); seq->write(cout, true); } /* # should indicate notes starting at 0, .25, .5, and .75 whole notes, # and as seconds, starting at 0, 1, 3, and 5 seconds */ void test9() { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); // just to be sure seq->write(cout, false); seq->get_time_map()->beats.len = 1; seq->get_time_map()->show(); seq->write(cout, false); printf("insert 30 1 returns %d\n", seq->insert_tempo(30.0, 1.0)); seq->get_time_map()->show(); printf("insert 15 2 returns %d\n", seq->insert_tempo(15.0, 2.0)); seq->get_time_map()->show(); seq->write(cout, false); seq->write(cout, true); } /* # show show # TW0.25 -tempor:30 # TW0.5 -tempor:15 # in the beat-based output, and beats at 0, 0.6, 2.6, 6.6 in the # time-based output */ void test10() { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); // just to be sure seq->set_time_sig(0.0, 4, 4); seq->set_time_sig(4.0, 3, 4); seq->set_time_sig(7.0, 5, 4); seq->set_time_sig(12.0, 4, 4); double btable[] = { 0.0, 4.0, 7.0, 12.0 }; for (int i = 0; i < 4; i++) { long m; double b, n, d; seq->beat_to_measure(btable[i], &m, &b, &n, &d); printf("%g -> %ld + %g (%g/%g)\n", btable[i], m, b, n, d); } } /* # result should show increasing measure numbers: # # [0, 0, 4, 4] # [1, 0, 3, 4] # [2, 0, 5, 4] # [3, 0, 4, 4] */ void test11() // add track { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); seq->add_track(3); Alg_note_ptr note = seq->create_note(2.0, 0, 50, 50, 100, 1.0); seq->add_event(note, 3); seq->write(cout, false); seq->write(cout, true); } /* # should put note in track3 at beat TW0.5 (same as T1.2). Make sure # in the beat representation, note has duration Q1. */ void test12() // test merge_tracks() { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); // just to be sure seq->add_track(3); Alg_note_ptr note = seq->create_note(2.0, 0, 50, 50, 100, 1.0); seq->add_event(note, 3); seq->write(cout, false); seq->merge_tracks(); seq->write(cout, false); } /* # test12() # # tracks 1, 2, 3 go away, and the note that was in track 3 appears in track 0 */ void test13() { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); // just to be sure seq->write(cout, false); seq->set_tempo(120.0, 1, 3); seq->write(cout, false); } /* # test13() # # tempo should be transformed to: # # TW0 -tempor:75 # TW0.25 -tempor:120 # TW0.75 -tempor:300 # TW1 -tempor:100 */ void test14() { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); // just to be sure seq->write(cout, false); seq->set_start_time((*(seq->track(0)))[3], 0.5); seq->write(cout, false); } /* # test14() # # should place pitch 67 note at time TW0.125 */ void test15() // test copy() routine { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); // just to be sure Alg_event_ptr event = (*(seq->track(0)))[3]; event->show(); event = seq->copy_event(event); event->show(); event = (*(seq->track(0)))[0]; event->show(); event = seq->copy_event(event); event->show(); } /* # test15() # # should print two identical notes, (orginal and a copy) # and two identical updates */ void test16() // test cut_from_track { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); // just to be sure seq->write(cout, false); Alg_track_ptr track = seq->cut_from_track(0, 2, 1, true); seq->track_list.append(track); seq->write(cout, false); } /* # test16() # # should print original score and modified score # modified score has: # K63 at TW0 # K65 at TW0.25 # K69 at TW0.5 # and on track 1 has # K67 at TW0 */ void test17() // test cut { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); // just to be sure seq->set_time_sig(0, 2, 4); seq->set_time_sig(2, 2, 8); seq->set_time_sig(3, 4, 4); seq->write(cout, false); Alg_seq_ptr new_seq = seq->cut(2, 1, true)->to_alg_seq(); printf("after cut, original is\n"); seq->write(cout, false); printf("after cut, new is\n"); new_seq->write(cout, false); } /* # test17() # # should see seq with everything, then seq with # 2/4 at 0, 4/4 at TW0.5 # and K63 at TW0, K65 at TW0.25, and K69 at TW0.5, # then in last seq, # 2/8 at 0, and K67 at 0 */ void test18() // test copy_interval_from_track { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); // just to be sure Alg_track_ptr track = seq->track_list[0].copy(1, 2, false); seq->track_list.append(track); seq->write(cout, false); } /* # test18() # # should see track 0 from beat 1 to 3, i.e. # K65 at T0, K67 at TW0.25 */ void test19() // test copy { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); seq->set_time_sig(0, 2, 4); seq->set_time_sig(2, 2, 8); seq->set_time_sig(3, 4, 4); seq->set_tempo(120.0, 1, 3); seq->write(cout, false); printf("\n"); Alg_seq_ptr new_seq = seq->copy(2, 1, true); printf("----------after cut, original---------\n"); seq->write(cout, false); printf("----------after cut, new--------------\n"); new_seq->write(cout, false); } /* # test19() # # should output original, original again (with no changes), # then a sequence with tempo 120 and k67 at TW0 */ void test20() // TEST 20 -- test track paste { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); Alg_track &track = *(seq->track(0)->copy(1, 2, false)); printf("-------seq:---------\n"); seq->write(cout, false); printf("-------track to paste ---------:\n"); Alg_seq_ptr new_seq = new Alg_seq(track); new_seq->write(cout, false); seq->track(0)->paste(2, &track); printf("----------after paste, seq is:---------\n"); seq->write(cout, false); } /* # test20() # # final printed sequence should be quarter notes as follows: # K63, K65, K65, K67, K67, K69 (last at TW1.25) */ void test21() // TEST 21 -- test paste { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); seq->set_time_sig(0, 2, 4); seq->set_time_sig(2, 2, 8); seq->set_time_sig(3, 4, 4); seq->set_tempo(120.0, 1, 3); printf("-------seq original:---------\n"); seq->write(cout, false); Alg_seq_ptr copy_buffer = seq->copy(1, 2, false); printf("-------what to paste:---------\n"); copy_buffer->write(cout, false); seq->paste(2, copy_buffer); printf("-------after paste: ---------:\n"); seq->write(cout, false); } /* # test21() # # should print like in test20, but with tempo as follows: # TW0: 75 # TW0.25: 120 # TW0.5: 120 # TW1: 120 # TW1.25 300 # TW1.5: 100 # and the time signatures should be: # TW0: 2/4 # TW0.5: 2/4 # TW0.75: 2/8 # TW1: 2/8 # TW1.25: 4/4 */ void test22() // TEST 22 -- test merge_to_track { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); Alg_track_ptr track = seq->track(0)->copy(1, 2, false); printf("seq\n"); seq->write(cout, false); printf("track:\n"); Alg_seq_ptr new_seq = new Alg_seq(track); new_seq->write(cout, false); seq->merge(2, new_seq); printf("seq after merge\n"); seq->write(cout, false); } /* #test22() # # should output as follows: # 0 K63 # 0.25 K65 # 0.5 K67 and K65 # 0.75 K69 and K67 */ void test23() // test merge { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); Alg_track_ptr track = seq->track(0)->copy(1, 2, false); printf("seq:\n"); seq->write(cout, false); printf("new_seq:\n"); Alg_seq_ptr new_seq = new Alg_seq(track); new_seq->write(cout, false); seq->merge(2, new_seq); printf("seq after merge:\n"); seq->write(cout, false); } /* # test23() # # should output same as test22 */ void test24() // test silence_track { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); seq->silence_track(0, 1, 2, true); seq->write(cout, false); } /* #test24() # # should print two notes: K63 at T0 and K69 at TW0.75 */ void test25() // test silence_events { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); // copy everything from track 0 Alg_track_ptr tr = seq->copy_track(0, 0, 10, false); // and make the new data be track 1 seq->track_list.append(tr); seq->silence(1, 2, true); seq->write(cout, false); } /* #test25() # # should print track 0 like test24, and track 1 like track 0 */ void test26() // test clear_track { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); seq->clear_track(0, 1, 2, true); seq->write(cout, false); } /* # test26() # # should print two notes: K63 at T0 and K69 at TW0.25 */ void test27() // test clear { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); // copy everything from track 0 Alg_track_ptr track = seq->copy_track(0, 0, 10, false); // and make the new data be track 1 seq->track_list.append(track); seq->clear(1, 2, true); seq->write(cout, false); } /* # # should print track 0 like test26, and track 1 like track 0 */ void test28() // test insert_silence_in_track { Alg_seq_ptr seq = make_score(); printf("BEFORE:\n"); seq->write(cout, false); seq->convert_to_beats(); seq->insert_silence_in_track(0, 1, 2); printf("AFTER:\n"); seq->write(cout, false); } /* # test28() # # should print this: # TW0 K63 # TW0.75 K65 # TW1 K67 # TW1.25 K69 */ void test29() // test insert_silence { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); seq->set_time_sig(0, 2, 4); seq->set_time_sig(2, 2, 8); printf("BEFORE:\n"); seq->write(cout, false); seq->insert_silence(1, 2); printf("AFTER:\n"); seq->write(cout, false); } /* # test29() # # should print # TW0 -tempor:75 # TW0.25 -tempor:150 # TW1 -tempor:100 # TW1.25 -tempor:300 # TW1.5 -tempor:100 # TW0 ... (2/4 time) ... # TW1 ... (2/8 time) ... # TW0 V0 -attackr:0.007 # TW0 V0 K63 P63 Q1 L105 # TW0.75 V0 K65 P65 Q1 L107 # TW1 V0 K67 P67 Q1 L107 # TW1.25 V0 K69 P69 Q1 L109 */ void test30() // test find on a track { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); Alg_event_list_ptr track = seq->track(0)->find(0, 2, false, 1 << 0, 1 << ALG_NOTE); seq->track_list.append(new Alg_track(*track, seq->get_time_map(), seq->get_units_are_seconds())); seq->write(cout, false); } /* # test30() # # sets track 1 to TW0 K63, TW0.25 K65 */ void test31() // test find_in_track { Alg_seq_ptr seq = make_score(); seq->convert_to_beats(); Alg_event_list_ptr track = seq->find_in_track(0, 0, 2, false, 1 << 0, 1 << ALG_NOTE); seq->track_list.append(new Alg_track(*track, seq->get_time_map(), seq->get_units_are_seconds())); seq->write(cout, false); } void test32() // serialize big midi file and unserialize { ifstream file("jsb-wtc-c-f.mid", ios::in | ios::binary); if (!file) { printf("Error: Could not open jsb-wtc-c-f.mid for reading\n"); return; } Alg_seq_ptr seq = new Alg_seq(file, true); // read midi file file.close(); ofstream ofile("bigseq1.alg", ios::out | ios::binary); printf("after reading, real_dur is %g, beat_dur is %g\n", seq->get_real_dur(), seq->get_beat_dur()); seq->write(ofile, true); ofile.close(); void *buffer; long bytes; seq->serialize(&buffer, &bytes); printf("Serialized %ld bytes\n", bytes); Alg_seq_ptr new_seq = (Alg_seq_ptr) seq->unserialize(buffer, bytes); ofstream sfile("bigseq2.alg", ios::out | ios::binary); new_seq->write(sfile, true); sfile.close(); } void test33() // cut and inspect some notes { ifstream file("be-ps-05.mid", ios::in | ios::binary); if (!file.is_open()) { printf("Error: Could not open be-ps-05.mid for reading\n"); return; } Alg_seq_ptr seq = new Alg_seq(file, true); // read midi file file.close(); seq->convert_to_seconds(); Alg_time_map_ptr tm = seq->get_time_map(); printf("time map %p before\n", tm); // tm->show(); printf("timestamp before %.15g\n", tm->beats[tm->locate_time(3.74)].time); ofstream ofile("before-33.alg", ios::out | ios::binary); seq->write(ofile, true); ofile.close(); Alg_seq_ptr cut = seq->cut(0.0, 3.0, false); tm = seq->get_time_map(); printf("timemap %p after\n", tm); // tm->show(); printf("timestamp after %.15g\n", tm->beats[tm->locate_time(0.74)].time); ofile.open("after-33.alg", ios::out | ios::binary); seq->write(ofile, true); ofile.close(); } int main() { test33(); printf("Test 33 done, type return to exit\n"); getchar(); }