You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
3.2KB

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