audio_buffer_bar控件

This commit is contained in:
Nanako 2024-05-20 21:01:24 +08:00
parent 5f6658e6be
commit 02517cb3cb
15 changed files with 156 additions and 65 deletions

View File

@ -1,6 +1,5 @@
#pragma once
#include <chrono>
#include "gtkmm.h"
class delta_timer {
@ -15,9 +14,10 @@ public:
}
bool on_timer() {
const auto now = std::chrono::steady_clock::now();
const auto delta_time = std::chrono::duration_cast<std::chrono::duration<float>>(now - last_time_).count();
const std::chrono::nanoseconds& delta_time_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(now - last_time_);
last_time_ = now;
tick_(delta_time);
// ns to s
tick_(static_cast<float>(delta_time_ns.count()) / 1e9);
return true;
}
private:

View File

@ -0,0 +1,23 @@
#pragma once
#include <cmath>
inline float finterp_ro_constant(float Current, float Target, float DeltaTime, float InterpSpeed)
{
// Calculate the distance to target
float Dist = Target - Current;
// If the distance is very small or speed is very small, return target
if (std::abs(Dist) < 1e-6 || std::abs(InterpSpeed) < 1e-6)
{
return Target;
}
// Calculate the step we can take this frame
float Step = InterpSpeed * DeltaTime;
// Clamp the step to the distance to ensure we don't overshoot
float ClampedStep = std::clamp(Dist, -Step, Step);
// Return the new interpolated value
return Current + ClampedStep;
}

View File

@ -1,6 +1,2 @@
#include "main_window.h"
#include "spdlog/spdlog.h"
void main_window::on_button_clicked() {
spdlog::info("Hello, world!");
}

View File

@ -1,26 +1,18 @@
#pragma once
#include "gtkmm.h"
#include "misc/volume_bar.h"
#include "mixer/w_mixer_list.h"
class main_window : public Gtk::Window {
public:
main_window() {
button_.set_margin(10);
button_.signal_clicked().connect(mem_fun(*this, &main_window::on_button_clicked));
button_.set_label("Hello, world!");
box_ = Gtk::Box(Gtk::Orientation::VERTICAL);
box_.append(button_);
box_.append(volume_bar_);
box_.append(mixer_list_);
set_default_size(800, 600);
set_child(box_);
set_title("Arona");
}
private:
void on_button_clicked();
Gtk::Box box_;
Gtk::Button button_;
volume_bar volume_bar_;
w_mixer_list mixer_list_;
};

View File

@ -1,31 +0,0 @@
#include "volume_bar.h"
#include "arona_application.h"
volume_bar::volume_bar()
{
timer_ = std::make_shared<delta_timer>(mem_fun(*this, &volume_bar::tick), 1000 / get_application()->get_screen_refresh_rate());
set_content_height(100);
set_content_width(100);
set_draw_func(sigc::mem_fun(*this, &volume_bar::on_draw));
}
void volume_bar::tick(double delta_time) {
value_ += delta_time;
if (value_ > 1.0f) {
value_ = 0.0f;
}
queue_draw();
}
void volume_bar::on_draw(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height) {
// Draw a black rectangle.
cr->set_source_rgba(0.0, 0.0, 0.0, 1.0);
cr->fill();
// draw value bar
cr->set_source_rgba(0.0, 1.0, 1.0, 1.0);
cr->rectangle(0, 0, width * value_, height);
cr->fill();
cr->stroke();
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "gtkmm.h"
#include "tool/delta_timer.h"
class volume_bar : public Gtk::DrawingArea {
public:
volume_bar();
void tick(double delta_time);
private:
void on_draw(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height);
std::shared_ptr<delta_timer> timer_;
float value_ = 0.0f;
};

View File

@ -0,0 +1,36 @@
#include "w_audio_buffer_bar.h"
#include "arona_application.h"
#include "audio/device/audio_device_manager.h"
#include "tool/delta_timer.h"
w_audio_buffer_bar::w_audio_buffer_bar(std::vector<circular_audio_buffer<float>>& in_buffer) : Box(Gtk::Orientation::HORIZONTAL), buffers(in_buffer) {
timer_ = std::make_shared<delta_timer>(mem_fun(*this, &w_audio_buffer_bar::on_timer), 1000.f / get_application()->get_screen_refresh_rate());
for (int32_t i = 0; i < buffers.size(); i++) {
w_volume_bar& bar = volume_bars_.emplace_back(w_volume_bar(true));
append(bar);
}
}
void w_audio_buffer_bar::on_timer(double delta_time) {
const uint32_t sample_rate = get_audio_device_manager()->get_sample_rate();
const auto delta_samples = static_cast<uint32_t>(delta_time * sample_rate);
static std::vector<float> temp;
for (int i = 0; i < buffers.size(); ++i) {
w_volume_bar& bar = volume_bars_[i];
circular_audio_buffer<float>& buffer = buffers[i];
const uint32_t available_samples = std::min(buffer.Num(), delta_samples);
temp.resize(available_samples);
buffer.Pop(temp.data(), available_samples);
float min_sample = *std::ranges::max_element(temp);
float max_sample = *std::ranges::min_element(temp);
float peak = std::max(std::abs(min_sample), max_sample);
bar.set_value(peak);
}
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "gtkmm/box.h"
#include "audio/misc/circular_audio_buffer.h"
#include "widget/misc/w_volume_bar.h"
class delta_timer;
class w_audio_buffer_bar : public Gtk::Box {
public:
explicit w_audio_buffer_bar(std::vector<circular_audio_buffer<float>>& in_buffer);
std::vector<circular_audio_buffer<float>>& buffers;
private:
void on_timer(double delta_time);
std::vector<w_volume_bar> volume_bars_;
std::shared_ptr<delta_timer> timer_;
};

View File

@ -0,0 +1,28 @@
#include "w_volume_bar.h"
#include "arona_application.h"
#include "tool/math/lerp.h"
w_volume_bar::w_volume_bar(bool vertical) : is_vertical(vertical)
{
set_content_height(10);
set_content_width(10);
set_draw_func(sigc::mem_fun(*this, &w_volume_bar::on_draw));
}
void w_volume_bar::on_draw(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height) {
// Draw a black rectangle.
cr->set_source_rgba(0.0, 0.0, 0.0, 1.0);
cr->fill();
// draw value bar
cr->set_source_rgba(0.0, 1.0, 1.0, 1.0);
if (is_vertical) {
cr->rectangle(0, height * (1 - value_), width, height * value_);
} else {
cr->rectangle(0, 0, width * value_, height);
}
cr->fill();
cr->stroke();
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "gtkmm/drawingarea.h"
class w_volume_bar : public Gtk::DrawingArea {
public:
explicit w_volume_bar(bool vertical = false);
void set_value(double value) {
value_ = value;
queue_draw();
}
const bool is_vertical;
private:
void on_draw(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height);
double value_ = 0.0;
};

View File

@ -1 +1,5 @@
#include "w_mixer_list.h"
w_mixer_list::w_mixer_list() {
}

View File

@ -1,5 +1,9 @@
#pragma once
#include <gtkmm/box.h>
class w_mixer_list {
class w_mixer_list : public Gtk::Box {
public:
w_mixer_list();
private:
};

View File

@ -1,2 +1,10 @@
#include "w_mixer_track.h"
#include "audio/mixer/mixer_track.h"
#include "widget/misc/w_audio_buffer_bar.h"
w_mixer_track::w_mixer_track(mixer_track* track) : Box(Gtk::Orientation::HORIZONTAL) {
track_ = track;
audio_buffer_bar_ = std::make_shared<w_audio_buffer_bar>(track_->ui_buffers);
append(*audio_buffer_bar_);
}

View File

@ -1 +1,14 @@
#pragma once
#include <gtkmm/box.h>
class w_audio_buffer_bar;
class mixer_track;
class w_mixer_track : public Gtk::Box {
public:
w_mixer_track(mixer_track* track);
private:
mixer_track* track_;
std::shared_ptr<w_audio_buffer_bar> audio_buffer_bar_;
};

@ -1 +1 @@
Subproject commit 6b7c8616eb99f0cdd2ed02a09b090e821735d6b8
Subproject commit 9c165fecb6b6c15b05c40e8361e212c4ef638834