From de84462f2dfa9519587f2b8aa14d5846222dbf74 Mon Sep 17 00:00:00 2001 From: jules Date: Sat, 5 Nov 2016 10:47:38 +0000 Subject: [PATCH] BLOCKS example apps: some cleanup, enabled DUMP_TOPOLOGY flag --- .../BlocksDrawing/JuceLibraryCode/AppConfig.h | 2 +- .../BlocksDrawing/Source/MainComponent.h | 74 ++++----- .../BlocksMonitor/JuceLibraryCode/AppConfig.h | 2 +- .../BlocksMonitor/Source/BlockComponents.h | 140 +++++++++--------- .../BlocksMonitor/Source/MainComponent.h | 16 +- .../BlocksSynth/JuceLibraryCode/AppConfig.h | 2 +- examples/BLOCKS/BlocksSynth/Source/Main.cpp | 5 +- .../BLOCKS/BlocksSynth/Source/MainComponent.h | 78 +++++----- .../BLOCKS/BlocksSynth/Source/Oscillators.h | 22 +-- 9 files changed, 172 insertions(+), 169 deletions(-) diff --git a/examples/BLOCKS/BlocksDrawing/JuceLibraryCode/AppConfig.h b/examples/BLOCKS/BlocksDrawing/JuceLibraryCode/AppConfig.h index b7aa780415..d610e97f1c 100644 --- a/examples/BLOCKS/BlocksDrawing/JuceLibraryCode/AppConfig.h +++ b/examples/BLOCKS/BlocksDrawing/JuceLibraryCode/AppConfig.h @@ -17,7 +17,7 @@ //============================================================================== // [BEGIN_USER_CODE_SECTION] -// (You can add your own code in this section, and the Projucer will not overwrite it) +#define DUMP_TOPOLOGY 1 // [END_USER_CODE_SECTION] diff --git a/examples/BLOCKS/BlocksDrawing/Source/MainComponent.h b/examples/BLOCKS/BlocksDrawing/Source/MainComponent.h index 06df6e317d..092e7c6019 100644 --- a/examples/BLOCKS/BlocksDrawing/Source/MainComponent.h +++ b/examples/BLOCKS/BlocksDrawing/Source/MainComponent.h @@ -4,6 +4,7 @@ #include "../JuceLibraryCode/JuceHeader.h" +//============================================================================== /** A struct that handles the setup and layout of the DrumPadGridProgram */ @@ -70,28 +71,31 @@ struct ColourGrid //============================================================================== int numColumns, numRows; - float width, height; Array gridFillArray; - Array colourArray = { Colours::white, Colours::red, Colours::green, Colours::blue, Colours::hotpink, - Colours::orange, Colours::magenta, Colours::cyan, Colours::black }; + + Array colourArray = { Colours::white, Colours::red, Colours::green, + Colours::blue, Colours::hotpink, Colours::orange, + Colours::magenta, Colours::cyan, Colours::black }; + Colour currentColour = Colours::hotpink; //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ColourGrid) }; +//============================================================================== /** The main component */ class MainComponent : public Component, - public TopologySource::Listener, - private TouchSurface::Listener, - private ControlButton::Listener, - private Timer + public TopologySource::Listener, + private TouchSurface::Listener, + private ControlButton::Listener, + private Timer { public: - MainComponent() : layout (3, 3) + MainComponent() { setSize (600, 400); @@ -110,7 +114,8 @@ public: void paint (Graphics& g) override { g.fillAll (Colours::lightgrey); - g.drawText ("Connect a Lightpad Block to draw.", getLocalBounds(), Justification::centred, false); + g.drawText ("Connect a Lightpad Block to draw.", + getLocalBounds(), Justification::centred, false); } void resized() override {} @@ -176,7 +181,7 @@ private: } /** Overridden from ControlButton::Listener. Called when a button on the Lightpad is pressed */ - void buttonPressed (ControlButton&, Block::Timestamp) override {}; + void buttonPressed (ControlButton&, Block::Timestamp) override {} /** Overridden from ControlButton::Listener. Called when a button on the Lightpad is released */ void buttonReleased (ControlButton&, Block::Timestamp) override @@ -257,7 +262,9 @@ private: grid->setProgram (colourPaletteProgram); // Setup the grid layout - colourPaletteProgram->setGridFills (layout.numColumns, layout.numRows, layout.gridFillArray); + colourPaletteProgram->setGridFills (layout.numColumns, + layout.numRows, + layout.gridFillArray); } } @@ -265,20 +272,12 @@ private: void drawLEDs (uint32 x0, uint32 y0, float z, Colour drawColour) { // Check if the activeLeds array already contains an ActiveLED object for this LED - int index = -1; - for (int i = 0; i < activeLeds.size(); ++i) - { - if (activeLeds.getReference(i).occupies (x0, y0)) - { - index = i; - break; - } - } + auto index = getLEDAt (x0, y0); // If the colour is black then just set the LED to black and return if (drawColour == Colours::black) { - if (index != -1) + if (index >= 0) { canvasProgram->setLED (x0, y0, Colours::black); activeLeds.remove (index); @@ -289,7 +288,7 @@ private: // If there is no ActiveLED obejct for this LED then create one, // add it to the array, set the LED on the Block and return - if (index == -1) + if (index < 0) { ActiveLED led; led.x = x0; @@ -333,37 +332,42 @@ private: */ struct ActiveLED { - uint32 x; - uint32 y; + uint32 x, y; Colour colour; float brightness; - /** Returns true if this LED occupies the given co-ordiantes */ + /** Returns true if this LED occupies the given co-ordinates */ bool occupies (uint32 xPos, uint32 yPos) const { - if (xPos == x && yPos == y) - return true; - - return false; + return xPos == x && yPos == y; } }; + Array activeLeds; - /** - enum for the two modes - */ + int getLEDAt (uint32 x, uint32 y) const + { + for (int i = 0; i < activeLeds.size(); ++i) + if (activeLeds.getReference(i).occupies (x, y)) + return i; + + return -1; + } + + //============================================================================== enum DisplayMode { colourPalette = 0, canvas }; + DisplayMode currentMode = colourPalette; //============================================================================== - BitmapLEDProgram* canvasProgram; - DrumPadGridProgram* colourPaletteProgram; + BitmapLEDProgram* canvasProgram = nullptr; + DrumPadGridProgram* colourPaletteProgram = nullptr; - ColourGrid layout; + ColourGrid layout { 3, 3 }; PhysicalTopologySource topologySource; Block::Ptr activeBlock; diff --git a/examples/BLOCKS/BlocksMonitor/JuceLibraryCode/AppConfig.h b/examples/BLOCKS/BlocksMonitor/JuceLibraryCode/AppConfig.h index 07401f2fb0..db501b1bcd 100644 --- a/examples/BLOCKS/BlocksMonitor/JuceLibraryCode/AppConfig.h +++ b/examples/BLOCKS/BlocksMonitor/JuceLibraryCode/AppConfig.h @@ -17,7 +17,7 @@ //============================================================================== // [BEGIN_USER_CODE_SECTION] -// (You can add your own code in this section, and the Projucer will not overwrite it) +#define DUMP_TOPOLOGY 1 // [END_USER_CODE_SECTION] diff --git a/examples/BLOCKS/BlocksMonitor/Source/BlockComponents.h b/examples/BLOCKS/BlocksMonitor/Source/BlockComponents.h index 960eb6944a..156dbf8bd8 100644 --- a/examples/BLOCKS/BlocksMonitor/Source/BlockComponents.h +++ b/examples/BLOCKS/BlocksMonitor/Source/BlockComponents.h @@ -15,7 +15,6 @@ class BlockComponent : public Component, private Timer { public: - /** Constructor */ BlockComponent (Block::Ptr blockToUse) : block (blockToUse) { @@ -38,7 +37,6 @@ public: startTimerHz (25); } - /** Destructor */ ~BlockComponent() { // Remove any listeners @@ -53,19 +51,16 @@ public: void updateStatsAndTooltip() { // Get the battery level of this Block and inform any subclasses - const float batteryLevel = block->getBatteryLevel(); + auto batteryLevel = block->getBatteryLevel(); handleBatteryLevelUpdate (batteryLevel); - // Format the tooltip string - const String ttString = "Name = " + block->getDeviceDescription() + "\n" - + "UID = " + String (block->uid) + "\n" - + "Serial number = " + block->serialNumber + "\n" - + "Battery level = " + String ((int) (batteryLevel * 100)) + "%" - + (block->isBatteryCharging() ? "++" : "--"); - - // Update the tooltip string if it has changed - if (ttString != getTooltip()) - setTooltip (ttString); + // Update the tooltip + setTooltip ("Name = " + block->getDeviceDescription() + "\n" + + "UID = " + String (block->uid) + "\n" + + "Serial number = " + block->serialNumber + "\n" + + "Battery level = " + String ((int) (batteryLevel * 100)) + "%" + + (block->isBatteryCharging() ? "++" + : "--")); } /** Subclasses should override this to paint the Block object on the screen */ @@ -88,31 +83,35 @@ public: //============================================================================== /** Returns an integer index corresponding to a physical position on the hardware - for each type of Control Block. */ + for each type of Control Block. */ static int controlButtonFunctionToIndex (ControlButton::ButtonFunction f) { - static std::initializer_list map[] = - {{ControlButton::mode, ControlButton::button0}, - {ControlButton::volume, ControlButton::button1}, - {ControlButton::scale, ControlButton::button2, ControlButton::click}, - {ControlButton::chord, ControlButton::button3, ControlButton::snap}, - {ControlButton::arp,ControlButton:: button4, ControlButton::back}, - {ControlButton::sustain, ControlButton::button5, ControlButton::playOrPause}, - {ControlButton::octave, ControlButton::button6, ControlButton::record}, - {ControlButton::love, ControlButton::button7, ControlButton::learn}, - {ControlButton::up}, - {ControlButton::down}}; + using CB = ControlButton; - for (size_t i = 0; i < (sizeof (map) / sizeof (map[0])); ++i) - if (std::find (map[i].begin(), map[i].end(), f) != map[i].end()) - return static_cast (i); + static Array map[] = + { + { CB::mode, CB::button0 }, + { CB::volume, CB::button1 }, + { CB::scale, CB::button2, CB::click }, + { CB::chord, CB::button3, CB::snap }, + { CB::arp, CB::button4, CB::back }, + { CB::sustain, CB::button5, CB::playOrPause }, + { CB::octave, CB::button6, CB::record }, + { CB::love, CB::button7, CB::learn }, + { CB::up }, + { CB::down } + }; + + for (int i = 0; i < numElementsInArray (map); ++i) + if (map[i].contains (f)) + return i; return -1; } private: /** Used to call repaint() periodically */ - void timerCallback() override { repaint(); } + void timerCallback() override { repaint(); } /** Overridden from TouchSurface::Listener */ void touchChanged (TouchSurface&, const TouchSurface::Touch& t) override { handleTouchChange (t); } @@ -123,14 +122,14 @@ private: /** Overridden from ControlButton::Listener */ void buttonReleased (ControlButton& b, Block::Timestamp t) override { handleButtonReleased (b.getType(), t); } - //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BlockComponent) }; +//============================================================================== /** Class that renders a Lightpad on the screen */ -class LightpadComponent : public BlockComponent +class LightpadComponent : public BlockComponent { public: LightpadComponent (Block::Ptr blockToUse) @@ -154,23 +153,25 @@ public: g.fillAll (Colours::black); // size ration between physical and on-screen blocks - const Point ratio (r.getWidth() / block->getWidth(), - r.getHeight() / block->getHeight()); - const float maxCircleSize = block->getWidth() / 3.0f; + Point ratio (r.getWidth() / block->getWidth(), + r.getHeight() / block->getHeight()); + + float maxCircleSize = block->getWidth() / 3.0f; // iterate over the list of current touches and draw them on the onscreen Block for (auto touch : touches) { - const float circleSize = touch.touch.z * maxCircleSize; - const Point touchPosition = Point (touch.touch.x, touch.touch.y); + float circleSize = touch.touch.z * maxCircleSize; - const Colour c = colourArray[touch.touch.index]; - const Rectangle blob = - (Rectangle (circleSize, circleSize).withCentre (touchPosition)) * ratio; + Point touchPosition (touch.touch.x, + touch.touch.y); - const ColourGradient cg = ColourGradient (colourArray[touch.touch.index], blob.getCentreX(), blob.getCentreY(), - Colours::transparentBlack, blob.getRight(), blob.getBottom(), - true); + auto blob = Rectangle (circleSize, circleSize) + .withCentre (touchPosition) * ratio; + + ColourGradient cg (colourArray[touch.touch.index], blob.getCentreX(), blob.getCentreY(), + Colours::transparentBlack, blob.getRight(), blob.getBottom(), + true); g.setGradientFill (cg); g.fillEllipse (blob); @@ -181,21 +182,26 @@ public: private: /** An Array of colours to use for touches */ - Array colourArray = { Colours::red, Colours::blue, Colours::green, - Colours::yellow, Colours::white, Colours::hotpink, + Array colourArray = { Colours::red, + Colours::blue, + Colours::green, + Colours::yellow, + Colours::white, + Colours::hotpink, Colours::mediumpurple }; /** A list of current Touch events */ TouchList touches; - //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LightpadComponent) }; + +//============================================================================== /** Class that renders a Control Block on the screen */ -class ControlBlockComponent : public BlockComponent +class ControlBlockComponent : public BlockComponent { public: ControlBlockComponent (Block::Ptr blockToUse) @@ -205,13 +211,12 @@ public: addAndMakeVisible (roundedRectangleButton); // Display the battery level on the LEDRow - int numLedsToTurnOn = static_cast (static_cast (numLeds) * block->getBatteryLevel()); + auto numLedsToTurnOn = static_cast (numLeds * block->getBatteryLevel()); // add LEDs - LEDComponent* ledComponent; for (int i = 0; i < numLeds; ++i) { - ledComponent = new LEDComponent(); + auto ledComponent = new LEDComponent(); ledComponent->setOnState (i < numLedsToTurnOn); addAndMakeVisible (leds.add (ledComponent)); @@ -238,9 +243,9 @@ public: auto buttonRow1 = row.removeFromTop (rowHeight * 2).withSizeKeepingCentre (r.getWidth(), buttonWidth); auto buttonRow2 = row.removeFromTop (rowHeight * 2).withSizeKeepingCentre (r.getWidth(), buttonWidth); - for (int i = 0; i < numLeds; ++i) + for (auto* led : leds) { - leds.getUnchecked (i)->setBounds (ledRow.removeFromLeft (ledWidth).reduced (2)); + led->setBounds (ledRow.removeFromLeft (ledWidth).reduced (2)); ledRow.removeFromLeft (5); } @@ -261,7 +266,7 @@ public: void paint (Graphics& g) override { - const auto r = getLocalBounds().toFloat(); + auto r = getLocalBounds().toFloat(); // Fill a black rectangle for the Control Block g.setColour (Colours::black); @@ -281,7 +286,7 @@ public: void handleBatteryLevelUpdate (float batteryLevel) override { // Update the number of LEDs that are on to represent the battery level - int numLedsOn = static_cast (static_cast (numLeds) * batteryLevel); + int numLedsOn = static_cast (numLeds * batteryLevel); if (numLedsOn != previousNumLedsOn) for (int i = 0; i < numLeds; ++i) @@ -292,22 +297,22 @@ public: } private: + //============================================================================== /** Base class that renders a Control Block button */ - struct ControlBlockSubComponent : public Component, - public TooltipClient + struct ControlBlockSubComponent : public Component, + public TooltipClient { ControlBlockSubComponent (Colour componentColourToUse) - : componentColour (componentColourToUse), - onState (false) + : componentColour (componentColourToUse) {} /** Subclasses should override this to paint the button on the screen */ virtual void paint (Graphics&) override = 0; /** Sets the colour of the button */ - void setColour (Colour c) { componentColour = c; } + void setColour (Colour c) { componentColour = c; } /** Sets the on state of the button */ void setOnState (bool isOn) @@ -320,15 +325,15 @@ private: String getTooltip() override { for (Component* comp = this; comp != nullptr; comp = comp->getParentComponent()) - if (SettableTooltipClient* sttc = dynamic_cast (comp)) + if (auto* sttc = dynamic_cast (comp)) return sttc->getTooltip(); - return String(); + return {}; } //============================================================================== Colour componentColour; - bool onState; + bool onState = false; //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ControlBlockSubComponent) @@ -372,8 +377,7 @@ private: void paint (Graphics& g) override { - const auto r = getLocalBounds().toFloat(); - + auto r = getLocalBounds().toFloat(); g.setColour (componentColour.withAlpha (0.2f)); g.fillRoundedRectangle (r.toFloat(), 20.0f); @@ -382,11 +386,11 @@ private: // is a button pressed? if (doubleButtonOnState[0] || doubleButtonOnState[1]) { - const float semiButtonWidth = r.getWidth() / 2.0f; - const auto semiButtonBounds = r.withWidth (semiButtonWidth) - .withX (doubleButtonOnState[1] ? semiButtonWidth : 0) - .reduced (5.0f, 2.0f); + auto semiButtonWidth = r.getWidth() / 2.0f; + auto semiButtonBounds = r.withWidth (semiButtonWidth) + .withX (doubleButtonOnState[1] ? semiButtonWidth : 0) + .reduced (5.0f, 2.0f); g.fillEllipse (semiButtonBounds); } @@ -399,7 +403,7 @@ private: } private: - bool doubleButtonOnState[2] = {false, false}; + bool doubleButtonOnState[2] = { false, false }; }; /** Displays a button press or release interaction for a button at a given index */ diff --git a/examples/BLOCKS/BlocksMonitor/Source/MainComponent.h b/examples/BLOCKS/BlocksMonitor/Source/MainComponent.h index 1ea567d9af..5e804688f3 100644 --- a/examples/BLOCKS/BlocksMonitor/Source/MainComponent.h +++ b/examples/BLOCKS/BlocksMonitor/Source/MainComponent.h @@ -46,10 +46,10 @@ public: } // Work out the maximum diplay area for each Block - const Rectangle bounds = getLocalBounds().reduced (20); + auto bounds = getLocalBounds().reduced (20); - auto squareRoot = sqrt (numBlockComponents); - int gridSize = (int)squareRoot; + auto squareRoot = std::sqrt (numBlockComponents); + int gridSize = (int) squareRoot; if (squareRoot - gridSize > 0) gridSize++; @@ -64,7 +64,7 @@ public: for (auto block : blockComponents) { Rectangle blockBounds; - const Block::Type type = block->block->getType(); + auto type = block->block->getType(); // Can fit 2 ControlBlockComponents in the space of one LightpadBlockComponent if (type == Block::liveBlock || type == Block::loopBlock) @@ -105,11 +105,11 @@ public: blockComponents.clear(); // Get the array of currently connected Block objects from the PhysicalTopologySource - Block::Array blocksArray = topologySource.getCurrentTopology().blocks; + auto blocksArray = topologySource.getCurrentTopology().blocks; // Create a BlockComponent object for each Block object for (auto& block : blocksArray) - if (BlockComponent* blockComponent = createBlockComponent (block)) + if (auto* blockComponent = createBlockComponent (block)) addAndMakeVisible (blockComponents.add (blockComponent)); // Update the display @@ -120,16 +120,16 @@ private: /** Creates a BlockComponent object for a new Block and adds it to the content component */ BlockComponent* createBlockComponent (Block::Ptr newBlock) { - const Block::Type type = newBlock->getType(); + auto type = newBlock->getType(); if (type == Block::lightPadBlock) return new LightpadComponent (newBlock); + if (type == Block::loopBlock || type == Block::liveBlock) return new ControlBlockComponent (newBlock); // should only be connecting a Lightpad or Control Block! jassertfalse; - return nullptr; } diff --git a/examples/BLOCKS/BlocksSynth/JuceLibraryCode/AppConfig.h b/examples/BLOCKS/BlocksSynth/JuceLibraryCode/AppConfig.h index 3b4800cfb8..6b01a22690 100644 --- a/examples/BLOCKS/BlocksSynth/JuceLibraryCode/AppConfig.h +++ b/examples/BLOCKS/BlocksSynth/JuceLibraryCode/AppConfig.h @@ -17,7 +17,7 @@ //============================================================================== // [BEGIN_USER_CODE_SECTION] -// (You can add your own code in this section, and the Projucer will not overwrite it) +#define DUMP_TOPOLOGY 1 // [END_USER_CODE_SECTION] diff --git a/examples/BLOCKS/BlocksSynth/Source/Main.cpp b/examples/BLOCKS/BlocksSynth/Source/Main.cpp index 91d0d7b358..97e97f19ab 100644 --- a/examples/BLOCKS/BlocksSynth/Source/Main.cpp +++ b/examples/BLOCKS/BlocksSynth/Source/Main.cpp @@ -27,9 +27,8 @@ public: void shutdown() override { mainWindow = nullptr; } //============================================================================== - class MainWindow : public DocumentWindow + struct MainWindow : public DocumentWindow { - public: MainWindow (String name) : DocumentWindow (name, Colours::lightgrey, DocumentWindow::allButtons) @@ -47,10 +46,8 @@ public: JUCEApplication::getInstance()->systemRequestedQuit(); } - private: TooltipWindow tooltipWindow; - //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow) }; diff --git a/examples/BLOCKS/BlocksSynth/Source/MainComponent.h b/examples/BLOCKS/BlocksSynth/Source/MainComponent.h index 415c73629c..9dee7a4274 100644 --- a/examples/BLOCKS/BlocksSynth/Source/MainComponent.h +++ b/examples/BLOCKS/BlocksSynth/Source/MainComponent.h @@ -5,6 +5,7 @@ #include "../JuceLibraryCode/JuceHeader.h" #include "Audio.h" +//============================================================================== /** A struct that handles the setup and layout of the DrumPadGridProgram */ @@ -41,7 +42,7 @@ struct SynthGrid } } - int getNoteNumberForPad (int x, int y) + int getNoteNumberForPad (int x, int y) const { int xIndex = x / 3; int yIndex = y / 3; @@ -64,6 +65,7 @@ struct SynthGrid JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SynthGrid) }; +//============================================================================== /** The main component */ @@ -74,7 +76,7 @@ class MainComponent : public Component, private Timer { public: - MainComponent() : layout (5, 5) + MainComponent() { setSize (600, 400); @@ -93,7 +95,8 @@ public: void paint (Graphics& g) override { g.fillAll (Colours::lightgrey); - g.drawText ("Connect a Lightpad Block to play.", getLocalBounds(), Justification::centred, false); + g.drawText ("Connect a Lightpad Block to play.", + getLocalBounds(), Justification::centred, false); } void resized() override {} @@ -106,7 +109,7 @@ public: detachActiveBlock(); // Get the array of currently connected Block objects from the PhysicalTopologySource - Block::Array blocks = topologySource.getCurrentTopology().blocks; + auto blocks = topologySource.getCurrentTopology().blocks; // Iterate over the array of Block objects for (auto b : blocks) @@ -180,10 +183,11 @@ private: if (touchMessageTimesInLastSecond.size() > maxNumTouchMessagesPerSecond / 3) return; - gridProgram->sendTouch (touch.x, touch.y, touch.z, layout.touchColour); + gridProgram->sendTouch (touch.x, touch.y, touch.z, + layout.touchColour); // Send pitch change and pressure values to the Audio class - audio.pitchChange (midiChannel, (touch.x - touch.startX) / static_cast (activeBlock->getWidth())); + audio.pitchChange (midiChannel, (touch.x - touch.startX) / activeBlock->getWidth()); audio.pressureChange (midiChannel, touch.z); } @@ -215,26 +219,18 @@ private: // Clear all LEDs for (uint32 x = 0; x < 15; ++x) for (uint32 y = 0; y < 15; ++y) - bitmapProgram->setLED (x, y, Colours::black); + setLED (x, y, Colours::black); // Determine which array to use based on waveshapeMode int* waveshapeY = nullptr; + switch (waveshapeMode) { - case 0: - waveshapeY = sineWaveY; - break; - case 1: - waveshapeY = squareWaveY; - break; - case 2: - waveshapeY = sawWaveY; - break; - case 3: - waveshapeY = triangleWaveY; - break; - default: - break; + case 0: waveshapeY = sineWaveY; break; + case 1: waveshapeY = squareWaveY; break; + case 2: waveshapeY = sawWaveY; break; + case 3: waveshapeY = triangleWaveY; break; + default: break; } // For each X co-ordinate @@ -306,7 +302,9 @@ private: grid->setProgram (gridProgram); // Setup the grid layout - gridProgram->setGridFills (layout.numColumns, layout.numRows, layout.gridFillArray); + gridProgram->setGridFills (layout.numColumns, + layout.numRows, + layout.gridFillArray); } } @@ -341,6 +339,7 @@ private: // Saw wave output, set flags for when vertical line should be drawn sawWaveY[x] = 14 - ((x / 2) % 15); + if (sawWaveY[x] == 0 && sawWaveY[x - 1] != -1) sawWaveY[x] = -1; @@ -361,42 +360,47 @@ private: } } + /** Simple wrapper function to set a LED colour */ + void setLED (uint32 x, uint32 y, Colour colour) + { + if (bitmapProgram != nullptr) + bitmapProgram->setLED (x, y, colour); + } + /** Draws a 'circle' on the Lightpad around an origin co-ordinate */ void drawLEDCircle (uint32 x0, uint32 y0) { - bitmapProgram->setLED (x0, y0, waveshapeColour); + setLED (x0, y0, waveshapeColour); const uint32 minLedIndex = 0; const uint32 maxLedIndex = 14; - bitmapProgram->setLED (jmin (x0 + 1, maxLedIndex), y0, waveshapeColour.withBrightness (0.4f)); - bitmapProgram->setLED (jmax (x0 - 1, minLedIndex), y0, waveshapeColour.withBrightness (0.4f)); - bitmapProgram->setLED (x0, jmin (y0 + 1, maxLedIndex), waveshapeColour.withBrightness (0.4f)); - bitmapProgram->setLED (x0, jmax (y0 - 1, minLedIndex), waveshapeColour.withBrightness (0.4f)); + setLED (jmin (x0 + 1, maxLedIndex), y0, waveshapeColour.withBrightness (0.4f)); + setLED (jmax (x0 - 1, minLedIndex), y0, waveshapeColour.withBrightness (0.4f)); + setLED (x0, jmin (y0 + 1, maxLedIndex), waveshapeColour.withBrightness (0.4f)); + setLED (x0, jmax (y0 - 1, minLedIndex), waveshapeColour.withBrightness (0.4f)); - bitmapProgram->setLED (jmin (x0 + 1, maxLedIndex), jmin (y0 + 1, maxLedIndex), waveshapeColour.withBrightness (0.1f)); - bitmapProgram->setLED (jmin (x0 + 1, maxLedIndex), jmax (y0 - 1, minLedIndex), waveshapeColour.withBrightness (0.1f)); - bitmapProgram->setLED (jmax (x0 - 1, minLedIndex), jmin (y0 + 1, maxLedIndex), waveshapeColour.withBrightness (0.1f)); - bitmapProgram->setLED (jmax (x0 - 1, minLedIndex), jmax (y0 - 1, minLedIndex), waveshapeColour.withBrightness (0.1f)); + setLED (jmin (x0 + 1, maxLedIndex), jmin (y0 + 1, maxLedIndex), waveshapeColour.withBrightness (0.1f)); + setLED (jmin (x0 + 1, maxLedIndex), jmax (y0 - 1, minLedIndex), waveshapeColour.withBrightness (0.1f)); + setLED (jmax (x0 - 1, minLedIndex), jmin (y0 + 1, maxLedIndex), waveshapeColour.withBrightness (0.1f)); + setLED (jmax (x0 - 1, minLedIndex), jmax (y0 - 1, minLedIndex), waveshapeColour.withBrightness (0.1f)); } - /** - enum for the two modes - */ enum BlocksSynthMode { waveformSelectionMode = 0, playMode }; + BlocksSynthMode currentMode = playMode; //============================================================================== Audio audio; - DrumPadGridProgram* gridProgram; - BitmapLEDProgram* bitmapProgram; + DrumPadGridProgram* gridProgram = nullptr; + BitmapLEDProgram* bitmapProgram = nullptr; - SynthGrid layout; + SynthGrid layout { 5, 5 }; PhysicalTopologySource topologySource; Block::Ptr activeBlock; diff --git a/examples/BLOCKS/BlocksSynth/Source/Oscillators.h b/examples/BLOCKS/BlocksSynth/Source/Oscillators.h index c7f70432ed..5e8c4694dd 100644 --- a/examples/BLOCKS/BlocksSynth/Source/Oscillators.h +++ b/examples/BLOCKS/BlocksSynth/Source/Oscillators.h @@ -7,7 +7,7 @@ /** Base class for oscillators */ -class Oscillator : public SynthesiserVoice +class Oscillator : public SynthesiserVoice { public: Oscillator() @@ -16,10 +16,6 @@ public: phaseIncrement.reset (getSampleRate(), 0.1); } - virtual ~Oscillator() - { - } - void startNote (int midiNoteNumber, float velocity, SynthesiserSound*, int) override { frequency = MidiMessage::getMidiNoteInHertz (midiNoteNumber); @@ -57,7 +53,7 @@ public: void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples) override { - while(--numSamples >= 0) + while (--numSamples >= 0) { double output = getSample() * amplitude.getNextValue(); @@ -82,22 +78,20 @@ public: } /** Subclasses should override this to say whether they can play the given sound */ - virtual bool canPlaySound (SynthesiserSound* sound) override = 0; + virtual bool canPlaySound (SynthesiserSound*) override = 0; /** Subclasses should override this to render a waveshape */ - virtual double renderWaveShape (const double currentPhase) = 0; + virtual double renderWaveShape (double currentPhase) = 0; private: - LinearSmoothedValue amplitude; - LinearSmoothedValue phaseIncrement; + LinearSmoothedValue amplitude, phaseIncrement; - double frequency; + double frequency = 0; double phasePos = 0.0f; double sampleRate = 44100.0; - int initialNote; - double maxFreq; - double minFreq; + int initialNote = 0; + double maxFreq = 0, minFreq = 0; //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Oscillator)