1 // playsmf.cpp 2 // 3 // Simple program to test the MidiFileIn class by reading and playing 4 // a single track from a given Standard MIDI file. 5 // 6 // by Gary Scavone, 2003. 7 8 #include "MidiFileIn.h" 9 #include "RtMidi.h" 10 #include <signal.h> 11 #include <cstdlib> 12 13 bool done = false; finish(int ignore)14static void finish(int ignore){ done = true; } 15 16 using namespace stk; 17 usage(void)18void usage(void) { 19 // Error function in case of incorrect command-line 20 // argument specifications. 21 std::cout << "\nusage: playsmf file track <port>\n"; 22 std::cout << " where file = a standard MIDI file,\n"; 23 std::cout << " track = the track to play (0 = 1st track),\n"; 24 std::cout << " and an optional port integer identifier can be specified\n"; 25 std::cout << " (default = 0) or a value of -1 to use a virtual MIDI output port.\n\n"; 26 exit( 0 ); 27 } 28 main(int argc,char * argv[])29int main( int argc, char *argv[] ) 30 { 31 RtMidiOut *midiout = 0; 32 33 if ( argc < 3 || argc > 4 ) usage(); 34 35 // Attempt to instantiate MIDI output class. 36 try { 37 midiout = new RtMidiOut(); 38 } 39 catch ( RtMidiError& error ) { 40 error.printMessage(); 41 exit(0); 42 } 43 44 // Check command-line arguments. 45 int port = 0; 46 if ( argc == 4 ) port = atoi( argv[3] ); 47 if ( port == -1 ) { 48 try { 49 midiout->openVirtualPort(); 50 } 51 catch ( RtMidiError& error ) { 52 error.printMessage(); 53 goto cleanup; 54 } 55 std::cout << "\nVirtual port open.\n\n"; 56 } 57 else { 58 if ( midiout->getPortCount() < 1 ) { 59 std::cout << "\nThere are no MIDI output destinations available!\n\n"; 60 goto cleanup; 61 } 62 try { 63 midiout->openPort( port ); 64 } 65 catch ( RtMidiError& error ) { 66 error.printMessage(); 67 goto cleanup; 68 } 69 } 70 71 // Install an interrupt handler function. Type "ctrl-c" to quit the 72 // program. 73 (void) signal( SIGINT, finish ); 74 75 try { 76 MidiFileIn midiFile( argv[1] ); 77 78 // Print a little information about the file. 79 std::cout << "\nThe MIDI file (" << argv[1] << ") information:\n"; 80 std::cout << " - format = " << midiFile.getFileFormat() << "\n"; 81 std::cout << " - tracks = " << midiFile.getNumberOfTracks() << "\n"; 82 std::cout << " - seconds / ticks = " << midiFile.getTickSeconds() << "\n"; 83 84 unsigned int track = (unsigned int) atoi( argv[2] ); 85 if ( midiFile.getNumberOfTracks() <= track ) { 86 std::cout << "\nInvalid track number ... playing track 0.\n"; 87 track = 0; 88 } 89 90 std::cout << "\nPress <enter> to start reading/playing.\n"; 91 char input; 92 std::cin.get(input); 93 94 std::vector<unsigned char> event; 95 unsigned long ticks = midiFile.getNextMidiEvent( &event, track ); 96 while ( !done && event.size() ) { 97 98 // Pause for the MIDI event delta time. 99 Stk::sleep( (unsigned long) (ticks * midiFile.getTickSeconds() * 1000 ) ); 100 101 midiout->sendMessage( &event ); 102 103 // Get a new event. 104 ticks = midiFile.getNextMidiEvent( &event, track ); 105 } 106 107 // Send a "all notes off" to the synthesizer. 108 event.clear(); 109 event.push_back( 0xb0 ); 110 event.push_back( 0x7b ); 111 event.push_back( 0x0 ); 112 midiout->sendMessage( &event ); 113 } 114 catch ( StkError & ) { 115 // You might want to do something more useful here. 116 std::cout << "\nAborting program!\n"; 117 goto cleanup; 118 } 119 120 cleanup: 121 delete midiout; 122 123 return 0; 124 } 125