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()));
80 void transport(time_value date,
const ossia::tick_transport_info& tinfo)
override
83 m_resampler.transport(file_sample_for_model_time(
84 date, tinfo.current_tempo, m_handle.sampleRate()));
88 int64_t start, int64_t samples_to_write,
double** audio_array_base)
noexcept
90 const int channels = this->channels();
91 const int file_duration = this->duration();
93 m_resampleBuffer.resize(channels);
94 for(
auto& buf : m_resampleBuffer)
95 buf.resize(samples_to_write);
97 float** audio_array = (
float**)alloca(
sizeof(
float*) * channels);
98 for(
int i = 0; i < channels; i++)
100 m_resampleBuffer[i].resize(samples_to_write);
101 audio_array[i] = m_resampleBuffer[i].data();
104 ossia::mutable_audio_span<float> source(channels);
106 double* frame_data{};
107 if(samples_to_write * channels > 10000)
109 m_safetyBuffer.resize(samples_to_write * channels);
110 frame_data = m_safetyBuffer.data();
116 frame_data = (
double*)alloca(
sizeof(
double) * samples_to_write * channels);
121 for(
int k = 0; k < samples_to_write; k++)
124 int pos = this->m_start_offset_samples
125 + ((start + k) % this->m_loop_duration_samples);
126 if(pos >= file_duration)
128 for(
int i = 0; i < channels; i++)
129 audio_array[i][k] = 0;
133 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
136 for(
int i = 0; i < channels; i++)
137 audio_array[i][k] = 0;
142 const auto count = this->m_handle.read_pcm_frames(
max, frame_data);
145 for(
int i = 0; i < channels; i++)
146 source[i] = std::span(audio_array[i] + k, count);
147 m_converter(source, frame_data, count);
151 for(
int i = 0; i < channels; i++)
152 audio_array[i][k] = 0;
158 for(
int i = 0; i < channels; i++)
160 source[i] = std::span(audio_array[i], samples_to_write);
163 bool ok = start + m_start_offset_samples < file_duration;
165 ok = ok && this->m_handle.seek_to_pcm_frame(start + m_start_offset_samples);
169 const auto count = this->m_handle.read_pcm_frames(samples_to_write, frame_data);
170 m_converter(source, frame_data, count);
171 for(
int i = 0; i < channels; i++)
172 for(
int k = count; k < samples_to_write; k++)
173 audio_array[i][k] = 0;
177 for(
int i = 0; i < channels; i++)
178 for(
int k = 0; k < samples_to_write; k++)
179 audio_array[i][k] = 0;
184 for(
int i = 0; i < channels; i++)
185 std::copy_n(audio_array[i], samples_to_write, audio_array_base[i]);
188 void fetch_audio(int64_t start, int64_t samples_to_write,
float** audio_array)
noexcept
190 const int channels = this->channels();
191 const int file_duration = this->duration();
193 ossia::mutable_audio_span<float> source(channels);
195 double* frame_data{};
196 if(samples_to_write * channels > 10000)
198 m_safetyBuffer.resize(samples_to_write * channels);
199 frame_data = m_safetyBuffer.data();
205 frame_data = (
double*)alloca(
sizeof(
double) * samples_to_write * channels);
210 for(
int k = 0; k < samples_to_write; k++)
213 int pos = this->m_start_offset_samples
214 + ((start + k) % this->m_loop_duration_samples);
215 if(pos >= file_duration)
217 for(
int i = 0; i < channels; i++)
218 audio_array[i][k] = 0;
222 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
225 for(
int i = 0; i < channels; i++)
226 audio_array[i][k] = 0;
231 const auto count = this->m_handle.read_pcm_frames(
max, frame_data);
234 for(
int i = 0; i < channels; i++)
235 source[i] = std::span(audio_array[i] + k, count);
236 m_converter(source, frame_data, count);
240 for(
int i = 0; i < channels; i++)
241 audio_array[i][k] = 0;
247 for(
int i = 0; i < channels; i++)
249 source[i] = std::span(audio_array[i], samples_to_write);
252 const bool ok = this->m_handle.seek_to_pcm_frame(start + m_start_offset_samples);
255 for(
int i = 0; i < channels; i++)
256 for(
int k = 0; k < samples_to_write; k++)
257 audio_array[i][k] = 0;
261 const auto count = this->m_handle.read_pcm_frames(samples_to_write, frame_data);
262 m_converter(source, frame_data, count);
263 for(
int i = 0; i < channels; i++)
264 for(
int k = count; k < samples_to_write; k++)
265 audio_array[i][k] = 0;
270 void fetch_audio_backward(
271 int64_t start, int64_t samples_to_write,
double** audio_array_base)
noexcept
273 const int channels = this->channels();
274 const int file_duration = this->duration();
276 m_resampleBuffer.resize(channels);
277 for(
auto& buf : m_resampleBuffer)
278 buf.resize(samples_to_write);
280 float** audio_array = (
float**)alloca(
sizeof(
float*) * channels);
281 for(
int i = 0; i < channels; i++)
283 m_resampleBuffer[i].resize(samples_to_write);
284 audio_array[i] = m_resampleBuffer[i].data();
287 ossia::mutable_audio_span<float> source(channels);
289 double* frame_data{};
290 if(samples_to_write * channels > 10000)
292 m_safetyBuffer.resize(samples_to_write * channels);
293 frame_data = m_safetyBuffer.data();
297 frame_data = (
double*)alloca(
sizeof(
double) * samples_to_write * channels);
300 if(m_loops && m_loop_duration_samples > 0)
303 for(
int k = 0; k < samples_to_write; k++)
305 int64_t raw_pos = start - k;
307 = ((raw_pos % m_loop_duration_samples) + m_loop_duration_samples)
308 % m_loop_duration_samples;
309 int64_t pos = m_start_offset_samples + wrapped_pos;
311 if(pos < 0 || pos >= file_duration)
313 for(
int i = 0; i < channels; i++)
314 audio_array[i][k] = 0;
318 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
321 for(
int i = 0; i < channels; i++)
322 audio_array[i][k] = 0;
326 const auto count = this->m_handle.read_pcm_frames(1, frame_data);
329 for(
int i = 0; i < channels; i++)
330 source[i] = std::span(audio_array[i] + k, count);
331 m_converter(source, frame_data, count);
335 for(
int i = 0; i < channels; i++)
336 audio_array[i][k] = 0;
343 for(
int k = 0; k < samples_to_write; k++)
345 int64_t pos = m_start_offset_samples + start - k;
347 if(pos < 0 || pos >= file_duration)
349 for(
int i = 0; i < channels; i++)
350 audio_array[i][k] = 0;
354 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
357 for(
int i = 0; i < channels; i++)
358 audio_array[i][k] = 0;
362 const auto count = this->m_handle.read_pcm_frames(1, frame_data);
365 for(
int i = 0; i < channels; i++)
366 source[i] = std::span(audio_array[i] + k, count);
367 m_converter(source, frame_data, count);
371 for(
int i = 0; i < channels; i++)
372 audio_array[i][k] = 0;
377 for(
int i = 0; i < channels; i++)
378 std::copy_n(audio_array[i], samples_to_write, audio_array_base[i]);
382 fetch_audio_backward(int64_t start, int64_t samples_to_write,
float** audio_array)
noexcept
384 const int channels = this->channels();
385 const int file_duration = this->duration();
387 ossia::mutable_audio_span<float> source(channels);
389 double* frame_data{};
390 if(samples_to_write * channels > 10000)
392 m_safetyBuffer.resize(samples_to_write * channels);
393 frame_data = m_safetyBuffer.data();
397 frame_data = (
double*)alloca(
sizeof(
double) * samples_to_write * channels);
400 if(m_loops && m_loop_duration_samples > 0)
403 for(
int k = 0; k < samples_to_write; k++)
405 int64_t raw_pos = start - k;
407 = ((raw_pos % m_loop_duration_samples) + m_loop_duration_samples)
408 % m_loop_duration_samples;
409 int64_t pos = m_start_offset_samples + wrapped_pos;
411 if(pos < 0 || pos >= file_duration)
413 for(
int i = 0; i < channels; i++)
414 audio_array[i][k] = 0;
418 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
421 for(
int i = 0; i < channels; i++)
422 audio_array[i][k] = 0;
426 const auto count = this->m_handle.read_pcm_frames(1, frame_data);
429 for(
int i = 0; i < channels; i++)
430 source[i] = std::span(audio_array[i] + k, count);
431 m_converter(source, frame_data, count);
435 for(
int i = 0; i < channels; i++)
436 audio_array[i][k] = 0;
443 for(
int k = 0; k < samples_to_write; k++)
445 int64_t pos = m_start_offset_samples + start - k;
447 if(pos < 0 || pos >= file_duration)
449 for(
int i = 0; i < channels; i++)
450 audio_array[i][k] = 0;
454 const bool ok = this->m_handle.seek_to_pcm_frame(pos);
457 for(
int i = 0; i < channels; i++)
458 audio_array[i][k] = 0;
462 const auto count = this->m_handle.read_pcm_frames(1, frame_data);
465 for(
int i = 0; i < channels; i++)
466 source[i] = std::span(audio_array[i] + k, count);
467 m_converter(source, frame_data, count);
471 for(
int i = 0; i < channels; i++)
472 audio_array[i][k] = 0;
478 void run(
const ossia::token_request& t, ossia::exec_state_facade e)
noexcept override
480 if(!m_handle || !m_converter)
483 const auto channels = m_handle.channels();
484 const auto len = m_handle.totalPCMFrameCount();
486 ossia::audio_port& ap = *audio_out;
487 ap.set_channels(std::max((std::size_t)upmix, (std::size_t)channels));
489 const auto [samples_to_read, samples_to_write]
490 = snd::sample_info(e.bufferSize(), e.modelToSamples(), t);
491 if(samples_to_write <= 0)
494 assert(samples_to_write > 0);
496 const auto samples_offset = t.physical_start(e.modelToSamples());
500 if(t.prev_date < m_prev_date)
505 m_prev_date = t.prev_date;
507 transport(t.prev_date);
512 if(t.prev_date > m_prev_date)
515 m_prev_date = t.prev_date;
517 transport(t.prev_date);
521 for(std::size_t chan = 0; chan < channels; chan++)
523 ap.channel(chan).resize(e.bufferSize());
526 const double stretch_ratio = update_stretch(t, e);
527 const double abs_stretch_ratio = std::abs(stretch_ratio);
530 *
this, t, e, stretch_ratio, channels, len, samples_to_read, samples_to_write,
533 const bool start_discontinuous = t.start_discontinuous || (m_last_stretch > 70.);
534 const bool end_discontinuous = t.end_discontinuous || (abs_stretch_ratio > 70.);
535 if(abs_stretch_ratio > 70. && m_last_stretch > 70.)
538 for(std::size_t i = 0; i < channels; i++)
540 ossia::snd::do_zero(ap.channel(i), samples_offset, samples_to_write);
546 for(std::size_t chan = 0; chan < channels; chan++)
550 start_discontinuous, end_discontinuous, ap.channel(chan), samples_offset,
555 ossia::snd::perform_upmix(this->upmix, channels, ap);
556 ossia::snd::perform_start_offset(this->start, ap);
558 m_prev_date = t.date;
559 m_last_stretch = abs_stretch_ratio;
562 [[nodiscard]] std::size_t channels()
const
564 return m_handle ? m_handle.channels() : 0;
566 [[nodiscard]] std::size_t duration()
const
568 return m_handle ? m_handle.totalPCMFrameCount() : 0;
572 drwav_handle m_handle{};
574 ossia::audio_outlet audio_out;
580 = void (*)(ossia::mutable_audio_span<float>& ap,
void* data, int64_t samples);
581 read_fn_t m_converter{};
582 std::vector<double> m_safetyBuffer;
583 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