Ejemplo n.º 1
0
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;
}
Ejemplo n.º 4
0
// 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.
}