CFugue
MidiRenderer.cpp
1 /*
2  This is part of CFugue, a C++ Runtime for MIDI Score Programming
3  Copyright (C) 2009 Gopalakrishna Palem
4 
5  For links to further information, or to contact the author,
6  see <http://cfugue.sourceforge.net/>.
7 
8  $LastChangedDate: 2014-05-11 07:42:46 +0530 (Sun, 11 May 2014) $
9  $Rev: 211 $
10  $LastChangedBy: krishnapg $
11 */
12 
13 #include "stdafx.h"
14 #include "jdkmidi/filewritemultitrack.h"
15 #include "Note.h"
16 #include "ChannelPressure.h"
17 #include "ControllerEvent.h"
18 #include "Instrument.h"
19 #include "KeySignature.h"
20 #include "Layer.h"
21 #include "PitchBend.h"
22 #include "PolyphonicPressure.h"
23 #include "Tempo.h"
24 #include "TimeToken.h"
25 #include "Voice.h"
26 
27 #if defined(_WIN32) // if this is Windows
28  #include "jdkmidi/driverwin32.h"
29  typedef jdkmidi::MIDIDriverWin32 CFugueMIDIDriver;
30 #else // this is Linux or Mac
31  #include "AlsaDriver.h"
33 #endif
34 #include "MidiRenderer.h"
35 
36 namespace CFugue
37 {
38  MIDIRenderer::MIDIRenderer(void) :
39  m_pMIDIDriver(new CFugueMIDIDriver(128)), m_MIDIManager(m_pMIDIDriver)
40  {
41  }
42 
43  MIDIRenderer::~MIDIRenderer(void)
44  {
45  Clear();
46  }
47 
48  void MIDIRenderer::Clear()
49  {
50  EndPlayAsync(); // Stop any current Play in progress
51  m_lFirstNoteTime = 0;
52  MIDIEventManager::Clear(); // Clear the Track content
53  }
54 
55  bool MIDIRenderer::BeginPlayAsync(int nMIDIOutPortID, unsigned int nTimerResolutionMS)
56  {
57  m_Sequencer.GoToZero();
58  m_MIDIManager.SetSeq(&m_Sequencer);
59  if(m_pMIDIDriver->OpenMIDIOutPort(nMIDIOutPortID))
60  {
61  m_MIDIManager.SeqPlay(); // Set into Play mode
62  m_MIDIManager.SetTimeOffset(MidiTimer::Now()); // Set the initial time offset
63  if(!m_pMIDIDriver->StartTimer(nTimerResolutionMS))
64  {
65  m_MIDIManager.SeqStop(); // Could not set a timer - Lets set into Stop mode
66  return false;
67  }
68  return true;
69  }
70  return false;
71  }
72 
73  void MIDIRenderer::EndPlayAsync()
74  {
75  m_MIDIManager.SeqStop(); // Set into Stop mode
76  m_pMIDIDriver->StopTimer(); // Stop the Timer
77  m_pMIDIDriver->CloseMIDIOutPort();
78  }
79 
80  void MIDIRenderer::WaitTillDone()
81  {
82 #if defined WIN32 || defined _WIN32
83  while(IsPlaying()) Sleep(500);
84 #else
85  m_pMIDIDriver->WaitTillDone();
86 #endif
87  }
88 
89  bool MIDIRenderer::SaveToFile(const char* szOutputFilePath)
90  {
91  jdkmidi::MIDIFileWriteStreamFileName outFile(szOutputFilePath);
92 
93  if(outFile.IsValid() == false) return false;
94 
95  jdkmidi::MIDIFileWriteMultiTrack WriterObj(&m_Tracks, &outFile);
96 
97  return WriterObj.Write();
98  }
99 
100  void MIDIRenderer::OnChannelPressureEvent(const CParser* pParser, const ChannelPressure* pCP)
101  {
102  AddChannelPressureEvent(pCP->GetPressure());
103  }
104 
105  void MIDIRenderer::OnControllerEvent(const CParser* pParser, const ControllerEvent* pConEvent)
106  {
107  AddControllerEvent(pConEvent->GetControl(), pConEvent->GetValue());
108  }
109 
110  void MIDIRenderer::OnInstrumentEvent(const CParser* pParser, const Instrument* pInstrument)
111  {
112  AddProgramChangeEvent(pInstrument->GetInstrumentID());
113  }
114 
115  void MIDIRenderer::OnKeySignatureEvent(const CParser* pParser, const KeySignature* pKeySig)
116  {
117  AddKeySignatureEvent(pKeySig->GetKey(), pKeySig->GetMajMin());
118  }
119 
120  void MIDIRenderer::OnLayerEvent(const CParser* pParser, const Layer* pLayer)
121  {
122  SetCurrentLayer(pLayer->GetLayer());
123  }
124 
125  void MIDIRenderer::OnPitchBendEvent(const CParser* pParser, const PitchBend* pPB)
126  {
127  AddPitchBendEvent(pPB->GetLowByte(), pPB->GetHighByte());
128  }
129 
130  void MIDIRenderer::OnPolyphonicPressureEvent(const CParser* pParser, const PolyphonicPressure* pPressure)
131  {
132  AddPolyphonicPressureEvent(pPressure->GetKey(), pPressure->GetPressure());
133  }
134 
135  void MIDIRenderer::OnTempoEvent(const CParser* pParser, const Tempo* pTempo)
136  {
137  AddTempoEvent(pTempo->GetTempo());
138  }
139 
140  void MIDIRenderer::OnTimeEvent(const CParser* pParser, const Time* pTime)
141  {
142  SetTrackTime(pTime->GetTime());
143  }
144 
145  void MIDIRenderer::OnVoiceEvent(const CParser* pParser, const Voice* pVoice)
146  {
147  SetCurrentTrack(pVoice->GetVoice());
148  }
149 
150  void MIDIRenderer::OnNoteEvent(const CParser* pParser, const Note* pNote)
151  {
152  if(pNote->duration == 0) return;
153 
154  if(pNote->isRest) // if this is a rest note, simply advance the track timer
155  {
156  AdvanceTrackTime(pNote->duration); return;
157  }
158 
159  if(pNote->type == pNote->FIRST) // if this is the first note save its track time. Useful for any later parallel notes
160  m_lFirstNoteTime = GetTrackTime();
161 
162  if(pNote->type == pNote->PARALLEL) // if this is a parallel note, use the same start time as the last seen first note
163  SetTrackTime(m_lFirstNoteTime);
164 
165  AddNoteEvent(pNote->noteNumber, pNote->attackVelocity, pNote->decayVelocity, pNote->duration, !pNote->isEndOfTie, !pNote->isStartOfTie);
166  }
167 
168 
169 } // namespace CFugue
Declares MIDIDriverAlsa class for CFugue.
Declares MIDI Controller Events used in MusicStrings.
Declares Instrument class.
MIDI Driver for Linux Alsa based machines
Definition: AlsaDriver.h:30
Base class that represents a Parser Object.
Definition: Parser.h:63
Declares KeySignature class used in CFugue MusicString.
Declares Tempo class used in Western music.
unsigned char GetPressure() const
Returns the Channel pressure value.

CFugue, the C++ Music Programming Library © Copyright 2009 Cenacle Research India Private Limited Gopalakrishna Palem