summaryrefslogtreecommitdiff
path: root/muse2/muse/audio.cpp
diff options
context:
space:
mode:
authorTim E. Real <termtech@rogers.com>2011-09-09 10:04:11 +0000
committerTim E. Real <termtech@rogers.com>2011-09-09 10:04:11 +0000
commit2120ea4f083228dde0d7307203391a4ec8f57e2d (patch)
tree3f8b5c3aeb6691c962d42fb4e3a01bcf511f023f /muse2/muse/audio.cpp
parentad72332d2cbd0d22e5d49d9fd60c985e563b17d0 (diff)
Mostly engine fixes/corrections. Please see ChangeLog.
Diffstat (limited to 'muse2/muse/audio.cpp')
-rw-r--r--muse2/muse/audio.cpp542
1 files changed, 34 insertions, 508 deletions
diff --git a/muse2/muse/audio.cpp b/muse2/muse/audio.cpp
index a82fbe13..60eb5c73 100644
--- a/muse2/muse/audio.cpp
+++ b/muse2/muse/audio.cpp
@@ -4,6 +4,7 @@
// $Id: audio.cpp,v 1.59.2.30 2009/12/20 05:00:35 terminator356 Exp $
//
// (C) Copyright 2001-2004 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Tim E. Real (terminator356 on users dot sourceforge dot net)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -30,10 +31,8 @@
#include "song.h"
#include "node.h"
#include "audiodev.h"
-//#include "driver/audiodev.h" // p4.0.2
#include "mididev.h"
#include "alsamidi.h"
-//#include "driver/alsamidi.h" // p4.0.2
#include "synth.h"
#include "audioprefetch.h"
#include "plugin.h"
@@ -55,8 +54,7 @@ extern double curTime();
Audio* audio;
AudioDevice* audioDevice; // current audio device in use
-// p3.3.25
-extern unsigned int volatile midiExtSyncTicks;
+extern unsigned int volatile midiExtSyncTicks; // p3.3.25
//static const unsigned char mmcDeferredPlayMsg[] = { 0x7f, 0x7f, 0x06, 0x03 };
@@ -126,7 +124,7 @@ Audio::Audio()
_pos.setType(Pos::FRAMES);
_pos.setFrame(0);
- curTickPos = 0;
+ nextTickPos = curTickPos = 0;
midiClick = 0;
clickno = 0;
@@ -140,10 +138,9 @@ Audio::Audio()
state = STOP;
msg = 0;
- // Changed by Tim. p3.3.8
//startRecordPos.setType(Pos::TICKS);
//endRecordPos.setType(Pos::TICKS);
- startRecordPos.setType(Pos::FRAMES);
+ startRecordPos.setType(Pos::FRAMES); // Tim
endRecordPos.setType(Pos::FRAMES);
_audioMonitor = 0;
@@ -187,16 +184,12 @@ bool Audio::start()
_loopCount = 0;
MusEGlobal::muse->setHeartBeat();
if (audioDevice) {
- // Added by Tim. p3.3.6
//_running = true;
-
//audioDevice->start();
}
else {
if(false == initJackAudio()) {
- // Added by Tim. p3.3.6
//_running = true;
-
InputList* itl = song->inputs();
for (iAudioInput i = itl->begin(); i != itl->end(); ++i) {
//printf("reconnecting input %s\n", (*i)->name().ascii());
@@ -253,25 +246,6 @@ void Audio::stop(bool)
bool Audio::sync(int jackState, unsigned frame)
{
-
-// Changed by Tim. p3.3.24
-/*
- bool done = true;
- if (state == LOOP1)
- state = LOOP2;
- else {
- if (_pos.frame() != frame) {
- Pos p(frame, false);
- seek(p);
- }
- state = State(jackState);
- if (!_freewheel)
- //done = audioPrefetch->seekDone;
- done = audioPrefetch->seekDone();
- }
-
- return done;
-*/
bool done = true;
if (state == LOOP1)
state = LOOP2;
@@ -283,8 +257,6 @@ bool Audio::sync(int jackState, unsigned frame)
// PLAY -> START_PLAY seek in play state
if (state != START_PLAY) {
- //Pos p(frame, AL::FRAMES);
- // seek(p);
Pos p(frame, false);
seek(p);
if (!_freewheel)
@@ -293,10 +265,8 @@ bool Audio::sync(int jackState, unsigned frame)
state = START_PLAY;
}
else {
- //if (frame != _seqTime.pos.frame()) {
if (frame != _pos.frame()) {
// seek during seek
- //seek(Pos(frame, AL::FRAMES));
seek(Pos(frame, false));
}
done = audioPrefetch->seekDone();
@@ -335,9 +305,8 @@ void Audio::shutdown()
void Audio::process(unsigned frames)
{
- // Disabled by Tim. p3.3.22
// extern int watchAudio;
-// ++watchAudio; // make a simple watchdog happy
+// ++watchAudio; // make a simple watchdog happy. Disabled.
if (!MusEGlobal::checkAudioDevice()) return;
if (msg) {
@@ -377,8 +346,8 @@ void Audio::process(unsigned frames)
startRolling();
}
else if (isPlaying() && jackState == STOP) {
- // p3.3.43 Make sure to stop bounce and freewheel mode, for example if user presses stop
- // in QJackCtl before right-hand marker is reached (which is handled below).
+ // Make sure to stop bounce and freewheel mode, for example if user presses stop
+ // in QJackCtl before right-hand marker is reached (which is handled below). p3.3.43
//printf("Audio::process isPlaying() && jackState == STOP\n");
//if (_bounce)
//{
@@ -485,15 +454,11 @@ void Audio::process(unsigned frames)
//audioDevice->seekTransport(_loopFrame);
Pos lp(_loopFrame, false);
audioDevice->seekTransport(lp);
-
-
// printf(" process: seek to %d, end %d\n", _loopFrame, loop.frame());
}
}
-
- // p3.3.25
- if(extSyncFlag.value())
+ if(extSyncFlag.value()) // p3.3.25
{
nextTickPos = curTickPos + midiExtSyncTicks;
// Probably not good - interfere with midi thread.
@@ -549,7 +514,6 @@ void Audio::process1(unsigned samplePos, unsigned offset, unsigned frames)
continue;
track = (AudioTrack*)(*it);
- // Added by T356.
// For audio track types, synths etc. which need some kind of non-audio
// (but possibly audio-affecting) processing always, even if their output path
// is ultimately unconnected.
@@ -560,23 +524,10 @@ void Audio::process1(unsigned samplePos, unsigned offset, unsigned frames)
// It should be used for things like midi events, gui events etc. - things which need to
// be done BEFORE all the AudioOutput::process() are called below. That does NOT include
// audio processing, because THAT is done at the very end of this routine.
- // This will also reset the track's processed flag.
+ // This will also reset the track's processed flag. Tim.
track->preProcessAlways();
-
- // Removed by T356
- /*
- if (track->noOutRoute() && !track->noInRoute() &&
- track->type() != Track::AUDIO_AUX && track->type() != Track::AUDIO_OUTPUT) {
- channels = track->channels();
- float* buffer[channels];
- float data[frames * channels];
- for (int i = 0; i < channels; ++i)
- buffer[i] = data + i * frames;
- track->copyData(samplePos, channels, frames, buffer);
- }
- */
-
}
+
// Pre-process the metronome.
((AudioTrack*)metronome)->preProcessAlways();
@@ -584,29 +535,12 @@ void Audio::process1(unsigned samplePos, unsigned offset, unsigned frames)
for (ciAudioOutput i = ol->begin(); i != ol->end(); ++i)
(*i)->process(samplePos, offset, frames);
- // Removed by T356
- /*
- AuxList* auxl = song->auxs();
- for (ciAudioAux ia = auxl->begin(); ia != auxl->end(); ++ia) {
- track = (AudioTrack*)(*ia);
- if (track->noOutRoute()) {
- channels = track->channels();
- float* buffer[channels];
- float data[frames * channels];
- for (int i = 0; i < channels; ++i)
- buffer[i] = data + i * frames;
- track->copyData(samplePos, channels, frames, buffer);
- }
- }
- */
-
- // Added by T356.
// Were ANY tracks unprocessed as a result of processing all the AudioOutputs, above?
// Not just unconnected ones, as previously done, but ones whose output path ultimately leads nowhere.
// Those tracks were missed, until this fix.
// Do them now. This will animate meters, and 'quietly' process some audio which needs to be done -
- // for example synths really need to be processed, 'quietly' or not, otherwise the next time
- // processing is 'turned on', if there was a backlog of events while it was off, then they all happen at once.
+ // for example synths really need to be processed, 'quietly' or not, otherwise the next time processing
+ // is 'turned on', if there was a backlog of events while it was off, then they all happen at once. Tim.
for(ciTrack it = tl->begin(); it != tl->end(); ++it)
{
if((*it)->isMidiTrack())
@@ -623,9 +557,6 @@ void Audio::process1(unsigned samplePos, unsigned offset, unsigned frames)
for (int i = 0; i < channels; ++i)
buffer[i] = data + i * frames;
//printf("Audio::process1 calling track->copyData for track:%s\n", track->name().toLatin1());
-
- // p3.3.38
- //track->copyData(samplePos, channels, frames, buffer);
track->copyData(samplePos, channels, -1, -1, frames, buffer);
}
}
@@ -647,7 +578,7 @@ void Audio::processMsg(AudioMsg* msg)
case AUDIO_ROUTEREMOVE:
removeRoute(msg->sroute, msg->droute);
break;
- case AUDIO_REMOVEROUTES: // p3.3.55
+ case AUDIO_REMOVEROUTES:
removeAllRoutes(msg->sroute, msg->droute);
break;
//case AUDIO_VOL:
@@ -670,7 +601,6 @@ void Audio::processMsg(AudioMsg* msg)
break;
//case AUDIO_SET_PLUGIN_CTRL_VAL:
//msg->plugin->track()->setPluginCtrlVal(msg->ival, msg->dval);
- // p3.3.43
// msg->snode->setPluginCtrlVal(msg->ival, msg->dval);
// break;
case AUDIO_SWAP_CONTROLLER_IDX:
@@ -721,8 +651,8 @@ void Audio::processMsg(AudioMsg* msg)
//printf("Audio::processMsg SEQM_RESET_DEVICES\n");
for (int i = 0; i < MIDI_PORTS; ++i)
{
- if(!midiPorts[i].device()) continue; // p4.0.15
- midiPorts[i].instrument()->reset(i, song->mtype());
+ if(midiPorts[i].device())
+ midiPorts[i].instrument()->reset(i, song->mtype());
}
break;
case SEQM_INIT_DEVICES:
@@ -759,7 +689,7 @@ void Audio::processMsg(AudioMsg* msg)
case MIDI_SHOW_INSTR_GUI:
midiSeq->msgUpdatePollFd();
break;
- case MIDI_SHOW_INSTR_NATIVE_GUI: // p4.0.20
+ case MIDI_SHOW_INSTR_NATIVE_GUI:
midiSeq->msgUpdatePollFd();
break;
case SEQM_ADD_TEMPO:
@@ -776,12 +706,12 @@ void Audio::processMsg(AudioMsg* msg)
frameOffset = syncFrame - samplePos;
}
break;
- case SEQM_ADD_TRACK:
- case SEQM_REMOVE_TRACK:
- case SEQM_CHANGE_TRACK:
- case SEQM_ADD_PART:
- case SEQM_REMOVE_PART:
- case SEQM_CHANGE_PART:
+ //case SEQM_ADD_TRACK:
+ //case SEQM_REMOVE_TRACK:
+ //case SEQM_CHANGE_TRACK:
+ //case SEQM_ADD_PART:
+ //case SEQM_REMOVE_PART:
+ //case SEQM_CHANGE_PART:
case SEQM_SET_TRACK_OUT_CHAN:
case SEQM_SET_TRACK_OUT_PORT:
case SEQM_REMAP_PORT_DRUM_CTL_EVS:
@@ -813,143 +743,26 @@ void Audio::seek(const Pos& p)
printf("Audio::seek already there\n");
return;
}
-
- // p3.3.23
- //printf("Audio::seek frame:%d\n", p.frame());
+ //printf("Audio::seek frame:%d\n", p.frame());
_pos = p;
if (!MusEGlobal::checkAudioDevice()) return;
syncFrame = audioDevice->framePos();
frameOffset = syncFrame - _pos.frame();
curTickPos = _pos.tick();
- // p4.0.22
- // Tell midi thread to tell ALSA devices to handle seek.
- midiSeq->msgSeek();
- // We are in the audio thread. Directly seek Jack midi devices.
+ if (curTickPos == 0 && !song->record())
+ audio->initDevices();
+
for(iMidiDevice i = midiDevices.begin(); i != midiDevices.end(); ++i)
- {
- MidiDevice* md = *i;
- if(md->deviceType() == MidiDevice::JACK_MIDI)
- md->handleSeek();
- }
-
- // Moved into MidiDevice::handleSeek
- #if 0
- // p3.3.31
- // Don't send if external sync is on. The master, and our sync routing system will take care of that.
- if(!extSyncFlag.value())
- {
-
- for(int port = 0; port < MIDI_PORTS; ++port)
- {
- MidiPort* mp = &midiPorts[port];
- MidiDevice* dev = mp->device();
- //if(!dev || !mp->syncInfo().MCOut())
- if(!dev || !mp->syncInfo().MRTOut())
- continue;
-
- // Added by T356: Shall we check for device write open flag to see if it's ok to send?...
- // This means obey what the user has chosen for read/write in the midi port config dialog,
- // which already takes into account whether the device is writable or not.
- //if(!(dev->rwFlags() & 0x1) || !(dev->openFlags() & 1))
- //if(!(dev->openFlags() & 1))
- // continue;
-
- //int port = dev->midiPort();
-
- // By checking for no port here (-1), (and out of bounds), it means
- // the device must be assigned to a port for these MMC commands to be sent.
- // Without this check, interesting sync things can be done by the user without ever
- // assigning any devices to ports !
- //if(port < 0 || port > MIDI_PORTS)
- //if(port < -1 || port > MIDI_PORTS)
- // continue;
-
- int beat = (curTickPos * 4) / MusEConfig::config.division;
-
- bool isPlaying=false;
- if(state == PLAY)
- isPlaying = true;
-
- mp->sendStop();
- mp->sendSongpos(beat);
- if(isPlaying)
- mp->sendContinue();
- }
- }
- #endif
-
- /*
- if(genMCSync)
- {
- for(iMidiDevice imd = midiDevices.begin(); imd != midiDevices.end(); ++imd)
- {
- MidiDevice* dev = (*imd);
- if(!dev->syncInfo().MCOut())
- continue;
-
- // Added by T356: Shall we check for device write open flag to see if it's ok to send?...
- // This means obey what the user has chosen for read/write in the midi port config dialog,
- // which already takes into account whether the device is writable or not.
- //if(!(dev->rwFlags() & 0x1) || !(dev->openFlags() & 1))
- //if(!(dev->openFlags() & 1))
- // continue;
-
- int port = dev->midiPort();
-
- // By checking for no port here (-1), (and out of bounds), it means
- // the device must be assigned to a port for these MMC commands to be sent.
- // Without this check, interesting sync things can be done by the user without ever
- // assigning any devices to ports !
- //if(port < 0 || port > MIDI_PORTS)
- if(port < -1 || port > MIDI_PORTS)
- continue;
-
- int beat = (curTickPos * 4) / MusEConfig::config.division;
-
- bool isPlaying=false;
- if(state == PLAY)
- isPlaying = true;
-
- if(port == -1)
- // Send straight to the device... Copied from MidiPort.
- {
- MidiPlayEvent event(0, 0, 0, ME_STOP, 0, 0);
- dev->putEvent(event);
-
- event.setType(ME_SONGPOS);
- event.setA(beat);
- dev->putEvent(event);
-
- if(isPlaying)
- {
- event.setType(ME_CONTINUE);
- event.setA(0);
- dev->putEvent(event);
- }
- }
- else
- // Go through the port...
- {
- MidiPort* mp = &midiPorts[port];
-
- mp->sendStop();
- mp->sendSongpos(beat);
- if(isPlaying)
- mp->sendContinue();
- }
- }
- }
- */
+ (*i)->handleSeek();
//loopPassed = true; // for record loop mode
if (state != LOOP2 && !freewheel())
{
- // Changed by T356 08/17/08. We need to force prefetch to update,
- // to ensure the most recent data. Things can happen to a part
- // before play is pressed - such as part muting, part moving etc.
- // Without a force, the wrong data was being played.
//audioPrefetch->msgSeek(_pos.frame());
+ // We need to force prefetch to update, to ensure the most recent data.
+ // Things can happen to a part before play is pressed - such as part muting,
+ // part moving etc. Without a force, the wrong data was being played. Tim 08/17/08
audioPrefetch->msgSeek(_pos.frame(), true);
}
@@ -984,8 +797,6 @@ void Audio::writeTick()
void Audio::startRolling()
{
- // Changed by Tim. p3.3.8
- //startRecordPos = _pos;
if (MusEGlobal::debugMsg)
printf("startRolling - loopCount=%d, _pos=%d\n", _loopCount, _pos.tick());
@@ -1005,20 +816,9 @@ void Audio::startRolling()
state = PLAY;
write(sigFd, "1", 1); // Play
- // p3.3.31
// Don't send if external sync is on. The master, and our sync routing system will take care of that.
if(!extSyncFlag.value())
{
-
- // Changed by Tim. p3.3.6
- //if (genMMC)
- // midiPorts[txSyncPort].sendSysex(mmcDeferredPlayMsg, sizeof(mmcDeferredPlayMsg));
- //if (genMCSync) {
- // if (curTickPos)
- // midiPorts[txSyncPort].sendContinue();
- // else
- // midiPorts[txSyncPort].sendStart();
- // }
for(int port = 0; port < MIDI_PORTS; ++port)
{
MidiPort* mp = &midiPorts[port];
@@ -1033,13 +833,9 @@ void Audio::startRolling()
MidiSyncInfo& si = mp->syncInfo();
- //if(genMMC && si.MMCOut())
if(si.MMCOut())
- //mp->sendSysex(mmcDeferredPlayMsg, sizeof(mmcDeferredPlayMsg));
mp->sendMMCDeferredPlay();
- //if(genMCSync && si.MCOut())
- //if(si.MCOut())
if(si.MRTOut())
{
if(curTickPos)
@@ -1050,68 +846,6 @@ void Audio::startRolling()
}
}
- /*
- for(iMidiDevice imd = midiDevices.begin(); imd != midiDevices.end(); ++imd)
- {
- MidiDevice* dev = (*imd);
-
- // Shall we check open flags?
- //if(!(dev->rwFlags() & 0x1) || !(dev->openFlags() & 1))
- //if(!(dev->openFlags() & 1))
- // continue;
-
- int port = dev->midiPort();
-
- // Without this -1 check, interesting sync things can be done by the user without ever
- // assigning any devices to ports !
- //if(port < 0 || port > MIDI_PORTS)
- if(port < -1 || port > MIDI_PORTS)
- continue;
-
- MidiSyncInfo& si = dev->syncInfo();
-
- if(port == -1)
- // Send straight to the device... Copied from MidiPort.
- {
- if(genMMC && si.MMCOut())
- {
- MidiPlayEvent event(0, 0, ME_SYSEX, mmcDeferredPlayMsg, sizeof(mmcDeferredPlayMsg));
- dev->putEvent(event);
- }
-
- if(genMCSync && si.MCOut())
- {
- if(curTickPos)
- {
- MidiPlayEvent event(0, 0, 0, ME_CONTINUE, 0, 0);
- dev->putEvent(event);
- }
- else
- {
- MidiPlayEvent event(0, 0, 0, ME_START, 0, 0);
- dev->putEvent(event);
- }
- }
- }
- else
- // Go through the port...
- {
- MidiPort* mp = &midiPorts[port];
-
- if(genMMC && si.MMCOut())
- mp->sendSysex(mmcDeferredPlayMsg, sizeof(mmcDeferredPlayMsg));
-
- if(genMCSync && si.MCOut())
- {
- if(curTickPos)
- mp->sendContinue();
- else
- mp->sendStart();
- }
- }
- }
- */
-
if (MusEGlobal::precountEnableFlag
&& song->click()
&& !extSyncFlag.value()
@@ -1150,9 +884,7 @@ void Audio::startRolling()
if(mp->device() != NULL) {
//printf("send enable sustain!!!!!!!! port %d ch %d\n", i,ch);
MidiPlayEvent ev(0, i, ch, ME_CONTROLLER, CTRL_SUSTAIN, 127);
-
- // may cause problems, called from audio thread
- mp->device()->playEvents()->add(ev);
+ mp->device()->addScheduledEvent(ev); // TODO: Not working? Try putEvent
}
}
}
@@ -1172,220 +904,14 @@ void Audio::stopRolling()
state = STOP;
- //playStateExt = false; // not playing // Moved here from MidiSeq::processStop() p4.0.22
-
- // p4.0.22
- // Tell midi thread to clear ALSA device notes and stop stuck notes.
- midiSeq->msgStop();
- // We are in the audio thread. Directly clear Jack midi device notes and stop stuck notes.
+ midiSeq->setExternalPlayState(false); // not playing Moved here from MidiSeq::processStop() p4.0.34
+
for(iMidiDevice id = midiDevices.begin(); id != midiDevices.end(); ++id)
{
MidiDevice* md = *id;
- if(md->deviceType() == MidiDevice::JACK_MIDI)
- md->handleStop();
+ md->handleStop();
}
- // Moved into MidiDevice::handleStop() // p4.0.22
- #if 0 //TODO
- //---------------------------------------------------
- // reset sustain
- //---------------------------------------------------
-
-
- // clear sustain
- for (int i = 0; i < MIDI_PORTS; ++i) {
- MidiPort* mp = &midiPorts[i];
- for (int ch = 0; ch < MIDI_CHANNELS; ++ch) {
- if (mp->hwCtrlState(ch, CTRL_SUSTAIN) == 127) {
- if(mp->device()!=NULL) {
- //printf("send clear sustain!!!!!!!! port %d ch %d\n", i,ch);
- MidiPlayEvent ev(0, i, ch, ME_CONTROLLER, CTRL_SUSTAIN, 0);
- // may cause problems, called from audio thread
- mp->device()->putEvent(ev);
- }
- }
- }
- }
- #endif
-
- // Moved into MidiDevice::handleStop() // p4.0.22
- #if 0
- // p3.3.31
- // Don't send if external sync is on. The master, and our sync routing system will take care of that.
- if(!extSyncFlag.value())
- {
-
- // Changed by Tim. p3.3.6
- //MidiPort* syncPort = &midiPorts[txSyncPort];
- //if (genMMC) {
- // unsigned char mmcPos[] = {
- // 0x7f, 0x7f, 0x06, 0x44, 0x06, 0x01,
- // 0, 0, 0, 0, 0
- // };
- // int frame = tempomap.tick2frame(curTickPos);
- // MTC mtc(double(frame) / double(MusEGlobal::sampleRate));
- // mmcPos[6] = mtc.h() | (mtcType << 5);
- // mmcPos[7] = mtc.m();
- // mmcPos[8] = mtc.s();
- // mmcPos[9] = mtc.f();
- // mmcPos[10] = mtc.sf();
- // syncPort->sendSysex(mmcStopMsg, sizeof(mmcStopMsg));
- // syncPort->sendSysex(mmcPos, sizeof(mmcPos));
- // }
- //if (genMCSync) { // Midi Clock
- // send STOP and
- // "set song position pointer"
- // syncPort->sendStop();
- // syncPort->sendSongpos(curTickPos * 4 / MusEConfig::config.division);
- // }
- for(int port = 0; port < MIDI_PORTS; ++port)
- {
- MidiPort* mp = &midiPorts[port];
- MidiDevice* dev = mp->device();
- if(!dev)
- continue;
-
- // Shall we check open flags?
- //if(!(dev->rwFlags() & 0x1) || !(dev->openFlags() & 1))
- //if(!(dev->openFlags() & 1))
- // continue;
-
- MidiSyncInfo& si = mp->syncInfo();
-
- //if(genMMC && si.MMCOut())
- if(si.MMCOut())
- {
- //unsigned char mmcPos[] = {
- // 0x7f, 0x7f, 0x06, 0x44, 0x06, 0x01,
- // 0, 0, 0, 0, 0
- // };
-
- // p3.3.31
- /*
- int frame = tempomap.tick2frame(curTickPos);
- MTC mtc(double(frame) / double(MusEGlobal::sampleRate));
- */
-
- //mmcPos[6] = mtc.h() | (mtcType << 5);
- //mmcPos[7] = mtc.m();
- //mmcPos[8] = mtc.s();
- //mmcPos[9] = mtc.f();
- //mmcPos[10] = mtc.sf();
-
- //mp->sendSysex(mmcStopMsg, sizeof(mmcStopMsg));
- mp->sendMMCStop();
- //mp->sendSysex(mmcPos, sizeof(mmcPos));
-
- // p3.3.31
- // Added check of option send continue not start.
- // Hmm, is this required? Seems to make other devices unhappy.
- /*
- if(!si.sendContNotStart())
- mp->sendMMCLocate(mtc.h() | (mtcType << 5),
- mtc.m(), mtc.s(), mtc.f(), mtc.sf());
- */
-
- }
-
- //if(genMCSync && si.MCOut()) // Midi Clock
- //if(si.MCOut()) // Midi Clock
- if(si.MRTOut()) //
- {
- // send STOP and
- // "set song position pointer"
- mp->sendStop();
-
- // p3.3.31
- // Added check of option send continue not start.
- // Hmm, is this required? Seems to make other devices unhappy.
- /*
- if(!si.sendContNotStart())
- mp->sendSongpos(curTickPos * 4 / MusEConfig::config.division);
- */
-
- }
- }
- }
- #endif
-
- /*
- for(iMidiDevice imd = midiDevices.begin(); imd != midiDevices.end(); ++imd)
- {
- MidiDevice* dev = (*imd);
-
- // Shall we check open flags?
- //if(!(dev->rwFlags() & 0x1) || !(dev->openFlags() & 1))
- //if(!(dev->openFlags() & 1))
- // continue;
-
- int port = dev->midiPort();
-
- // Without this -1 check, interesting sync things can be done by the user without ever
- // assigning any devices to ports !
- //if(port < 0 || port > MIDI_PORTS)
- if(port < -1 || port > MIDI_PORTS)
- continue;
-
- MidiSyncInfo& si = dev->syncInfo();
-
- MidiPort* mp = 0;
- if(port != -1)
- mp = &midiPorts[port];
-
- if(genMMC && si.MMCOut())
- {
- unsigned char mmcPos[] = {
- 0x7f, 0x7f, 0x06, 0x44, 0x06, 0x01,
- 0, 0, 0, 0, 0
- };
- int frame = tempomap.tick2frame(curTickPos);
- MTC mtc(double(frame) / double(MusEGlobal::sampleRate));
- mmcPos[6] = mtc.h() | (mtcType << 5);
- mmcPos[7] = mtc.m();
- mmcPos[8] = mtc.s();
- mmcPos[9] = mtc.f();
- mmcPos[10] = mtc.sf();
-
- if(mp)
- // Go through the port...
- {
- mp->sendSysex(mmcStopMsg, sizeof(mmcStopMsg));
- mp->sendSysex(mmcPos, sizeof(mmcPos));
- }
- else
- // Send straight to the device... Copied from MidiPort.
- {
- MidiPlayEvent event(0, 0, ME_SYSEX, mmcStopMsg, sizeof(mmcStopMsg));
- dev->putEvent(event);
-
- event.setData(mmcPos, sizeof(mmcPos));
- dev->putEvent(event);
- }
- }
-
- if(genMCSync && si.MCOut()) // Midi Clock
- {
- // send STOP and
- // "set song position pointer"
- if(mp)
- // Go through the port...
- {
- mp->sendStop();
- mp->sendSongpos(curTickPos * 4 / MusEConfig::config.division);
- }
- else
- // Send straight to the device... Copied from MidiPort.
- {
- MidiPlayEvent event(0, 0, 0, ME_STOP, 0, 0);
- dev->putEvent(event);
- event.setType(ME_SONGPOS);
- event.setA(curTickPos * 4 / MusEConfig::config.division);
- dev->putEvent(event);
- }
- }
- }
- */
-
WaveTrackList* tracks = song->waves();
for (iWaveTrack i = tracks->begin(); i != tracks->end(); ++i) {
WaveTrack* track = *i;