mirror of
https://gitlab.com/square-game-liberation-front/F.E.I.S.git
synced 2025-02-20 12:31:01 +01:00
Save sound params
This commit is contained in:
parent
10bae5b0c7
commit
2d4a4219e9
@ -1,11 +1,11 @@
|
||||
# v2.0.0
|
||||
*(+ 2.0.0-rc.1)*
|
||||
## 🥝🍇🍓🍊🍏 New Stuff 🍏🍊🍓🍇🥝
|
||||
- BPM Changes
|
||||
- BPM Autodetect
|
||||
- Waveform mode for the Linear View
|
||||
- memon 1.0 + 0.3 + 0.2 support
|
||||
- BPM Changes
|
||||
- MP3 support
|
||||
- BPM Autodetect
|
||||
|
||||
## 🍒 Small improvements 🍒
|
||||
- Claps and Beats ticks should now be perfectly synced !
|
||||
@ -35,6 +35,7 @@
|
||||
- Support for negative time playback (lead in before the song starts)
|
||||
- The editable time range of a chart now grows in a way that should interfere less with editing
|
||||
- Support for the jujube marker format
|
||||
- Sound parameters are saved
|
||||
|
||||
## 🚧 Changes 🚧
|
||||
- Force using the asset folder next to the executable
|
||||
|
@ -94,6 +94,48 @@ void config::Editor::dump_as_v1_0_0(toml::table& tbl) {
|
||||
});
|
||||
}
|
||||
|
||||
void config::Sound::load_from_v1_0_0_table(const toml::table& tbl) {
|
||||
if (not tbl["sound"].is_table()) {
|
||||
return;
|
||||
}
|
||||
const auto sound_table = tbl["sound"].ref<toml::table>();
|
||||
if (sound_table["music_volume"].is_integer()) {
|
||||
const auto val = sound_table["music_volume"].value<int>();
|
||||
music_volume = std::clamp(*val, 0, 10);
|
||||
}
|
||||
if (sound_table["beat_tick"].is_boolean()) {
|
||||
beat_tick = *sound_table["beat_tick"].value<bool>();
|
||||
}
|
||||
if (sound_table["beat_tick_volume"].is_integer()) {
|
||||
const auto val = sound_table["beat_tick_volume"].value<int>();
|
||||
beat_tick_volume = std::clamp(*val, 0, 10);
|
||||
}
|
||||
if (sound_table["note_clap"].is_boolean()) {
|
||||
note_clap = *sound_table["note_clap"].value<bool>();
|
||||
}
|
||||
if (sound_table["note_clap_volume"].is_integer()) {
|
||||
const auto val = sound_table["note_clap_volume"].value<int>();
|
||||
note_clap_volume = std::clamp(*val, 0, 10);
|
||||
}
|
||||
if (sound_table["clap_on_long_note_ends"].is_boolean()) {
|
||||
clap_on_long_note_ends = *sound_table["clap_on_long_note_ends"].value<bool>();
|
||||
}
|
||||
if (sound_table["distinct_chord_clap"].is_boolean()) {
|
||||
distinct_chord_clap = *sound_table["distinct_chord_clap"].value<bool>();
|
||||
}
|
||||
}
|
||||
|
||||
void config::Sound::dump_as_v1_0_0(toml::table& tbl) {
|
||||
tbl.insert_or_assign("sound", toml::table{
|
||||
{"music_volume", music_volume},
|
||||
{"beat_tick", beat_tick},
|
||||
{"beat_tick_volume", beat_tick_volume},
|
||||
{"note_clap", note_clap},
|
||||
{"note_clap_volume", note_clap_volume},
|
||||
{"clap_on_long_note_ends", clap_on_long_note_ends},
|
||||
{"distinct_chord_clap", distinct_chord_clap}
|
||||
});
|
||||
}
|
||||
|
||||
config::Config::Config(const std::filesystem::path& settings) :
|
||||
config_path(settings / "config.toml")
|
||||
@ -132,6 +174,7 @@ toml::table config::Config::dump_as_v1_0_0() {
|
||||
marker.dump_as_v1_0_0(tbl);
|
||||
linear_view.dump_as_v1_0_0(tbl);
|
||||
editor.dump_as_v1_0_0(tbl);
|
||||
sound.dump_as_v1_0_0(tbl);
|
||||
return tbl;
|
||||
}
|
||||
|
||||
@ -151,4 +194,5 @@ void config::Config::load_from_v1_0_0_table(const toml::table& tbl) {
|
||||
marker.load_from_v1_0_0_table(tbl);
|
||||
linear_view.load_from_v1_0_0_table(tbl);
|
||||
editor.load_from_v1_0_0_table(tbl);
|
||||
sound.load_from_v1_0_0_table(tbl);
|
||||
}
|
@ -43,6 +43,19 @@ namespace config {
|
||||
void dump_as_v1_0_0(toml::table& tbl);
|
||||
};
|
||||
|
||||
struct Sound {
|
||||
int music_volume = 10;
|
||||
bool beat_tick = false;
|
||||
int beat_tick_volume = 10;
|
||||
bool note_clap = false;
|
||||
int note_clap_volume = 10;
|
||||
bool clap_on_long_note_ends = false;
|
||||
bool distinct_chord_clap = false;
|
||||
|
||||
void load_from_v1_0_0_table(const toml::table& tbl);
|
||||
void dump_as_v1_0_0(toml::table& tbl);
|
||||
};
|
||||
|
||||
/* RAII-style class that holds settings we wish to save on disk and saves
|
||||
them upon being destroyed */
|
||||
class Config {
|
||||
@ -55,6 +68,7 @@ namespace config {
|
||||
Marker marker;
|
||||
LinearView linear_view;
|
||||
Editor editor;
|
||||
Sound sound;
|
||||
|
||||
private:
|
||||
void load_from_v1_0_0_table(const toml::table& tbl);
|
||||
|
@ -111,22 +111,22 @@ waveform::Status EditorState::waveform_status() {
|
||||
}
|
||||
|
||||
int EditorState::get_volume() const {
|
||||
return volume;
|
||||
return config.sound.music_volume;
|
||||
}
|
||||
|
||||
void EditorState::set_volume(int volume_) {
|
||||
if (music.has_value()) {
|
||||
(**music).set_volume(volume_);
|
||||
volume = (**music).get_volume();
|
||||
config.sound.music_volume = (**music).get_volume();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorState::volume_up() {
|
||||
set_volume(volume + 1);
|
||||
set_volume(get_volume() + 1);
|
||||
}
|
||||
|
||||
void EditorState::volume_down() {
|
||||
set_volume(volume - 1);
|
||||
set_volume(get_volume() - 1);
|
||||
}
|
||||
|
||||
int EditorState::get_speed() const {
|
||||
@ -240,19 +240,16 @@ void EditorState::toggle_playback() {
|
||||
}
|
||||
|
||||
void EditorState::toggle_note_claps() {
|
||||
if (
|
||||
audio.contains_stream(note_clap_stream)
|
||||
or audio.contains_stream(chord_clap_stream)
|
||||
) {
|
||||
if (note_clap_stream_is_on()) {
|
||||
audio.update_streams({}, {note_clap_stream, chord_clap_stream});
|
||||
} else {
|
||||
note_claps = note_claps->with_params(
|
||||
get_pitch(),
|
||||
not distinct_chord_clap,
|
||||
clap_on_long_note_ends
|
||||
not config.sound.distinct_chord_clap,
|
||||
config.sound.clap_on_long_note_ends
|
||||
);
|
||||
std::map<std::string, NewStream> streams = {{note_clap_stream, {note_claps, true}}};
|
||||
if (distinct_chord_clap) {
|
||||
if (config.sound.distinct_chord_clap) {
|
||||
chord_claps = chord_claps->with_pitch(get_pitch());
|
||||
streams[chord_clap_stream] = {chord_claps, true};
|
||||
}
|
||||
@ -261,23 +258,21 @@ void EditorState::toggle_note_claps() {
|
||||
}
|
||||
|
||||
void EditorState::toggle_clap_on_long_note_ends() {
|
||||
clap_on_long_note_ends = not clap_on_long_note_ends;
|
||||
note_claps = note_claps->with_params(
|
||||
get_pitch(),
|
||||
not distinct_chord_clap,
|
||||
clap_on_long_note_ends
|
||||
not config.sound.distinct_chord_clap,
|
||||
config.sound.clap_on_long_note_ends
|
||||
);
|
||||
audio.update_streams({{note_clap_stream, {note_claps, true}}});
|
||||
}
|
||||
|
||||
void EditorState::toggle_distinct_chord_claps() {
|
||||
distinct_chord_clap = not distinct_chord_clap;
|
||||
note_claps = note_claps->with_params(
|
||||
get_pitch(),
|
||||
not distinct_chord_clap,
|
||||
clap_on_long_note_ends
|
||||
not config.sound.distinct_chord_clap,
|
||||
config.sound.clap_on_long_note_ends
|
||||
);
|
||||
if (distinct_chord_clap) {
|
||||
if (config.sound.distinct_chord_clap) {
|
||||
chord_claps = chord_claps->with_pitch(get_pitch());
|
||||
audio.update_streams(
|
||||
{
|
||||
@ -294,7 +289,7 @@ void EditorState::toggle_distinct_chord_claps() {
|
||||
}
|
||||
|
||||
void EditorState::toggle_beat_ticks() {
|
||||
if (audio.contains_stream(beat_tick_stream)) {
|
||||
if (beat_tick_stream_is_on()) {
|
||||
audio.remove_stream(beat_tick_stream);
|
||||
} else {
|
||||
beat_ticks = beat_ticks->with_pitch(get_pitch());
|
||||
@ -1028,56 +1023,56 @@ void EditorState::display_linear_view() {
|
||||
void EditorState::display_sound_settings() {
|
||||
if (ImGui::Begin("Sound Settings", &show_sound_settings)) {
|
||||
if (ImGui::TreeNodeEx("Music", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
ImGui::BeginDisabled(not music.has_value());
|
||||
{
|
||||
auto volume = get_volume();
|
||||
if (ImGui::SliderInt("Volume##Music", &volume, 0, 10)) {
|
||||
set_volume(volume);
|
||||
}
|
||||
const auto music_exists = music.has_value();
|
||||
if (not music_exists) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
if (ImGui::SliderInt("Volume##Music", &config.sound.music_volume, 0, 10)) {
|
||||
set_volume(config.sound.music_volume);
|
||||
}
|
||||
if (not music_exists) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNodeEx("Beat Tick", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
bool beat_tick = beat_ticks_are_on();
|
||||
if (ImGui::Checkbox("On/Off##Beat Tick", &beat_tick)) {
|
||||
if (ImGui::Checkbox("On/Off##Beat Tick", &config.sound.beat_tick)) {
|
||||
toggle_beat_ticks();
|
||||
}
|
||||
ImGui::BeginDisabled(not beat_tick);
|
||||
{
|
||||
auto volume = beat_ticks->get_volume();
|
||||
if (ImGui::SliderInt("Volume##Beat Tick", &volume, 0, 10)) {
|
||||
beat_ticks->set_volume(volume);
|
||||
}
|
||||
if (not config.sound.beat_tick) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
if (ImGui::SliderInt("Volume##Beat Tick", &config.sound.beat_tick_volume, 0, 10)) {
|
||||
beat_ticks->set_volume(config.sound.beat_tick_volume);
|
||||
}
|
||||
if (not config.sound.beat_tick) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNodeEx("Note Clap", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
bool note_clap = note_claps_are_on();
|
||||
if (ImGui::Checkbox("On/Off##Note Clap", ¬e_clap)) {
|
||||
if (ImGui::Checkbox("On/Off##Note Clap", &config.sound.note_clap)) {
|
||||
toggle_note_claps();
|
||||
}
|
||||
ImGui::BeginDisabled(not note_clap);
|
||||
{
|
||||
auto volume = note_claps->get_volume();
|
||||
if (ImGui::SliderInt("Volume##Note Clap", &volume, 0, 10)) {
|
||||
note_claps->set_volume(volume);
|
||||
chord_claps->set_volume(volume);
|
||||
}
|
||||
if (ImGui::TreeNode("Advanced##Note Clap")) {
|
||||
bool long_end = get_clap_on_long_note_ends();
|
||||
if (ImGui::Checkbox("Clap on long note ends", &long_end)) {
|
||||
toggle_clap_on_long_note_ends();
|
||||
}
|
||||
bool chord_clap = get_distinct_chord_claps();
|
||||
if (ImGui::Checkbox("Distinct chord clap", &chord_clap)) {
|
||||
toggle_distinct_chord_claps();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (not config.sound.note_clap) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
if (ImGui::SliderInt("Volume##Note Clap", &config.sound.note_clap_volume, 0, 10)) {
|
||||
note_claps->set_volume(config.sound.note_clap_volume);
|
||||
chord_claps->set_volume(config.sound.note_clap_volume);
|
||||
}
|
||||
if (ImGui::TreeNode("Advanced##Note Clap")) {
|
||||
if (ImGui::Checkbox("Clap on long note ends", &config.sound.clap_on_long_note_ends)) {
|
||||
toggle_clap_on_long_note_ends();
|
||||
}
|
||||
if (ImGui::Checkbox("Distinct chord clap", &config.sound.distinct_chord_clap)) {
|
||||
toggle_distinct_chord_claps();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (not config.sound.note_clap) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
@ -1535,6 +1530,15 @@ void EditorState::replace_applicable_timing_with(const better::Timing& new_timin
|
||||
}
|
||||
}
|
||||
|
||||
bool EditorState::note_clap_stream_is_on() const {
|
||||
return audio.contains_stream(note_clap_stream) or audio.contains_stream(chord_clap_stream);
|
||||
}
|
||||
|
||||
bool EditorState::beat_tick_stream_is_on() const {
|
||||
return audio.contains_stream(beat_tick_stream);
|
||||
}
|
||||
|
||||
|
||||
Interval<sf::Time> EditorState::choose_editable_range() {
|
||||
Interval<sf::Time> new_range{sf::Time::Zero, sf::Time::Zero};
|
||||
// In all cases, allow editing from beat zero (which might be at a negative
|
||||
@ -1599,6 +1603,7 @@ std::optional<std::filesystem::path> EditorState::full_audio_path() {
|
||||
* Reloads music from what's indicated in the "music path" field of the song
|
||||
* Resets the music state in case anything fails
|
||||
* Updates playbackPosition and preview_end as well
|
||||
* Sets claps and ticks according to config
|
||||
*/
|
||||
void EditorState::reload_music() {
|
||||
const auto status_before = get_status();
|
||||
@ -1620,6 +1625,22 @@ void EditorState::reload_music() {
|
||||
if (music.has_value()) {
|
||||
audio.add_stream(music_stream, {*music, false});
|
||||
}
|
||||
set_volume(config.sound.music_volume);
|
||||
if (config.sound.beat_tick != beat_tick_stream_is_on()) {
|
||||
toggle_beat_ticks();
|
||||
}
|
||||
beat_ticks->set_volume(config.sound.beat_tick_volume);
|
||||
if (config.sound.note_clap != note_clap_stream_is_on()) {
|
||||
toggle_note_claps();
|
||||
}
|
||||
note_claps->set_volume(config.sound.note_clap_volume);
|
||||
chord_claps->set_volume(config.sound.note_clap_volume);
|
||||
if (config.sound.clap_on_long_note_ends != note_claps->does_play_long_note_ends()) {
|
||||
toggle_clap_on_long_note_ends();
|
||||
}
|
||||
if (config.sound.distinct_chord_clap != not note_claps->does_play_chords()) {
|
||||
toggle_distinct_chord_claps();
|
||||
}
|
||||
pause();
|
||||
set_playback_position(current_time());
|
||||
switch (status_before) {
|
||||
|
@ -79,8 +79,6 @@ public:
|
||||
std::future<std::vector<TempoCandidate>> tempo_candidates_loader;
|
||||
std::optional<std::vector<TempoCandidate>> tempo_candidates;
|
||||
|
||||
|
||||
|
||||
int get_volume() const;
|
||||
void set_volume(int newMusicVolume);
|
||||
void volume_up();
|
||||
@ -118,13 +116,9 @@ public:
|
||||
bool has_any_audio() const;
|
||||
void toggle_playback();
|
||||
void toggle_note_claps();
|
||||
bool note_claps_are_on() const {return audio.contains_stream(note_clap_stream);};
|
||||
void toggle_clap_on_long_note_ends();
|
||||
bool get_clap_on_long_note_ends() const {return clap_on_long_note_ends;};
|
||||
void toggle_distinct_chord_claps();
|
||||
bool get_distinct_chord_claps() const {return distinct_chord_clap;};
|
||||
void toggle_beat_ticks();
|
||||
bool beat_ticks_are_on() const {return audio.contains_stream(beat_tick_stream);};
|
||||
void play();
|
||||
void pause();
|
||||
void stop();
|
||||
@ -253,11 +247,11 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
int volume = 10; // 0 -> 10
|
||||
int speed = 10; // 1 -> 20
|
||||
|
||||
bool clap_on_long_note_ends = false;
|
||||
bool distinct_chord_clap = false;
|
||||
bool note_clap_stream_is_on() const;
|
||||
bool beat_tick_stream_is_on() const;
|
||||
|
||||
|
||||
// Playback status used when there is no actual audio being played
|
||||
sf::SoundSource::Status status = sf::SoundSource::Stopped;
|
||||
|
Loading…
x
Reference in New Issue
Block a user