~aleteoryx/muditaos

muditaos/module-audio/Audio/Stream.hpp -rw-r--r-- 4.6 KiB
a405cad6Aleteoryx trim readme 6 days 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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/blob/master/LICENSE.md

#pragma once

#include "AbstractStream.hpp"
#include "AudioFormat.hpp"

#include <memory/NonCachedMemAllocator.hpp>
#include <CriticalSectionGuard.hpp>

#include <algorithm>
#include <cstdint>
#include <functional>
#include <list>
#include <memory>
#include <utility>

namespace audio
{
    class Stream : public AbstractStream
    {
      public:
        using UniqueStreamBuffer = std::unique_ptr<std::uint8_t[], std::function<void(uint8_t[])>>;
        using AbstractStream::Span;

        class RawBlockIterator
        {
          public:
            RawBlockIterator(std::uint8_t *bufStart, std::size_t bufSize, std::uint8_t *ptr, std::size_t stepSize);

            bool operator==(const RawBlockIterator &rhs);
            bool operator!=(const RawBlockIterator &rhs);
            RawBlockIterator &operator++();
            RawBlockIterator &operator--();
            RawBlockIterator operator++(int);
            RawBlockIterator operator--(int);
            Span operator*();

          private:
            std::uint8_t *_bufStart = nullptr;
            std::uint8_t *_bufEnd   = nullptr;
            std::uint8_t *_curPos   = nullptr;
            std::size_t _stepSize   = 0;
        };

        class Allocator
        {
          public:
            virtual UniqueStreamBuffer allocate(std::size_t size) = 0;
        };

        static constexpr auto defaultBufferingSize = 24U;

        Stream(AudioFormat format,
               Allocator &allocator,
               std::size_t blockSize,
               unsigned int bufferingSize = defaultBufferingSize);

        void registerListener(AbstractStream::EventListener *listener) override;
        void unregisterListeners(AbstractStream::EventListener *listener) override;

        /// push
        bool push(void *data, std::size_t dataSize) override;
        bool push(const Span &span) override;
        bool push() override;

        /// pop
        bool pop(Span &span) override;

        /// zero copy write
        bool reserve(Span &span) override;
        void commit() override;
        void release() override;

        /// zero copy read
        bool peek(Span &span) override;
        void consume() override;
        void unpeek() override;

        void reset() override;

        /// get empty data span
        Span getNullSpan() const noexcept;

        [[nodiscard]] auto getInputTraits() const noexcept -> Traits override;
        [[nodiscard]] auto getOutputTraits() const noexcept -> Traits override;
        [[nodiscard]] bool isEmpty() const noexcept override;
        [[nodiscard]] bool isFull() const noexcept override;

        [[nodiscard]] std::size_t getBlockCount() const noexcept;
        [[nodiscard]] std::size_t getUsedBlockCount() const noexcept;
        [[nodiscard]] std::size_t getPeekedCount() const noexcept;
        [[nodiscard]] std::size_t getReservedCount() const noexcept;
        [[nodiscard]] bool blocksAvailable() const noexcept;

      private:
        using LockGuard = cpp_freertos::CriticalSectionGuard;

        void broadcastEvent(Event event);
        void broadcastStateEvents();
        auto getIOTraits() const noexcept -> Traits;

        Allocator &_allocator;
        std::size_t _blockSize    = 0;
        std::size_t _blockCount   = 0;
        std::size_t _blocksUsed   = 0;
        std::size_t _peekCount    = 0;
        std::size_t _reserveCount = 0;
        AudioFormat _format       = nullFormat;
        UniqueStreamBuffer _buffer;
        UniqueStreamBuffer _emptyBuffer;
        std::list<AbstractStream::EventListener *> listeners;

        RawBlockIterator _dataStart;
        RawBlockIterator _dataEnd;
        RawBlockIterator _peekPosition;
        RawBlockIterator _writeReservationPosition;
    };

    class StandardStreamAllocator : public Stream::Allocator
    {
      public:
        Stream::UniqueStreamBuffer allocate(std::size_t size);
    };

    class NonCacheableStreamAllocator : public Stream::Allocator
    {
      public:
        NonCacheableStreamAllocator() = default;
        Stream::UniqueStreamBuffer allocate(std::size_t size);

      private:
        NonCachedMemAllocator<uint8_t> allocator;
    };

} // namespace audio

namespace std
{
    template <>
    struct iterator_traits<audio::Stream::RawBlockIterator>
    {
        using iterator_category = std::forward_iterator_tag;
        using value_type        = audio::Stream::Span;
        using difference_type   = std::size_t;
        using pointer           = audio::Stream::Span *;
        using reference         = audio::Stream::Span &;
    };
}; // namespace std