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>
16class sound_mmap final :
public ossia::sound_node
19 sound_mmap() { m_outlets.push_back(&audio_out); }
21 ~sound_mmap() =
default;
23 std::string label() const noexcept
override {
return "sound_mmap"; }
25 void set_start(std::size_t v) { start = v; }
27 void set_upmix(std::size_t v) { upmix = v; }
29 void set_sound(drwav_handle hdl)
32 m_handle = std::move(hdl);
35 switch(m_handle.translatedFormatTag())
37 case DR_WAVE_FORMAT_PCM: {
38 switch(m_handle.bitsPerSample())
41 m_converter = read_u8;
44 m_converter = read_s16;
47 m_converter = read_s24;
50 m_converter = read_s32;
55 case DR_WAVE_FORMAT_IEEE_FLOAT: {
56 switch(m_handle.bitsPerSample())
59 m_converter = read_f32;
62 m_converter = read_f64;
68 m_converter =
nullptr;
74 void transport(time_value date)
override
77 m_resampler.transport(to_sample(date, m_handle.sampleRate()));
81 int64_t start, int64_t samples_to_write,
double** audio_array_base)
noexcept
83 const int channels = this->channels();
84 const int file_duration = this->duration();
86 m_resampleBuffer.resize(channels);
87 for(
auto& buf : m_resampleBuffer)
88 buf.resize(samples_to_write);
90 float** audio_array = (
float**)alloca(
sizeof(
float*) * channels);
91 for(
int i = 0; i < channels; i++)
93 m_resampleBuffer[i].resize(samples_to_write);
94 audio_array[i] = m_resampleBuffer[i].data();
97 ossia::mutable_audio_span<float> source(channels);
100 if(samples_to_write * channels > 10000)
102 m_safetyBuffer.resize(samples_to_write * channels);
103 frame_data = m_safetyBuffer.data();
109 frame_data = (
double*)alloca(
sizeof(
double) * samples_to_write * channels);
114 for(
int k = 0; k < samples_to_write; k++)
117 int pos = this->m_start_offset_samples
118 + ((start + k) % this->m_loop_duration_samples);
119 if(pos >= file_duration)
121 for(
int i = 0; i < channels; i++)
122 audio_array[i][k] = 0;
126 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
129 for(
int i = 0; i < channels; i++)
130 audio_array[i][k] = 0;
135 const auto count = this->m_handle.read_pcm_frames(
max, frame_data);
138 for(
int i = 0; i < channels; i++)
139 source[i] = std::span(audio_array[i] + k, count);
140 m_converter(source, frame_data, count);
144 for(
int i = 0; i < channels; i++)
145 audio_array[i][k] = 0;
151 for(
int i = 0; i < channels; i++)
153 source[i] = std::span(audio_array[i], samples_to_write);
156 bool ok = start + m_start_offset_samples < file_duration;
158 ok = ok && this->m_handle.seek_to_pcm_frame(start + m_start_offset_samples);
162 const auto count = this->m_handle.read_pcm_frames(samples_to_write, frame_data);
163 m_converter(source, frame_data, count);
164 for(
int i = 0; i < channels; i++)
165 for(
int k = count; k < samples_to_write; k++)
166 audio_array[i][k] = 0;
170 for(
int i = 0; i < channels; i++)
171 for(
int k = 0; k < samples_to_write; k++)
172 audio_array[i][k] = 0;
177 for(
int i = 0; i < channels; i++)
178 std::copy_n(audio_array[i], samples_to_write, audio_array_base[i]);
181 void fetch_audio(int64_t start, int64_t samples_to_write,
float** audio_array)
noexcept
183 const int channels = this->channels();
184 const int file_duration = this->duration();
186 ossia::mutable_audio_span<float> source(channels);
188 double* frame_data{};
189 if(samples_to_write * channels > 10000)
191 m_safetyBuffer.resize(samples_to_write * channels);
192 frame_data = m_safetyBuffer.data();
198 frame_data = (
double*)alloca(
sizeof(
double) * samples_to_write * channels);
203 for(
int k = 0; k < samples_to_write; k++)
206 int pos = this->m_start_offset_samples
207 + ((start + k) % this->m_loop_duration_samples);
208 if(pos >= file_duration)
210 for(
int i = 0; i < channels; i++)
211 audio_array[i][k] = 0;
215 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
218 for(
int i = 0; i < channels; i++)
219 audio_array[i][k] = 0;
224 const auto count = this->m_handle.read_pcm_frames(
max, frame_data);
227 for(
int i = 0; i < channels; i++)
228 source[i] = std::span(audio_array[i] + k, count);
229 m_converter(source, frame_data, count);
233 for(
int i = 0; i < channels; i++)
234 audio_array[i][k] = 0;
240 for(
int i = 0; i < channels; i++)
242 source[i] = std::span(audio_array[i], samples_to_write);
245 const bool ok = this->m_handle.seek_to_pcm_frame(start + m_start_offset_samples);
248 for(
int i = 0; i < channels; i++)
249 for(
int k = 0; k < samples_to_write; k++)
250 audio_array[i][k] = 0;
254 const auto count = this->m_handle.read_pcm_frames(samples_to_write, frame_data);
255 m_converter(source, frame_data, count);
256 for(
int i = 0; i < channels; i++)
257 for(
int k = count; k < samples_to_write; k++)
258 audio_array[i][k] = 0;
263 void fetch_audio_backward(
264 int64_t start, int64_t samples_to_write,
double** audio_array_base)
noexcept
266 const int channels = this->channels();
267 const int file_duration = this->duration();
269 m_resampleBuffer.resize(channels);
270 for(
auto& buf : m_resampleBuffer)
271 buf.resize(samples_to_write);
273 float** audio_array = (
float**)alloca(
sizeof(
float*) * channels);
274 for(
int i = 0; i < channels; i++)
276 m_resampleBuffer[i].resize(samples_to_write);
277 audio_array[i] = m_resampleBuffer[i].data();
280 ossia::mutable_audio_span<float> source(channels);
282 double* frame_data{};
283 if(samples_to_write * channels > 10000)
285 m_safetyBuffer.resize(samples_to_write * channels);
286 frame_data = m_safetyBuffer.data();
290 frame_data = (
double*)alloca(
sizeof(
double) * samples_to_write * channels);
293 if(m_loops && m_loop_duration_samples > 0)
296 for(
int k = 0; k < samples_to_write; k++)
298 int64_t raw_pos = start - k;
300 = ((raw_pos % m_loop_duration_samples) + m_loop_duration_samples)
301 % m_loop_duration_samples;
302 int64_t pos = m_start_offset_samples + wrapped_pos;
304 if(pos < 0 || pos >= file_duration)
306 for(
int i = 0; i < channels; i++)
307 audio_array[i][k] = 0;
311 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
314 for(
int i = 0; i < channels; i++)
315 audio_array[i][k] = 0;
319 const auto count = this->m_handle.read_pcm_frames(1, frame_data);
322 for(
int i = 0; i < channels; i++)
323 source[i] = std::span(audio_array[i] + k, count);
324 m_converter(source, frame_data, count);
328 for(
int i = 0; i < channels; i++)
329 audio_array[i][k] = 0;
336 for(
int k = 0; k < samples_to_write; k++)
338 int64_t pos = m_start_offset_samples + start - k;
340 if(pos < 0 || pos >= file_duration)
342 for(
int i = 0; i < channels; i++)
343 audio_array[i][k] = 0;
347 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
350 for(
int i = 0; i < channels; i++)
351 audio_array[i][k] = 0;
355 const auto count = this->m_handle.read_pcm_frames(1, frame_data);
358 for(
int i = 0; i < channels; i++)
359 source[i] = std::span(audio_array[i] + k, count);
360 m_converter(source, frame_data, count);
364 for(
int i = 0; i < channels; i++)
365 audio_array[i][k] = 0;
370 for(
int i = 0; i < channels; i++)
371 std::copy_n(audio_array[i], samples_to_write, audio_array_base[i]);
375 fetch_audio_backward(int64_t start, int64_t samples_to_write,
float** audio_array)
noexcept
377 const int channels = this->channels();
378 const int file_duration = this->duration();
380 ossia::mutable_audio_span<float> source(channels);
382 double* frame_data{};
383 if(samples_to_write * channels > 10000)
385 m_safetyBuffer.resize(samples_to_write * channels);
386 frame_data = m_safetyBuffer.data();
390 frame_data = (
double*)alloca(
sizeof(
double) * samples_to_write * channels);
393 if(m_loops && m_loop_duration_samples > 0)
396 for(
int k = 0; k < samples_to_write; k++)
398 int64_t raw_pos = start - k;
400 = ((raw_pos % m_loop_duration_samples) + m_loop_duration_samples)
401 % m_loop_duration_samples;
402 int64_t pos = m_start_offset_samples + wrapped_pos;
404 if(pos < 0 || pos >= file_duration)
406 for(
int i = 0; i < channels; i++)
407 audio_array[i][k] = 0;
411 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
414 for(
int i = 0; i < channels; i++)
415 audio_array[i][k] = 0;
419 const auto count = this->m_handle.read_pcm_frames(1, frame_data);
422 for(
int i = 0; i < channels; i++)
423 source[i] = std::span(audio_array[i] + k, count);
424 m_converter(source, frame_data, count);
428 for(
int i = 0; i < channels; i++)
429 audio_array[i][k] = 0;
436 for(
int k = 0; k < samples_to_write; k++)
438 int64_t pos = m_start_offset_samples + start - k;
440 if(pos < 0 || pos >= file_duration)
442 for(
int i = 0; i < channels; i++)
443 audio_array[i][k] = 0;
447 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
450 for(
int i = 0; i < channels; i++)
451 audio_array[i][k] = 0;
455 const auto count = this->m_handle.read_pcm_frames(1, frame_data);
458 for(
int i = 0; i < channels; i++)
459 source[i] = std::span(audio_array[i] + k, count);
460 m_converter(source, frame_data, count);
464 for(
int i = 0; i < channels; i++)
465 audio_array[i][k] = 0;
471 void run(
const ossia::token_request& t, ossia::exec_state_facade e)
noexcept override
473 if(!m_handle || !m_converter)
476 const auto channels = m_handle.channels();
477 const auto len = m_handle.totalPCMFrameCount();
479 ossia::audio_port& ap = *audio_out;
480 ap.set_channels(std::max((std::size_t)upmix, (std::size_t)channels));
482 const auto [samples_to_read, samples_to_write]
483 = snd::sample_info(e.bufferSize(), e.modelToSamples(), t);
484 if(samples_to_write <= 0)
487 assert(samples_to_write > 0);
489 const auto samples_offset = t.physical_start(e.modelToSamples());
494 if(t.prev_date < m_prev_date)
499 if(t.prev_date != 0_tv)
501 transport(t.prev_date);
511 transport(t.prev_date);
518 if(t.prev_date > m_prev_date)
523 transport(t.prev_date);
527 transport(t.prev_date);
532 for(std::size_t chan = 0; chan < channels; chan++)
534 ap.channel(chan).resize(e.bufferSize());
537 const double stretch_ratio = update_stretch(t, e);
538 const double abs_stretch_ratio = std::abs(stretch_ratio);
542 *
this, t, e, stretch_ratio, channels, len, samples_to_read, samples_to_write,
545 const bool start_discontinuous = t.start_discontinuous || (m_last_stretch > 70.);
546 const bool end_discontinuous = t.end_discontinuous || (abs_stretch_ratio > 70.);
547 if(abs_stretch_ratio > 70. && m_last_stretch > 70.)
550 for(std::size_t i = 0; i < channels; i++)
552 ossia::snd::do_zero(ap.channel(i), samples_offset, samples_to_write);
558 for(std::size_t chan = 0; chan < channels; chan++)
562 start_discontinuous, end_discontinuous, ap.channel(chan), samples_offset,
567 ossia::snd::perform_upmix(this->upmix, channels, ap);
568 ossia::snd::perform_start_offset(this->start, ap);
570 m_prev_date = t.date;
571 m_last_stretch = abs_stretch_ratio;
574 [[nodiscard]] std::size_t channels()
const
576 return m_handle ? m_handle.channels() : 0;
578 [[nodiscard]] std::size_t duration()
const
580 return m_handle ? m_handle.totalPCMFrameCount() : 0;
584 drwav_handle m_handle{};
586 ossia::audio_outlet audio_out;
592 = void (*)(ossia::mutable_audio_span<float>& ap,
void* data, int64_t samples);
593 read_fn_t m_converter{};
594 std::vector<double> m_safetyBuffer;
595 std::vector<std::vector<float>> m_resampleBuffer;
OSSIA_INLINE constexpr 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:30