Serenity Operating System
at master 95 lines 2.6 kB view raw
1/* 2 * Copyright (c) 2021, Cesar Torres <shortanemoia@protonmail.com> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/FixedArray.h> 10#include <AK/Forward.h> 11#include <AK/TypedTransfer.h> 12#include <LibAudio/Sample.h> 13#include <LibGUI/Frame.h> 14#include <LibGUI/Painter.h> 15 16class VisualizationWidget : public GUI::Frame { 17 C_OBJECT_ABSTRACT(VisualizationWidget) 18 19public: 20 virtual void render(GUI::PaintEvent&, FixedArray<float> const& samples) = 0; 21 22 void set_buffer(FixedArray<Audio::Sample> const& buffer) 23 { 24 if (buffer.is_empty()) 25 return; 26 27 if (m_sample_buffer.size() != buffer.size()) 28 m_sample_buffer.resize(buffer.size()); 29 30 for (size_t i = 0; i < buffer.size(); i++) 31 m_sample_buffer.data()[i] = (buffer[i].left + buffer[i].right) / 2.f; 32 33 m_frame_count = 0; 34 } 35 36 virtual void set_samplerate(int samplerate) 37 { 38 m_samplerate = samplerate; 39 } 40 41 virtual void paint_event(GUI::PaintEvent& event) override 42 { 43 if (m_sample_buffer.size() == 0) { 44 Frame::paint_event(event); 45 GUI::Painter painter(*this); 46 painter.add_clip_rect(event.rect()); 47 painter.fill_rect(frame_inner_rect(), Color::Black); 48 return; 49 } 50 51 if (m_render_buffer.size() == 0) 52 return; 53 54 size_t buffer_position = (m_frame_count * REFRESH_TIME_MILLISECONDS) * m_samplerate / 1000; 55 if (buffer_position + m_render_buffer.size() >= m_sample_buffer.size()) 56 buffer_position = m_sample_buffer.size() - m_render_buffer.size(); 57 58 AK::TypedTransfer<float>::copy(m_render_buffer.data(), m_sample_buffer.span().slice(buffer_position).data(), m_render_buffer.size()); 59 60 render(event, m_render_buffer); 61 } 62 63 virtual void timer_event(Core::TimerEvent&) override 64 { 65 update(); 66 m_frame_count++; 67 } 68 69 size_t frame_count() const { return m_frame_count; } 70 71 ErrorOr<void> set_render_sample_count(size_t count) 72 { 73 auto new_buffer = TRY(FixedArray<float>::create(count)); 74 m_render_buffer.swap(new_buffer); 75 return {}; 76 } 77 virtual void start_new_file(StringView) { } 78 79protected: 80 int m_samplerate; 81 size_t m_frame_count; 82 Vector<float> m_sample_buffer; 83 FixedArray<float> m_render_buffer; 84 85 static constexpr size_t REFRESH_TIME_MILLISECONDS = 30; 86 87 VisualizationWidget() 88 : m_samplerate(-1) 89 , m_frame_count(0) 90 { 91 start_timer(REFRESH_TIME_MILLISECONDS); 92 } 93 94 virtual ~VisualizationWidget() = default; 95};