From 1befa02cd806c0cb3e85fce68f82405737743481 Mon Sep 17 00:00:00 2001 From: Stepland <10530295-Buggyroom@users.noreply.gitlab.com> Date: Sun, 15 Jan 2023 02:06:05 +0100 Subject: [PATCH] Compute more downsampled versions of the audio --- src/widgets/waveform_view.cpp | 52 +++++++++++++++++++++++++++++------ src/widgets/waveform_view.hpp | 3 ++ 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/widgets/waveform_view.cpp b/src/widgets/waveform_view.cpp index cce02af..e7fbb6f 100644 --- a/src/widgets/waveform_view.cpp +++ b/src/widgets/waveform_view.cpp @@ -9,7 +9,9 @@ #include #include #include +#include #include +#include #include "toolbox.hpp" #include "utf8_file_input_stream.hpp" #include "utf8_sfml.hpp" @@ -70,25 +72,28 @@ void WaveformView::draw(const sf::Time current_time) { ImGui::End(); } -void WaveformView::prepare_data() { - - const std::size_t chunk_size = 64 * sound_file.getChannelCount(); - const std::size_t point_count = (sound_file.getSampleCount() / sound_file.getChannelCount() / 64) + 1; +Channels load_initial_summary( + feis::HoldFileStreamMixin& sound_file, + const unsigned int window_size +) { + const std::size_t chunk_size = window_size * sound_file.getChannelCount(); + const std::size_t point_count = (sound_file.getSampleCount() / sound_file.getChannelCount() / window_size) + 1; Channels summary{sound_file.getChannelCount(), DataFrame{point_count}}; std::vector samples; samples.resize(chunk_size); for (std::size_t point_index = 0; point_index < point_count; point_index++) { const auto samples_read = sound_file.read(samples.data(), chunk_size); - if (samples_read < chunk_size) { - // looks like we are done reading the file ? + if (samples_read == 0) { + // we are done reading the file break; } + const auto sample_indicies = samples_read / sound_file.getChannelCount(); for (std::size_t channel_index = 0; channel_index < summary.size(); channel_index++) { auto& point = summary[channel_index][point_index]; point.max = std::numeric_limits::min(); point.min = std::numeric_limits::max(); - for (std::size_t sample_index = 0; sample_index < 64; sample_index++) { + for (std::size_t sample_index = 0; sample_index < sample_indicies; sample_index++) { auto& sample = samples[sample_index * sound_file.getChannelCount() + channel_index]; if (sample > point.max) { point.max = sample; @@ -100,6 +105,37 @@ void WaveformView::prepare_data() { } std::ranges::fill(samples, 0); } - channels_per_chunk_size[64] = summary; + return summary; +} + +Channels downsample_to_half(const Channels& summary) { + Channels downsample; + for (const auto& channel : summary) { + std::vector downsampled{(channel.size() / 2) + 1}; + auto out = downsampled.begin(); + auto in = channel.begin(); + while (in != channel.end() and out != downsampled.end()) { + const auto next_in = std::next(in); + if (next_in != channel.end()) { + out->max = std::max(in->max, next_in->max); + out->min = std::max(in->min, next_in->min); + } else { + *out = *in; + break; + } + out = std::next(out); + std::advance(in, 2); + } + } + return downsample; +}; + +void WaveformView::prepare_data() { + unsigned int size = 8; + channels_per_chunk_size[size] = load_initial_summary(sound_file, size); + while (channels_per_chunk_size.size() < 10) { + channels_per_chunk_size[size * 2] = downsample_to_half(channels_per_chunk_size[size]); + size *= 2; + } data_is_ready = true; } diff --git a/src/widgets/waveform_view.hpp b/src/widgets/waveform_view.hpp index 099fcc2..e1c9a8c 100644 --- a/src/widgets/waveform_view.hpp +++ b/src/widgets/waveform_view.hpp @@ -28,10 +28,13 @@ class WaveformView { public: explicit WaveformView(const std::filesystem::path& file); void draw(const sf::Time current_time); + void draw_settings(); + bool display = false; private: feis::HoldFileStreamMixin sound_file; std::atomic data_is_ready = false; std::map channels_per_chunk_size; + std::optional::iterator> selected_size; std::jthread worker; void prepare_data();