예제 #1
0
uint32 AudioStream::Read(short* buffer, size_t count)
{
	size_t cnt;
	size_t toRead = count; // Count is the amount of s16 samples.

	if (!mSource || !mSource->IsValid())
	{
		mIsPlaying = false;
		return 0;
	}
	
	if (PaUtil_GetRingBufferReadAvailable(&mRingBuf) < toRead || !mIsPlaying)
	{
		memset(buffer, 0, toRead);
		toRead = PaUtil_GetRingBufferReadAvailable(&mRingBuf);
	}

	if (mIsPlaying)
	{
		cnt = PaUtil_ReadRingBuffer(&mRingBuf, buffer, toRead);
		mStreamTime += (double)(cnt/Channels) / (double)mSource->GetRate();
		mPlaybackTime = mStreamTime - MixerGetLatency();
	}else
		return 0;

	return cnt ? cnt : mIsPlaying;
}
예제 #2
0
void ScreenGameplay::RenderObjects(float TimeDelta, bool drawPlayable)
{
    Vec2 mpos = WindowFrame.GetRelativeMPos();

    Cursor.SetPosition(mpos);

    Cursor.AddRotation(CursorRotospeed * TimeDelta);

    int Beat = MeasureRatio * MySong->MeasureLength;
    float Fraction = (float(MeasureRatio * MySong->MeasureLength) - Beat);
    Lifebar.SetScaleX(1.0 - 0.05 * Fraction);

    // Rendering ahead.

    if (IsPaused)
    {
        Background.Blue = Background.Red = Background.Green = 0.5;
    }
    else
        Background.Blue = Background.Red = Background.Green = 1;

    Background.Render();

    MarkerA.Render();
    MarkerB.Render();

    if (!EditMode)
        Lifebar.Render();

    if (drawPlayable)
    {
        DrawVector(NotesHeld, TimeDelta);
        DrawVector(AnimateOnly, TimeDelta);

        if (Measure > 0)
        {
            if (NotesInMeasure.size() && // there are measures and
                Measure - 1 < NotesInMeasure.size() && // the measure is within the range and
                NotesInMeasure.at(Measure - 1).size() > 0) // there are notes in this measure
            {
                DrawVector(NotesInMeasure[Measure - 1], TimeDelta);
            }
        }

        // Render current measure on front of the next!
        if (Measure + 1 < CurrentDiff->Measures.size())
        {
            if (NotesInMeasure.size() > Measure + 1 && NotesInMeasure.at(Measure + 1).size() > 0)
            {
                DrawVector(NotesInMeasure[Measure + 1], TimeDelta);
            }
        }

        if (Measure < CurrentDiff->Measures.size())
        {
            if (NotesInMeasure.size() > Measure && NotesInMeasure.at(Measure).size() > 0)
            {
                DrawVector(NotesInMeasure[Measure], TimeDelta);
            }
        }
    }

    Barline.Render();

    if (!EditMode)
        aJudgment.Render();

    // Combo rendering.
    std::stringstream str;
    str << Combo;

    float textX = GetScreenOffset(0.5).x - (str.str().length() * ComboSizeX / 2);
    MyFont.Render(str.str(), Vec2(textX, 0));

    std::stringstream str2;
    str2 << int32_t(1000000.0 * Evaluation.dpScoreSquare / (Evaluation.totalNotes * (Evaluation.totalNotes + 1)));
    textX = GetScreenOffset(0.5).x - (str2.str().length() * ComboSizeX / 2);
    MyFont.Render(str2.str(), Vec2(textX, 720));

    /* Lengthy information printing code goes here.*/
    std::stringstream info;

    if (IsAutoplaying)
        info << "Autoplay";

#ifndef NDEBUG
    info << "\nSongTime: " << SongTime << "\nPlaybackTime: ";
    if (Music)
        info << Music->GetPlayedTime();
    else
        info << "???";
    /*info << "\nStreamTime: ";
    if(Music)
        info << Music->GetStreamedTime();
    else
        info << "???";
        */

    info << "\naudioFactor: " << MixerGetFactor();
    info << "\nSongDelta: " << SongDelta;
    info << "\nDevice Latency: " << (int)(MixerGetLatency() * 1000);
    /*
    if (Music)
        info << Music->GetStreamedTime() - Music->GetPlaybackTime();
    else
        info << "???";
        */
    info << "\nScreenTime: " << GetScreenTime();
    info << "\nMeasureRatio: " << MeasureRatio;
    info << "\nMeasureRatioPerSecond: " << RatioPerSecond;
#endif
    if (TappingMode)
        info << "\nTapping mode";
    if (!FailEnabled)
        info << "\nFailing Disabled";

#ifdef NDEBUG
    if (EditMode)
#endif
        info << "\nMeasure: " << Measure;
    SongInfo.Render(info.str(), Vec2(0, 0));

    ReadySign.Render();

    Cursor.Render();
}
bool ScreenGameplay7K::ProcessSong()
{
    TimeCompensation = 0;

    double DesiredDefaultSpeed = Configuration::GetSkinConfigf("DefaultSpeedUnits");

    ESpeedType Type = (ESpeedType)(int)Configuration::GetSkinConfigf("DefaultSpeedKind");
    double SpeedConstant = 0; // Unless set, assume we're using speed changes

    int ApplyDriftVirtual = Configuration::GetConfigf("UseAudioCompensationKeysounds");
    int ApplyDriftDecoder = Configuration::GetConfigf("UseAudioCompensationNonKeysounded");

    if (AudioCompensation &&  // Apply drift is enabled and:
        ((ApplyDriftVirtual && CurrentDiff->IsVirtual) ||  // We want to apply it to a keysounded file and it's virtual
        (ApplyDriftDecoder && !CurrentDiff->IsVirtual))) // or we want to apply it to a non-keysounded file and it's not virtual
        TimeCompensation += MixerGetLatency();

    TimeCompensation += Configuration::GetConfigf("Offset7K");

    if (CurrentDiff->IsVirtual)
        TimeCompensation += Configuration::GetConfigf("OffsetKeysounded");
    else
        TimeCompensation += Configuration::GetConfigf("OffsetNonKeysounded");

    JudgeOffset = Configuration::GetConfigf("JudgeOffsetMS") / 1000;

    double Drift = TimeCompensation;

    Log::Logf("TimeCompensation: %f (Latency: %f / Offset: %f)\n", TimeCompensation, MixerGetLatency(), CurrentDiff->Offset);

    /*
 * 		There are three kinds of speed modifiers:
 * 			-CMod (Keep speed the same through the song, equal to a constant)
 * 			-MMod (Find highest speed and set multiplier to such that the highest speed is equal to a constant)
 *			-First (Find the first speed in the chart, and set multiplier to such that the first speed is equal to a constant)
 *
 *			The calculations are done ahead, and while SpeedConstant = 0 either MMod or first are assumed
 *			but only if there's a constant specified by the user.
 * */

 // What, you mean we don't have timing data at all?
    if (CurrentDiff->Timing.size() == 0)
    {
        Log::Printf("Error loading chart: No timing data.\n");
        return false;
    }

    Log::Printf("Processing song... ");

    if (DesiredDefaultSpeed)
    {
        if (Type == SPEEDTYPE_CMOD) // cmod
        {
            SpeedMultiplierUser = 1;
            SpeedConstant = DesiredDefaultSpeed;
        }

        CurrentDiff->GetPlayableData(NotesByChannel, BPS, VSpeeds, Warps, Drift, SpeedConstant);

        if (Type == SPEEDTYPE_MMOD) // mmod
        {
            double speed_max = 0; // Find the highest speed
            for (auto i = VSpeeds.begin();
            i != VSpeeds.end();
                ++i)
            {
                speed_max = std::max(speed_max, abs(i->Value));
            }

            double Ratio = DesiredDefaultSpeed / speed_max; // How much above or below are we from the maximum speed?
            SpeedMultiplierUser = Ratio;
        }
        else if (Type == SPEEDTYPE_FIRST) // We use this case as default. The logic is "Not a CMod, Not a MMod, then use first, the default.
        {
            double DesiredMultiplier = DesiredDefaultSpeed / VSpeeds[0].Value;

            SpeedMultiplierUser = DesiredMultiplier;
        }
        else if (Type != SPEEDTYPE_CMOD) // other cases
        {
            double bpsd = 4.0 / (BPS[0].Value);
            double Speed = (MeasureBaseSpacing / bpsd);
            double DesiredMultiplier = DesiredDefaultSpeed / Speed;

            SpeedMultiplierUser = DesiredMultiplier;
        }
    }
    else
        CurrentDiff->GetPlayableData(NotesByChannel, BPS, VSpeeds, Warps, Drift); // Regular processing

    if (Type != SPEEDTYPE_CMOD)
        Speeds = CurrentDiff->Data->Speeds;

    for (auto&& w : Warps)
        w.Time += Drift;
    for (auto&& s : Speeds)
        s.Time += Drift;

    // Toggle whether we can use our guarantees for optimizations or not at rendering time.
    HasNegativeScroll = false;

    for (auto S : Speeds) if (S.Value < 0) HasNegativeScroll = true;
    for (auto S : VSpeeds) if (S.Value < 0) HasNegativeScroll = true;

    if (Random) NoteTransform::Randomize(NotesByChannel, CurrentDiff->Channels, CurrentDiff->Data->Turntable);

    // Load up BGM events
    std::vector<AutoplaySound> BGMs = CurrentDiff->Data->BGMEvents;
    if (Configuration::GetConfigf("DisableKeysounds"))
        NoteTransform::MoveKeysoundsToBGM(CurrentDiff->Channels, NotesByChannel, BGMs);

    std::sort(BGMs.begin(), BGMs.end());
    for (auto &s : BGMs)
        BGMEvents.push(s);

    return true;
}