~aleteoryx/muditaos

ref: 00fd29f8bd867f09f7d34b032e3dab5067ccc539 muditaos/module-audio/board/linux/LinuxAudioDevice.cpp -rw-r--r-- 3.4 KiB
00fd29f8 — Marcin Zieliński [MOS-477] Add the call log erasing option 3 years ago
                                                                                
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "LinuxAudioDevice.hpp"
#include <Audio/Stream.hpp>
#include <log/log.hpp>
#include <cmath>

namespace audio
{
    LinuxAudioDevice::LinuxAudioDevice(const float initialVolume)
        : supportedFormats(
              audio::AudioFormat::makeMatrix(supportedSampleRates, supportedBitWidths, supportedChannelModes)),
          audioProxy("audioProxy", [this](const auto &data) {
              requestedBytes = data;
              onDataSend();
          })
    {
        setOutputVolume(initialVolume);
    }

    auto LinuxAudioDevice::Start() -> RetCode
    {
        if (!isSinkConnected()) {
            return AudioDevice::RetCode::Failure;
        }
        return AudioDevice::RetCode::Success;
    }

    auto LinuxAudioDevice::Stop() -> RetCode
    {
        return AudioDevice::RetCode::Success;
    }

    auto LinuxAudioDevice::setOutputVolume(float vol) -> RetCode
    {
        vol = std::clamp(vol, minVolume, maxVolume);
        /// Using y=x^4 function as an approximation seems very natural and sufficient
        /// For more info check: https://www.dr-lex.be/info-stuff/volumecontrols.html
        volumeFactor = std::pow(1.0f * (vol / maxVolume), 4);
        return RetCode::Success;
    }

    auto LinuxAudioDevice::setInputGain([[maybe_unused]] float gain) -> RetCode
    {
        return RetCode::Success;
    }

    auto LinuxAudioDevice::getTraits() const -> Traits
    {
        return Traits{};
    }

    auto LinuxAudioDevice::getSupportedFormats() -> std::vector<audio::AudioFormat>
    {
        return supportedFormats;
    }

    auto LinuxAudioDevice::getSourceFormat() -> audio::AudioFormat
    {
        return currentFormat;
    }

    void LinuxAudioDevice::onDataSend()
    {
        audio::Stream::Span dataSpan;
        if (!isSinkConnected()) {
            return;
        }
        Sink::_stream->peek(dataSpan);
        scaleVolume(dataSpan);
        pulseAudioWrapper->insert(dataSpan);
        Sink::_stream->consume();

        if (pulseAudioWrapper->bytes() >= requestedBytes) {
            pulseAudioWrapper->consume();
        }
        else {
            audioProxy.post(requestedBytes);
        }
    }

    void LinuxAudioDevice::onDataReceive()
    {}

    void LinuxAudioDevice::enableInput()
    {}

    void LinuxAudioDevice::enableOutput()
    {
        if (!isSinkConnected()) {
            LOG_ERROR("Output stream is not connected!");
            return;
        }

        currentFormat = Sink::_stream->getOutputTraits().format;

        pulseAudioWrapper = std::make_unique<PulseAudioWrapper>(
            [this](const std::size_t size) { audioProxy.post(size); }, currentFormat);
    }

    void LinuxAudioDevice::disableInput()
    {}

    void LinuxAudioDevice::disableOutput()
    {
        if (!isSinkConnected()) {
            LOG_ERROR("Error while stopping Linux Audio Device! Null stream.");
            return;
        }
        close         = true;
        currentFormat = {};
    }
    void LinuxAudioDevice::scaleVolume(audio::AbstractStream::Span data)
    {
        const auto samplesBeg = reinterpret_cast<std::int16_t *>(data.data);
        const auto samplesEnd = samplesBeg + data.dataSize / 2;
        std::for_each(samplesBeg, samplesEnd, [this](auto &sample) { sample *= volumeFactor; });
    }
} // namespace audio