Пример #1
0
void LoopingControl::slotLoopEndPos(double pos) {
    if (!m_pTrack) {
        return;
    }

    int newpos = pos;
    if (newpos != -1 && !even(newpos)) {
        newpos--;
    }

    if (m_iLoopEndSample == newpos) {
        //nothing to do
        return;
    }

    // Reject if the loop-in is not set, or if the new position is before the
    // start point (but not -1).
    if (m_iLoopStartSample == -1 ||
        (newpos != -1 && newpos < m_iLoopStartSample)) {
        m_pCOLoopEndPosition->set(m_iLoopEndSample);
        return;
    }

    clearActiveBeatLoop();

    if (pos == -1.0) {
        setLoopingEnabled(false);
    }
    m_iLoopEndSample = newpos;
    m_pCOLoopEndPosition->set(newpos);
}
Пример #2
0
void LoopingControl::slotLoopStartPos(double pos) {
    if (!m_pTrack) {
        return;
    }

    int newpos = pos;
    if (newpos != -1 && !even(newpos)) {
        newpos--;
    }


    if (m_iLoopStartSample == newpos) {
        //nothing to do
        return;
    }

    clearActiveBeatLoop();

    if (pos == -1.0) {
        setLoopingEnabled(false);
    }

    m_iLoopStartSample = newpos;
    m_pCOLoopStartPosition->set(newpos);

    if (m_iLoopEndSample != -1 &&
        m_iLoopEndSample < m_iLoopStartSample) {
        m_iLoopEndSample = -1;
        m_pCOLoopEndPosition->set(kNoTrigger);
        setLoopingEnabled(false);
    }
}
Пример #3
0
void LoopingControl::trackUnloaded(TrackPointer pTrack) {
    Q_UNUSED(pTrack);
    if (m_pTrack) {
        disconnect(m_pTrack.data(), SIGNAL(beatsUpdated()),
                   this, SLOT(slotUpdatedTrackBeats()));
    }
    m_pTrack.clear();
    m_pBeats.clear();
    clearActiveBeatLoop();
}
Пример #4
0
void LoopingControl::trackLoaded(TrackPointer pTrack) {
    if (m_pTrack) {
        trackUnloaded(m_pTrack);
    }

    clearActiveBeatLoop();

    if (pTrack) {
        m_pTrack = pTrack;
        m_pBeats = m_pTrack->getBeats();
        connect(m_pTrack.data(), SIGNAL(beatsUpdated()),
                this, SLOT(slotUpdatedTrackBeats()));
    }
}
Пример #5
0
void LoopingControl::slotLoopOut(double val) {
    if (!m_pTrack) {
        return;
    }
    if (val) {
        int pos =
                (m_pQuantizeEnabled->get() > 0.0 && m_pClosestBeat->get() != -1) ?
                static_cast<int>(floorf(m_pClosestBeat->get())) : m_iCurrentSample;

        // If the user is trying to set a loop-out before the loop in or without
        // having a loop-in, then ignore it.
        if (m_iLoopStartSample == -1 || pos < m_iLoopStartSample) {
            return;
        }

        // If the loop-in and out points are set so close that the loop would be
        //  inaudible (which can happen easily with quantize-to-beat enabled,)
        //  use the smallest pre-defined beatloop instead (when possible)
        if (pos - m_iLoopStartSample < MINIMUM_AUDIBLE_LOOP_SIZE) {
            pos = m_iLoopStartSample;
            if (m_pQuantizeEnabled->get() > 0.0 && m_pBeats) {
                // 1 would have just returned loop_in, so give 2 to get the beat
                // following loop_in
                int nextbeat = m_pBeats->findNthBeat(m_iLoopStartSample, 2);
                pos += (nextbeat - pos) * s_dBeatSizes[0];
            } else {
                pos += MINIMUM_AUDIBLE_LOOP_SIZE;
            }
        }

        if (pos != -1 && !even(pos)) {
            pos++;  // Increment to avoid shortening too-short loops
        }

        clearActiveBeatLoop();

        //set loop out position
        m_iLoopEndSample = pos;
        m_pCOLoopEndPosition->set(m_iLoopEndSample);

        // start looping
        if (m_iLoopStartSample != -1 &&
            m_iLoopEndSample != -1) {
            setLoopingEnabled(true);
        }
//         qDebug() << "set loop_out to " << m_iLoopEndSample;
    }
}
Пример #6
0
void LoopingControl::slotLoopScale(double scale) {
    if (m_iLoopStartSample == kNoTrigger || m_iLoopEndSample == kNoTrigger) {
        return;
    }
    int loop_length = m_iLoopEndSample - m_iLoopStartSample;
    int old_loop_end = m_iLoopEndSample;
    int samples = m_pTrackSamples->get();
    loop_length *= scale;

    // Abandon loops that are too short of extend beyond the end of the file.
    if (loop_length < MINIMUM_AUDIBLE_LOOP_SIZE ||
        m_iLoopStartSample + loop_length > samples) {
        return;
    }

    m_iLoopEndSample = m_iLoopStartSample + loop_length;

    if (!even(m_iLoopEndSample)) {
        m_iLoopEndSample--;
    }

    // TODO(XXX) we could be smarter about taking the active beatloop, scaling
    // it by the desired amount and trying to find another beatloop that matches
    // it, but for now we just clear the active beat loop if somebody scales.
    clearActiveBeatLoop();

    // Don't allow 0 samples loop, so one can still manipulate it
    if (m_iLoopEndSample == m_iLoopStartSample) {
        if ((m_iLoopEndSample+2) >= samples)
            m_iLoopStartSample -= 2;
        else
            m_iLoopEndSample += 2;
    }
    // Do not allow loops to go past the end of the song
    else if (m_iLoopEndSample > samples) {
        m_iLoopEndSample = samples;
    }

    // Update CO for loop end marker
    m_pCOLoopEndPosition->set(m_iLoopEndSample);

    // Reseek if the loop shrank out from under the playposition.
    if (m_bLoopingEnabled && scale < 1.0) {
        seekInsideAdjustedLoop(
                m_iLoopStartSample, old_loop_end,
                m_iLoopStartSample, m_iLoopEndSample);
    }
}
Пример #7
0
void LoopingControl::slotLoopIn(double val) {
    if (!m_pTrack) {
        return;
    }
    if (val) {
        clearActiveBeatLoop();

        // set loop-in position
        int pos =
                (m_pQuantizeEnabled->get() > 0.0 && m_pClosestBeat->get() != -1) ?
                static_cast<int>(floorf(m_pClosestBeat->get())) : m_iCurrentSample;

        // If we're looping and the loop-in and out points are now so close
        //  that the loop would be inaudible (which can happen easily with
        //  quantize-to-beat enabled,) set the in point to the smallest
        //  pre-defined beatloop size instead (when possible)
        if (m_bLoopingEnabled &&
            (m_iLoopEndSample - pos) < MINIMUM_AUDIBLE_LOOP_SIZE) {
            pos = m_iLoopEndSample;
            if (m_pQuantizeEnabled->get() > 0.0 && m_pBeats) {
                // 1 would have just returned loop_in, so give 2 to get the beat
                // following loop_in
                int nextbeat = m_pBeats->findNthBeat(pos, 2);
                pos -= (nextbeat - pos) * s_dBeatSizes[0];
            }
            else pos -= MINIMUM_AUDIBLE_LOOP_SIZE;
        }

        if (pos != -1 && !even(pos)) {
            pos--;
        }

        m_iLoopStartSample = pos;
        m_pCOLoopStartPosition->set(m_iLoopStartSample);

        // Reset the loop out position if it is before the loop in so that loops
        // cannot be inverted.
        if (m_iLoopEndSample != -1 &&
            m_iLoopEndSample < m_iLoopStartSample) {
            m_iLoopEndSample = -1;
            m_pCOLoopEndPosition->set(kNoTrigger);
        }
//         qDebug() << "set loop_in to " << m_iLoopStartSample;
    }
}
Пример #8
0
void LoopingControl::trackLoaded(TrackPointer pNewTrack, TrackPointer pOldTrack) {
    Q_UNUSED(pOldTrack);
    if (m_pTrack) {
        disconnect(m_pTrack.data(), SIGNAL(beatsUpdated()),
                   this, SLOT(slotUpdatedTrackBeats()));
    }

    clearActiveBeatLoop();

    if (pNewTrack) {
        m_pTrack = pNewTrack;
        m_pBeats = m_pTrack->getBeats();
        connect(m_pTrack.data(), SIGNAL(beatsUpdated()),
                this, SLOT(slotUpdatedTrackBeats()));
    } else {
        m_pTrack.clear();
        m_pBeats.clear();
    }
}
Пример #9
0
void LoopingControl::slotBeatLoop(double beats, bool keepStartPoint) {
    int samples = m_pTrackSamples->get();
    if (!m_pTrack || samples == 0) {
        clearActiveBeatLoop();
        return;
    }


    if (!m_pBeats) {
        clearActiveBeatLoop();
        return;
    }

    // For now we do not handle negative beatloops.
    if (beats < 0) {
        clearActiveBeatLoop();
        return;
    }

    // O(n) search, but there are only ~10-ish beatloop controls so this is
    // fine.
    foreach (BeatLoopingControl* pBeatLoopControl, m_beatLoops) {
        if (pBeatLoopControl->getSize() == beats) {
            if (m_pActiveBeatLoop != pBeatLoopControl) {
                if (m_pActiveBeatLoop) {
                    m_pActiveBeatLoop->deactivate();
                }
                m_pActiveBeatLoop = pBeatLoopControl;
            }
            pBeatLoopControl->activate();
            break;
        }
    }

    // give loop_in and loop_out defaults so we can detect problems
    int loop_in = -1;
    int loop_out = -1;

    // For positive numbers we start from the current position/closest beat and
    // create the loop around X beats from there.
    if (beats > 0) {
        if (keepStartPoint) {
            loop_in = m_iLoopStartSample;
        } else {
            // loop_in is set to the previous beat if quantize is on.  The
            // closest beat might be ahead of play position which would cause a seek.
            // TODO: If in reverse, should probably choose nextBeat.
            double cur_pos = getCurrentSample();
            double prevBeat =
                    floorf(m_pBeats->findPrevBeat(cur_pos));

            if (m_pQuantizeEnabled->get() > 0.0 && prevBeat != -1) {
                if (beats >= 1.0) {
                    loop_in = prevBeat;
                } else {
                    // In case of beat length less then 1 beat:
                    // (| - beats, ^ - current track's position):
                    //
                    // ...|...................^........|...
                    //
                    // If we press 1/2 beatloop we want loop from 50% to 100%,
                    // If I press 1/4 beatloop, we want loop from 50% to 75% etc
                    double nextBeat =
                            floorf(m_pBeats->findNextBeat(cur_pos));
                    double beat_len = nextBeat - prevBeat;
                    double loops_per_beat = 1.0 / beats;
                    double beat_pos = cur_pos - prevBeat;
                    int beat_frac =
                            static_cast<int>(floor((beat_pos / beat_len) *
                                                   loops_per_beat));
                    loop_in = prevBeat + beat_len / loops_per_beat * beat_frac;
                }

            } else {
                loop_in = floorf(cur_pos);
            }


            if (!even(loop_in)) {
                loop_in--;
            }
        }

        int fullbeats = static_cast<int>(floorf(beats));
        double fracbeats = beats - static_cast<double>(fullbeats);

        // Now we need to calculate the length of the beatloop. We do this by
        // taking the current beat and the fullbeats'th beat and measuring the
        // distance between them.
        loop_out = loop_in;

        if (fullbeats > 0) {
            // Add the length between this beat and the fullbeats'th beat to the
            // loop_out position;
            double this_beat = m_pBeats->findNthBeat(loop_in, 1);
            double nth_beat = m_pBeats->findNthBeat(loop_in, 1 + fullbeats);
            loop_out += (nth_beat - this_beat);
        }

        if (fracbeats > 0) {
            // Add the fraction of the beat following the current loop_out
            // position to loop out.
            double loop_out_beat = m_pBeats->findNthBeat(loop_out, 1);
            double loop_out_next_beat = m_pBeats->findNthBeat(loop_out, 2);
            loop_out += (loop_out_next_beat - loop_out_beat) * fracbeats;
        }
    }

    if ((loop_in == -1) || ( loop_out == -1))
        return;

    if (!even(loop_in))
        loop_in--;
    if (!even(loop_out))
        loop_out--;

    if (loop_in == loop_out) {
        if ((loop_out+2) > samples) {
            loop_in -= 2;
        } else {
            loop_out += 2;
        }
    } else if (loop_out > samples) {
        // Do not allow beat loops to go beyond the end of the track
        loop_out = samples;
    }

    m_iLoopStartSample = loop_in;
    m_pCOLoopStartPosition->set(loop_in);
    m_iLoopEndSample = loop_out;
    m_pCOLoopEndPosition->set(loop_out);
    setLoopingEnabled(true);
}