Loading...
Searching...
No Matches
AudioFrameEncoder.hpp
1#pragma once
2
3#include <Media/Libav.hpp>
4#if SCORE_HAS_LIBAV
5extern "C" {
6#include <libavutil/frame.h>
7}
8
9#include <ossia/dataflow/float_to_sample.hpp>
10
11#include <algorithm>
12#include <cstring>
13
14namespace Gfx
15{
16
18{
19 explicit AudioFrameEncoder(int target_buffer_size)
20 : target_buffer_size{target_buffer_size}
21 {
22 }
23
24 // We assume that vec has correct channel count here
25 // Also that vec.size() > 0
26 virtual void add_frame(AVFrame& frame, const std::span<ossia::float_vector> vec) = 0;
27 virtual ~AudioFrameEncoder() = default;
28 int target_buffer_size{};
29
30 // How many samples may be written into `frame`. Its buffers were allocated
31 // for nb_samples once, at avcodec_open2 time; `vec` carries whatever the
32 // audio engine produced this tick, which is a different number as soon as
33 // the engine's buffer size and the codec's frame size disagree.
34 static int writable(
35 const AVFrame& frame, const std::span<ossia::float_vector>& vec) noexcept
36 {
37 if(frame.nb_samples <= 0)
38 return 0;
39 return std::min(int(vec[0].size()), frame.nb_samples);
40 }
41};
42
44{
45 using AudioFrameEncoder::AudioFrameEncoder;
46
47 void add_frame(AVFrame& frame, const std::span<ossia::float_vector> vec) override
48 {
49 const int channels = vec.size();
50 const int frames = writable(frame, vec);
51 auto* ptr = reinterpret_cast<int16_t*>(frame.data[0]);
52 for(int i = 0; i < frames; i++)
53 for(int c = 0; c < channels; c++)
54 *ptr++ = ossia::float_to_sample<int16_t, 16>(vec[c][i]);
55 }
56};
57
59{
60 using AudioFrameEncoder::AudioFrameEncoder;
61
62 void add_frame(AVFrame& frame, const std::span<ossia::float_vector> vec) override
63 {
64 const int channels = vec.size();
65 const int frames = writable(frame, vec);
66 auto* ptr = reinterpret_cast<int32_t*>(frame.data[0]);
67 for(int i = 0; i < frames; i++)
68 for(int c = 0; c < channels; c++)
69 *ptr++ = ossia::float_to_sample<int32_t, 24>(vec[c][i]);
70 }
71};
72
74{
75 using AudioFrameEncoder::AudioFrameEncoder;
76
77 void add_frame(AVFrame& frame, const std::span<ossia::float_vector> vec) override
78 {
79 const int channels = vec.size();
80 const int frames = writable(frame, vec);
81 auto* ptr = reinterpret_cast<int32_t*>(frame.data[0]);
82 for(int i = 0; i < frames; i++)
83 for(int c = 0; c < channels; c++)
84 *ptr++ = ossia::float_to_sample<int32_t, 32>(vec[c][i]);
85 }
86};
87
89{
90 using AudioFrameEncoder::AudioFrameEncoder;
91
92 void add_frame(AVFrame& frame, const std::span<ossia::float_vector> vec) override
93 {
94 const int channels = vec.size();
95 const int frames = writable(frame, vec);
96 auto* ptr = reinterpret_cast<float*>(frame.data[0]);
97 for(int i = 0; i < frames; i++)
98 for(int c = 0; c < channels; c++)
99 *ptr++ = vec[c][i];
100 }
101};
102
104{
105 using AudioFrameEncoder::AudioFrameEncoder;
106
107 void add_frame(AVFrame& frame, const std::span<ossia::float_vector> vec) override
108 {
109 const int channels = vec.size();
110 const int frames = writable(frame, vec);
111 auto* ptr = reinterpret_cast<double*>(frame.data[0]);
112 for(int i = 0; i < frames; i++)
113 for(int c = 0; c < channels; c++)
114 *ptr++ = vec[c][i];
115 }
116};
117
119{
120 using AudioFrameEncoder::AudioFrameEncoder;
121
122 void add_frame(AVFrame& frame, const std::span<ossia::float_vector> vec) override
123 {
124 const int channels = vec.size();
125 const int frames = writable(frame, vec);
126 // Copy into the AVFrame's own planar buffers (allocated by av_frame_get_buffer)
127 for(int i = 0; i < channels; ++i)
128 {
129 uint8_t* dst = (i < AV_NUM_DATA_POINTERS) ? frame.data[i]
130 : frame.extended_data[i];
131 if(dst)
132 std::memcpy(dst, vec[i].data(), std::size_t(frames) * sizeof(float));
133 }
134 }
135};
136
138{
139 using AudioFrameEncoder::AudioFrameEncoder;
140
141 void add_frame(AVFrame& frame, const std::span<ossia::float_vector> vec) override
142 {
143 const int channels = vec.size();
144 const int frames = writable(frame, vec);
145 for(int i = 0; i < channels; ++i)
146 {
147 auto* dst = reinterpret_cast<int16_t*>(
148 (i < AV_NUM_DATA_POINTERS) ? frame.data[i] : frame.extended_data[i]);
149 if(dst)
150 for(int j = 0; j < frames; ++j)
151 dst[j] = ossia::float_to_sample<int16_t, 16>(vec[i][j]);
152 }
153 }
154};
155
157{
158 using AudioFrameEncoder::AudioFrameEncoder;
159
160 void add_frame(AVFrame& frame, const std::span<ossia::float_vector> vec) override
161 {
162 const int channels = vec.size();
163 const int frames = writable(frame, vec);
164 for(int i = 0; i < channels; ++i)
165 {
166 auto* dst = reinterpret_cast<int32_t*>(
167 (i < AV_NUM_DATA_POINTERS) ? frame.data[i] : frame.extended_data[i]);
168 if(dst)
169 for(int j = 0; j < frames; ++j)
170 dst[j] = ossia::float_to_sample<int32_t, 32>(vec[i][j]);
171 }
172 }
173};
174
176{
177 using AudioFrameEncoder::AudioFrameEncoder;
178
179 void add_frame(AVFrame& frame, const std::span<ossia::float_vector> vec) override
180 {
181 const int channels = vec.size();
182 const int frames = writable(frame, vec);
183 for(int i = 0; i < channels; ++i)
184 {
185 auto* dst = reinterpret_cast<double*>(
186 (i < AV_NUM_DATA_POINTERS) ? frame.data[i] : frame.extended_data[i]);
187 if(dst)
188 for(int j = 0; j < frames; ++j)
189 dst[j] = static_cast<double>(vec[i][j]);
190 }
191 }
192};
193}
194#endif
Binds the rendering pipeline to ossia processes.
Definition AssetTable.cpp:7
Definition AudioFrameEncoder.hpp:18
Definition AudioFrameEncoder.hpp:104
Definition AudioFrameEncoder.hpp:176
Definition AudioFrameEncoder.hpp:89
Definition AudioFrameEncoder.hpp:119
Definition AudioFrameEncoder.hpp:44
Definition AudioFrameEncoder.hpp:138
Definition AudioFrameEncoder.hpp:59
Definition AudioFrameEncoder.hpp:74
Definition AudioFrameEncoder.hpp:157