Compare commits
2 Commits
master
...
feature/pa
| Author | SHA1 | Date | |
|---|---|---|---|
|
19c90b0434
|
|||
|
b996685fe6
|
15
.vscode/settings.json
vendored
15
.vscode/settings.json
vendored
@@ -64,7 +64,20 @@
|
|||||||
"__string": "cpp",
|
"__string": "cpp",
|
||||||
"compare": "cpp",
|
"compare": "cpp",
|
||||||
"concepts": "cpp",
|
"concepts": "cpp",
|
||||||
"numeric": "cpp"
|
"numeric": "cpp",
|
||||||
|
"__tree": "cpp",
|
||||||
|
"any": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"forward_list": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"shared_mutex": "cpp",
|
||||||
|
"span": "cpp",
|
||||||
|
"stack": "cpp",
|
||||||
|
"valarray": "cpp",
|
||||||
|
"ranges": "cpp",
|
||||||
|
"iostream": "cpp"
|
||||||
},
|
},
|
||||||
"FSharp.suggestGitignore": false,
|
"FSharp.suggestGitignore": false,
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,10 @@ FetchContent_Declare(
|
|||||||
|
|
||||||
FetchContent_MakeAvailable(raylib)
|
FetchContent_MakeAvailable(raylib)
|
||||||
|
|
||||||
|
# Add nlohmann_json
|
||||||
|
# FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz)
|
||||||
|
# FetchContent_MakeAvailable(json)
|
||||||
|
|
||||||
# Adding our source files
|
# Adding our source files
|
||||||
file(GLOB_RECURSE PROJECT_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_LIST_DIR}/src/*.cpp") # Define PROJECT_SOURCES as a list of all source files
|
file(GLOB_RECURSE PROJECT_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_LIST_DIR}/src/*.cpp") # Define PROJECT_SOURCES as a list of all source files
|
||||||
set(PROJECT_INCLUDE "${CMAKE_CURRENT_LIST_DIR}/inc/") # Define PROJECT_INCLUDE to be the path to the include directory of the project
|
set(PROJECT_INCLUDE "${CMAKE_CURRENT_LIST_DIR}/inc/") # Define PROJECT_INCLUDE to be the path to the include directory of the project
|
||||||
@@ -31,6 +35,7 @@ set_target_properties(
|
|||||||
target_sources(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCES})
|
target_sources(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCES})
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_INCLUDE})
|
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_INCLUDE})
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE raylib)
|
target_link_libraries(${PROJECT_NAME} PRIVATE raylib)
|
||||||
|
# target_link_libraries(${PROJECT_NAME} PRIVATE json)
|
||||||
|
|
||||||
# Setting ASSETS_PATH
|
# Setting ASSETS_PATH
|
||||||
target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="${CMAKE_CURRENT_SOURCE_DIR}/assets/") # Set the asset path macro to the absolute path on the dev machine
|
target_compile_definitions(${PROJECT_NAME} PUBLIC ASSETS_PATH="${CMAKE_CURRENT_SOURCE_DIR}/assets/") # Set the asset path macro to the absolute path on the dev machine
|
||||||
|
|||||||
@@ -23,4 +23,5 @@ class Application {
|
|||||||
Application(/* args */);
|
Application(/* args */);
|
||||||
~Application();
|
~Application();
|
||||||
void Run();
|
void Run();
|
||||||
|
void ParsePatch(std::string file_path);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class Oscillator {
|
|||||||
~Oscillator();
|
~Oscillator();
|
||||||
OscillatorType GetType() { return m_osc; }
|
OscillatorType GetType() { return m_osc; }
|
||||||
void SetType(OscillatorType osc);
|
void SetType(OscillatorType osc);
|
||||||
|
void SetType(std::string const& osc_name);
|
||||||
float GetVolume() { return m_volume; }
|
float GetVolume() { return m_volume; }
|
||||||
void SetVolume(float volume) { m_volume = volume; }
|
void SetVolume(float volume) { m_volume = volume; }
|
||||||
float GetKey() { return m_key; }
|
float GetKey() { return m_key; }
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class Synth {
|
|||||||
std::vector<IEffect*> m_effects;
|
std::vector<IEffect*> m_effects;
|
||||||
std::vector<float> m_out_signal;
|
std::vector<float> m_out_signal;
|
||||||
LFO* m_lfo;
|
LFO* m_lfo;
|
||||||
|
float m_lfo_level;
|
||||||
void ZeroSignal();
|
void ZeroSignal();
|
||||||
void GetNote();
|
void GetNote();
|
||||||
void TriggerNoteOnEffects();
|
void TriggerNoteOnEffects();
|
||||||
@@ -36,5 +37,8 @@ class Synth {
|
|||||||
const bool& GetIsNoteTriggered() { return is_note_triggered; }
|
const bool& GetIsNoteTriggered() { return is_note_triggered; }
|
||||||
ADSR* GetADSR() { return (ADSR*)m_effects[0]; }
|
ADSR* GetADSR() { return (ADSR*)m_effects[0]; }
|
||||||
Filter* GetFilter() { return (Filter*)m_effects[1]; }
|
Filter* GetFilter() { return (Filter*)m_effects[1]; }
|
||||||
|
LFO* GetLFO() { return m_lfo; }
|
||||||
|
const float& GetLFOLevel() { return m_lfo_level; }
|
||||||
|
void SetLFOLevel(float lvl) { assert(0.f >= lvl <= 1.f); m_lfo_level = lvl; }
|
||||||
void SetFilter(FilterType type);
|
void SetFilter(FilterType type);
|
||||||
};
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "OscillatorType.h"
|
#include "OscillatorType.h"
|
||||||
#include "raygui.h"
|
#include "raysan/raygui.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "Filter.h"
|
#include "Filter.h"
|
||||||
|
|
||||||
|
|||||||
24765
inc/nlohmann/json.hpp
Normal file
24765
inc/nlohmann/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,12 @@
|
|||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
#include <cmath> // log10f
|
||||||
|
#include <fstream> // read file
|
||||||
|
#include <iostream> // log error
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
Application::Application(/* args */) {
|
Application::Application(/* args */) {
|
||||||
InitSynth();
|
InitSynth();
|
||||||
@@ -94,7 +99,7 @@ void Application::UpdateOnNoteInput() {
|
|||||||
if (!m_synth.GetIsNoteTriggered()) {
|
if (!m_synth.GetIsNoteTriggered()) {
|
||||||
m_synth.Trigger((*m_current_note));
|
m_synth.Trigger((*m_current_note));
|
||||||
}
|
}
|
||||||
//write_log("Note played: %s\n", m_current_note->name.c_str());
|
// write_log("Note played: %s\n", m_current_note->name.c_str());
|
||||||
} else if (is_note_up() && m_synth.GetIsNoteTriggered()) {
|
} else if (is_note_up() && m_synth.GetIsNoteTriggered()) {
|
||||||
m_synth.Release();
|
m_synth.Release();
|
||||||
}
|
}
|
||||||
@@ -118,3 +123,67 @@ void Application::Run() {
|
|||||||
m_renderer.Draw(m_synth, m_synth_gui_state);
|
m_renderer.Draw(m_synth, m_synth_gui_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::ParsePatch(std::string file_path) {
|
||||||
|
std::ifstream f(file_path);
|
||||||
|
if (!f.is_open()) {
|
||||||
|
std::cerr << "[ERR] failed to open " << file_path << '\n';
|
||||||
|
} else {
|
||||||
|
json data = json::parse(f);
|
||||||
|
|
||||||
|
auto oscillators = m_synth.GetOscillators();
|
||||||
|
for (int i = 0; i < oscillators.size(); i++) {
|
||||||
|
auto osc = oscillators[i];
|
||||||
|
auto gui_osc = m_synth_gui_state.oscillators[i];
|
||||||
|
|
||||||
|
std::string type =
|
||||||
|
data["Oscillators"][i]["Wave"].template get<std::string>();
|
||||||
|
float fine = data["Oscillators"][i]["Tune"].template get<float>();
|
||||||
|
float volume =
|
||||||
|
data["Oscillators"][i]["Volume"].template get<float>();
|
||||||
|
|
||||||
|
osc->SetType(type);
|
||||||
|
osc->SetFine(fine);
|
||||||
|
osc->SetVolume(volume);
|
||||||
|
|
||||||
|
gui_osc->waveshape = osc->GetType();
|
||||||
|
gui_osc->fine = fine;
|
||||||
|
gui_osc->volume = volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto adsr = m_synth.GetADSR();
|
||||||
|
auto gui_adsr = m_synth_gui_state.adsr;
|
||||||
|
|
||||||
|
auto adsr_params = data["ADSR"];
|
||||||
|
float attack = adsr_params["Attack"].template get<float>();
|
||||||
|
float decay = adsr_params["Decay"].template get<float>();
|
||||||
|
float sustain = adsr_params["Sustain"].template get<float>();
|
||||||
|
float release = adsr_params["Release"].template get<float>();
|
||||||
|
|
||||||
|
adsr->SetParameters(attack, decay, sustain, release);
|
||||||
|
gui_adsr.attack = attack;
|
||||||
|
gui_adsr.decay = decay;
|
||||||
|
gui_adsr.sustain = sustain;
|
||||||
|
gui_adsr.release = release;
|
||||||
|
|
||||||
|
auto lfo = m_synth.GetLFO();
|
||||||
|
lfo->SetFreq(data["LFO"]["Freq"].template get<float>());
|
||||||
|
m_synth.SetLFOLevel(data["LFO"]["Level"].template get<float>());
|
||||||
|
|
||||||
|
auto filter_type =
|
||||||
|
(FilterType)data["Filter"]["Type"].template get<int>();
|
||||||
|
m_synth.SetFilter(filter_type);
|
||||||
|
|
||||||
|
auto filter = m_synth.GetFilter();
|
||||||
|
auto gui_filter = m_synth_gui_state.filter;
|
||||||
|
|
||||||
|
float filter_freq =
|
||||||
|
std::log10f(data["Filter"]["Cutoff"].template get<float>());
|
||||||
|
float filter_res = data["Filter"]["Res"].template get<float>();
|
||||||
|
float filter_drive = data["Filter"]["Drive"].template get<float>();
|
||||||
|
|
||||||
|
filter->SetParameters(filter_freq, filter_res, filter_drive);
|
||||||
|
gui_filter.freq = filter_freq;
|
||||||
|
gui_filter.type = filter_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,6 +43,19 @@ void Oscillator::SetType(OscillatorType osc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Oscillator::SetType(std::string const& osc_name) {
|
||||||
|
if (osc_name == "Sine")
|
||||||
|
m_osc = Sine;
|
||||||
|
else if (osc_name == "Triangle")
|
||||||
|
m_osc = Triangle;
|
||||||
|
else if (osc_name == "Saw")
|
||||||
|
m_osc = Saw;
|
||||||
|
else if (osc_name == "Square")
|
||||||
|
m_osc = Square;
|
||||||
|
|
||||||
|
SetType(m_osc);
|
||||||
|
}
|
||||||
|
|
||||||
void Oscillator::SetKey(float key) {
|
void Oscillator::SetKey(float key) {
|
||||||
m_key = key;
|
m_key = key;
|
||||||
float freq = KeyBoard::GetHzBySemitone(m_key + m_fine);
|
float freq = KeyBoard::GetHzBySemitone(m_key + m_fine);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
|
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
|
||||||
#pragma clang diagnostic ignored "-Wunused-variable"
|
#pragma clang diagnostic ignored "-Wunused-variable"
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
#include "raygui.h"
|
#include "raysan/raygui.h"
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
Renderer::Renderer(/* args */) {
|
Renderer::Renderer(/* args */) {
|
||||||
|
|||||||
@@ -1,7 +1,57 @@
|
|||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
inline bool file_exists(const std::string& name) {
|
||||||
|
if (FILE *file = fopen(name.c_str(), "r")) {
|
||||||
|
fclose(file);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[noreturn]] void print_help(char* const executable) {
|
||||||
|
std::cout << executable << " [options]\n" <<
|
||||||
|
"Options:\n" <<
|
||||||
|
" -h | --help Print this help\n" <<
|
||||||
|
" -p | --patch Path to a json file with a patch to apply\n" <<
|
||||||
|
" -v | --version Print a program version" << std::endl;
|
||||||
|
std::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc > 32) {
|
||||||
|
throw std::runtime_error("Too many input parameters!");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string patch_file_path;
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
auto arg = std::string(argv[i]);
|
||||||
|
if (arg == "-p" || arg == "--patch") {
|
||||||
|
patch_file_path = std::string(argv[i+1]);
|
||||||
|
if (patch_file_path.empty()) {
|
||||||
|
std::cerr << "no file path provided\n";
|
||||||
|
print_help(argv[0]);
|
||||||
|
}
|
||||||
|
else if (!file_exists(patch_file_path)) {
|
||||||
|
std::cerr << patch_file_path << ": no such file\n";
|
||||||
|
print_help(argv[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arg == "-h" || arg == "--help") {
|
||||||
|
print_help(argv[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
|
||||||
Application* app = new Application();
|
Application* app = new Application();
|
||||||
|
|
||||||
|
if (!patch_file_path.empty()) {
|
||||||
|
app->ParsePatch(patch_file_path);
|
||||||
|
}
|
||||||
|
|
||||||
app->Run();
|
app->Run();
|
||||||
|
|
||||||
delete app;
|
delete app;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
Synth::Synth(/* args */) {
|
Synth::Synth(/* args */) {
|
||||||
m_lfo = new LFO();
|
m_lfo = new LFO();
|
||||||
m_lfo->SetFreq(5.0);
|
m_lfo->SetFreq(2.0);
|
||||||
AddOscillator();
|
AddOscillator();
|
||||||
AddOscillator();
|
AddOscillator();
|
||||||
AddEffect(new ADSR());
|
AddEffect(new ADSR());
|
||||||
@@ -79,7 +79,7 @@ void Synth::ApplyFilterLfo() {
|
|||||||
float dt = m_lfo->Process();
|
float dt = m_lfo->Process();
|
||||||
Filter* filter = (Filter*)m_effects[1];
|
Filter* filter = (Filter*)m_effects[1];
|
||||||
float freq = filter->GetFreq();
|
float freq = filter->GetFreq();
|
||||||
filter->SetParameters(freq + dt, filter->GetRes(), filter->GetPeakGain());
|
filter->SetParameters(freq + dt*0.5f, filter->GetRes(), filter->GetPeakGain());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Synth::Process() {
|
void Synth::Process() {
|
||||||
|
|||||||
Reference in New Issue
Block a user