Skip to content
This repository has been archived by the owner on Oct 16, 2021. It is now read-only.

DPCM (Xxx Retrigger)

nyanpasu64 edited this page May 7, 2018 · 3 revisions

Overview of DPCM sample playback

triggerSample() {
    mTriggerSample = true   // play sample this frame.
    queueSample()           // If mRetriggerPeriod != 0, this initializes retriggering.
                            // Otherwise reset mRetriggerCtr.
}
queueSample() {
    if (mRetriggerPeriod == 0)  mRetriggerCtr = 0;
    else                        mRetriggerCtr = mRetriggerPeriod + 1;
}

If new row:
CDPCMChan::HandleNoteData():
  mRetriggerPeriod = 0.
  CChannelHandler::HandleNoteData():
    If Xxx:
        HandleEffect() finds HandleEffect.EF_RETRIGGER
        mRetriggerPeriod = xx
        if mRetriggerCtr == 0:  // recent row contains note without Xxx
            queueSample()

    if note:
        PlaySample() is called
        triggerSample()

Each frame: CDPCMChan::RefreshChannel():   // renders channel (pushes registers to 2a03)
    If mRetriggerPeriod:
        mRetriggerCtr--
        If zero:
            mRetriggerCtr = mRetriggerPeriod
            mEnabled = true
            mTriggerSample = true

    if mTriggerSample:
        play DPCM.


In the absence of queueSample(), mRetriggerCtr is cycled within [1..mRetriggerPeriod] by RefreshChannel().
If a row-note plays on any non-Xxx row, mRetriggerCtr is reset to mRetriggerPeriod=0.

queueSample queues a sample after mRetriggerPeriod frames

void CDPCMChan::triggerSample() {
    // Trigger sample.
    mEnabled = true;
    mTriggerSample = true;

    // If mRetriggerPeriod != 0, this initializes retriggering. Otherwise reset mRetriggerCtr.
    queueSample();
}
void CDPCMChan::queueSample() {
    if (mRetriggerPeriod == 0) {
        // Not retriggering, reset mRetriggerCtr.
        mRetriggerCtr = 0;
    } else {
        // mRetriggerCtr gets decremented this frame, and reaches 0 in mRetriggerPeriod frames.
        mRetriggerCtr = mRetriggerPeriod + 1;
    }
}