audio_buffer_bar控件
This commit is contained in:
parent
5f6658e6be
commit
02517cb3cb
@ -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:
|
||||
|
23
Arona/src/tool/math/lerp.h
Normal file
23
Arona/src/tool/math/lerp.h
Normal 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;
|
||||
}
|
@ -1,6 +1,2 @@
|
||||
#include "main_window.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
void main_window::on_button_clicked() {
|
||||
spdlog::info("Hello, world!");
|
||||
}
|
||||
|
@ -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_;
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
@ -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;
|
||||
};
|
36
Arona/src/widget/misc/w_audio_buffer_bar.cpp
Normal file
36
Arona/src/widget/misc/w_audio_buffer_bar.cpp
Normal 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);
|
||||
}
|
||||
}
|
17
Arona/src/widget/misc/w_audio_buffer_bar.h
Normal file
17
Arona/src/widget/misc/w_audio_buffer_bar.h
Normal 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_;
|
||||
};
|
28
Arona/src/widget/misc/w_volume_bar.cpp
Normal file
28
Arona/src/widget/misc/w_volume_bar.cpp
Normal 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();
|
||||
}
|
15
Arona/src/widget/misc/w_volume_bar.h
Normal file
15
Arona/src/widget/misc/w_volume_bar.h
Normal 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;
|
||||
};
|
@ -1 +1,5 @@
|
||||
#include "w_mixer_list.h"
|
||||
|
||||
w_mixer_list::w_mixer_list() {
|
||||
|
||||
}
|
||||
|
@ -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:
|
||||
|
||||
};
|
||||
|
@ -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_);
|
||||
}
|
||||
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user