From c00e79dd68a68ab0ec30034612d3c8826107b8db Mon Sep 17 00:00:00 2001 From: Robert Jonsson Date: Sun, 8 May 2011 21:20:35 +0000 Subject: structure menu fixes --- muse2/ChangeLog | 2 + muse2/awl/posedit.cpp | 2 + muse2/muse/CMakeLists.txt | 1 + muse2/muse/app.cpp | 280 ++----------------------------- muse2/muse/app.h | 5 +- muse2/muse/marker/marker.h | 2 +- muse2/muse/master/lmaster.cpp | 4 + muse2/muse/part.h | 1 + muse2/muse/song.cpp | 160 ++++++++++-------- muse2/muse/song.h | 4 +- muse2/muse/songfile.cpp | 3 + muse2/muse/structure.cpp | 368 +++++++++++++++++++++++++++++++++++++++++ muse2/muse/undo.cpp | 30 +++- muse2/muse/widgets/songinfo.ui | 7 + 14 files changed, 524 insertions(+), 345 deletions(-) create mode 100644 muse2/muse/structure.cpp diff --git a/muse2/ChangeLog b/muse2/ChangeLog index ab11a07b..291bcd6f 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,5 +1,7 @@ 08.05.2011: - Draw event canvas notes if they extend past part end. (Tim) + - Added checkbox to select if songinfo should be displayed on song start (rj) + - fixups to structure functions, now inserts/cuts markers, and master track events with undo (rj) 06.05.2011: - MusE 2.0beta2 released (rj) - Added Yamaha-CS1x.idf instrument from Ernie Rymer Thanks! (Tim) diff --git a/muse2/awl/posedit.cpp b/muse2/awl/posedit.cpp index e9cddd44..6ca49566 100644 --- a/muse2/awl/posedit.cpp +++ b/muse2/awl/posedit.cpp @@ -433,6 +433,8 @@ QValidator::State PosEdit::validate(QString& s,int& /*i*/) const int tb = AL::sigmap.ticksBeat(_pos.tick()); unsigned tm = AL::sigmap.ticksMeasure(_pos.tick()); + if (tm==0) + return QValidator::Invalid; int bm = tm / tb; validator->setRange(1, 9999); diff --git a/muse2/muse/CMakeLists.txt b/muse2/muse/CMakeLists.txt index 2d2a9fe3..d89bb007 100644 --- a/muse2/muse/CMakeLists.txt +++ b/muse2/muse/CMakeLists.txt @@ -120,6 +120,7 @@ file (GLOB core_source_files song.cpp songfile.cpp stringparam.cpp + structure.cpp sync.cpp synth.cpp tempo.cpp diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index 052bb48b..59993911 100644 --- a/muse2/muse/app.cpp +++ b/muse2/muse/app.cpp @@ -974,10 +974,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow() editCopyAction = new QAction(QIcon(*editcopyIconSet), tr("&Copy"), this); editPasteAction = new QAction(QIcon(*editpasteIconSet), tr("&Paste"), this); editInsertAction = new QAction(QIcon(*editpasteIconSet), tr("&Insert"), this); + editInsertEMAction = new QAction(QIcon(*editpasteIconSet), tr("&Insert Empty Measure"), this); editPasteCloneAction = new QAction(QIcon(*editpasteCloneIconSet), tr("Paste c&lone"), this); editPaste2TrackAction = new QAction(QIcon(*editpaste2TrackIconSet), tr("Paste to &track"), this); editPasteC2TAction = new QAction(QIcon(*editpasteClone2TrackIconSet), tr("Paste clone to trac&k"), this); - editInsertEMAction = new QAction(QIcon(*editpasteIconSet), tr("&Insert Empty Measure"), this); editDeleteSelectedAction = new QAction(QIcon(*edit_track_delIcon), tr("Delete Selected Tracks"), this); @@ -1123,10 +1123,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow() connect(editCopyAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editPasteAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editInsertAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); + connect(editInsertEMAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editPasteCloneAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editPaste2TrackAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editPasteC2TAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); - connect(editInsertEMAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editDeleteSelectedAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editSelectAllAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); @@ -1183,7 +1183,7 @@ MusE::MusE(int argc, char** argv) : QMainWindow() connect(strGlobalCutAction, SIGNAL(activated()), SLOT(globalCut())); connect(strGlobalInsertAction, SIGNAL(activated()), SLOT(globalInsert())); connect(strGlobalSplitAction, SIGNAL(activated()), SLOT(globalSplit())); - connect(strCopyRangeAction, SIGNAL(activated()), SLOT(copyRange())); + connect(strCopyRangeAction, SIGNAL(activated()), SLOT(copyRange())); connect(strCutEventsAction, SIGNAL(activated()), SLOT(cutEvents())); //-------- Midi connections @@ -1357,10 +1357,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow() menuEdit->addAction(editCopyAction); menuEdit->addAction(editPasteAction); menuEdit->addAction(editInsertAction); + menuEdit->addAction(editInsertEMAction); menuEdit->addAction(editPasteCloneAction); menuEdit->addAction(editPaste2TrackAction); menuEdit->addAction(editPasteC2TAction); - menuEdit->addAction(editInsertEMAction); menuEdit->addSeparator(); menuEdit->addAction(editDeleteSelectedAction); @@ -1738,14 +1738,16 @@ void MusE::loadProjectFile(const QString& name, bool songTemplate, bool loadAll) if (restartSequencer) seqStart(); - if (song->getSongInfo().length()>0) - startSongInfo(false); - visTracks->updateVisibleTracksButtons(); progress->setValue(100); delete progress; progress=0; + QApplication::restoreOverrideCursor(); + + if (song->getSongInfo().length()>0 && song->showSongInfoOnStartup()) { + startSongInfo(false); + } } //--------------------------------------------------------- @@ -3378,7 +3380,7 @@ bool MusE::saveAs() return false; } - song->setSongInfo(pci.getSongInfo()); + song->setSongInfo(pci.getSongInfo(), true); name = pci.getProjectPath(); } else { name = getSaveFileName(QString(""), med_file_save_pattern, this, tr("MusE: Save As")); @@ -3670,12 +3672,16 @@ void MusE::startWaveEditor(PartList* pl) void MusE::startSongInfo(bool editable) { SongInfoWidget info; + info.viewCheckBox->setChecked(song->showSongInfoOnStartup()); + info.viewCheckBox->setEnabled(editable); info.songInfoText->setPlainText(song->getSongInfo()); info.songInfoText->setReadOnly(!editable); + info.setModal(true); info.show(); if( info.exec() == QDialog::Accepted) { - if (editable) - song->setSongInfo(info.songInfoText->toPlainText()); + if (editable) { + song->setSongInfo(info.songInfoText->toPlainText(), info.viewCheckBox->isChecked()); + } } } @@ -3691,7 +3697,7 @@ void MusE::showDidYouKnowDialog() dyk.show(); if( dyk.exec()) { if (dyk.dontShowCheckBox->isChecked()) { - printf("disables dialog!\n"); + //printf("disables dialog!\n"); config.showDidYouKnow=false; muse->changeConfig(true); // save settings } @@ -4389,256 +4395,6 @@ void MusE::configShortCuts() changeConfig(true); } -//--------------------------------------------------------- -// globalCut -// - remove area between left and right locator -// - do not touch muted track -// - cut master track -//--------------------------------------------------------- - -void MusE::globalCut() - { - int lpos = song->lpos(); - int rpos = song->rpos(); - if ((lpos - rpos) >= 0) - return; - - song->startUndo(); - TrackList* tracks = song->tracks(); - for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { - MidiTrack* track = dynamic_cast(*it); - if (track == 0 || track->mute()) - continue; - PartList* pl = track->parts(); - for (iPart p = pl->begin(); p != pl->end(); ++p) { - Part* part = p->second; - int t = part->tick(); - int l = part->lenTick(); - if (t + l <= lpos) - continue; - if ((t >= lpos) && ((t+l) <= rpos)) { - audio->msgRemovePart(part, false); - } - else if ((t < lpos) && ((t+l) > lpos) && ((t+l) <= rpos)) { - // remove part tail - int len = lpos - t; - MidiPart* nPart = new MidiPart(*(MidiPart*)part); - nPart->setLenTick(len); - // - // cut Events in nPart - EventList* el = nPart->events(); - iEvent ie = el->lower_bound(t + len); - for (; ie != el->end();) { - iEvent i = ie; - ++ie; - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgDeleteEvent(i->second, nPart, false); - audio->msgDeleteEvent(i->second, nPart, false, false, false); - } - // Indicate no undo, and do port controller values and clone parts. - //audio->msgChangePart(part, nPart, false); - audio->msgChangePart(part, nPart, false, true, true); - } - else if ((t < lpos) && ((t+l) > lpos) && ((t+l) > rpos)) { - //---------------------- - // remove part middle - //---------------------- - - MidiPart* nPart = new MidiPart(*(MidiPart*)part); - EventList* el = nPart->events(); - iEvent is = el->lower_bound(lpos); - iEvent ie = el->upper_bound(rpos); - for (iEvent i = is; i != ie;) { - iEvent ii = i; - ++i; - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgDeleteEvent(ii->second, nPart, false); - audio->msgDeleteEvent(ii->second, nPart, false, false, false); - } - - ie = el->lower_bound(rpos); - for (; ie != el->end();) { - iEvent i = ie; - ++ie; - Event event = i->second; - Event nEvent = event.clone(); - nEvent.setTick(nEvent.tick() - (rpos-lpos)); - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgChangeEvent(event, nEvent, nPart, false); - audio->msgChangeEvent(event, nEvent, nPart, false, false, false); - } - nPart->setLenTick(l - (rpos-lpos)); - // Indicate no undo, and do port controller values and clone parts. - //audio->msgChangePart(part, nPart, false); - audio->msgChangePart(part, nPart, false, true, true); - } - else if ((t >= lpos) && (t < rpos) && (t+l) > rpos) { - // TODO: remove part head - } - else if (t >= rpos) { - MidiPart* nPart = new MidiPart(*(MidiPart*)part); - int nt = part->tick(); - nPart->setTick(nt - (rpos -lpos)); - // Indicate no undo, and do port controller values but not clone parts. - //audio->msgChangePart(part, nPart, false); - audio->msgChangePart(part, nPart, false, true, false); - } - } - } - // TODO: cut tempo track - // TODO: process marker - song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_REMOVED); - } - -//--------------------------------------------------------- -// globalInsert -// - insert empty space at left locator position upto -// right locator -// - do not touch muted track -// - insert in master track -//--------------------------------------------------------- - -void MusE::globalInsert() - { - unsigned lpos = song->lpos(); - unsigned rpos = song->rpos(); - if (lpos >= rpos) - return; - - song->startUndo(); - TrackList* tracks = song->tracks(); - for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { - MidiTrack* track = dynamic_cast(*it); - // - // process only non muted midi tracks - // - if (track == 0 || track->mute()) - continue; - PartList* pl = track->parts(); - for (iPart p = pl->begin(); p != pl->end(); ++p) { - Part* part = p->second; - unsigned t = part->tick(); - int l = part->lenTick(); - if (t + l <= lpos) - continue; - if (lpos >= t && lpos < (t+l)) { - MidiPart* nPart = new MidiPart(*(MidiPart*)part); - nPart->setLenTick(l + (rpos-lpos)); - EventList* el = nPart->events(); - - iEvent i = el->end(); - while (i != el->begin()) { - --i; - if (i->first < lpos) - break; - Event event = i->second; - Event nEvent = i->second.clone(); - nEvent.setTick(nEvent.tick() + (rpos-lpos)); - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgChangeEvent(event, nEvent, nPart, false); - audio->msgChangeEvent(event, nEvent, nPart, false, false, false); - } - // Indicate no undo, and do port controller values and clone parts. - //audio->msgChangePart(part, nPart, false); - audio->msgChangePart(part, nPart, false, true, true); - } - else if (t > lpos) { - MidiPart* nPart = new MidiPart(*(MidiPart*)part); - nPart->setTick(t + (rpos -lpos)); - // Indicate no undo, and do port controller values but not clone parts. - //audio->msgChangePart(part, nPart, false); - audio->msgChangePart(part, nPart, false, true, false); - } - } - } - // TODO: process tempo track - // TODO: process marker - song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_REMOVED); - } - -//--------------------------------------------------------- -// globalSplit -// - split all parts at the song position pointer -// - do not touch muted track -//--------------------------------------------------------- - -void MusE::globalSplit() - { - int pos = song->cpos(); - song->startUndo(); - TrackList* tracks = song->tracks(); - for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { - Track* track = *it; - PartList* pl = track->parts(); - for (iPart p = pl->begin(); p != pl->end(); ++p) { - Part* part = p->second; - int p1 = part->tick(); - int l0 = part->lenTick(); - if (pos > p1 && pos < (p1+l0)) { - Part* p1; - Part* p2; - track->splitPart(part, pos, p1, p2); - // Indicate no undo, and do port controller values but not clone parts. - //audio->msgChangePart(part, p1, false); - audio->msgChangePart(part, p1, false, true, false); - audio->msgAddPart(p2, false); - break; - } - } - } - song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_INSERTED); - } - -//--------------------------------------------------------- -// copyRange -// - copy space between left and right locator position -// to song position pointer -// - dont process muted tracks -// - create a new part for every track containing the -// copied events -//--------------------------------------------------------- - -void MusE::copyRange() - { - QMessageBox::critical(this, - tr("MusE: Copy Range"), - tr("not implemented") - ); - } - -//--------------------------------------------------------- -// cutEvents -// - make sure that all events in a part end where the -// part ends -// - process only marked parts -//--------------------------------------------------------- - -void MusE::cutEvents() - { - QMessageBox::critical(this, - tr("MusE: Cut Events"), - tr("not implemented") - ); - } - -//--------------------------------------------------------- -// checkRegionNotNull -// return true if (rPos - lPos) <= 0 -//--------------------------------------------------------- - -bool MusE::checkRegionNotNull() - { - int start = song->lPos().frame(); - int end = song->rPos().frame(); - if (end - start <= 0) { - QMessageBox::critical(this, - tr("MusE: Bounce"), - tr("set left/right marker for bounce range") - ); - return true; - } - return false; - } #if 0 //--------------------------------------------------------- @@ -5050,10 +4806,10 @@ void MusE::updateConfiguration() editCopyAction->setShortcut(shortcuts[SHRT_COPY].key); editPasteAction->setShortcut(shortcuts[SHRT_PASTE].key); editInsertAction->setShortcut(shortcuts[SHRT_INSERT].key); + editInsertEMAction->setShortcut(shortcuts[SHRT_INSERTMEAS].key); editPasteCloneAction->setShortcut(shortcuts[SHRT_PASTE_CLONE].key); editPaste2TrackAction->setShortcut(shortcuts[SHRT_PASTE_TO_TRACK].key); editPasteC2TAction->setShortcut(shortcuts[SHRT_PASTE_CLONE_TO_TRACK].key); - editInsertEMAction->setShortcut(shortcuts[SHRT_INSERTMEAS].key); //editDeleteSelectedAction has no acceleration diff --git a/muse2/muse/app.h b/muse2/muse/app.h index 2fd83854..42aebf3b 100644 --- a/muse2/muse/app.h +++ b/muse2/muse/app.h @@ -108,7 +108,7 @@ class MusE : public QMainWindow // Edit Menu actions QAction *editCutAction, *editCopyAction, *editPasteAction, *editInsertAction, *editPasteCloneAction, *editPaste2TrackAction; - QAction *editPasteC2TAction, *editInsertEMAction, *editDeleteSelectedAction, *editSelectAllAction, *editDeselectAllAction; + QAction *editInsertEMAction, *editPasteC2TAction, *editDeleteSelectedAction, *editSelectAllAction, *editDeselectAllAction; QAction *editInvertSelectionAction, *editInsideLoopAction, *editOutsideLoopAction, *editAllPartsAction; QAction *trackMidiAction, *trackDrumAction, *trackWaveAction, *trackAOutputAction, *trackAGroupAction; QAction *trackAInputAction, *trackAAuxAction; @@ -334,6 +334,9 @@ class MusE : public QMainWindow void execDeliveredScript(int); void execUserScript(int); + private: + void adjustGlobalLists(int startPos, int diff); + public slots: bool saveAs(); diff --git a/muse2/muse/marker/marker.h b/muse2/muse/marker/marker.h index f1a587f7..012cce80 100644 --- a/muse2/muse/marker/marker.h +++ b/muse2/muse/marker/marker.h @@ -24,7 +24,7 @@ class Marker : public Pos { bool _current; public: - Marker() : _current(false) {} + Marker() : _name(""),_current(false) {} Marker(const QString& s, bool cur = false) : _name(s), _current(cur) {} void read(Xml&); diff --git a/muse2/muse/master/lmaster.cpp b/muse2/muse/master/lmaster.cpp index 21cadfdd..2f921cdc 100644 --- a/muse2/muse/master/lmaster.cpp +++ b/muse2/muse/master/lmaster.cpp @@ -207,13 +207,17 @@ LMaster::LMaster() updateList(); tempo_editor = new QLineEdit(view->viewport()); + tempo_editor->hide(); connect(tempo_editor, SIGNAL(returnPressed()), SLOT(returnPressed())); sig_editor = new SigEdit(view->viewport()); + sig_editor->hide(); connect(sig_editor, SIGNAL(returnPressed()), SLOT(returnPressed())); pos_editor = new Awl::PosEdit(view->viewport()); + pos_editor->hide(); connect(pos_editor, SIGNAL(returnPressed()), SLOT(returnPressed())); key_editor = new QComboBox(view->viewport()); key_editor->addItems(keyStrs); + key_editor->hide(); connect(key_editor, SIGNAL(currentIndexChanged(int)), SLOT(returnPressed())); connect(view, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), SLOT(select(QTreeWidgetItem*, QTreeWidgetItem*))); diff --git a/muse2/muse/part.h b/muse2/muse/part.h index 11ff2fd4..f7a864e5 100644 --- a/muse2/muse/part.h +++ b/muse2/muse/part.h @@ -143,6 +143,7 @@ class WavePart : public Part { //--------------------------------------------------------- typedef std::multimap >::iterator iPart; +typedef std::multimap >::reverse_iterator riPart; typedef std::multimap >::const_iterator ciPart; class PartList : public std::multimap > { diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp index cf040348..e6fa9cab 100644 --- a/muse2/muse/song.cpp +++ b/muse2/muse/song.cpp @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include "app.h" #include "driver/jackmidi.h" @@ -85,6 +87,7 @@ Song::Song(const char* name) redoList = new UndoList; _markerList = new MarkerList; _globalPitchShift = 0; + showSongInfo=true; clear(false); } @@ -1767,6 +1770,24 @@ Marker* Song::setMarkerLock(Marker* m, bool f) return m; } +// kommer inte att gå göra undo på, kanske skulle fixa det. + +//void Song::moveMarkers(int startOffset, int ticks) +//{ +// iMarker markerI; +// for (markerI=_markerList->rbegin(); markerI != _markerList->rend(); ++markerI) { +// if (markerI->second.tick() > startOffset) { +// if (markerI-> ) +// } +// +// +// +// if (unsigned(t) == markerI->second.tick())//prevent of copmiler warning: comparison signed/unsigned +// return &markerI->second; +// } +// +//} + //--------------------------------------------------------- // setRecordFlag //--------------------------------------------------------- @@ -3696,79 +3717,74 @@ void Song::executeScript(const char* scriptfile, PartList* parts, int quant, boo } fclose(fp); - // Call external program, let it manipulate the file - int pid = fork(); - if (pid == 0) { - if (execlp(scriptfile, scriptfile, tmp, NULL) == -1) { - perror("Failed to launch script!"); - // Get out of here - - // cannot report error through gui, we are in another fork! - //@!TODO: Handle unsuccessful attempts - exit(99); - } - exit(0); - } - else if (pid == -1) { - perror("fork failed"); - } - else { - int status; - waitpid(pid, &status, 0); - if (WEXITSTATUS(status) != 0 ) { - QMessageBox::warning(muse, tr("MusE - external script failed"), - tr("MusE was unable to launch the script\n") - ); - endUndo(SC_EVENT_REMOVED); - return; - } - else { // d0 the fun55or5! - // TODO: Create a new part, update the entire editor from it, hehh.... - - QFile file(tmp); - if ( file.open( QIODevice::ReadOnly ) ) { - QTextStream stream( &file ); - QString line; - while ( !stream.atEnd() ) { - line = stream.readLine(); // line of text excluding '\n' - if (line.startsWith("NOTE")) - { - QStringList sl = line.split(" "); - - Event e(Note); - int tick = sl[1].toInt(); - int pitch = sl[2].toInt(); - int len = sl[3].toInt(); - int velo = sl[4].toInt(); - printf ("tick=%d pitch=%d velo=%d len=%d\n", tick,pitch,velo,len); - e.setTick(tick); - e.setPitch(pitch); - e.setVelo(velo); - e.setLenTick(len); - // Indicate no undo, and do not do port controller values and clone parts. - audio->msgAddEvent(e, part, false, false, false); - } - if (line.startsWith("CONTROLLER")) - { - QStringList sl = line.split(" "); - - Event e(Controller); - int tick = sl[1].toInt(); - int a = sl[2].toInt(); - int b = sl[3].toInt(); - int c = sl[4].toInt(); - printf ("tick=%d a=%d b=%d c=%d\n", tick,a,b,c); - e.setA(a); - e.setB(b); - e.setB(c); - // Indicate no undo, and do not do port controller values and clone parts. - audio->msgAddEvent(e, part, false, false, false); - } - } - file.close(); - } - } +// QString program(scriptfile); + QStringList arguments; + arguments << tmp; + + QProcess *myProcess = new QProcess(muse); + myProcess->start(scriptfile, arguments); + myProcess->waitForFinished(); + QByteArray errStr = myProcess->readAllStandardError(); + if (errStr.size()) { + QMessageBox::warning(muse, tr("MusE - external script failed"), + "Script returned the following error\n"+ QString(errStr)); + endUndo(SC_EVENT_REMOVED); + return; + + } else if (myProcess->exitCode()) { + QMessageBox::warning(muse, tr("MusE - external script failed"), + tr("MusE was unable to launch the script\n") + ); + endUndo(SC_EVENT_REMOVED); + return; } + else { // d0 the fun55or5! + // TODO: Create a new part, update the entire editor from it, hehh.... + + QFile file(tmp); + if ( file.open( QIODevice::ReadOnly ) ) { + QTextStream stream( &file ); + QString line; + while ( !stream.atEnd() ) { + line = stream.readLine(); // line of text excluding '\n' + if (line.startsWith("NOTE")) + { + QStringList sl = line.split(" "); + + Event e(Note); + int tick = sl[1].toInt(); + int pitch = sl[2].toInt(); + int len = sl[3].toInt(); + int velo = sl[4].toInt(); + //printf ("tick=%d pitch=%d velo=%d len=%d\n", tick,pitch,velo,len); + e.setTick(tick); + e.setPitch(pitch); + e.setVelo(velo); + e.setLenTick(len); + // Indicate no undo, and do not do port controller values and clone parts. + audio->msgAddEvent(e, part, false, false, false); + } + if (line.startsWith("CONTROLLER")) + { + QStringList sl = line.split(" "); + + Event e(Controller); + int tick = sl[1].toInt(); + int a = sl[2].toInt(); + int b = sl[3].toInt(); + int c = sl[4].toInt(); + //printf ("tick=%d a=%d b=%d c=%d\n", tick,a,b,c); + e.setA(a); + e.setB(b); + e.setB(c); + // Indicate no undo, and do not do port controller values and clone parts. + audio->msgAddEvent(e, part, false, false, false); + } + } + file.close(); + } + } + remove(tmp); } diff --git a/muse2/muse/song.h b/muse2/muse/song.h index b097a5ee..e1378480 100644 --- a/muse2/muse/song.h +++ b/muse2/muse/song.h @@ -139,6 +139,7 @@ class Song : public QObject { void readMarker(Xml&); QString songInfoStr; // contains user supplied song information, stored in song file. + bool showSongInfo; QStringList deliveredScriptNames; QStringList userScriptNames; @@ -167,7 +168,8 @@ class Song : public QObject { const QFont& font) const; QFont readFont(Xml& xml, const char* name); QString getSongInfo() { return songInfoStr; } - void setSongInfo(QString info) { songInfoStr = info; } + void setSongInfo(QString info, bool show) { songInfoStr = info; showSongInfo = show; } + bool showSongInfoOnStartup() { return showSongInfo; } // If clear_all is false, it will not touch things like midi ports. void clear(bool signal, bool clear_all = true); diff --git a/muse2/muse/songfile.cpp b/muse2/muse/songfile.cpp index 9a577308..a8134b1d 100644 --- a/muse2/muse/songfile.cpp +++ b/muse2/muse/songfile.cpp @@ -1232,6 +1232,8 @@ void Song::read(Xml& xml) setMasterFlag(xml.parseInt()); else if (tag == "info") songInfoStr = xml.parse1(); + else if (tag == "showinfo") + showSongInfo = xml.parseInt(); else if (tag == "loop") setLoop(xml.parseInt()); else if (tag == "punchin") @@ -1437,6 +1439,7 @@ void Song::write(int level, Xml& xml) const { xml.tag(level++, "song"); xml.strTag(level, "info", songInfoStr); + xml.intTag(level, "showinfo", showSongInfo); xml.intTag(level, "automation", automation); xml.intTag(level, "cpos", song->cpos()); xml.intTag(level, "rpos", song->rpos()); diff --git a/muse2/muse/structure.cpp b/muse2/muse/structure.cpp new file mode 100644 index 00000000..f0a4308a --- /dev/null +++ b/muse2/muse/structure.cpp @@ -0,0 +1,368 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: app.cpp,v 1.113.2.68 2009/12/21 14:51:51 spamatica Exp $ +// +// (C) Copyright 1999-2004 Werner Schweer (ws@seh.de) +// (C) Copyright 2011 Robert Jonsson (rj@spamatica.se) +//========================================================= + +#include +#include "app.h" +#include "track.h" +#include "song.h" +#include "tempo.h" +#include "al/sig.h" +#include "keyevent.h" +#include "audio.h" +#include "marker/marker.h" + + +//--------------------------------------------------------- +// adjustGlobalLists +// helper that adjusts tempo, sig, key and marker +// lists everything from startPos is adjusted +// 'diff' number of ticks. +// function requires undo to be handled outside +//--------------------------------------------------------- + +void MusE::adjustGlobalLists(int startPos, int diff) +{ + const TempoList* t = &tempomap; + const AL::SigList* s = &AL::sigmap; + const KeyList* k = &keymap; + + criTEvent it = t->rbegin(); + AL::criSigEvent is = s->rbegin(); + criKeyEvent ik = k->rbegin(); + + // key + for (; ik != k->rend(); ik++) { + const KeyEvent &ev = (KeyEvent)ik->second; + int tick = ev.tick; + int key = ev.key; + if (tick < startPos ) + break; + + if (tick > startPos && tick +diff < startPos ) { // remove + audio->msgRemoveKey(tick, key, false); + } + else { + audio->msgRemoveKey(tick, key, false); + audio->msgAddKey(tick+diff, key, false); + } + } + + // tempo + for (; it != t->rend(); it++) { + const TEvent* ev = (TEvent*)it->second; + int tick = ev->tick; + int tempo = ev->tempo; + if (tick < startPos ) + break; + + if (tick > startPos && tick +diff < startPos ) { // remove + audio->msgDeleteTempo(tick, tempo, false); + } + else { + audio->msgDeleteTempo(tick, tempo, false); + audio->msgAddTempo(tick+diff, tempo, false); + } + } + + // sig + for (; is != s->rend(); is++) { + const AL::SigEvent* ev = (AL::SigEvent*)is->second; + int tick = ev->tick; + if (tick < startPos ) + break; + + int z = ev->sig.z; + int n = ev->sig.n; + if (tick > startPos && tick +diff < startPos ) { // remove + audio->msgRemoveSig(tick, z, n, false); + } + else { + audio->msgRemoveSig(tick, z, n, false); + audio->msgAddSig(tick+diff, z, n, false); + } + } + + MarkerList *markerlist = song->marker(); + for(iMarker i = markerlist->begin(); i != markerlist->end(); ++i) + { + Marker* m = &i->second; + int tick = m->tick(); + if (tick > startPos) + { + if (tick + diff < startPos ) { // these ticks should be removed + Marker *oldMarker = new Marker(); + *oldMarker = *m; + markerlist->remove(m); + song->undoOp(UndoOp::ModifyMarker,oldMarker, 0); + } else { + Marker *oldMarker = new Marker(); + *oldMarker = *m; + m->setTick(tick + diff); + song->undoOp(UndoOp::ModifyMarker,oldMarker, m); + } + } + } + +} + +//--------------------------------------------------------- +// globalCut +// - remove area between left and right locator +// - do not touch muted track +// - cut master track +//--------------------------------------------------------- + +void MusE::globalCut() + { + int lpos = song->lpos(); + int rpos = song->rpos(); + if ((lpos - rpos) >= 0) + return; + + song->startUndo(); + TrackList* tracks = song->tracks(); + for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { + MidiTrack* track = dynamic_cast(*it); + if (track == 0 || track->mute()) + continue; + PartList* pl = track->parts(); + for (iPart p = pl->begin(); p != pl->end(); ++p) { + Part* part = p->second; + int t = part->tick(); + int l = part->lenTick(); + if (t + l <= lpos) + continue; + if ((t >= lpos) && ((t+l) <= rpos)) { + audio->msgRemovePart(part, false); + } + else if ((t < lpos) && ((t+l) > lpos) && ((t+l) <= rpos)) { + // remove part tail + int len = lpos - t; + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + nPart->setLenTick(len); + // + // cut Events in nPart + EventList* el = nPart->events(); + iEvent ie = el->lower_bound(t + len); + for (; ie != el->end();) { + iEvent i = ie; + ++ie; + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgDeleteEvent(i->second, nPart, false); + audio->msgDeleteEvent(i->second, nPart, false, false, false); + } + // Indicate no undo, and do port controller values and clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, true); + } + else if ((t < lpos) && ((t+l) > lpos) && ((t+l) > rpos)) { + //---------------------- + // remove part middle + //---------------------- + + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + EventList* el = nPart->events(); + iEvent is = el->lower_bound(lpos); + iEvent ie = el->upper_bound(rpos); + for (iEvent i = is; i != ie;) { + iEvent ii = i; + ++i; + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgDeleteEvent(ii->second, nPart, false); + audio->msgDeleteEvent(ii->second, nPart, false, false, false); + } + + ie = el->lower_bound(rpos); + for (; ie != el->end();) { + iEvent i = ie; + ++ie; + Event event = i->second; + Event nEvent = event.clone(); + nEvent.setTick(nEvent.tick() - (rpos-lpos)); + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgChangeEvent(event, nEvent, nPart, false); + audio->msgChangeEvent(event, nEvent, nPart, false, false, false); + } + nPart->setLenTick(l - (rpos-lpos)); + // Indicate no undo, and do port controller values and clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, true); + } + else if ((t >= lpos) && (t < rpos) && (t+l) > rpos) { + // TODO: remove part head + } + else if (t >= rpos) { + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + int nt = part->tick(); + nPart->setTick(nt - (rpos -lpos)); + // Indicate no undo, and do port controller values but not clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, false); + } + } + } + int diff = lpos - rpos; + adjustGlobalLists(lpos, diff); + + song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_REMOVED | SC_TEMPO | SC_KEY | SC_SIG); + } + +//--------------------------------------------------------- +// globalInsert +// - insert empty space at left locator position upto +// right locator +// - do not touch muted track +// - insert in master track +//--------------------------------------------------------- + +void MusE::globalInsert() + { + unsigned lpos = song->lpos(); + unsigned rpos = song->rpos(); + if (lpos >= rpos) + return; + + song->startUndo(); + TrackList* tracks = song->tracks(); + for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { + MidiTrack* track = dynamic_cast(*it); + // + // process only non muted midi tracks + // + if (track == 0 || track->mute()) + continue; + PartList* pl = track->parts(); + for (riPart p = pl->rbegin(); p != pl->rend(); ++p) { + Part* part = p->second; + unsigned t = part->tick(); + int l = part->lenTick(); + if (t + l <= lpos) + continue; + if (lpos >= t && lpos < (t+l)) { + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + nPart->setLenTick(l + (rpos-lpos)); + EventList* el = nPart->events(); + + iEvent i = el->end(); + while (i != el->begin()) { + --i; + if (i->first < lpos) + break; + Event event = i->second; + Event nEvent = i->second.clone(); + nEvent.setTick(nEvent.tick() + (rpos-lpos)); + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgChangeEvent(event, nEvent, nPart, false); + audio->msgChangeEvent(event, nEvent, nPart, false, false, false); + } + // Indicate no undo, and do port controller values and clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, true); + } + else if (t > lpos) { + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + nPart->setTick(t + (rpos -lpos)); + // Indicate no undo, and do port controller values but not clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, false); + } + } + } + + int diff = rpos - lpos; + adjustGlobalLists(lpos, diff); + + song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_REMOVED | SC_TEMPO | SC_KEY | SC_SIG ); + } + + +//--------------------------------------------------------- +// globalSplit +// - split all parts at the song position pointer +// - do not touch muted track +//--------------------------------------------------------- + +void MusE::globalSplit() + { + int pos = song->cpos(); + song->startUndo(); + TrackList* tracks = song->tracks(); + for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { + Track* track = *it; + PartList* pl = track->parts(); + for (iPart p = pl->begin(); p != pl->end(); ++p) { + Part* part = p->second; + int p1 = part->tick(); + int l0 = part->lenTick(); + if (pos > p1 && pos < (p1+l0)) { + Part* p1; + Part* p2; + track->splitPart(part, pos, p1, p2); + // Indicate no undo, and do port controller values but not clone parts. + //audio->msgChangePart(part, p1, false); + audio->msgChangePart(part, p1, false, true, false); + audio->msgAddPart(p2, false); + break; + } + } + } + song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_INSERTED); + } + +//--------------------------------------------------------- +// copyRange +// - copy space between left and right locator position +// to song position pointer +// - dont process muted tracks +// - create a new part for every track containing the +// copied events +//--------------------------------------------------------- + +void MusE::copyRange() + { + QMessageBox::critical(this, + tr("MusE: Copy Range"), + tr("not implemented") + ); + } + +//--------------------------------------------------------- +// cutEvents +// - make sure that all events in a part end where the +// part ends +// - process only marked parts +//--------------------------------------------------------- + +void MusE::cutEvents() + { + QMessageBox::critical(this, + tr("MusE: Cut Events"), + tr("not implemented") + ); + } + +//--------------------------------------------------------- +// checkRegionNotNull +// return true if (rPos - lPos) <= 0 +//--------------------------------------------------------- + +bool MusE::checkRegionNotNull() + { + int start = song->lPos().frame(); + int end = song->rPos().frame(); + if (end - start <= 0) { + QMessageBox::critical(this, + tr("MusE: Bounce"), + tr("set left/right marker for bounce range") + ); + return true; + } + return false; + } + diff --git a/muse2/muse/undo.cpp b/muse2/muse/undo.cpp index 44d37591..a31b8e7a 100644 --- a/muse2/muse/undo.cpp +++ b/muse2/muse/undo.cpp @@ -897,10 +897,18 @@ void Song::doUndo3() break; case UndoOp::ModifyMarker: { - //printf("performing undo for one marker at %d\n", i->realMarker->tick()); - Marker tmpMarker = *i->realMarker; - *i->realMarker = *i->copyMarker; // swap them - *i->copyMarker = tmpMarker; + //printf("performing undo for one marker at copy %d real %d\n", i->copyMarker, i->realMarker); + if (i->realMarker) { + Marker tmpMarker = *i->realMarker; + *i->realMarker = *i->copyMarker; // swap them + *i->copyMarker = tmpMarker; + } + else { + //printf("flipping marker\n"); + i->realMarker = _markerList->add(*i->copyMarker); + delete i->copyMarker; + i->copyMarker = 0; + } } break; default: @@ -979,10 +987,16 @@ void Song::doRedo3() break; case UndoOp::ModifyMarker: { - //printf("performing redo for one marker at %d\n", i->realMarker->tick()); - Marker tmpMarker = *i->realMarker; - *i->realMarker = *i->copyMarker; // swap them - *i->copyMarker = tmpMarker; + //printf("performing redo for one marker at copy %d real %d\n", i->copyMarker, i->realMarker); + if (i->copyMarker) { + Marker tmpMarker = *i->realMarker; + *i->realMarker = *i->copyMarker; // swap them + *i->copyMarker = tmpMarker; + } else { + i->copyMarker = new Marker(*i->realMarker); + _markerList->remove(i->realMarker); + i->realMarker = 0; + } } break; default: diff --git a/muse2/muse/widgets/songinfo.ui b/muse2/muse/widgets/songinfo.ui index 0944ce93..c313fd9f 100644 --- a/muse2/muse/widgets/songinfo.ui +++ b/muse2/muse/widgets/songinfo.ui @@ -24,6 +24,13 @@ + + + + Show on song load + + + -- cgit v1.2.3 From 4f2e54561260eb8382953d5723d5d111353a22c9 Mon Sep 17 00:00:00 2001 From: "Tim E. Real" Date: Tue, 10 May 2011 21:23:00 +0000 Subject: Added general settings audio item: Minimum control process period Added Yamaha Mo6 instrument file by Geoff King --- muse2/ChangeLog | 5 + muse2/muse/conf.cpp | 3 + muse2/muse/dssihost.cpp | 27 +- muse2/muse/gconfig.cpp | 3 +- muse2/muse/gconfig.h | 1 + muse2/muse/plugin.cpp | 21 +- muse2/muse/widgets/genset.cpp | 19 + muse2/muse/widgets/gensetbase.ui | 147 +++- muse2/muse/widgets/musewidgetsplug.cpp | 4 + muse2/share/instruments/yam_mo6_v3.idf | 1290 ++++++++++++++++++++++++++++++++ 10 files changed, 1500 insertions(+), 20 deletions(-) create mode 100644 muse2/share/instruments/yam_mo6_v3.idf diff --git a/muse2/ChangeLog b/muse2/ChangeLog index 291bcd6f..a091bf49 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,8 @@ +10.05.2011: + - Added general settings audio item: Minimum control process period 1-2048, default 64. Test OK. (Tim) + Adjusts minimum allowable number of samples in a LADSPA or DSSI run, ie control 'smoothness'. + Still TODO: AudioTrack controllers contribution. + - Added Yamaha Mo6 instrument file by Geoff King gsking1 A T gmail D O T com. (Tim) 08.05.2011: - Draw event canvas notes if they extend past part end. (Tim) - Added checkbox to select if songinfo should be displayed on song start (rj) diff --git a/muse2/muse/conf.cpp b/muse2/muse/conf.cpp index c79c3928..2f391445 100644 --- a/muse2/muse/conf.cpp +++ b/muse2/muse/conf.cpp @@ -923,6 +923,8 @@ void readConfiguration(Xml& xml, bool readOnlySequencer) config.dummyAudioSampleRate = xml.parseInt(); else if (tag == "dummyAudioBufSize") config.dummyAudioBufSize = xml.parseInt(); + else if (tag == "minControlProcessPeriod") + config.minControlProcessPeriod = xml.parseUInt(); else if (tag == "guiRefresh") config.guiRefresh = xml.parseInt(); else if (tag == "userInstrumentsDir") @@ -1182,6 +1184,7 @@ void MusE::writeGlobalConfiguration(int level, Xml& xml) const xml.intTag(level, "vstInPlace", config.vstInPlace); xml.intTag(level, "dummyAudioBufSize", config.dummyAudioBufSize); xml.intTag(level, "dummyAudioSampleRate", config.dummyAudioSampleRate); + xml.uintTag(level, "minControlProcessPeriod", config.minControlProcessPeriod); xml.intTag(level, "guiRefresh", config.guiRefresh); xml.strTag(level, "userInstrumentsDir", config.userInstrumentsDir); diff --git a/muse2/muse/dssihost.cpp b/muse2/muse/dssihost.cpp index cbb908e6..49a63643 100644 --- a/muse2/muse/dssihost.cpp +++ b/muse2/muse/dssihost.cpp @@ -2342,6 +2342,9 @@ iMPEvent DssiSynthIF::getData(MidiPort* /*mp*/, MPEventList* el, iMPEvent i, uns unsigned long sample = 0; int loopcount = 0; // REMOVE Tim. + // To remember the last retrieved value of each AudioTrack controller. + //float prev_ctrl_values[synth->_controlInPorts]; + // NOTE Tested: Variable run-lengths worked superbly for LADSPA and DSSI synths. But DSSI-VST definitely // does NOT like changing sample run length. It crashes the plugin and Wine (but MusE keeps running!). // Furthermore, it resizes the shared memory (mmap, remap) upon each run length DIFFERENT from the last. @@ -2372,11 +2375,15 @@ iMPEvent DssiSynthIF::getData(MidiPort* /*mp*/, MPEventList* el, iMPEvent i, uns if(fixedsize > n) fixedsize = n; + unsigned long min_per = config.minControlProcessPeriod; + if(min_per > n) + min_per = n; + // Process automation control values now. // TODO: This needs to be respect frame resolution. Put this inside the sample loop below. - for(unsigned long k = 0; k < synth->_controlInPorts; ++k) + if(automation && synti && synti->automationType() != AUTO_OFF && id() != -1) { - if(automation && synti && synti->automationType() != AUTO_OFF && id() != -1) + for(unsigned long k = 0; k < synth->_controlInPorts; ++k) { if(controls[k].enCtrl && controls[k].en2Ctrl ) controls[k].val = synti->pluginCtrlVal(genACnum(id(), k)); @@ -2393,7 +2400,7 @@ iMPEvent DssiSynthIF::getData(MidiPort* /*mp*/, MPEventList* el, iMPEvent i, uns unsigned long index = 0; unsigned long evframe; // Get all control ring buffer items valid for this time period... - //for(int m = 0; m < cbsz; ++m) + //for(int m = 0; m < cbsz; ++m) // Doesn't like this. Why? while(!_controlFifo.isEmpty()) { //ControlValue v = _controlFifo.get(); @@ -2424,7 +2431,9 @@ iMPEvent DssiSynthIF::getData(MidiPort* /*mp*/, MPEventList* el, iMPEvent i, uns if(evframe >= n //|| (found && v.frame != frame) //|| (!usefixedrate && found && !v.unique && v.frame != frame) - || (found && !v.unique && evframe != frame) + //|| (found && !v.unique && evframe != frame) + // Not enough requested samples to satisfy minimum setting? Keep going. + || (found && !v.unique && (evframe - sample >= min_per)) // dssi-vst needs them serialized and accounted for, no matter what. This works with fixed rate // because nsamp is constant. But with packets, we need to guarantee at least one-frame spacing. // Although we likely won't be using packets with dssi-vst, so it's OK for now. @@ -2443,6 +2452,16 @@ iMPEvent DssiSynthIF::getData(MidiPort* /*mp*/, MPEventList* el, iMPEvent i, uns controls[v.idx].val = v.value; } + // Process automation control values now. + //if(automation && synti && synti->automationType() != AUTO_OFF && id() != -1) + //{ + // for(unsigned long k = 0; k < synth->_controlInPorts; ++k) + // { + // if(controls[k].enCtrl && controls[k].en2Ctrl ) + // controls[k].val = synti->pluginCtrlVal(genACnum(id(), k)); + // } + //} + //if(found) if(found && !usefixedrate) //nsamp = frame - sample + 1; diff --git a/muse2/muse/gconfig.cpp b/muse2/muse/gconfig.cpp index ee6123ef..4d22ad4c 100644 --- a/muse2/muse/gconfig.cpp +++ b/muse2/muse/gconfig.cpp @@ -167,6 +167,7 @@ GlobalConfigValues config = { 512, // Dummy audio buffer size QString("./"), // projectBaseFolder true, // projectStoreInFolder - true // useProjectSaveDialog + true, // useProjectSaveDialog + 64 // minControlProcessPeriod }; diff --git a/muse2/muse/gconfig.h b/muse2/muse/gconfig.h index 6fb1bb17..cd236b36 100644 --- a/muse2/muse/gconfig.h +++ b/muse2/muse/gconfig.h @@ -142,6 +142,7 @@ struct GlobalConfigValues { QString projectBaseFolder; bool projectStoreInFolder; bool useProjectSaveDialog; + unsigned long minControlProcessPeriod; }; extern GlobalConfigValues config; diff --git a/muse2/muse/plugin.cpp b/muse2/muse/plugin.cpp index 76ebeb1b..215a7844 100644 --- a/muse2/muse/plugin.cpp +++ b/muse2/muse/plugin.cpp @@ -2560,6 +2560,9 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float** // } //} + // Grab the control ring buffer size now. + //const int cbsz = _controlFifo.getSize(); + //unsigned endPos = pos + n; //unsigned long frameOffset = audio->getFrameOffset(); unsigned long syncFrame = audio->curSyncFrame(); @@ -2581,12 +2584,16 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float** // so that users can select a small audio period but a larger control period. if(fixedsize > n) fixedsize = n; + + unsigned long min_per = config.minControlProcessPeriod; + if(min_per > n) + min_per = n; // Process automation control values now. // TODO: This needs to be respect frame resolution. Put this inside the sample loop below. - for(unsigned long k = 0; k < controlPorts; ++k) + if(automation && _track && _track->automationType() != AUTO_OFF && _id != -1) { - if(automation && _track && _track->automationType() != AUTO_OFF && _id != -1) + for(unsigned long k = 0; k < controlPorts; ++k) { if(controls[k].enCtrl && controls[k].en2Ctrl ) controls[k].tmpVal = _track->pluginCtrlVal(genACnum(_id, k)); @@ -2603,7 +2610,7 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float** unsigned long index = 0; unsigned long evframe; // Get all control ring buffer items valid for this time period... - //for(int m = 0; m < cbsz; ++m) + //for(int m = 0; m < cbsz; ++m) // Doesn't like this. Why? while(!_controlFifo.isEmpty()) { //ControlValue v = _controlFifo.get(); @@ -2632,7 +2639,9 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float** if(evframe >= n //|| (found && v.frame != frame) //|| (!usefixedrate && found && !v.unique && v.frame != frame) - || (found && !v.unique && evframe != frame) + //|| (found && !v.unique && evframe != frame) + // Not enough requested samples to satisfy minimum setting? Keep going. + || (found && !v.unique && (evframe - sample >= min_per)) // Protection. Observed this condition (dummy audio so far). Why? Supposed to be linear timestamps. //|| (found && evframe < frame) // dssi-vst needs them serialized and accounted for, no matter what. This works with fixed rate @@ -2700,7 +2709,7 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float** //printf("PluginI::apply ports:%lu n:%lu frame:%lu sample:%lu nsamp:%lu syncFrame:%lu loopcount:%d\n", // ports, n, frame, sample, nsamp, syncFrame, loopcount); // REMOVE Tim. - // TODO: TESTING: Don't allow zero-length runs. This could/should be checked in the control loop instead. + // Don't allow zero-length runs. This could/should be checked in the control loop instead. // Note this means it is still possible to get stuck in the top loop (at least for a while). if(nsamp == 0) continue; @@ -2712,7 +2721,7 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float** //fprintf(stderr, "PluginI::apply handle %d\n", i); _plugin->apply(handle[i], nsamp); } - + sample += nsamp; loopcount++; // REMOVE Tim. } diff --git a/muse2/muse/widgets/genset.cpp b/muse2/muse/widgets/genset.cpp index 4a0550bb..edf3cfda 100644 --- a/muse2/muse/widgets/genset.cpp +++ b/muse2/muse/widgets/genset.cpp @@ -28,6 +28,9 @@ static int divisions[] = { static int dummyAudioBufSizes[] = { 16, 32, 64, 128, 256, 512, 1024, 2048 }; +static unsigned long minControlProcessPeriods[] = { + 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 + }; //--------------------------------------------------------- // GlobalSettingsConfig @@ -66,6 +69,13 @@ GlobalSettingsConfig::GlobalSettingsConfig(QWidget* parent) } } + for (unsigned i = 0; i < sizeof(minControlProcessPeriods)/sizeof(*minControlProcessPeriods); ++i) { + if (minControlProcessPeriods[i] == config.minControlProcessPeriod) { + minControlProcessPeriodComboBox->setCurrentIndex(i); + break; + } + } + userInstrumentsPath->setText(config.userInstrumentsDir); selectInstrumentsDirButton->setIcon(*openIcon); defaultInstrumentsDirButton->setIcon(*undoIcon); @@ -185,6 +195,13 @@ void GlobalSettingsConfig::updateSettings() } } + for (unsigned i = 0; i < sizeof(minControlProcessPeriods)/sizeof(*minControlProcessPeriods); ++i) { + if (minControlProcessPeriods[i] == config.minControlProcessPeriod) { + minControlProcessPeriodComboBox->setCurrentIndex(i); + break; + } + } + guiRefreshSelect->setValue(config.guiRefresh); minSliderSelect->setValue(int(config.minSlider)); minMeterSelect->setValue(config.minMeter); @@ -279,6 +296,8 @@ void GlobalSettingsConfig::apply() int das = dummyAudioSize->currentIndex(); config.dummyAudioBufSize = dummyAudioBufSizes[das]; config.dummyAudioSampleRate = dummyAudioRate->value(); + int mcp = minControlProcessPeriodComboBox->currentIndex(); + config.minControlProcessPeriod = minControlProcessPeriods[mcp]; int div = midiDivisionSelect->currentIndex(); config.division = divisions[div]; diff --git a/muse2/muse/widgets/gensetbase.ui b/muse2/muse/widgets/gensetbase.ui index a48dd3f0..ca4b97f8 100644 --- a/muse2/muse/widgets/gensetbase.ui +++ b/muse2/muse/widgets/gensetbase.ui @@ -6,8 +6,8 @@ 0 0 - 522 - 528 + 526 + 506 @@ -550,11 +550,20 @@ Mixer - + 11 + + 2 + + + 11 + + + 2 + - 6 + 2 @@ -617,8 +626,7 @@ - Use Jack freewheel mode if possible. -(Speeds up bounce operations). + Try to use Jack Freewheel false @@ -634,6 +642,13 @@ + + Speeds bounce operations + + + Use Jack Freewheel mode if possible. +This dramatically speeds bounce operations. + @@ -669,8 +684,7 @@ - Enable in-place processing for VST plugins. -(Requires restart.) + VST in-place false @@ -679,14 +693,105 @@ + + Enable VST in-place processing (restart required) + - Turn this off if VST Ladspa effect rack plugins do not work or feedback loudly, even if they are supposed to be in-place capable. + Enable VST in-place processing. Turn this off if + VST Ladspa effect rack plugins do not work or + feedback loudly, even if they are supposed to + be in-place capable. Setting requires a restart. + + + + Minimum control period + + + + + + + Minimum audio controller process period (samples). + + + + Minimum audio controller process period (samples). +Adjusts responsiveness of audio controls and + controller graphs. Set a low value for fast, smooth + control. If it causes performance problems, set a + higher value. + + + 15 + + + + 1 + + + + + 2 + + + + + 4 + + + + + 8 + + + + + 16 + + + + + 32 + + + + + 64 + + + + + 128 + + + + + 256 + + + + + 512 + + + + + 1024 + + + + + 2048 + + + + @@ -696,6 +801,15 @@ External Waveditor + + 2 + + + 2 + + + 2 + @@ -771,6 +885,21 @@ Dummy Audio Driver (settings require restart) + + 11 + + + 2 + + + 11 + + + 2 + + + 2 + diff --git a/muse2/muse/widgets/musewidgetsplug.cpp b/muse2/muse/widgets/musewidgetsplug.cpp index 4b61cf2a..8cb0b57e 100644 --- a/muse2/muse/widgets/musewidgetsplug.cpp +++ b/muse2/muse/widgets/musewidgetsplug.cpp @@ -193,6 +193,10 @@ GlobalConfigValues config = { false, // vstInPlace Enable VST in-place processing 44100, // Dummy audio preferred sample rate 512 // Dummy audio buffer size + QString("./"), // projectBaseFolder + true, // projectStoreInFolder + true, // useProjectSaveDialog + 64 // minControlProcessPeriod }; //--------------------------------------------------------- diff --git a/muse2/share/instruments/yam_mo6_v3.idf b/muse2/share/instruments/yam_mo6_v3.idf new file mode 100644 index 00000000..da3ad8c7 --- /dev/null +++ b/muse2/share/instruments/yam_mo6_v3.idf @@ -0,0 +1,1290 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3