From a3f4ac00ee76f5e3b2dae7838a6c13ccae40ceac Mon Sep 17 00:00:00 2001 From: cflip Date: Sun, 20 Feb 2022 09:15:40 -0700 Subject: Set up CMake build system --- .gitignore | 24 ++++++++++------ CMakeLists.txt | 16 +++++++++++ Makefile | 6 ---- audio.cpp | 88 ---------------------------------------------------------- audio.h | 24 ---------------- gui.cpp | 78 --------------------------------------------------- gui.h | 37 ------------------------ main.cpp | 57 ------------------------------------- sequence.h | 12 -------- src/audio.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/audio.h | 24 ++++++++++++++++ src/gui.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/gui.h | 37 ++++++++++++++++++++++++ src/main.cpp | 57 +++++++++++++++++++++++++++++++++++++ src/sequence.h | 12 ++++++++ 15 files changed, 326 insertions(+), 311 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 Makefile delete mode 100644 audio.cpp delete mode 100644 audio.h delete mode 100644 gui.cpp delete mode 100644 gui.h delete mode 100644 main.cpp delete mode 100644 sequence.h create mode 100644 src/audio.cpp create mode 100644 src/audio.h create mode 100644 src/gui.cpp create mode 100644 src/gui.h create mode 100644 src/main.cpp create mode 100644 src/sequence.h diff --git a/.gitignore b/.gitignore index 93659d7..1b963c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,16 @@ -.vscode -fmseq +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles/ +CMakeScripts/ +Testing/ +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps/ + +Makefile +out/ +.vs/ -# Visual Studio garbage -Debug/ -*.sln -*.vcxproj -*.vcxproj.filters -*.vcxproj.user -*.pdb \ No newline at end of file +fmseq diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f9c8fa9 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.5) +set(CMAKE_CXX_STANDARD 17) + +project(fmseq) + +find_package(SDL2 REQUIRED) +include_directories(${SDL2_INCLUDE_DIRS}) + +set(SOURCES + src/audio.cpp + src/main.cpp + src/gui.cpp +) + +add_executable(fmseq ${SOURCES}) +target_link_libraries(fmseq ${SDL2_LIBRARIES}) \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index 4cfed7a..0000000 --- a/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -SRC=main.cpp\ - audio.cpp\ - gui.cpp - -fmseq: ${SRC} - g++ ${SRC} -lSDL2 -o fmseq \ No newline at end of file diff --git a/audio.cpp b/audio.cpp deleted file mode 100644 index 712dddc..0000000 --- a/audio.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "audio.h" - -#define _USE_MATH_DEFINES -#include -#include -#include - -#include "sequence.h" - -static const float AMPLITUDE = 0.2f; - -// SDL periodically calls this function to fill a chunk of the audio output buffer -static void AudioCallback(void* userData, Uint8* rawBuffer, int bytes) -{ - float* buffer = (float*)rawBuffer; - int length = bytes / sizeof(float); - CallbackInfo* info = (CallbackInfo*)userData; - StepData& step = info->seq->steps[info->currentStep]; - - for (int i = 0; i < length; i++, info->samplesDone++) { - float time = (float)info->samplesDone / (float)info->sampleRate; - float modWave = sinf(2.0f * M_PI * step.modFreq * time); - float freq = step.carrierFreq + modWave * step.modDepth; - - // Check if enough samples have been generated for this step - if (info->samplesDone >= info->samplesPerStep) { - // If so, move on to the next step - info->samplesDone = 0; - step = info->seq->steps[info->currentStep]; - info->currentStep = (info->currentStep + 1) % 8; - } - - buffer[i] = (sinf(2.0f * M_PI * freq * time)) * AMPLITUDE; - } -} - -AudioContext::AudioContext(Sequence& seq) -{ - SDL_AudioSpec desiredSpec; - desiredSpec.freq = 44100; - desiredSpec.format = AUDIO_F32SYS; - desiredSpec.channels = 1; - desiredSpec.samples = 2048; - desiredSpec.callback = AudioCallback; - desiredSpec.userdata = &m_info; - - SDL_AudioSpec obtainedSpec; - if (SDL_OpenAudio(&desiredSpec, &obtainedSpec) < 0) { - std::cerr << "Failed to initalize audio! " << SDL_GetError() << std::endl; - std::exit(1); - } - - // The audio callback expects float values, so if a different data type - // is obtained we should throw an error. - if (desiredSpec.format != obtainedSpec.format) { - std::cerr << "Unexpected audio format: " << obtainedSpec.format << std::endl; - std::exit(1); - } - - m_info.samplesDone = 0; - m_info.samplesPerStep = obtainedSpec.freq * 0.4f; - m_info.currentStep = 0; - m_info.sampleRate = obtainedSpec.freq; - m_info.seq = &seq; - - this->Start(); -} - -AudioContext::~AudioContext() -{ - this->Stop(); - SDL_CloseAudio(); -} - -void AudioContext::Start() -{ - SDL_PauseAudio(0); -} - -void AudioContext::Stop() -{ - SDL_PauseAudio(1); -} - -int AudioContext::CurrentStep() -{ - return m_info.currentStep; -} \ No newline at end of file diff --git a/audio.h b/audio.h deleted file mode 100644 index 6205de7..0000000 --- a/audio.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -class Sequence; - -struct CallbackInfo { - int samplesDone; - int samplesPerStep; - int currentStep; - int sampleRate; - Sequence* seq; -}; - -class AudioContext { -public: - AudioContext(Sequence&); - ~AudioContext(); - - void Start(); - void Stop(); - - int CurrentStep(); -private: - CallbackInfo m_info; -}; \ No newline at end of file diff --git a/gui.cpp b/gui.cpp deleted file mode 100644 index 1070e9f..0000000 --- a/gui.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "gui.h" - -#include -#include "sequence.h" - -void Slider::Draw(SDL_Renderer* renderer) -{ - SDL_RenderDrawRect(renderer, &m_bounds); - SDL_RenderDrawLine(renderer, m_bounds.x, m_bounds.y + (*value * valueScaling), m_bounds.x + m_bounds.w, m_bounds.y + (*value * valueScaling)); -} - -bool Slider::InBounds(int x, int y) -{ - SDL_Point point = { x, y }; - return SDL_PointInRect(&point, &m_bounds); -} - -GUI::GUI(Sequence& seq) - : m_sequence(seq) -{ - int i = 0; - for (auto& step : seq.steps) { - m_sliders.emplace_back(i * 40 + 14, 60, &step.carrierFreq, 0.1f); - m_sliders.emplace_back(i * 40 + 14, 145, &step.modFreq); - m_sliders.emplace_back(i * 40 + 14, 230, &step.modDepth, 3.0f); - i++; - } -} - -void GUI::OnMouseDown(int x, int y) -{ - for (Slider& slider : m_sliders) { - if (slider.InBounds(x, y)) { - m_activeSlider = &slider; - m_dragStart = y; - return; - } - } -} - -void GUI::OnMouseUp() -{ - m_activeSlider = nullptr; - m_dragStart = 0; -} - -void GUI::OnMouseMove(int x, int y) -{ - if (m_activeSlider) { - *m_activeSlider->value -= (m_dragStart - y) / m_activeSlider->valueScaling; - m_dragStart = y; - - if (*m_activeSlider->value < 0) - *m_activeSlider->value = 0; - } -} - -void GUI::Repaint(SDL_Renderer* renderer, int currentStep) -{ - SDL_Rect rect = { 10, 10, 32, 32 }; - - for (int i = 0; i < 8; i++) { - SDL_SetRenderDrawColor(renderer, m_sequence.steps[i].modDepth * 8, m_sequence.steps[i].modFreq * 2, m_sequence.steps[i].carrierFreq / 3, 255); - - if (i == currentStep) - SDL_RenderFillRect(renderer, &rect); - else - SDL_RenderDrawRect(renderer, &rect); - - rect.x += rect.w + 8; - } - - SDL_SetRenderDrawColor(renderer, 127, 127, 255, 255); - - for (Slider& slider : m_sliders) { - slider.Draw(renderer); - } -} \ No newline at end of file diff --git a/gui.h b/gui.h deleted file mode 100644 index ee6a51c..0000000 --- a/gui.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include - -#include -#include "sequence.h" - -class Slider { -public: - Slider(int x, int y, float* valuePtr, float scaling = 1.f) - : m_bounds({ x, y, 25, 75 }), value(valuePtr), valueScaling(scaling) {} - - void Draw(SDL_Renderer*); - bool InBounds(int x, int y); - - float* value; - float valueScaling; -private: - SDL_Rect m_bounds; -}; - -class GUI { -public: - GUI(Sequence&); - - void OnMouseDown(int x, int y); - void OnMouseUp(); - void OnMouseMove(int x, int y); - - void Repaint(SDL_Renderer*, int currentStep); -private: - std::vector m_sliders; - - Sequence& m_sequence; - Slider* m_activeSlider{ nullptr }; - int m_dragStart{ 0 }; -}; \ No newline at end of file diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 8fd1f2a..0000000 --- a/main.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include - -#include "audio.h" -#include "gui.h" -#include "sequence.h" - -int main(int argc, char** argv) -{ - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { - std::cerr << "Failed to initalize SDL! " << SDL_GetError() << std::endl; - return 1; - } - - SDL_Window* window = SDL_CreateWindow("fmseq", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 320, SDL_WINDOW_SHOWN); - SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); - SDL_Event event; - - Sequence sequence; - AudioContext audio(sequence); - GUI gui(sequence); - - bool running = true; - while (running) { - while (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_QUIT: - running = false; - break; - case SDL_MOUSEBUTTONDOWN: - gui.OnMouseDown(event.button.x, event.button.y); - break; - case SDL_MOUSEMOTION: - gui.OnMouseMove(event.button.x, event.button.y); - break; - case SDL_MOUSEBUTTONUP: - gui.OnMouseUp(); - break; - } - } - - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - SDL_RenderClear(renderer); - - gui.Repaint(renderer, audio.CurrentStep()); - - SDL_RenderPresent(renderer); - SDL_UpdateWindowSurface(window); - - SDL_Delay(10); - } - - SDL_DestroyWindow(window); - SDL_Quit(); - - return 0; -} \ No newline at end of file diff --git a/sequence.h b/sequence.h deleted file mode 100644 index decd9fd..0000000 --- a/sequence.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -struct StepData { - float carrierFreq = 110.f; - float modFreq = 0; - float modDepth = 1; -}; - -class Sequence { -public: - StepData steps[8]; -}; \ No newline at end of file diff --git a/src/audio.cpp b/src/audio.cpp new file mode 100644 index 0000000..db915e1 --- /dev/null +++ b/src/audio.cpp @@ -0,0 +1,88 @@ +#include "audio.h" + +#define _USE_MATH_DEFINES +#include +#include +#include + +#include "sequence.h" + +static const float AMPLITUDE = 0.2f; + +// SDL periodically calls this function to fill a chunk of the audio output buffer +static void AudioCallback(void* userData, Uint8* rawBuffer, int bytes) +{ + float* buffer = (float*)rawBuffer; + int length = bytes / sizeof(float); + CallbackInfo* info = (CallbackInfo*)userData; + StepData& step = info->seq->steps[info->currentStep]; + + for (int i = 0; i < length; i++, info->samplesDone++) { + float time = (float)info->samplesDone / (float)info->sampleRate; + float modWave = sinf(2.0f * M_PI * step.modFreq * time); + float freq = step.carrierFreq + modWave * step.modDepth; + + // Check if enough samples have been generated for this step + if (info->samplesDone >= info->samplesPerStep) { + // If so, move on to the next step + info->samplesDone = 0; + step = info->seq->steps[info->currentStep]; + info->currentStep = (info->currentStep + 1) % 8; + } + + buffer[i] = (sinf(2.0f * M_PI * freq * time)) * AMPLITUDE; + } +} + +AudioContext::AudioContext(Sequence& seq) +{ + SDL_AudioSpec desiredSpec; + desiredSpec.freq = 44100; + desiredSpec.format = AUDIO_F32SYS; + desiredSpec.channels = 1; + desiredSpec.samples = 2048; + desiredSpec.callback = AudioCallback; + desiredSpec.userdata = &m_info; + + SDL_AudioSpec obtainedSpec; + if (SDL_OpenAudio(&desiredSpec, &obtainedSpec) < 0) { + std::cerr << "Failed to initalize audio! " << SDL_GetError() << std::endl; + std::exit(1); + } + + // The audio callback expects float values, so if a different data type + // is obtained we should throw an error. + if (desiredSpec.format != obtainedSpec.format) { + std::cerr << "Unexpected audio format: " << obtainedSpec.format << std::endl; + std::exit(1); + } + + m_info.samplesDone = 0; + m_info.samplesPerStep = obtainedSpec.freq * 0.4f; + m_info.currentStep = 0; + m_info.sampleRate = obtainedSpec.freq; + m_info.seq = &seq; + + this->Start(); +} + +AudioContext::~AudioContext() +{ + this->Stop(); + SDL_CloseAudio(); +} + +void AudioContext::Start() +{ + SDL_PauseAudio(0); +} + +void AudioContext::Stop() +{ + SDL_PauseAudio(1); +} + +int AudioContext::CurrentStep() +{ + return m_info.currentStep; +} \ No newline at end of file diff --git a/src/audio.h b/src/audio.h new file mode 100644 index 0000000..6205de7 --- /dev/null +++ b/src/audio.h @@ -0,0 +1,24 @@ +#pragma once + +class Sequence; + +struct CallbackInfo { + int samplesDone; + int samplesPerStep; + int currentStep; + int sampleRate; + Sequence* seq; +}; + +class AudioContext { +public: + AudioContext(Sequence&); + ~AudioContext(); + + void Start(); + void Stop(); + + int CurrentStep(); +private: + CallbackInfo m_info; +}; \ No newline at end of file diff --git a/src/gui.cpp b/src/gui.cpp new file mode 100644 index 0000000..fcd4511 --- /dev/null +++ b/src/gui.cpp @@ -0,0 +1,77 @@ +#include "gui.h" + +#include "sequence.h" + +void Slider::Draw(SDL_Renderer* renderer) +{ + SDL_RenderDrawRect(renderer, &m_bounds); + SDL_RenderDrawLine(renderer, m_bounds.x, m_bounds.y + (*value * valueScaling), m_bounds.x + m_bounds.w, m_bounds.y + (*value * valueScaling)); +} + +bool Slider::InBounds(int x, int y) +{ + SDL_Point point = { x, y }; + return SDL_PointInRect(&point, &m_bounds); +} + +GUI::GUI(Sequence& seq) + : m_sequence(seq) +{ + int i = 0; + for (auto& step : seq.steps) { + m_sliders.emplace_back(i * 40 + 14, 60, &step.carrierFreq, 0.1f); + m_sliders.emplace_back(i * 40 + 14, 145, &step.modFreq); + m_sliders.emplace_back(i * 40 + 14, 230, &step.modDepth, 3.0f); + i++; + } +} + +void GUI::OnMouseDown(int x, int y) +{ + for (Slider& slider : m_sliders) { + if (slider.InBounds(x, y)) { + m_activeSlider = &slider; + m_dragStart = y; + return; + } + } +} + +void GUI::OnMouseUp() +{ + m_activeSlider = nullptr; + m_dragStart = 0; +} + +void GUI::OnMouseMove(int x, int y) +{ + if (m_activeSlider) { + *m_activeSlider->value -= (m_dragStart - y) / m_activeSlider->valueScaling; + m_dragStart = y; + + if (*m_activeSlider->value < 0) + *m_activeSlider->value = 0; + } +} + +void GUI::Repaint(SDL_Renderer* renderer, int currentStep) +{ + SDL_Rect rect = { 10, 10, 32, 32 }; + + for (int i = 0; i < 8; i++) { + SDL_SetRenderDrawColor(renderer, m_sequence.steps[i].modDepth * 8, m_sequence.steps[i].modFreq * 2, m_sequence.steps[i].carrierFreq / 3, 255); + + if (i == currentStep) + SDL_RenderFillRect(renderer, &rect); + else + SDL_RenderDrawRect(renderer, &rect); + + rect.x += rect.w + 8; + } + + SDL_SetRenderDrawColor(renderer, 127, 127, 255, 255); + + for (Slider& slider : m_sliders) { + slider.Draw(renderer); + } +} \ No newline at end of file diff --git a/src/gui.h b/src/gui.h new file mode 100644 index 0000000..76a1128 --- /dev/null +++ b/src/gui.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +#include +#include "sequence.h" + +class Slider { +public: + Slider(int x, int y, float* valuePtr, float scaling = 1.f) + : m_bounds({ x, y, 25, 75 }), value(valuePtr), valueScaling(scaling) {} + + void Draw(SDL_Renderer*); + bool InBounds(int x, int y); + + float* value; + float valueScaling; +private: + SDL_Rect m_bounds; +}; + +class GUI { +public: + GUI(Sequence&); + + void OnMouseDown(int x, int y); + void OnMouseUp(); + void OnMouseMove(int x, int y); + + void Repaint(SDL_Renderer*, int currentStep); +private: + std::vector m_sliders; + + Sequence& m_sequence; + Slider* m_activeSlider{ nullptr }; + int m_dragStart{ 0 }; +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..6056442 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,57 @@ +#include +#include + +#include "audio.h" +#include "gui.h" +#include "sequence.h" + +int main(int argc, char** argv) +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { + std::cerr << "Failed to initalize SDL! " << SDL_GetError() << std::endl; + return 1; + } + + SDL_Window* window = SDL_CreateWindow("fmseq", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 320, SDL_WINDOW_SHOWN); + SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + SDL_Event event; + + Sequence sequence; + AudioContext audio(sequence); + GUI gui(sequence); + + bool running = true; + while (running) { + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + running = false; + break; + case SDL_MOUSEBUTTONDOWN: + gui.OnMouseDown(event.button.x, event.button.y); + break; + case SDL_MOUSEMOTION: + gui.OnMouseMove(event.button.x, event.button.y); + break; + case SDL_MOUSEBUTTONUP: + gui.OnMouseUp(); + break; + } + } + + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); + + gui.Repaint(renderer, audio.CurrentStep()); + + SDL_RenderPresent(renderer); + SDL_UpdateWindowSurface(window); + + SDL_Delay(10); + } + + SDL_DestroyWindow(window); + SDL_Quit(); + + return 0; +} \ No newline at end of file diff --git a/src/sequence.h b/src/sequence.h new file mode 100644 index 0000000..decd9fd --- /dev/null +++ b/src/sequence.h @@ -0,0 +1,12 @@ +#pragma once + +struct StepData { + float carrierFreq = 110.f; + float modFreq = 0; + float modDepth = 1; +}; + +class Sequence { +public: + StepData steps[8]; +}; \ No newline at end of file -- cgit v1.2.3