Program Listing for File MUSIC_CTR.cpp

Return to documentation for file (include\audioRender\MixMachine\MUSIC_CTR\MUSIC_CTR.cpp)

#include "MUSIC_CTR.hpp"
#include "PDJE_LOG_SETTER.hpp"

MUSIC_CTR::MUSIC_CTR()
{
    st.emplace();
    st->setChannels(CHANNEL);
    st->setSampleRate(SAMPLERATE);
    st->setSetting(0, 1);
    st->setSetting(2, 0);
    st->setTempo(1.0);
    D.emplace();
}

bool
MUSIC_CTR::SendData(soundtouch::SoundTouch *&stp, Decoder *&dp)
{
    if (st.has_value() && D.has_value()) {
        stp = &(st.value());
        dp  = &(D.value());
        return true;
    } else {
        critlog("failed to give soundtouch & decoder object from MUSIC_CTR "
                "SendData.");
        return false;
    }
}

void
MUSIC_CTR::ChangeBpm(double targetbpm, double originBpm)
{
    st->setTempo(targetbpm / originBpm);
}

bool
MUSIC_CTR::checkUsable()
{
    // if(!PausePos.has_value() && FullPos.has_value()){
    //     PausePos = FullPos.value();
    // }
    bool Usable = D.has_value() && songPath.has_value();

    if (!Usable) {
        critlog("usable check failed. Decoder or songpath not valid from "
                "MUSIC_CTR checkUsable.");
    }
    return Usable;
}

bool
MUSIC_CTR::TimeStretch(const FRAME_POS Frame, float *&masterPTR)
{

    const FRAME_POS Sola = Frame / st->getInputOutputSampleRatio();
    if (!D->getRange(Sola, timeStretchBuffer)) {
        critlog("failed to get musicdata from decoder. From MUSIC_CTR "
                "timeStretch.");
        return false;
    }
    st->putSamples(timeStretchBuffer.data(), Sola);
    st->receiveSamples(masterPTR, Frame);
    masterPTR += (Frame * CHANNEL);
    return true;
}

bool
MUSIC_CTR::Render(const double     targetBpm,
                  const double     originBpm,
                  const LOCAL_POS  LocalIDX,
                  const GLOBAL_POS RenderAmount,
                  float          *&masterPTR)
{
    D->changePos(LocalIDX);
    ChangeBpm(targetBpm, originBpm);
    FRAME_POS ItrTimes   = RenderAmount / BPM_WINDOWS_SIZE;
    FRAME_POS remainLast = RenderAmount % BPM_WINDOWS_SIZE;
    for (auto j = 0; j < ItrTimes - 1; ++j) {
        if (!TimeStretch(BPM_WINDOWS_SIZE, masterPTR)) {
            critlog("failed to Timestretch. From MUSIC_CTR Render");
            return false;
        }
    }
    if (!TimeStretch(BPM_WINDOWS_SIZE + remainLast, masterPTR)) {
        critlog("failed to Timestretch. From MUSIC_CTR Render");
        return false;
    }
    return true;
}

std::optional<SIMD_FLOAT *>
MUSIC_CTR::Execute(const BPM &bpms, SIMD_FLOAT *PCMS, litedb &db)
{
    if (!checkUsable()) {
        critlog("failed to execute because usable check failed. From MUSIC_CTR "
                "Execute");
        return std::nullopt;
    }
    if (!D->init(db, songPath.value())) {
        critlog("failed to execute because Decoder init failed. From MUSIC_CTR "
                "Execute");
        return std::nullopt;
    }
    QDatas.Ready(bpms.bpmVec, Mus.bpms);

    GLOBAL_POS RfullFrameSize =
        QDatas.pos.back().Gidx - QDatas.pos.front().Gidx;

    PCMS->resize(RfullFrameSize * CHANNEL);
    auto masterPTR = PCMS->data();
    for (unsigned int i = 0; i < QDatas.pos.size() - 1; ++i) {
        if (QDatas.pos[i].status == PLAY) {
            GLOBAL_POS range = QDatas.pos[i + 1].Gidx - QDatas.pos[i].Gidx;
            Render(QDatas.pos[i].TargetBPM,
                   QDatas.pos[i].OriginBPM,
                   QDatas.pos[i].Lidx,
                   range,
                   masterPTR);
        }
    }

    return PCMS;
}
bool
MUSIC_CTR::setLOAD(MBData::Reader &RP, litedb &db, FRAME_POS FrameIn)
{
    musdata md;
    md.title    = RP.getFirst();
    md.composer = RP.getSecond();
    md.bpm      = std::stod(RP.getThird().cStr());

    auto searchRes = db << md;
    if (!searchRes.has_value()) {
        critlog("search music failed. From MUSIC_CTR setLOAD. ErrTitle: ");
        critlog(md.title);
        return false;
    }
    if (searchRes->empty()) {
        critlog(
            "cannot find music from DB. From MUSIC_CTR setLOAD. ErrTitle: ");
        critlog(md.title);
        return false;
    }
    songPath = searchRes.value()[0].musicPath;
    PlayPosition startpos;
    startpos.Gidx = FrameIn;

    try {
        startpos.Lidx = std::stoull(searchRes.value()[0].firstBeat);
    } catch (std::exception &e) {
        critlog("failed to convert string to unsigned longlong. From MUSIC_CTR "
                "setLOAD. ErrTitle: ");
        critlog(md.title);
        return false;
    }
    startpos.status = MIXSTATE::PLAY;
    QDatas.pos.push_back(startpos);

    if (!capnpMus.open(searchRes.value()[0].bpmBinary)) {
        critlog(
            "failed to open capnpBinary. From MUSIC_CTR setLOAD. ErrTitle: ");
        critlog(md.title);
        return false;
    }
    if (!Mus.Read(capnpMus, startpos.Lidx)) {
        critlog(
            "failed to Read CapnpReader. From MUSIC_CTR setLOAD. ErrTitle: ");
        critlog(md.title);
        return false;
    }
    return true;
}