新增垂直音量控制器
This commit is contained in:
parent
080d0986f5
commit
eac45751d2
@ -1,5 +1,4 @@
|
||||
#include "widgets.h"
|
||||
#include "imgui.h"
|
||||
|
||||
#include "audio/plugin_host/plugin_host_manager.h"
|
||||
#include "audio/plugin_host/plugin_host.h"
|
||||
@ -88,7 +87,7 @@ void draw_mixer_track(uint32_t delta_sample_count, mixer_track* track, int32_t i
|
||||
|
||||
std::string track_label = track->get_name();
|
||||
std::string child_id = "MixerTrack" + std::to_string(index);
|
||||
std::string slider_id = "##" + std::to_string(index);
|
||||
std::string slider_id = "MixerTrackVolume##" + std::to_string(index);
|
||||
std::string volume_bar_id = "VolumeBar" + std::to_string(index);
|
||||
|
||||
ImGui::BeginGroup();
|
||||
@ -96,9 +95,9 @@ void draw_mixer_track(uint32_t delta_sample_count, mixer_track* track, int32_t i
|
||||
ImGui::Text(track_label.c_str());
|
||||
|
||||
float widget_height = ImGui::GetContentRegionAvail().y;
|
||||
const ImVec2 slider_size = ImGui::CalcItemSize(ImVec2(20, widget_height), 20, widget_height);
|
||||
const ImVec2 slider_size = ImGui::CalcItemSize(ImVec2(25, widget_height), 25, widget_height);
|
||||
float volume = track->get_volume();
|
||||
if (ImGui::VSliderFloat(slider_id.c_str(), slider_size,&volume, 0.0f, 1.2f)) {
|
||||
if (vertical_volume_slider(slider_id.c_str(), slider_size, &volume, 0.f, 1.25f)) {
|
||||
track->set_volume(volume);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
@ -139,13 +138,6 @@ void draw_mixer_track(uint32_t delta_sample_count, mixer_track* track, int32_t i
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
// on hover
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text(track_label.c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
void draw_volume_bar(const char* id, float height, std::vector<float> sample_value, std::vector<float> sample_peak) {
|
||||
@ -188,11 +180,11 @@ void draw_volume_bar(const char* id, float height, std::vector<float> sample_val
|
||||
ImVec2 temp_pos = pos;
|
||||
// 坐标系原点在左上角
|
||||
for (int32_t i = 0; i < channel_count; ++i) {
|
||||
float value_db = sample_to_db(sample_value.at(i));
|
||||
float value = db_to_percent(value_db);
|
||||
float value_db = gain_to_db(sample_value.at(i));
|
||||
float value = db_to_percentage_log(value_db, -75.0f, 6.0f);
|
||||
|
||||
float peak_db = sample_to_db(sample_peak.at(i));
|
||||
float peak = db_to_percent(peak_db);
|
||||
float peak_db = gain_to_db(sample_peak.at(i));
|
||||
float peak = db_to_percentage_log(peak_db, -75.0f, 6.0f);
|
||||
|
||||
// 绘制矩形(60%以下的部分绘制绿色,80%以下的部分绘制黄色,100%以下的部分绘制红色)
|
||||
if (value > volume_bar_inf) {
|
||||
@ -251,3 +243,58 @@ void draw_volume_bar(const char* id, float height, std::vector<float> sample_val
|
||||
|
||||
window->DrawList->PopClipRect();
|
||||
}
|
||||
|
||||
bool vertical_volume_slider(const char* id, ImVec2 size, float* volume, float min_volume, float max_volume) {
|
||||
ImGuiWindow *window = ImGui::GetCurrentWindow();
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
|
||||
ImVec2 cur_pos = window->DC.CursorPos;
|
||||
ImRect bb(cur_pos, cur_pos + size);
|
||||
ImGui::ItemSize(size, 0.0f);
|
||||
if (!ImGui::ItemAdd(bb, 0))
|
||||
return false;
|
||||
|
||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
||||
ImGui::RenderFrame(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_FrameBg), true, 0.0f);
|
||||
|
||||
float percent = mapping(*volume, min_volume, max_volume, 0.f, 1.0f);
|
||||
ImVec2 pos = ImVec2(bb.Min.x, bb.Min.y + size.y * (1 - percent));
|
||||
draw_list->AddRectFilled(pos, bb.Max, ImGui::GetColorU32(ImGuiCol_SliderGrabActive), 0.0f);
|
||||
|
||||
bool on_hovered = ImGui::IsItemHovered();
|
||||
|
||||
if (on_hovered) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("Volume: %.3fdb", 20.0f * log10f(*volume));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
|
||||
*volume = 1.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
static float drag_start_value = 0.0f;
|
||||
static ImGuiID dragging = 0;
|
||||
|
||||
const bool clicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
|
||||
const bool released = ImGui::IsMouseReleased(ImGuiMouseButton_Left);
|
||||
ImGuiID current_id = ImGui::GetID(id);
|
||||
|
||||
if (released) {
|
||||
dragging = 0;
|
||||
} else if (!dragging && on_hovered && clicked) {
|
||||
drag_start_value = *volume;
|
||||
dragging = current_id;
|
||||
}
|
||||
|
||||
if (dragging != current_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float mouse_drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Left).y;
|
||||
float delta = (mouse_drag_delta / size.y) * (max_volume - min_volume);
|
||||
*volume = std::clamp(drag_start_value - delta, min_volume, max_volume);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -3,19 +3,48 @@
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
#include "extern.h"
|
||||
#include "imgui.h"
|
||||
|
||||
class mixer_track;
|
||||
|
||||
inline sample_t sample_to_db(sample_t sample) {
|
||||
inline float mapping(float value, float in_min, float in_max, float out_min, float out_max) {
|
||||
return (value - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
|
||||
inline sample_t gain_to_db(sample_t sample) {
|
||||
return 20.0f * log10f(sample);
|
||||
}
|
||||
|
||||
// convert db(-60db, 10db) to percent in range [0, 1]
|
||||
inline float db_to_percent(float db) {
|
||||
return (db + 60.0f) / 70.0f;
|
||||
inline float db_to_gain(sample_t db) {
|
||||
return powf(10.0f, db / 20.0f);
|
||||
}
|
||||
|
||||
inline float db_to_percentage_log(float db_value, float min_db = -60.0f, float max_db = 0.0f) {
|
||||
if (db_value < min_db) db_value = min_db;
|
||||
if (db_value > max_db) db_value = max_db;
|
||||
// 计算对数比例
|
||||
float log_min = std::log10(1.0f + std::pow(10.0f, min_db / 20.0f));
|
||||
float log_max = std::log10(1.0f + std::pow(10.0f, max_db / 20.0f));
|
||||
float log_value = std::log10(1.0f + std::pow(10.0f, db_value / 20.0f));
|
||||
|
||||
// 线性映射到0到100的范围
|
||||
float percentage = (log_value - log_min) / (log_max - log_min);
|
||||
return percentage;
|
||||
}
|
||||
|
||||
inline float percentage_to_db(float percentage, float min_db = -60.0f, float max_db = 0.0f) {
|
||||
// 计算对数比例
|
||||
float log_min = std::log10(1.0f + std::pow(10.0f, min_db / 20.0f));
|
||||
float log_max = std::log10(1.0f + std::pow(10.0f, max_db / 20.0f));
|
||||
float log_value = log_min + percentage * (log_max - log_min);
|
||||
|
||||
// 计算db值
|
||||
float db_value = 20.0f * std::log10(std::pow(10.0f, log_value) - 1.0f);
|
||||
return db_value;
|
||||
}
|
||||
|
||||
void vertical_text(const char* text);
|
||||
bool vertical_volume_slider(const char* id, ImVec2 size, float* volume, float min_volume = 0.0f, float max_volume = 1.0f);
|
||||
|
||||
void draw_instrument_track();
|
||||
void draw_mixer();
|
||||
|
Loading…
x
Reference in New Issue
Block a user