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
79 m_resampler.transport(
80 file_sample_for_model_time(date, 0., m_handle.sampleRate()));
83 void transport(time_value date,
const ossia::tick_transport_info& tinfo)
override
86 m_resampler.transport(file_sample_for_model_time(
87 date, tinfo.current_tempo, m_handle.sampleRate()));
91 int64_t start, int64_t samples_to_write,
double** audio_array_base)
noexcept
93 const int channels = this->channels();
94 const int file_duration = this->duration();
96 m_resampleBuffer.resize(channels);
97 for(
auto& buf : m_resampleBuffer)
98 buf.resize(samples_to_write);
100 float** audio_array = (
float**)alloca(
sizeof(
float*) * channels);
101 for(
int i = 0; i < channels; i++)
103 m_resampleBuffer[i].resize(samples_to_write);
104 audio_array[i] = m_resampleBuffer[i].data();
107 ossia::mutable_audio_span<float> source(channels);
109 double* frame_data{};
110 if(samples_to_write * channels > 10000)
112 m_safetyBuffer.resize(samples_to_write * channels);
113 frame_data = m_safetyBuffer.data();
119 frame_data = (
double*)alloca(
sizeof(
double) * samples_to_write * channels);
124 for(
int k = 0; k < samples_to_write; k++)
127 int pos = this->m_start_offset_samples
128 + ((start + k) % this->m_loop_duration_samples);
129 if(pos >= file_duration)
131 for(
int i = 0; i < channels; i++)
132 audio_array[i][k] = 0;
136 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
139 for(
int i = 0; i < channels; i++)
140 audio_array[i][k] = 0;
145 const auto count = this->m_handle.read_pcm_frames(
max, frame_data);
148 for(
int i = 0; i < channels; i++)
149 source[i] = std::span(audio_array[i] + k, count);
150 m_converter(source, frame_data, count);
154 for(
int i = 0; i < channels; i++)
155 audio_array[i][k] = 0;
161 for(
int i = 0; i < channels; i++)
163 source[i] = std::span(audio_array[i], samples_to_write);
166 bool ok = start + m_start_offset_samples < file_duration;
168 ok = ok && this->m_handle.seek_to_pcm_frame(start + m_start_offset_samples);
172 const auto count = this->m_handle.read_pcm_frames(samples_to_write, frame_data);
173 m_converter(source, frame_data, count);
174 for(
int i = 0; i < channels; i++)
175 for(
int k = count; k < samples_to_write; k++)
176 audio_array[i][k] = 0;
180 for(
int i = 0; i < channels; i++)
181 for(
int k = 0; k < samples_to_write; k++)
182 audio_array[i][k] = 0;
187 for(
int i = 0; i < channels; i++)
188 std::copy_n(audio_array[i], samples_to_write, audio_array_base[i]);
191 void fetch_audio(int64_t start, int64_t samples_to_write,
float** audio_array)
noexcept
193 const int channels = this->channels();
194 const int file_duration = this->duration();
196 ossia::mutable_audio_span<float> source(channels);
198 double* frame_data{};
199 if(samples_to_write * channels > 10000)
201 m_safetyBuffer.resize(samples_to_write * channels);
202 frame_data = m_safetyBuffer.data();
208 frame_data = (
double*)alloca(
sizeof(
double) * samples_to_write * channels);
213 for(
int k = 0; k < samples_to_write; k++)
216 int pos = this->m_start_offset_samples
217 + ((start + k) % this->m_loop_duration_samples);
218 if(pos >= file_duration)
220 for(
int i = 0; i < channels; i++)
221 audio_array[i][k] = 0;
225 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
228 for(
int i = 0; i < channels; i++)
229 audio_array[i][k] = 0;
234 const auto count = this->m_handle.read_pcm_frames(
max, frame_data);
237 for(
int i = 0; i < channels; i++)
238 source[i] = std::span(audio_array[i] + k, count);
239 m_converter(source, frame_data, count);
243 for(
int i = 0; i < channels; i++)
244 audio_array[i][k] = 0;
250 for(
int i = 0; i < channels; i++)
252 source[i] = std::span(audio_array[i], samples_to_write);
255 const bool ok = this->m_handle.seek_to_pcm_frame(start + m_start_offset_samples);
258 for(
int i = 0; i < channels; i++)
259 for(
int k = 0; k < samples_to_write; k++)
260 audio_array[i][k] = 0;
264 const auto count = this->m_handle.read_pcm_frames(samples_to_write, frame_data);
265 m_converter(source, frame_data, count);
266 for(
int i = 0; i < channels; i++)
267 for(
int k = count; k < samples_to_write; k++)
268 audio_array[i][k] = 0;
273 void fetch_audio_backward(
274 int64_t start, int64_t samples_to_write,
double** audio_array_base)
noexcept
276 const int channels = this->channels();
277 const int file_duration = this->duration();
279 m_resampleBuffer.resize(channels);
280 for(
auto& buf : m_resampleBuffer)
281 buf.resize(samples_to_write);
283 float** audio_array = (
float**)alloca(
sizeof(
float*) * channels);
284 for(
int i = 0; i < channels; i++)
286 m_resampleBuffer[i].resize(samples_to_write);
287 audio_array[i] = m_resampleBuffer[i].data();
290 ossia::mutable_audio_span<float> source(channels);
292 double* frame_data{};
293 if(samples_to_write * channels > 10000)
295 m_safetyBuffer.resize(samples_to_write * channels);
296 frame_data = m_safetyBuffer.data();
300 frame_data = (
double*)alloca(
sizeof(
double) * samples_to_write * channels);
303 if(m_loops && m_loop_duration_samples > 0)
306 for(
int k = 0; k < samples_to_write; k++)
308 int64_t raw_pos = start - k;
310 = ((raw_pos % m_loop_duration_samples) + m_loop_duration_samples)
311 % m_loop_duration_samples;
312 int64_t pos = m_start_offset_samples + wrapped_pos;
314 if(pos < 0 || pos >= file_duration)
316 for(
int i = 0; i < channels; i++)
317 audio_array[i][k] = 0;
321 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
324 for(
int i = 0; i < channels; i++)
325 audio_array[i][k] = 0;
329 const auto count = this->m_handle.read_pcm_frames(1, frame_data);
332 for(
int i = 0; i < channels; i++)
333 source[i] = std::span(audio_array[i] + k, count);
334 m_converter(source, frame_data, count);
338 for(
int i = 0; i < channels; i++)
339 audio_array[i][k] = 0;
346 for(
int k = 0; k < samples_to_write; k++)
348 int64_t pos = m_start_offset_samples + start - k;
350 if(pos < 0 || pos >= file_duration)
352 for(
int i = 0; i < channels; i++)
353 audio_array[i][k] = 0;
357 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
360 for(
int i = 0; i < channels; i++)
361 audio_array[i][k] = 0;
365 const auto count = this->m_handle.read_pcm_frames(1, frame_data);
368 for(
int i = 0; i < channels; i++)
369 source[i] = std::span(audio_array[i] + k, count);
370 m_converter(source, frame_data, count);
374 for(
int i = 0; i < channels; i++)
375 audio_array[i][k] = 0;
380 for(
int i = 0; i < channels; i++)
381 std::copy_n(audio_array[i], samples_to_write, audio_array_base[i]);
385 fetch_audio_backward(int64_t start, int64_t samples_to_write,
float** audio_array)
noexcept
387 const int channels = this->channels();
388 const int file_duration = this->duration();
390 ossia::mutable_audio_span<float> source(channels);
392 double* frame_data{};
393 if(samples_to_write * channels > 10000)
395 m_safetyBuffer.resize(samples_to_write * channels);
396 frame_data = m_safetyBuffer.data();
400 frame_data = (
double*)alloca(
sizeof(
double) * samples_to_write * channels);
403 if(m_loops && m_loop_duration_samples > 0)
406 for(
int k = 0; k < samples_to_write; k++)
408 int64_t raw_pos = start - k;
410 = ((raw_pos % m_loop_duration_samples) + m_loop_duration_samples)
411 % m_loop_duration_samples;
412 int64_t pos = m_start_offset_samples + wrapped_pos;
414 if(pos < 0 || pos >= file_duration)
416 for(
int i = 0; i < channels; i++)
417 audio_array[i][k] = 0;
421 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
424 for(
int i = 0; i < channels; i++)
425 audio_array[i][k] = 0;
429 const auto count = this->m_handle.read_pcm_frames(1, frame_data);
432 for(
int i = 0; i < channels; i++)
433 source[i] = std::span(audio_array[i] + k, count);
434 m_converter(source, frame_data, count);
438 for(
int i = 0; i < channels; i++)
439 audio_array[i][k] = 0;
446 for(
int k = 0; k < samples_to_write; k++)
448 int64_t pos = m_start_offset_samples + start - k;
450 if(pos < 0 || pos >= file_duration)
452 for(
int i = 0; i < channels; i++)
453 audio_array[i][k] = 0;
457 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
460 for(
int i = 0; i < channels; i++)
461 audio_array[i][k] = 0;
465 const auto count = this->m_handle.read_pcm_frames(1, frame_data);
468 for(
int i = 0; i < channels; i++)
469 source[i] = std::span(audio_array[i] + k, count);
470 m_converter(source, frame_data, count);
474 for(
int i = 0; i < channels; i++)
475 audio_array[i][k] = 0;
481 void run(
const ossia::token_request& t, ossia::exec_state_facade e)
noexcept override
483 if(!m_handle || !m_converter)
486 const auto channels = m_handle.channels();
487 const auto len = m_handle.totalPCMFrameCount();
489 ossia::audio_port& ap = *audio_out;
490 ap.set_channels(std::max((std::size_t)upmix, (std::size_t)channels));
492 const auto [samples_to_read, samples_to_write]
493 = snd::sample_info(e.bufferSize(), e.modelToSamples(), t);
494 if(samples_to_write <= 0)
497 assert(samples_to_write > 0);
499 const auto samples_offset = t.physical_start(e.modelToSamples());
503 if(t.prev_date < m_prev_date)
508 m_prev_date = t.prev_date;
510 transport(t.prev_date);
515 if(t.prev_date > m_prev_date)
518 m_prev_date = t.prev_date;
520 transport(t.prev_date);
524 for(std::size_t chan = 0; chan < channels; chan++)
526 ap.channel(chan).resize(e.bufferSize());
529 const double stretch_ratio = update_stretch(t, e);
530 const double abs_stretch_ratio = std::abs(stretch_ratio);
533 *
this, t, e, stretch_ratio, channels, len, samples_to_read, samples_to_write,
536 const bool start_discontinuous = t.start_discontinuous || (m_last_stretch > 70.);
537 const bool end_discontinuous = t.end_discontinuous || (abs_stretch_ratio > 70.);
538 if(abs_stretch_ratio > 70. && m_last_stretch > 70.)
541 for(std::size_t i = 0; i < channels; i++)
543 ossia::snd::do_zero(ap.channel(i), samples_offset, samples_to_write);
549 for(std::size_t chan = 0; chan < channels; chan++)
553 start_discontinuous, end_discontinuous, ap.channel(chan), samples_offset,
558 ossia::snd::perform_upmix(this->upmix, channels, ap);
559 ossia::snd::perform_start_offset(this->start, ap);
561 m_prev_date = t.date;
562 m_last_stretch = abs_stretch_ratio;
565 [[nodiscard]] std::size_t channels()
const
567 return m_handle ? m_handle.channels() : 0;
569 [[nodiscard]] std::size_t duration()
const
571 return m_handle ? m_handle.totalPCMFrameCount() : 0;
575 drwav_handle m_handle{};
577 ossia::audio_outlet audio_out;
583 = void (*)(ossia::mutable_audio_span<float>& ap,
void* data, int64_t samples);
584 read_fn_t m_converter{};
585 std::vector<double> m_safetyBuffer;
586 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