diff --git a/src/Squidbox.cpp b/src/Squidbox.cpp index 850c451..2a0433d 100644 --- a/src/Squidbox.cpp +++ b/src/Squidbox.cpp @@ -35,6 +35,7 @@ void Squidbox::init() { midiController->begin(); commander->begin(); Config::begin(); + randomSeed(micros()); //Added to ensure different random velocities each time the device is turned on // Initialize the scenes with this Squidbox instance scenes[MAIN_SCENE] = new MainScene(this); @@ -117,3 +118,46 @@ const char *Squidbox::getName() { sprintf(name, "Squidbox %s", deviceId); return name; } + +//All helper functions for random velocity below + +bool Squidbox::isRandomVelocityEnabled() const { + return randomVelocityEnabled; +} + +void Squidbox::setRandomVelocityEnabled(bool enabled) { + randomVelocityEnabled = enabled; +} + +void Squidbox::toggleRandomVelocity() { + randomVelocityEnabled = !randomVelocityEnabled; +} + +uint8_t Squidbox::getNoteOnVelocity() { + if (randomVelocityEnabled) { + return random(randomVelocityMin, randomVelocityMax + 1); + } + return fixedVelocity; +} + +uint8_t Squidbox::getFixedVelocity() const { + return fixedVelocity; +} + +void Squidbox::setFixedVelocity(uint8_t velocity) { + fixedVelocity = velocity; +} + +void Squidbox::setRandomVelocityRange(uint8_t minVelocity, + uint8_t maxVelocity) { + randomVelocityMin = minVelocity; + randomVelocityMax = maxVelocity; +} + +uint8_t Squidbox::getRandomVelocityMin() const { + return randomVelocityMin; +} + +uint8_t Squidbox::getRandomVelocityMax() const { + return randomVelocityMax; +} \ No newline at end of file diff --git a/src/Squidbox.h b/src/Squidbox.h index 5a1ec43..cc79ac9 100644 --- a/src/Squidbox.h +++ b/src/Squidbox.h @@ -143,6 +143,55 @@ class Squidbox { */ const int getBatteryPercent(); + /** + * @brief Returns whether random velocity is enabled + */ + bool isRandomVelocityEnabled() const; + + /** + * @brief Enable or disable random velocity + * @param enabled true = random velocity, false = fixed velocity + */ + void setRandomVelocityEnabled(bool enabled); + + /** + * @brief Toggle random velocity on/off + */ + void toggleRandomVelocity(); + + /** + * @brief Get the velocity that should be used for a Note On + * @return Either a fixed velocity or a randomized one + */ + uint8_t getNoteOnVelocity(); + + /** + * @brief Get the fixed velocity value + */ + uint8_t getFixedVelocity() const; + + /** + * @brief Set the fixed velocity value + */ + void setFixedVelocity(uint8_t velocity); + + /** + * @brief Set the random velocity range + * @param minVelocity minimum random velocity + * @param maxVelocity maximum random velocity + */ + void setRandomVelocityRange(uint8_t minVelocity, uint8_t maxVelocity); + + /** + * @brief Get the minimum random velocity + */ + uint8_t getRandomVelocityMin() const; + + /** + * @brief Get the maximum random velocity + */ + uint8_t getRandomVelocityMax() const; + private: Config *config; ///< A pointer to the configuration of the Squidbox Scene *scenes[NUM_SCENES]; ///< An array of pointers to the scenes in the @@ -151,13 +200,19 @@ class Squidbox { Screen *screen; ///< A pointer to the screen of the Squidbox Joystick *joystick; ///< A pointer to the joystick of the Squidbox Knob *knob; ///< A pointer to the knob of the Squidbox - Button *backButton; ///< A pointer to the back button of the Squidbox - Button *okButton; ///< A pointer to the OK button of the Squidbox - Button *buttons[NUM_BUTTONS]; ///< An array of pointers to the buttons of the - ///< Squidbox + Button *backButton; ///< A pointer to the back button of the Squidbox + Button *okButton; ///< A pointer to the OK button of the Squidbox + Button *buttons[NUM_BUTTONS]; ///< An array of pointers to the buttons of the + ///< Squidbox MidiController *midiController; ///< A pointer to the MIDI controller of the Squidbox bool currentSceneInitialized = false; ///< A flag indicating whether the ///< current scene has been initialized Commander *commander; ///< A pointer to the commander of the Squidbox + + // Velocity settings + bool randomVelocityEnabled = false; + uint8_t fixedVelocity = 127; + uint8_t randomVelocityMin = 70; + uint8_t randomVelocityMax = 127; }; \ No newline at end of file diff --git a/src/gui/menu-item/random-velocity/RandomVelocityMenuItem.cpp b/src/gui/menu-item/random-velocity/RandomVelocityMenuItem.cpp new file mode 100644 index 0000000..1a80117 --- /dev/null +++ b/src/gui/menu-item/random-velocity/RandomVelocityMenuItem.cpp @@ -0,0 +1,37 @@ +#include "RandomVelocityMenuItem.h" +#include "Squidbox.h" + +RandomVelocityMenuItem::RandomVelocityMenuItem(Squidbox *squidbox) + : MenuItem(), squidbox(squidbox) { + + // Set knob callbacks + setOnKnobLeftCallback(onKnobLeft, this); + setOnKnobRightCallback(onKnobRight, this); + + // Set initial label + updateName(); +} + +void RandomVelocityMenuItem::updateName() { + if (squidbox->isRandomVelocityEnabled()) { + setName("Velocity: Random"); + } else { + setName("Velocity: Fixed"); + } +} + +void RandomVelocityMenuItem::onKnobLeft(void *arg) { + RandomVelocityMenuItem *self = + static_cast(arg); + + self->squidbox->toggleRandomVelocity(); + self->updateName(); +} + +void RandomVelocityMenuItem::onKnobRight(void *arg) { + RandomVelocityMenuItem *self = + static_cast(arg); + + self->squidbox->toggleRandomVelocity(); + self->updateName(); +} \ No newline at end of file diff --git a/src/gui/menu-item/random-velocity/RandomVelocityMenuItem.h b/src/gui/menu-item/random-velocity/RandomVelocityMenuItem.h new file mode 100644 index 0000000..5f8ac52 --- /dev/null +++ b/src/gui/menu-item/random-velocity/RandomVelocityMenuItem.h @@ -0,0 +1,35 @@ +#pragma once + +#include "gui/menu-item/MenuItem.h" + +class Squidbox; + +/** + * @class RandomVelocityMenuItem + * @brief Toggle between fixed and random velocity + */ +class RandomVelocityMenuItem : public MenuItem { +private: + Squidbox *squidbox; + + /** + * @brief Handle knob left + */ + static void onKnobLeft(void *arg); + + /** + * @brief Handle knob right + */ + static void onKnobRight(void *arg); + + /** + * @brief Update label based on current state + */ + void updateName(); + +public: + /** + * @brief Construct a new RandomVelocityMenuItem + */ + RandomVelocityMenuItem(Squidbox *squidbox); +}; \ No newline at end of file diff --git a/src/scene/chord/ChordScene.cpp b/src/scene/chord/ChordScene.cpp index 3cd516b..c8effd3 100644 --- a/src/scene/chord/ChordScene.cpp +++ b/src/scene/chord/ChordScene.cpp @@ -1,19 +1,23 @@ +#include "ChordScene.h" #include "Squidbox.h" +#include "gui/menu-item/random-velocity/RandomVelocityMenuItem.h" ChordScene::ChordScene(Squidbox *squidbox) : Scene(squidbox, nullptr) { - // Create menu items for root note, scale, and chord type + // Create menu items for root note, scale, chord type, and random velocity rootMenuItem = new RootNoteMenuItem(); scaleMenuItem = new ScaleMenuItem(); chordTypeMenuItem = new ChordTypeMenuItem(); + randomVelocityMenuItem = new RandomVelocityMenuItem(squidbox); // Create an array of menu items - MenuItem **menuItems = new MenuItem *[3]; + MenuItem **menuItems = new MenuItem *[4]; menuItems[0] = rootMenuItem; menuItems[1] = scaleMenuItem; menuItems[2] = chordTypeMenuItem; + menuItems[3] = randomVelocityMenuItem; // Create a new menu with the menu items - menu = new Menu("Chords", 3, menuItems, MAIN_SCENE); + menu = new Menu("Chords", 4, menuItems, MAIN_SCENE); // Create a new keyboard keyboard = new Keyboard(squidbox); @@ -52,11 +56,9 @@ void ChordScene::playChord(int index, bool on) { // Play or stop playing the notes for (int i = 0; i < chordType->numNotes; i++) { keyboard->setKeyDown(notes[i], on); - if (on) { - // If the chord should be played, play the note - squidbox->getMidiController()->sendNoteOn(notes[i], 127, 0); - } else { - // If the chord should be stopped, stop playing the note + if (on) { // If the chord should be played, play the note + squidbox->getMidiController()->sendNoteOn(notes[i], squidbox->getNoteOnVelocity(), 0); //changed to have a randomized velocity if enabled + } else { // If the chord should be stopped, stop playing the note squidbox->getMidiController()->sendNoteOff(notes[i], 127, 0); } } diff --git a/src/scene/chord/ChordScene.h b/src/scene/chord/ChordScene.h index dc8de0d..a660a5e 100644 --- a/src/scene/chord/ChordScene.h +++ b/src/scene/chord/ChordScene.h @@ -1,5 +1,6 @@ #pragma once +#include "gui/menu-item/random-velocity/RandomVelocityMenuItem.h" #include "gui/keyboard/Keyboard.h" #include "gui/menu-item/chord-type/ChordTypeMenuItem.h" #include "gui/menu-item/root-note/RootNoteMenuItem.h" @@ -21,6 +22,7 @@ class ChordScene : public Scene { RootNoteMenuItem *rootMenuItem; ///< The menu item for selecting the root note. ScaleMenuItem *scaleMenuItem; ///< The menu item for selecting the scale. + RandomVelocityMenuItem *randomVelocityMenuItem; ///< The menu item for toggling random velocity. ChordTypeMenuItem *chordTypeMenuItem; ///< The menu item for selecting the chord type. Keyboard *keyboard; ///< The keyboard for playing chords. diff --git a/src/scene/custom/CustomScene.cpp b/src/scene/custom/CustomScene.cpp index 919085e..19696b1 100644 --- a/src/scene/custom/CustomScene.cpp +++ b/src/scene/custom/CustomScene.cpp @@ -1,14 +1,18 @@ +#include "CustomScene.h" #include "Squidbox.h" +#include "gui/menu-item/random-velocity/RandomVelocityMenuItem.h" CustomScene::CustomScene(Squidbox *squidbox) : Scene(squidbox, nullptr) { presetMenuItem = new PresetMenuItem(); + randomVelocityMenuItem = new RandomVelocityMenuItem(squidbox); // Create an array of menu items - MenuItem **menuItems = new MenuItem *[1]; + MenuItem **menuItems = new MenuItem *[2]; menuItems[0] = presetMenuItem; + menuItems[1] = randomVelocityMenuItem; // Create a new menu with the menu items - menu = new Menu("Custom", 1, menuItems, MAIN_SCENE); + menu = new Menu("Custom", 2, menuItems, MAIN_SCENE); // Create a new keyboard keyboard = new Keyboard(squidbox); @@ -43,7 +47,8 @@ void CustomScene::playChord(int index, bool on) { keyboard->setKeyDown(notes[i], on); if (on) { // If the chord should be played, send a note on message - squidbox->getMidiController()->sendNoteOn(notes[i], 127, 0); + squidbox->getMidiController()->sendNoteOn( + notes[i], squidbox->getNoteOnVelocity(), 0); } else { // If the chord should be stopped, send a note off message squidbox->getMidiController()->sendNoteOff(notes[i], 127, 0); diff --git a/src/scene/custom/CustomScene.h b/src/scene/custom/CustomScene.h index 84e1873..da2098f 100644 --- a/src/scene/custom/CustomScene.h +++ b/src/scene/custom/CustomScene.h @@ -6,6 +6,7 @@ #include "util/note/Note.h" #include "util/scale/Scale.h" #include +#include "gui/menu-item/random-velocity/RandomVelocityMenuItem.h" //includes new random velocity for notes /** * @class CustomScene @@ -19,6 +20,7 @@ class CustomScene : public Scene { PresetMenuItem *presetMenuItem; ///< The menu item for selecting the preset. Keyboard *keyboard; ///< The keyboard for playing chords. + RandomVelocityMenuItem *randomVelocityMenuItem; ///< The menu item for toggling random velocity. static const Note MIN_NOTE = NOTE_C1; ///< The minimum note that can be played. static const Note MAX_NOTE = diff --git a/src/scene/drum/DrumScene.cpp b/src/scene/drum/DrumScene.cpp index a163416..a9b30a3 100644 --- a/src/scene/drum/DrumScene.cpp +++ b/src/scene/drum/DrumScene.cpp @@ -1,16 +1,19 @@ #include "DrumScene.h" #include "Squidbox.h" +#include "gui/menu-item/random-velocity/RandomVelocityMenuItem.h" DrumScene::DrumScene(Squidbox *squidbox) : Scene(squidbox, nullptr) { - // Create a new menu item for the octave + // Create menu items octaveMenuItem = new OctaveMenuItem(); + randomVelocityMenuItem = new RandomVelocityMenuItem(squidbox); // Create an array of menu items - MenuItem **menuItems = new MenuItem *[1]; + MenuItem **menuItems = new MenuItem *[2]; menuItems[0] = octaveMenuItem; + menuItems[1] = randomVelocityMenuItem; // Create a new menu with the menu items - menu = new Menu("Drums", 1, menuItems, MAIN_SCENE); + menu = new Menu("Drums", 2, menuItems, MAIN_SCENE); } void DrumScene::update() { @@ -40,7 +43,8 @@ void DrumScene::playDrum(int index, bool on) { // Play or stop playing the note if (on) { - squidbox->getMidiController()->sendNoteOn(note, 127, 0); + squidbox->getMidiController()->sendNoteOn( + note, squidbox->getNoteOnVelocity(), 0); } else { squidbox->getMidiController()->sendNoteOff(note, 127, 0); } diff --git a/src/scene/drum/DrumScene.h b/src/scene/drum/DrumScene.h index 40c5429..81cfa21 100644 --- a/src/scene/drum/DrumScene.h +++ b/src/scene/drum/DrumScene.h @@ -3,6 +3,8 @@ #include "gui/menu-item/octave/OctaveMenuItem.h" #include "scene/Scene.h" #include "util/note/Note.h" +#include "gui/menu-item/random-velocity/RandomVelocityMenuItem.h" + /** * @class DrumScene @@ -15,7 +17,7 @@ class DrumScene : public Scene { private: OctaveMenuItem *octaveMenuItem; ///< The menu item for selecting the octave. - + RandomVelocityMenuItem *randomVelocityMenuItem; ///< The menu item for toggling random velocity. public: /** * @brief Construct a new DrumScene object. diff --git a/src/scene/note/NoteScene.cpp b/src/scene/note/NoteScene.cpp index 252b001..a0c3069 100644 --- a/src/scene/note/NoteScene.cpp +++ b/src/scene/note/NoteScene.cpp @@ -7,12 +7,15 @@ NoteScene::NoteScene(Squidbox *squidbox) : Scene(squidbox, nullptr) { scaleMenuItem = new ScaleMenuItem(); // Create an array of menu items - MenuItem **menuItems = new MenuItem *[2]; + randomVelocityMenuItem = new RandomVelocityMenuItem(squidbox); + + MenuItem **menuItems = new MenuItem *[3]; menuItems[0] = rootMenuItem; menuItems[1] = scaleMenuItem; + menuItems[2] = randomVelocityMenuItem; // Create a new menu with the menu items - menu = new Menu("Chords", 2, menuItems, MAIN_SCENE); + menu = new Menu("Notes", 3, menuItems, MAIN_SCENE); // Create a new keyboard keyboard = new Keyboard(squidbox); @@ -50,7 +53,7 @@ void NoteScene::playNote(int index, bool on) { // Play notes keyboard->setKeyDown(note, on); if (on) { - squidbox->getMidiController()->sendNoteOn(note, 127, 0); + squidbox->getMidiController()->sendNoteOn(note, squidbox->getNoteOnVelocity(), 0); } else { squidbox->getMidiController()->sendNoteOff(note, 127, 0); } diff --git a/src/scene/note/NoteScene.h b/src/scene/note/NoteScene.h index 3f478d4..62960e7 100644 --- a/src/scene/note/NoteScene.h +++ b/src/scene/note/NoteScene.h @@ -7,6 +7,7 @@ #include "util/ChordType.h" #include "util/note/Note.h" #include "util/scale/Scale.h" +#include "gui/menu-item/random-velocity/RandomVelocityMenuItem.h" //includes new random velocity for notes /** * @class NoteScene @@ -20,6 +21,7 @@ class NoteScene : public Scene { RootNoteMenuItem *rootMenuItem; ///< The menu item for selecting the root note. ScaleMenuItem *scaleMenuItem; ///< The menu item for selecting the scale. + RandomVelocityMenuItem *randomVelocityMenuItem; ///< The menu item for toggling random velocity. Keyboard *keyboard; ///< The keyboard for playing notes. static const Note MIN_NOTE = NOTE_C1; ///< The minimum note that can be played.