void SegmentJoinCommand::execute() { Composition *composition = m_oldSegments[0]->getComposition(); if (!composition) { RG_DEBUG << "SegmentJoinCommand::execute: ERROR: old segments are not in composition!"; return ; } if (!m_newSegment) { m_newSegment = makeSegment(m_oldSegments); } composition->addSegment(m_newSegment); // Select this new joined segment. RosegardenMainWindow::self()->getView()->getTrackEditor()-> getCompositionView()->getModel()->setSelected(m_newSegment); for (size_t i = 0; i < m_oldSegments.size(); ++i) { composition->detachSegment(m_oldSegments[i]); } m_detached = true; }
void AudioSegmentResizeFromStartCommand::execute() { Composition *c = m_segment->getComposition(); if (!m_newSegment) { RealTime oldRT = c->getElapsedRealTime(m_oldStartTime); RealTime newRT = c->getElapsedRealTime(m_newStartTime); m_newSegment = m_segment->clone(false); m_newSegment->setStartTime(m_newStartTime); // Compute an audio start time that will keep the audio exactly where // it was in time. RealTime audioStartTime = m_segment->getAudioStartTime() - (oldRT - newRT); // Do not allow a negative audio start time. // ??? This is a stopgap measure as the audio segment preview code // will crash if the audio start time is negative. Need to fix the // preview code, then check to see if the playback code works // properly given a negative start time. Then this can be removed. if (audioStartTime <= RealTime::zeroTime) m_newSegment->setAudioStartTime(RealTime::zeroTime); else m_newSegment->setAudioStartTime( m_segment->getAudioStartTime() - (oldRT - newRT)); } c->addSegment(m_newSegment); m_newSegment->setEndMarkerTime(m_segment->getEndMarkerTime()); c->detachSegment(m_segment); m_detached = false; }
void AudioSegmentResizeFromStartCommand::unexecute() { Composition *c = m_newSegment->getComposition(); c->addSegment(m_segment); c->detachSegment(m_newSegment); m_detached = true; }
// Initialize FitToBeatsCommand // @author Tom Breton (Tehom) void FitToBeatsCommand::initialise(Segment *s) { m_oldTempi.clear(); m_newTempi.clear(); m_oldSegments.clear(); m_newSegments.clear(); // Get the real times from the beat segment vecRealTime beatRealTimes; int success = getBeatRealTimes(s, beatRealTimes); if(!success) { return; } // Store the current tempos getCurrentTempi(*m_composition, m_oldTempi); tempoT defaultTempo = m_composition->getCompositionDefaultTempo(); // A temporary copy of the composition. It is not intended to be // a complete copy, it just provides a place for new segments and // tempi to live until we have fully copied events to their new // state. Composition scratchComposition; scratchComposition.clear(); scratchComposition.setCompositionDefaultTempo(defaultTempo); // Set tempos in scratchComposition such that each observed beat // in beatRealTimes takes one beatTime. { // Starting time is the same for both. timeT firstBeatTime = m_composition->getElapsedTimeForRealTime(beatRealTimes[0]); unsigned int numBeats = beatRealTimes.size(); // Get interval between beats from time signature. // Get time signature TimeSignature timeSig = m_composition->getTimeSignatureAt(firstBeatTime); timeT beatTime = timeSig.getBeatDuration(); // We're going to visit the beats in reverse order, and always // remembering the next beat (the next beat time-wise, which // the iterator visited last time) vecRealTime::const_reverse_iterator i = beatRealTimes.rbegin(); // Treat the final beat specially timeT finalBeatTime = firstBeatTime + ((numBeats - 1) * beatTime); RealTime finalRealTime = beatRealTimes.back(); scratchComposition.addTempoAtTime(finalBeatTime, defaultTempo, -1); // Step past it ++i; // Set up loop variables timeT nextBeatTime = finalBeatTime; RealTime nextRealTime = finalRealTime; // nextTempo is unused, it will be used if we make ramped // tempi. /* tempoT nextTempo = defaultTempo; */ // Treat all the other beats. while (i != beatRealTimes.rend()) { timeT timeNow = nextBeatTime - beatTime; RealTime realTimeNow = *i; RealTime realTimeDelta = nextRealTime - realTimeNow; // Calculate what tempoT will get us to the right real // time. For now, we use unramped tempi. tempoT rampTo = -1; tempoT tempo = Composition::timeRatioToTempo(realTimeDelta, beatTime, rampTo); scratchComposition.addTempoAtTime(timeNow, tempo, rampTo); // Step nextBeatTime = timeNow; nextRealTime = realTimeNow; /* nextTempo = tempo; */ ++i; } } // We don't try to copy over tempo changes that are outside the // range of the groove segment (before or after). We don't try to // correct for accumulated error. // Done setting Tempi // Collect tempi getCurrentTempi(scratchComposition, m_newTempi); // Copy all the events to scratchComposition. The copies will be // at the same realtime but not the same timeT. Even events in // the groove segment get copied. segmentcontainer &origSegments = m_composition->getSegments(); for (Composition::iterator i = origSegments.begin(); i != origSegments.end(); ++i) { Segment * const oldSegment = *i; // We'd prefer to just make a segment with no events that's // otherwise the same as the old one but we can't. Segment *newSegment = oldSegment->clone(false); newSegment->clear(); // Add the segments into appropriate containers. // scratchComposition owns the new segments during initialise, // but m_newSegments will own them after initialise returns. m_oldSegments.insert(oldSegment); m_newSegments.insert(newSegment); scratchComposition.addSegment(newSegment); //Iterate over notes in the old segment. const timeT earliestTime = 0; for (Segment::iterator j = oldSegment->findTime(earliestTime); oldSegment->isBeforeEndMarker(j); ++j) { // Get the old-timed event times. timeT oldStartTime = (*j)->getAbsoluteTime(); timeT duration = (*j)->getDuration(); // Get the real event times. RealTime RealStartTime = m_composition->getElapsedRealTime(oldStartTime); RealTime RealEndTime; if (duration == 0) { RealEndTime = RealStartTime; } else { timeT oldEndTime = oldStartTime + duration; RealEndTime = m_composition->getElapsedRealTime(oldEndTime); } // Get the new target times. Use scratchComposition // because its times use the new Tempi. timeT newStartTime = scratchComposition.getElapsedTimeForRealTime(RealStartTime); timeT newDuration; if (duration == 0) { newDuration = 0; } else { timeT newEndTime = scratchComposition.getElapsedTimeForRealTime(RealEndTime); newDuration = newEndTime - newStartTime; } // Add a parallel event in the new segment. newSegment->insert(new Event(**j, newStartTime, newDuration)); } } // Detach the segments before scratchComposition goes out of // scope. m_newSegments contains exactly the segments that need // to be detached. for (segmentcontainer::iterator i = m_newSegments.begin(); i != m_newSegments.end(); ++i) { scratchComposition.weakDetachSegment(*i); } // We do the actual swapping of old <-> new in (un)execute. }