2 #include <ossia/audio/audio_parameter.hpp>
3 #include <ossia/audio/drwav_handle.hpp>
4 #include <ossia/dataflow/audio_stretch_mode.hpp>
5 #include <ossia/dataflow/graph_node.hpp>
6 #include <ossia/dataflow/nodes/media.hpp>
7 #include <ossia/dataflow/nodes/sound.hpp>
8 #include <ossia/dataflow/port.hpp>
9 #include <ossia/detail/pod_vector.hpp>
11 #include <type_traits>
13 namespace ossia::nodes
16 class sound_mmap final :
public ossia::sound_node
19 sound_mmap() { m_outlets.push_back(&audio_out); }
21 ~sound_mmap() =
default;
23 void set_start(std::size_t v) { start = v; }
25 void set_upmix(std::size_t v) { upmix = v; }
27 void set_sound(drwav_handle hdl)
30 m_handle = std::move(hdl);
33 switch(m_handle.translatedFormatTag())
35 case DR_WAVE_FORMAT_PCM: {
36 switch(m_handle.bitsPerSample())
39 m_converter = read_u8;
42 m_converter = read_s16;
45 m_converter = read_s24;
48 m_converter = read_s32;
53 case DR_WAVE_FORMAT_IEEE_FLOAT: {
54 switch(m_handle.bitsPerSample())
57 m_converter = read_f32;
60 m_converter = read_f64;
66 m_converter =
nullptr;
72 void transport(time_value date)
override
74 m_resampler.transport(to_sample(date, m_handle.sampleRate()));
78 int64_t start, int64_t samples_to_write,
double** audio_array_base) noexcept
80 const int channels = this->channels();
81 const int file_duration = this->duration();
83 m_resampleBuffer.resize(channels);
84 for(
auto& buf : m_resampleBuffer)
85 buf.resize(samples_to_write);
87 float** audio_array = (
float**)alloca(
sizeof(
float*) * channels);
88 for(
int i = 0; i < channels; i++)
90 m_resampleBuffer[i].resize(samples_to_write);
91 audio_array[i] = m_resampleBuffer[i].data();
94 ossia::mutable_audio_span<float> source(channels);
97 if(samples_to_write * channels > 10000)
99 m_safetyBuffer.resize(samples_to_write * channels);
100 frame_data = m_safetyBuffer.data();
106 frame_data = (
double*)alloca(
sizeof(
double) * samples_to_write * channels);
111 for(
int k = 0; k < samples_to_write; k++)
114 int pos = this->m_start_offset_samples
115 + ((start + k) % this->m_loop_duration_samples);
116 if(pos >= file_duration)
118 for(
int i = 0; i < channels; i++)
119 audio_array[i][k] = 0;
123 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
126 for(
int i = 0; i < channels; i++)
127 audio_array[i][k] = 0;
132 const auto count = this->m_handle.read_pcm_frames(
max, frame_data);
135 for(
int i = 0; i < channels; i++)
136 source[i] = tcb::span(audio_array[i] + k, count);
137 m_converter(source, frame_data, count);
141 for(
int i = 0; i < channels; i++)
142 audio_array[i][k] = 0;
148 for(
int i = 0; i < channels; i++)
150 source[i] = tcb::span(audio_array[i], samples_to_write);
153 bool ok = start + m_start_offset_samples < file_duration;
155 ok = ok && this->m_handle.seek_to_pcm_frame(start + m_start_offset_samples);
159 const auto count = this->m_handle.read_pcm_frames(samples_to_write, frame_data);
160 m_converter(source, frame_data, count);
161 for(
int i = 0; i < channels; i++)
162 for(
int k = count; k < samples_to_write; k++)
163 audio_array[i][k] = 0;
167 for(
int i = 0; i < channels; i++)
168 for(
int k = 0; k < samples_to_write; k++)
169 audio_array[i][k] = 0;
174 for(
int i = 0; i < channels; i++)
175 std::copy_n(audio_array[i], samples_to_write, audio_array_base[i]);
178 void fetch_audio(int64_t start, int64_t samples_to_write,
float** audio_array) noexcept
180 const int channels = this->channels();
181 const int file_duration = this->duration();
183 ossia::mutable_audio_span<float> source(channels);
185 double* frame_data{};
186 if(samples_to_write * channels > 10000)
188 m_safetyBuffer.resize(samples_to_write * channels);
189 frame_data = m_safetyBuffer.data();
195 frame_data = (
double*)alloca(
sizeof(
double) * samples_to_write * channels);
200 for(
int k = 0; k < samples_to_write; k++)
203 int pos = this->m_start_offset_samples
204 + ((start + k) % this->m_loop_duration_samples);
205 if(pos >= file_duration)
207 for(
int i = 0; i < channels; i++)
208 audio_array[i][k] = 0;
212 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
215 for(
int i = 0; i < channels; i++)
216 audio_array[i][k] = 0;
221 const auto count = this->m_handle.read_pcm_frames(
max, frame_data);
224 for(
int i = 0; i < channels; i++)
225 source[i] = tcb::span(audio_array[i] + k, count);
226 m_converter(source, frame_data, count);
230 for(
int i = 0; i < channels; i++)
231 audio_array[i][k] = 0;
237 for(
int i = 0; i < channels; i++)
239 source[i] = tcb::span(audio_array[i], samples_to_write);
242 const bool ok = this->m_handle.seek_to_pcm_frame(start + m_start_offset_samples);
245 for(
int i = 0; i < channels; i++)
246 for(
int k = 0; k < samples_to_write; k++)
247 audio_array[i][k] = 0;
251 const auto count = this->m_handle.read_pcm_frames(samples_to_write, frame_data);
252 m_converter(source, frame_data, count);
253 for(
int i = 0; i < channels; i++)
254 for(
int k = count; k < samples_to_write; k++)
255 audio_array[i][k] = 0;
259 void run(
const ossia::token_request& t, ossia::exec_state_facade e) noexcept
override
261 if(!m_handle || !m_converter)
268 const auto channels = m_handle.channels();
269 const auto len = m_handle.totalPCMFrameCount();
271 ossia::audio_port& ap = *audio_out;
272 ap.set_channels(
std::max((std::size_t)upmix, (std::size_t)channels));
274 const auto [samples_to_read, samples_to_write]
275 = snd::sample_info(e.bufferSize(), e.modelToSamples(), t);
276 if(samples_to_write <= 0)
279 assert(samples_to_write > 0);
281 const auto samples_offset = t.physical_start(e.modelToSamples());
284 if(t.prev_date < m_prev_date)
289 if(t.prev_date != 0_tv)
291 transport(t.prev_date);
301 transport(t.prev_date);
305 for(std::size_t chan = 0; chan < channels; chan++)
307 ap.channel(chan).resize(e.bufferSize());
310 double stretch_ratio = update_stretch(t, e);
314 *
this, t, e, stretch_ratio, channels, len, samples_to_read, samples_to_write,
317 for(std::size_t chan = 0; chan < channels; chan++)
321 t.start_discontinuous, t.end_discontinuous, ap.channel(chan), samples_offset,
325 ossia::snd::perform_upmix(this->upmix, channels, ap);
326 ossia::snd::perform_start_offset(this->start, ap);
328 m_prev_date = t.date;
336 [[nodiscard]] std::size_t channels()
const
338 return m_handle ? m_handle.channels() : 0;
340 [[nodiscard]] std::size_t duration()
const
342 return m_handle ? m_handle.totalPCMFrameCount() : 0;
346 drwav_handle m_handle{};
348 ossia::audio_outlet audio_out;
354 = void (*)(ossia::mutable_audio_span<float>& ap,
void* data, int64_t samples);
355 read_fn_t m_converter{};
356 std::vector<double> m_safetyBuffer;
357 std::vector<std::vector<float>> m_resampleBuffer;
constexpr OSSIA_INLINE auto max(const T a, const U b) noexcept -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U >::type
max function tailored for values
Definition: math.hpp:96
The time_value class.
Definition: ossia/editor/scenario/time_value.hpp:28