aboutsummaryrefslogtreecommitdiffstats
path: root/alc/backends/base.cpp
blob: 78b9196eb101f913552422118e7bb0134168d6bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

#include "config.h"

#include "base.h"

#include <atomic>
#include <thread>

#include "AL/al.h"

#include "alcmain.h"
#include "alnumeric.h"
#include "atomic.h"


ClockLatency GetClockLatency(ALCdevice *device)
{
    BackendBase *backend{device->Backend.get()};
    ClockLatency ret{backend->getClockLatency()};
    ret.Latency += device->FixedLatency;
    return ret;
}


/* BackendBase method implementations. */
BackendBase::BackendBase(ALCdevice *device) noexcept : mDevice{device}
{ }

BackendBase::~BackendBase() = default;

ALCboolean BackendBase::reset()
{ return ALC_FALSE; }

ALCenum BackendBase::captureSamples(void*, ALCuint)
{ return ALC_INVALID_DEVICE; }

ALCuint BackendBase::availableSamples()
{ return 0; }

ClockLatency BackendBase::getClockLatency()
{
    ClockLatency ret;

    ALuint refcount;
    do {
        while(((refcount=mDevice->MixCount.load(std::memory_order_acquire))&1))
            std::this_thread::yield();
        ret.ClockTime = GetDeviceClockTime(mDevice);
        std::atomic_thread_fence(std::memory_order_acquire);
    } while(refcount != mDevice->MixCount.load(std::memory_order_relaxed));

    /* NOTE: The device will generally have about all but one periods filled at
     * any given time during playback. Without a more accurate measurement from
     * the output, this is an okay approximation.
     */
    ret.Latency  = std::chrono::seconds{maxi(mDevice->BufferSize-mDevice->UpdateSize, 0)};
    ret.Latency /= mDevice->Frequency;

    return ret;
}