From: Chris C. <ca...@us...> - 2004-11-27 14:53:05
|
Update of /cvsroot/rosegarden/sound In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15131/sound Modified Files: Tag: stg_1_0 AlsaDriver.cpp AlsaDriver.h AudioProcess.cpp AudioProcess.h JackDriver.cpp MappedEvent.h MidiFile.cpp Log Message: * stg branch Index: JackDriver.cpp =================================================================== RCS file: /cvsroot/rosegarden/sound/JackDriver.cpp,v retrieving revision 1.84 retrieving revision 1.84.2.1 diff -C2 -d -r1.84 -r1.84.2.1 *** JackDriver.cpp 19 Nov 2004 17:57:29 -0000 1.84 --- JackDriver.cpp 27 Nov 2004 14:52:39 -0000 1.84.2.1 *************** *** 268,271 **** --- 268,277 ---- // outs. // + m_outputMasters.clear(); + m_outputMonitors.clear(); + m_outputSubmasters.clear(); + m_outputInstruments.clear(); + m_inputPorts.clear(); + if (!createMainOutputs()) { // one stereo pair master, one pair monitor audit << "JackDriver::initialise - " *************** *** 434,437 **** --- 440,445 ---- JackDriver::createMainOutputs() { + if (!m_client) return false; + jack_port_t *port = jack_port_register (m_client, "master out L", *************** *** 464,467 **** --- 472,477 ---- JackDriver::createFaderOutputs(int pairs) { + if (!m_client) return false; + int pairsNow = m_outputInstruments.size() / 2; if (pairs == pairsNow) return true; *************** *** 505,508 **** --- 515,520 ---- JackDriver::createSubmasterOutputs(int pairs) { + if (!m_client) return false; + int pairsNow = m_outputSubmasters.size() / 2; if (pairs == pairsNow) return true; *************** *** 545,548 **** --- 557,562 ---- JackDriver::createRecordInputs(int pairs) { + if (!m_client) return false; + int pairsNow = m_inputPorts.size() / 2; if (pairs == pairsNow) return true; *************** *** 586,589 **** --- 600,605 ---- JackDriver::setAudioPorts(bool faderOuts, bool submasterOuts) { + if (!m_client) return; + Audit audit; #ifdef DEBUG_JACK_DRIVER *************** *** 628,631 **** --- 644,649 ---- JackDriver::getAudioPlayLatency() const { + if (!m_client) return RealTime::zeroTime; + jack_nframes_t latency = jack_port_get_total_latency(m_client, m_outputMasters[0]); *************** *** 637,640 **** --- 655,660 ---- JackDriver::getAudioRecordLatency() const { + if (!m_client) return RealTime::zeroTime; + jack_nframes_t latency = jack_port_get_total_latency(m_client, m_inputPorts[0]); *************** *** 670,674 **** JackDriver::jackProcess(jack_nframes_t nframes) { ! if (!m_ok) { #ifdef DEBUG_JACK_PROCESS std::cerr << "JackDriver::jackProcess: not OK" << std::endl; --- 690,694 ---- JackDriver::jackProcess(jack_nframes_t nframes) { ! if (!m_ok || !m_client) { #ifdef DEBUG_JACK_PROCESS std::cerr << "JackDriver::jackProcess: not OK" << std::endl; *************** *** 684,687 **** --- 704,713 ---- } + if (m_alsaDriver->areClocksRunning()) { + m_alsaDriver->checkTimerSync(m_framesProcessed); + } else { + m_alsaDriver->checkTimerSync(0); + } + bool lowLatencyMode = m_alsaDriver->getLowLatencyMode(); bool clocksRunning = m_alsaDriver->areClocksRunning(); *************** *** 719,723 **** } ! if (jack_cpu_load(m_client) > 98.0) { reportFailure(Rosegarden::MappedEvent::FailureCPUOverload); return jackProcessEmpty(nframes); --- 745,749 ---- } ! if (jack_cpu_load(m_client) > 97.0) { reportFailure(Rosegarden::MappedEvent::FailureCPUOverload); return jackProcessEmpty(nframes); *************** *** 1290,1293 **** --- 1316,1321 ---- if (!inst) return true; // or rather, return "huh?" + inst->m_alsaDriver->checkTimerSync(0); // reset, as not processing + if (!inst->m_jackTransportEnabled) return true; // ignore *************** *** 1555,1558 **** --- 1583,1588 ---- inst->m_ok = false; inst->m_kickedOutAt = time(0); + + inst->reportFailure(Rosegarden::MappedEvent::FailureJackDied); } *************** *** 1581,1601 **** } void JackDriver::restoreIfRestorable() { if (m_kickedOutAt == 0) return; time_t now = time(0); if (now < m_kickedOutAt || now >= m_kickedOutAt + 5) { initialise(true); if (m_ok) { reportFailure(Rosegarden::MappedEvent::FailureJackRestart); } else { ! reportFailure(Rosegarden::MappedEvent::FailureJackDied); } - } ! m_kickedOutAt = 0; } --- 1611,1641 ---- } + void + JackDriver::restoreIfRestorable() { if (m_kickedOutAt == 0) return; + if (m_client) { + jack_client_close(m_client); + std::cerr << "closed client" << std::endl; + m_client = 0; + } + time_t now = time(0); if (now < m_kickedOutAt || now >= m_kickedOutAt + 5) { + initialise(true); + if (m_ok) { reportFailure(Rosegarden::MappedEvent::FailureJackRestart); } else { ! reportFailure(Rosegarden::MappedEvent::FailureJackRestartFailed); } ! m_kickedOutAt = 0; ! } } *************** *** 1669,1672 **** --- 1709,1714 ---- JackDriver::updateAudioData() { + if (!m_ok || !m_client) return; + MappedAudioBuss *mbuss = m_alsaDriver->getMappedStudio()->getAudioBuss(0); *************** *** 1797,1800 **** --- 1839,1843 ---- } + m_maxInstrumentLatency = maxLatency; m_directMasterAudioInstruments = directMasterAudioInstruments; m_directMasterSynthInstruments = directMasterSynthInstruments; Index: AudioProcess.cpp =================================================================== RCS file: /cvsroot/rosegarden/sound/AudioProcess.cpp,v retrieving revision 1.71 retrieving revision 1.71.2.1 diff -C2 -d -r1.71 -r1.71.2.1 *** AudioProcess.cpp 17 Nov 2004 10:13:48 -0000 1.71 --- AudioProcess.cpp 27 Nov 2004 14:52:39 -0000 1.71.2.1 *************** *** 49,52 **** --- 49,68 ---- { + /* Branch-free optimizer-resistant denormal killer courtesy of Simon + Jenkins on LAD: */ + + static inline float flushToZero(volatile float f) + { + f += 9.8607615E-32f; + return f - 9.8607615E-32f; + } + + static inline void denormalKill(float *buffer, int size) + { + for (int i = 0; i < size; ++i) { + buffer[i] = flushToZero(buffer[i]); + } + } + AudioThread::AudioThread(std::string name, SoundDriver *driver, *************** *** 613,616 **** --- 629,688 ---- } + if (m_instrumentMixer) { + AudioInstrumentMixer::PluginList &plugins = + m_instrumentMixer->getBussPlugins(buss + 1); + + // This will have to do for now! + if (!plugins.empty()) dormant = false; + + for (AudioInstrumentMixer::PluginList::iterator pli = + plugins.begin(); pli != plugins.end(); ++pli) { + + RunnablePluginInstance *plugin = *pli; + if (!plugin || plugin->isBypassed()) continue; + + unsigned int ch = 0; + + while (ch < plugin->getAudioInputCount()) { + if (ch < 2) { + memcpy(plugin->getAudioInputBuffers()[ch], + m_processBuffers[ch], + m_blockSize * sizeof(sample_t)); + } else { + memset(plugin->getAudioInputBuffers()[ch], 0, + m_blockSize * sizeof(sample_t)); + } + ++ch; + } + + #ifdef DEBUG_BUSS_MIXER + std::cerr << "Running buss plugin with " << plugin->getAudioInputCount() + << " inputs, " << plugin->getAudioOutputCount() << " outputs" << std::endl; + #endif + + // We don't currently maintain a record of our + // frame time in the buss mixer. This will screw + // up any plugin that requires a good frame count: + // at the moment that only means DSSI effects + // plugins using run_multiple_synths, which would + // be an unusual although plausible combination + plugin->run(RealTime::zeroTime); + + ch = 0; + + while (ch < 2 && ch < plugin->getAudioOutputCount()) { + + denormalKill(plugin->getAudioOutputBuffers()[ch], + m_blockSize); + + memcpy(m_processBuffers[ch], + plugin->getAudioOutputBuffers()[ch], + m_blockSize * sizeof(sample_t)); + + ++ch; + } + } + } + for (int ch = 0; ch < 2; ++ch) { if (dormant) { *************** *** 953,960 **** // activate/deactivate at the same time as run() - getLock(); - std::cerr << "AudioInstrumentMixer::resetAllPlugins!" << std::endl; for (SynthPluginMap::iterator j = m_synths.begin(); j != m_synths.end(); ++j) { --- 1025,1033 ---- // activate/deactivate at the same time as run() std::cerr << "AudioInstrumentMixer::resetAllPlugins!" << std::endl; + getLock(); + if (m_bussMixer) m_bussMixer->getLock(); + for (SynthPluginMap::iterator j = m_synths.begin(); j != m_synths.end(); ++j) { *************** *** 997,1000 **** --- 1070,1074 ---- } + if (m_bussMixer) m_bussMixer->releaseLock(); releaseLock(); } *************** *** 1004,1007 **** --- 1078,1082 ---- { getLock(); + if (m_bussMixer) m_bussMixer->getLock(); // Delete immediately, as we're probably exiting here -- don't use *************** *** 1034,1037 **** --- 1109,1113 ---- m_driver->scavengePlugins(); + if (m_bussMixer) m_bussMixer->releaseLock(); releaseLock(); } *************** *** 1140,1143 **** --- 1216,1228 ---- } + if (m_bussMixer) { + for (int i = 0; i < m_bussMixer->getBussCount(); ++i) { + PluginList &list = m_plugins[i + 1]; + while (list.size() < Instrument::PLUGIN_COUNT) { + list.push_back(0); + } + } + } + while (m_processBuffers.size() > maxChannels) { std::vector<sample_t *>::iterator bi = m_processBuffers.end(); *************** *** 1205,1224 **** } - /* Branch-free optimizer-resistant denormal killer courtesy of Simon - Jenkins on LAD: */ - - static inline float flushToZero(volatile float f) - { - f += 9.8607615E-32f; - return f - 9.8607615E-32f; - } - - static inline void denormalKill(float *buffer, int size) - { - for (int i = 0; i < size; ++i) { - buffer[i] = flushToZero(buffer[i]); - } - } - void AudioInstrumentMixer::setInstrumentLevels(InstrumentId id, float dB, float pan) --- 1290,1293 ---- Index: AlsaDriver.h =================================================================== RCS file: /cvsroot/rosegarden/sound/AlsaDriver.h,v retrieving revision 1.118 retrieving revision 1.118.2.1 diff -C2 -d -r1.118 -r1.118.2.1 *** AlsaDriver.h 19 Nov 2004 17:57:28 -0000 1.118 --- AlsaDriver.h 27 Nov 2004 14:52:39 -0000 1.118.2.1 *************** *** 334,338 **** ssInstrumentBase = SoftSynthInstrumentBase; #ifdef HAVE_DSSI ! ssInstrumentCount = 16; #else ssInstrumentCount = 0; --- 334,338 ---- ssInstrumentBase = SoftSynthInstrumentBase; #ifdef HAVE_DSSI ! ssInstrumentCount = 24; #else ssInstrumentCount = 0; *************** *** 342,345 **** --- 342,348 ---- virtual QString getStatusLog(); + // To be called regularly from JACK driver when idle + void checkTimerSync(size_t frames); + virtual void runTasks(); *************** *** 363,367 **** virtual void generateTimerList(); ! virtual std::string getAutoTimer(); void addInstrumentsForDevice(MappedDevice *device); --- 366,370 ---- virtual void generateTimerList(); ! virtual std::string getAutoTimer(bool &wantTimerChecks); void addInstrumentsForDevice(MappedDevice *device); *************** *** 451,454 **** --- 454,460 ---- bool m_portCheckNeeded; + + bool m_doTimerChecks; + bool m_firstTimerCheck; }; Index: MappedEvent.h =================================================================== RCS file: /cvsroot/rosegarden/sound/MappedEvent.h,v retrieving revision 1.74 retrieving revision 1.74.2.1 diff -C2 -d -r1.74 -r1.74.2.1 *** MappedEvent.h 19 Nov 2004 17:57:29 -0000 1.74 --- MappedEvent.h 27 Nov 2004 14:52:39 -0000 1.74.2.1 *************** *** 185,188 **** --- 185,190 ---- // JACK kicked us out, but we've reconnected FailureJackRestart = 8, + // JACK kicked us out, and now the reconnection has failed + FailureJackRestartFailed = 9, } FailureCode; Index: AlsaDriver.cpp =================================================================== RCS file: /cvsroot/rosegarden/sound/AlsaDriver.cpp,v retrieving revision 1.352 retrieving revision 1.352.2.1 diff -C2 -d -r1.352 -r1.352.2.1 *** AlsaDriver.cpp 19 Nov 2004 17:57:27 -0000 1.352 --- AlsaDriver.cpp 27 Nov 2004 14:52:38 -0000 1.352.2.1 *************** *** 49,52 **** --- 49,53 ---- #include <pthread.h> + //#define DEBUG_ALSA 1 //#define DEBUG_PROCESS_MIDI_OUT 1 *************** *** 90,94 **** #endif ,m_queueRunning(false) ! ,m_portCheckNeeded(false) { --- 91,97 ---- #endif ,m_queueRunning(false) ! ,m_portCheckNeeded(false), ! m_doTimerChecks(false), ! m_firstTimerCheck(true) { *************** *** 312,324 **** std::string ! AlsaDriver::getAutoTimer() { ! // Look for the apparent best-choice timer if (m_timers.empty()) return ""; #ifdef HAVE_LIBJACK if (m_jackDriver) { // look for the first PCM playback timer; that's all we know // about for now (until JACK becomes able to tell us which PCM --- 315,365 ---- std::string ! AlsaDriver::getAutoTimer(bool &wantTimerChecks) { ! // Look for the apparent best-choice timer. if (m_timers.empty()) return ""; + // The system RTC timer ought to be good, but it doesn't look like + // a very safe choice -- we've seen some system lockups apparently + // connected with use of this timer on 2.6 kernels. So we avoid + // that unless the alternative is a 100Hz system timer. + + // Looks like our most reliable options for timers are, in order: + // + // 1. System timer if at 1000Hz, with timer checks (i.e. automatic + // drift correction against PCM frame count). Only available + // when JACK is running. + // + // 2. PCM playback timer currently in use by JACK (no drift, but + // suffers from jitter). + // + // 3. System timer if at 1000Hz. + // + // 4. System RTC timer. + // + // 5. System timer. + + wantTimerChecks = false; // for most options + #ifdef HAVE_LIBJACK if (m_jackDriver) { + // use system timer with timer checks if at 1000Hz or more + + for (std::vector<AlsaTimerInfo>::iterator i = m_timers.begin(); + i != m_timers.end(); ++i) { + if (i->sclas != SND_TIMER_SCLASS_NONE) continue; + if (i->clas == SND_TIMER_CLASS_GLOBAL) { + if (i->device == SND_TIMER_GLOBAL_SYSTEM) { + long hz = 1000000000 / i->resolution; + if (hz > 900) { + wantTimerChecks = true; + return i->name; + } + } + } + } + // look for the first PCM playback timer; that's all we know // about for now (until JACK becomes able to tell us which PCM *************** *** 333,338 **** #endif ! // look for the system RTC timer if available, system timer ! // otherwise for (std::vector<AlsaTimerInfo>::iterator i = m_timers.begin(); --- 374,393 ---- #endif ! // look for a system timer with a frequency of 1000Hz or more ! ! for (std::vector<AlsaTimerInfo>::iterator i = m_timers.begin(); ! i != m_timers.end(); ++i) { ! if (i->sclas != SND_TIMER_SCLASS_NONE) continue; ! if (i->clas == SND_TIMER_CLASS_GLOBAL) { ! if (i->device == SND_TIMER_GLOBAL_SYSTEM) { ! long hz = 1000000000 / i->resolution; ! if (hz > 900) { ! return i->name; ! } ! } ! } ! } ! ! // look for the system RTC timer if available for (std::vector<AlsaTimerInfo>::iterator i = m_timers.begin(); *************** *** 344,347 **** --- 399,404 ---- } + // next look for slow, unpopular 100Hz 2.4 system timer + for (std::vector<AlsaTimerInfo>::iterator i = m_timers.begin(); i != m_timers.end(); ++i) { *************** *** 349,356 **** if (i->clas == SND_TIMER_CLASS_GLOBAL) { if (i->device == SND_TIMER_GLOBAL_SYSTEM) { ! long hz = 1000000000 / i->resolution; ! if (hz < 900) { ! reportFailure(Rosegarden::MappedEvent::WarningImpreciseTimer); ! } return i->name; } --- 406,410 ---- if (i->clas == SND_TIMER_CLASS_GLOBAL) { if (i->device == SND_TIMER_GLOBAL_SYSTEM) { ! reportFailure(Rosegarden::MappedEvent::WarningImpreciseTimer); return i->name; } *************** *** 358,364 **** } return m_timers.begin()->name; } ! void --- 412,422 ---- } + // falling back to something that almost certainly won't work, + // if for any reason all of the above failed + return m_timers.begin()->name; } ! ! void *************** *** 1078,1081 **** --- 1136,1231 ---- } + + void + AlsaDriver::checkTimerSync(size_t frames) + { + if (!m_doTimerChecks) return; + + #ifdef HAVE_LIBJACK + if (!m_jackDriver || !m_queueRunning || frames == 0) { + m_firstTimerCheck = true; + return; + } + + static RealTime startAlsaTime; + static size_t startJackFrames = 0; + static size_t lastJackFrames = 0; + + size_t nowJackFrames = m_jackDriver->getFramesProcessed(); + RealTime nowAlsaTime = getAlsaTime(); + + if (m_firstTimerCheck || + (nowJackFrames <= lastJackFrames) || + (nowAlsaTime <= startAlsaTime)) { + + startAlsaTime = nowAlsaTime; + startJackFrames = nowJackFrames; + lastJackFrames = nowJackFrames; + + m_firstTimerCheck = false; + return; + } + + RealTime jackDiff = RealTime::frame2RealTime + (nowJackFrames - startJackFrames, + m_jackDriver->getSampleRate()); + + RealTime alsaDiff = nowAlsaTime - startAlsaTime; + + if (alsaDiff > RealTime(10, 0)) { + + if (!m_playing) { + std::cout << "\nALSA:" << startAlsaTime << "\t->" << nowAlsaTime << "\nJACK: " << startJackFrames << "\t\t-> " << nowJackFrames << std::endl; + std::cout << "ALSA diff: " << alsaDiff << "\nJACK diff: " << jackDiff << std::endl; + } + + double ratio = (jackDiff - alsaDiff) / alsaDiff; + + if (fabs(ratio) > 0.1) { + if (!m_playing) { + std::cout << "Ignoring excessive ratio " << ratio + << ", hoping for a more likely result next time" + << std::endl; + } + } else if (fabs(ratio) > 0.000001) { + + if (alsaDiff > RealTime::zeroTime && jackDiff > RealTime::zeroTime) { + if (!m_playing) { + if (jackDiff < alsaDiff) { + std::cout << "<<<< ALSA timer is faster by " << 100.0 * ((alsaDiff - jackDiff) / alsaDiff) << "% (1/" << int(1.0/ratio) << ")" << std::endl; + } else { + std::cout << ">>>> JACK timer is faster by " << 100.0 * ((jackDiff - alsaDiff) / alsaDiff) << "% (1/" << int(1.0/ratio) << ")" << std::endl; + } + } + } + + snd_seq_queue_tempo_t *q_ptr; + snd_seq_queue_tempo_alloca(&q_ptr); + + snd_seq_get_queue_tempo(m_midiHandle, m_queue, q_ptr); + + unsigned int t_skew = snd_seq_queue_tempo_get_skew(q_ptr); + unsigned int t_base = snd_seq_queue_tempo_get_skew_base(q_ptr); + + if (!m_playing) { + std::cerr << "Skew: " << t_skew << "/" << t_base; + } + + t_skew = t_skew + (unsigned int)(t_skew * ratio); + + if (!m_playing) { + std::cerr << " changed to " << t_skew << endl; + } + + snd_seq_queue_tempo_set_skew(q_ptr, t_skew); + snd_seq_set_queue_tempo( m_midiHandle, m_queue, q_ptr); + } + + m_firstTimerCheck = true; + } + #endif + } + + unsigned int AlsaDriver::getTimers() *************** *** 1109,1115 **** if (name == AUTO_TIMER_NAME) { ! name = getAutoTimer(); } ! // Stop and restart the queue around the timer change. We don't // call stopClocks/startClocks here because they do the wrong --- 1259,1267 ---- if (name == AUTO_TIMER_NAME) { ! name = getAutoTimer(m_doTimerChecks); ! } else { ! m_doTimerChecks = false; } ! // Stop and restart the queue around the timer change. We don't // call stopClocks/startClocks here because they do the wrong *************** *** 1149,1154 **** snd_seq_set_queue_timer(m_midiHandle, m_queue, timer); ! audit << " Current timer set to \"" << name << "\"" ! << std::endl; if (m_timers[i].clas == SND_TIMER_CLASS_GLOBAL && --- 1301,1311 ---- snd_seq_set_queue_timer(m_midiHandle, m_queue, timer); ! if (m_doTimerChecks) { ! audit << " Current timer set to \"" << name << "\" with timer checks" ! << std::endl; ! } else { ! audit << " Current timer set to \"" << name << "\"" ! << std::endl; ! } if (m_timers[i].clas == SND_TIMER_CLASS_GLOBAL && *************** *** 1172,1175 **** --- 1329,1334 ---- checkAlsaError(snd_seq_drain_output(m_midiHandle), "setCurrentTimer(): draining output to continue queue"); m_queueRunning = true; + + m_firstTimerCheck = true; } Index: MidiFile.cpp =================================================================== RCS file: /cvsroot/rosegarden/sound/MidiFile.cpp,v retrieving revision 1.169 retrieving revision 1.169.4.1 diff -C2 -d -r1.169 -r1.169.4.1 *** MidiFile.cpp 7 Nov 2004 23:14:41 -0000 1.169 --- MidiFile.cpp 27 Nov 2004 14:52:39 -0000 1.169.4.1 *************** *** 210,214 **** // bytesGot += numberOfBytes; ! if (bytesGot > 1000) { emit setProgress((int)(double(midiFile->tellg())/ --- 210,214 ---- // bytesGot += numberOfBytes; ! if (bytesGot > 2000) { emit setProgress((int)(double(midiFile->tellg())/ *************** *** 334,338 **** #ifdef MIDI_DEBUG ! std::std::cerr << "Parsing Track " << j << endl; #endif --- 334,338 ---- #ifdef MIDI_DEBUG ! std::cerr << "Parsing Track " << j << endl; #endif *************** *** 348,352 **** #ifdef MIDI_DEBUG ! std::std::cerr << "Track has " << m_trackByteCount << " bytes" << std::endl; #endif --- 348,352 ---- #ifdef MIDI_DEBUG ! std::cerr << "Track has " << m_trackByteCount << " bytes" << std::endl; #endif *************** *** 577,581 **** /* ! std::std::cerr << "MIDI event for channel " << channel << " (track " << trackNum << ")" << std::endl; midiEvent->print(); --- 577,581 ---- /* ! std::cerr << "MIDI event for channel " << channel << " (track " << trackNum << ")" << std::endl; midiEvent->print(); *************** *** 652,655 **** --- 652,671 ---- } + // borrowed from ALSA pcm_timer.c + // + static unsigned long gcd(unsigned long a, unsigned long b) + { + unsigned long r; + if (a < b) { + r = a; + a = b; + b = r; + } + while ((r = a % b) != 0) { + a = b; + b = r; + } + return b; + } // If we wanted to abstract the MidiFile class to make it more useful to *************** *** 709,714 **** timeT crotchetTime = Note(Note::Crotchet).getDuration(); int divisor = m_timingDivision ? m_timingDivision : 96; - bool haveTimeSignatures = false; InstrumentId compInstrument = MidiInstrumentBase; --- 725,738 ---- timeT crotchetTime = Note(Note::Crotchet).getDuration(); int divisor = m_timingDivision ? m_timingDivision : 96; + unsigned long multiplier = crotchetTime; + int g = (int)gcd(crotchetTime, divisor); + multiplier /= g; + divisor /= g; + + timeT maxRawTime = LONG_MAX; + if (multiplier > divisor) maxRawTime = (maxRawTime / multiplier) * divisor; + + bool haveTimeSignatures = false; InstrumentId compInstrument = MidiInstrumentBase; *************** *** 779,788 **** rosegardenEvent = 0; ! // [cc] -- avoid floating-point ! rosegardenTime = origin + ! timeT(((*midiEvent)->getTime() * crotchetTime) / divisor); ! rosegardenDuration = ! timeT(((*midiEvent)->getDuration() * crotchetTime) / divisor); ! if (rosegardenTime + rosegardenDuration > maxTime) { #ifdef MIDI_DEBUG --- 803,820 ---- rosegardenEvent = 0; ! // [cc] -- avoid floating-point where possible ! ! timeT rawTime = (*midiEvent)->getTime(); ! ! if (rawTime < maxRawTime) { ! rosegardenTime = origin + ! timeT((rawTime * multiplier) / divisor); ! } else { ! rosegardenTime = origin + ! timeT((double(rawTime) * multiplier) / double(divisor) + 0.01); ! } ! ! rosegardenDuration = ! timeT(((*midiEvent)->getDuration() * multiplier) / divisor); #ifdef MIDI_DEBUG *************** *** 792,798 **** << ", event type " << (int)(*midiEvent)->getMessageType() << ", previous max time " << maxTime ! << ", new max time " << (rosegardenTime + rosegardenDuration) << std::endl; #endif maxTime = rosegardenTime + rosegardenDuration; } --- 824,836 ---- << ", event type " << (int)(*midiEvent)->getMessageType() << ", previous max time " << maxTime ! << ", potential max time " << (rosegardenTime + rosegardenDuration) ! << ", ev raw time " << (*midiEvent)->getTime() ! << ", crotchet " << crotchetTime ! << ", multiplier " << multiplier ! << ", divisor " << divisor ! << std::endl; #endif + if (rosegardenTime + rosegardenDuration > maxTime) { maxTime = rosegardenTime + rosegardenDuration; } *************** *** 1179,1182 **** --- 1217,1224 ---- } + #ifdef MIDI_DEBUG + std::cerr << "MIDI import: adding segment with start time " << rosegardenSegment->getStartTime() << " and end time " << rosegardenSegment->getEndTime() << std::endl; + #endif + // add the Segment to the Composition and increment the // Rosegarden segment number Index: AudioProcess.h =================================================================== RCS file: /cvsroot/rosegarden/sound/AudioProcess.h,v retrieving revision 1.31 retrieving revision 1.31.2.1 diff -C2 -d -r1.31 -r1.31.2.1 *** AudioProcess.h 13 Nov 2004 19:06:18 -0000 1.31 --- AudioProcess.h 27 Nov 2004 14:52:39 -0000 1.31.2.1 *************** *** 174,177 **** --- 174,181 ---- { public: + typedef std::vector<RunnablePluginInstance *> PluginList; + typedef std::map<InstrumentId, PluginList> PluginMap; + typedef std::map<InstrumentId, RunnablePluginInstance *> SynthPluginMap; + AudioInstrumentMixer(SoundDriver *driver, AudioFileReader *fileReader, *************** *** 188,196 **** --- 192,203 ---- void removePlugin(InstrumentId id, int position); void removeAllPlugins(); + void setPluginPortValue(InstrumentId id, int position, unsigned int port, float value); float getPluginPortValue(InstrumentId id, int position, unsigned int port); + void setPluginBypass(InstrumentId, int position, bool bypass); + QStringList getPluginPrograms(InstrumentId, int); QString getPluginProgram(InstrumentId, int); *************** *** 198,202 **** --- 205,211 ---- unsigned long getPluginProgram(InstrumentId, int, QString); void setPluginProgram(InstrumentId, int, QString); + QString configurePlugin(InstrumentId, int, QString, QString); + void resetAllPlugins(); void destroyAllPlugins(); *************** *** 205,208 **** --- 214,225 ---- /** + * Return the plugins intended for a particular buss. (By coincidence, + * this will also work for instruments, but it's not to be relied on.) + * It's purely by historical accident that the instrument mixer happens + * to hold buss plugins as well -- this could do with being refactored. + */ + PluginList &getBussPlugins(unsigned int bussId) { return m_plugins[bussId]; } + + /** * Return the total of the plugin latencies for a given instrument * or buss id. *************** *** 274,280 **** // fixed size during normal run time; this will allow us to add // and edit plugins without locking. - typedef std::vector<RunnablePluginInstance *> PluginList; - typedef std::map<InstrumentId, PluginList> PluginMap; - typedef std::map<InstrumentId, RunnablePluginInstance *> SynthPluginMap; RunnablePluginInstance *getPluginInstance(InstrumentId, int); PluginMap m_plugins; --- 291,294 ---- |