File: playsmf.cpp

package info (click to toggle)
stk 5.0.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 5,908 kB
  • sloc: cpp: 33,513; ansic: 3,216; sh: 2,900; tcl: 2,444; perl: 114; objc: 60; makefile: 54
file content (124 lines) | stat: -rw-r--r-- 3,295 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// playsmf.cpp
//
// Simple program to test the MidiFileIn class by reading and playing
// a single track from a given Standard MIDI file.
//
// by Gary Scavone, 2003.

#include "MidiFileIn.h"
#include "RtMidi.h"
#include <signal.h>
#include <cstdlib>

bool done = false;
static void finish(int ignore){ done = true; }

using namespace stk;

void usage(void) {
  // Error function in case of incorrect command-line
  // argument specifications.
  std::cout << "\nusage: playsmf file track <port>\n";
  std::cout << "   where file = a standard MIDI file,\n";
  std::cout << "   track = the track to play (0 = 1st track),\n";
  std::cout << "   and an optional port integer identifier can be specified\n";
  std::cout << "   (default = 0) or a value of -1 to use a virtual MIDI output port.\n\n";
  exit( 0 );
}

int main( int argc, char *argv[] )
{
  RtMidiOut *midiout = 0;

  if ( argc < 3 || argc > 4 ) usage();

  // Attempt to instantiate MIDI output class.
  try {
    midiout = new RtMidiOut();
  }
  catch ( RtMidiError& error ) {
    error.printMessage();
    exit(0);
  }

  // Check command-line arguments.
  int port = 0;
  if ( argc == 4 ) port = atoi( argv[3] );
  if ( port == -1 ) {
    try {
      midiout->openVirtualPort();
    }
    catch ( RtMidiError& error ) {
      error.printMessage();
      goto cleanup;
    }
    std::cout << "\nVirtual port open.\n\n";
  }
  else {
    if ( midiout->getPortCount() < 1 ) {
      std::cout << "\nThere are no MIDI output destinations available!\n\n";
      goto cleanup;
    }
    try {
      midiout->openPort( port );
    }
    catch ( RtMidiError& error ) {
      error.printMessage();
      goto cleanup;
    }
  }

  // Install an interrupt handler function.  Type "ctrl-c" to quit the
  // program.
  (void) signal( SIGINT, finish );
  
  try {
    MidiFileIn midiFile( argv[1] );

    // Print a little information about the file.
    std::cout << "\nThe MIDI file (" << argv[1] << ") information:\n";
    std::cout << "  - format = " << midiFile.getFileFormat() << "\n";
    std::cout << "  - tracks = " << midiFile.getNumberOfTracks() << "\n";
    std::cout << "  - seconds / ticks = " << midiFile.getTickSeconds() << "\n";

    unsigned int track = (unsigned int) atoi( argv[2] );
    if ( midiFile.getNumberOfTracks() <= track ) {
      std::cout << "\nInvalid track number ... playing track 0.\n";
      track = 0;
    }

    std::cout << "\nPress <enter> to start reading/playing.\n";
    char input;
    std::cin.get(input);
    
    std::vector<unsigned char> event;
    unsigned long ticks = midiFile.getNextMidiEvent( &event, track );
    while ( !done && event.size() ) {

      // Pause for the MIDI event delta time.
      Stk::sleep( (unsigned long) (ticks * midiFile.getTickSeconds() * 1000 ) );

      midiout->sendMessage( &event );

      // Get a new event.
      ticks = midiFile.getNextMidiEvent( &event, track );
    }

    // Send a "all notes off" to the synthesizer.
    event.clear();
    event.push_back( 0xb0 );
    event.push_back( 0x7b );
    event.push_back( 0x0 );
    midiout->sendMessage( &event );
  }
  catch ( StkError & ) {
    // You might want to do something more useful here.
    std::cout << "\nAborting program!\n";
    goto cleanup;
  }

 cleanup:
  delete midiout;

  return 0;
}