mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Working LittleFoot program for waveshape drawing
This commit is contained in:
parent
91e8d27b70
commit
e5d677072b
2 changed files with 78 additions and 64 deletions
|
|
@ -73,7 +73,8 @@ struct SynthGrid
|
|||
class MainComponent : public Component,
|
||||
public TopologySource::Listener,
|
||||
private TouchSurface::Listener,
|
||||
private ControlButton::Listener
|
||||
private ControlButton::Listener,
|
||||
private Timer
|
||||
{
|
||||
public:
|
||||
MainComponent()
|
||||
|
|
@ -144,15 +145,18 @@ private:
|
|||
/** Overridden from TouchSurface::Listener. Called when a Touch is received on the Lightpad */
|
||||
void touchChanged (TouchSurface&, const TouchSurface::Touch& touch) override
|
||||
{
|
||||
if (currentMode == waveformSelectionMode && touch.isTouchStart)
|
||||
if (currentMode == waveformSelectionMode && touch.isTouchStart && allowTouch)
|
||||
{
|
||||
// Change the displayed waveshape to the next one
|
||||
++waveshapeMode;
|
||||
|
||||
if (waveshapeMode > 3)
|
||||
waveshapeMode = 0;
|
||||
|
||||
|
||||
waveshapeProgram->setWaveshapeType (waveshapeMode);
|
||||
|
||||
allowTouch = false;
|
||||
startTimer (500);
|
||||
}
|
||||
else if (currentMode == playMode)
|
||||
{
|
||||
|
|
@ -240,10 +244,13 @@ private:
|
|||
if (currentMode == waveformSelectionMode)
|
||||
{
|
||||
// Create a new BitmapLEDProgram for the LEDGrid
|
||||
waveshapeProgram = new WaveshapeProgram (*grid, waveshapeMode);
|
||||
waveshapeProgram = new WaveshapeProgram (*grid);
|
||||
|
||||
// Set the LEDGrid program
|
||||
grid->setProgram (waveshapeProgram);
|
||||
|
||||
waveshapeProgram->setWaveshapeType (waveshapeMode);
|
||||
waveshapeProgram->generateWaveshapes();
|
||||
}
|
||||
else if (currentMode == playMode)
|
||||
{
|
||||
|
|
@ -260,6 +267,11 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
allowTouch = true;
|
||||
}
|
||||
|
||||
enum BlocksSynthMode
|
||||
{
|
||||
waveformSelectionMode = 0,
|
||||
|
|
@ -283,10 +295,12 @@ private:
|
|||
Colour waveshapeColour = Colours::red;
|
||||
|
||||
int waveshapeMode = 0;
|
||||
|
||||
|
||||
float scaleX = 0.0;
|
||||
float scaleY = 0.0;
|
||||
|
||||
bool allowTouch = true;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,29 +14,27 @@
|
|||
class WaveshapeProgram : public LEDGrid::Program
|
||||
{
|
||||
public:
|
||||
WaveshapeProgram (LEDGrid& lg, int waveshape) : Program (lg)
|
||||
WaveshapeProgram (LEDGrid& lg) : Program (lg)
|
||||
{
|
||||
setWaveshapeType (waveshape);
|
||||
generateWaveshapes();
|
||||
}
|
||||
|
||||
void generateWaveshapes()
|
||||
{
|
||||
int sineWaveY[45];
|
||||
int squareWaveY[45];
|
||||
int sawWaveY[45];
|
||||
int triangleWaveY[45];
|
||||
|
||||
uint8 sineWaveY[45];
|
||||
uint8 squareWaveY[45];
|
||||
uint8 sawWaveY[45];
|
||||
uint8 triangleWaveY[45];
|
||||
|
||||
// Set current phase position to 0 and work out the required phase increment for one cycle
|
||||
double currentPhase = 0.0;
|
||||
double phaseInc = (1.0 / 30.0) * (2.0 * double_Pi);
|
||||
|
||||
|
||||
for (int x = 0; x < 30; ++x)
|
||||
{
|
||||
// Scale and offset the sin output to the Lightpad display
|
||||
double sineOutput = sin (currentPhase);
|
||||
sineWaveY[x] = roundToInt ((sineOutput * 6.5) + 7.0);
|
||||
|
||||
|
||||
// Square wave output, set flags for when vertical line should be drawn
|
||||
if (currentPhase < double_Pi)
|
||||
{
|
||||
|
|
@ -49,19 +47,19 @@ public:
|
|||
{
|
||||
if (squareWaveY[x - 1] == 1)
|
||||
squareWaveY[x - 1] = 20;
|
||||
|
||||
|
||||
squareWaveY[x] = 13;
|
||||
}
|
||||
|
||||
|
||||
// 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] != 20)
|
||||
sawWaveY[x] = 20;
|
||||
|
||||
|
||||
// Triangle wave output
|
||||
triangleWaveY[x] = x < 15 ? x : 14 - (x % 15);
|
||||
|
||||
|
||||
// Add half cycle to end of array so it loops correctly
|
||||
if (x < 15)
|
||||
{
|
||||
|
|
@ -70,30 +68,39 @@ public:
|
|||
sawWaveY[x + 30] = sawWaveY[x];
|
||||
triangleWaveY[x + 30] = triangleWaveY[x];
|
||||
}
|
||||
|
||||
|
||||
// Increment the current phase
|
||||
currentPhase += phaseInc;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < 45; ++i)
|
||||
{
|
||||
ledGrid.setDataBits ((sineWaveOffset * 8) + (32 * i), 32, sineWaveY[i]);
|
||||
jassert (ledGrid.getDataByte (sineWaveOffset + (i * 4)) == sineWaveY[i]);
|
||||
|
||||
ledGrid.setDataBits ((squareWaveOffset * 8) + (32 * i), 32, squareWaveY[i]);
|
||||
jassert (ledGrid.getDataByte (squareWaveOffset + (i * 4)) == squareWaveY[i]);
|
||||
|
||||
ledGrid.setDataBits ((sawWaveOffset * 8) + (32 * i), 32, sawWaveY[i]);
|
||||
jassert (ledGrid.getDataByte (sawWaveOffset + (i * 4)) == sawWaveY[i]);
|
||||
|
||||
ledGrid.setDataBits ((triangleWaveOffset * 8) + (32 * i), 32, triangleWaveY[i]);
|
||||
jassert (ledGrid.getDataByte (triangleWaveOffset + (i * 4)) == triangleWaveY[i]);
|
||||
ledGrid.setDataByte (sineWaveOffset + i, sineWaveY[i]);
|
||||
int sineByte = ledGrid.getDataByte (sineWaveOffset + i);
|
||||
jassert (sineByte == sineWaveY[i]);
|
||||
|
||||
ledGrid.setDataByte (squareWaveOffset + i, squareWaveY[i]);
|
||||
int squareByte = ledGrid.getDataByte (squareWaveOffset + i);
|
||||
jassert (squareByte == squareWaveY[i]);
|
||||
|
||||
ledGrid.setDataByte (sawWaveOffset + i, sawWaveY[i]);
|
||||
int sawByte = ledGrid.getDataByte (sawWaveOffset + i);
|
||||
jassert (sawByte == sawWaveY[i]);
|
||||
|
||||
ledGrid.setDataByte (triangleWaveOffset + i, triangleWaveY[i]);
|
||||
int triangleByte = ledGrid.getDataByte (triangleWaveOffset + i);
|
||||
jassert (triangleByte == triangleWaveY[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void setWaveshapeType (int type)
|
||||
|
||||
void setWaveshapeType (uint8 type)
|
||||
{
|
||||
ledGrid.setDataBits (0, 4, type);
|
||||
ledGrid.setDataByte (0, type);
|
||||
}
|
||||
|
||||
uint32 getHeapSize() override
|
||||
{
|
||||
return totalDataSize;
|
||||
}
|
||||
|
||||
String getLittleFootProgram() override
|
||||
|
|
@ -101,27 +108,27 @@ public:
|
|||
return R"littlefoot(
|
||||
|
||||
int yOffset;
|
||||
|
||||
|
||||
int min (int a, int b)
|
||||
{
|
||||
if (a > b)
|
||||
return b;
|
||||
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
int max (int a, int b)
|
||||
{
|
||||
if (a > b)
|
||||
return a;
|
||||
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
void drawLEDCircle (int x0, int y0)
|
||||
{
|
||||
setLED (x0, y0, 0xffffffff);
|
||||
|
||||
setLED (x0, y0, 0xffff0000);
|
||||
|
||||
int minLedIndex = 0;
|
||||
int maxLedIndex = 14;
|
||||
|
||||
|
|
@ -135,20 +142,19 @@ public:
|
|||
setLED (max (x0 - 1, minLedIndex), min (y0 + 1, maxLedIndex), 0xff1a0000);
|
||||
setLED (max (x0 - 1, minLedIndex), max (y0 - 1, minLedIndex), 0xff1a0000);
|
||||
}
|
||||
|
||||
|
||||
void repaint()
|
||||
{
|
||||
// Clear LEDs to black
|
||||
fillRect (0xff000000, 0, 0, 15, 15);
|
||||
|
||||
// Get the waveshape type
|
||||
int type = getHeapInt (0);
|
||||
int offset = 4 + (type * 180) + yOffset;
|
||||
|
||||
int type = getHeapByte (0);
|
||||
int offset = 1 + (type * 45) + yOffset;
|
||||
|
||||
for (int x = 0; x < 15; ++x)
|
||||
{
|
||||
// Find the corresponding Y co-ordinate for the current waveshape
|
||||
int y = getHeapInt (offset + (x * 4));
|
||||
int y = getHeapByte (offset + x);
|
||||
|
||||
// Draw a vertical line if flag is set or draw an LED circle
|
||||
if (y == 20)
|
||||
|
|
@ -162,28 +168,22 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// Increment the offset to draw a 'moving' waveshape
|
||||
yOffset += 4;
|
||||
if (yOffset == (4 * 30))
|
||||
yOffset -= (4 * 30);
|
||||
if (++yOffset == 30)
|
||||
yOffset = 0;
|
||||
|
||||
}
|
||||
|
||||
)littlefoot";
|
||||
}
|
||||
|
||||
uint32 getHeapSize() override
|
||||
{
|
||||
return totalDataSize;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr uint32 waveshapeType = 0; // 4 bytes
|
||||
static constexpr uint32 sineWaveOffset = 4; // 4 byte * 45
|
||||
static constexpr uint32 squareWaveOffset = 184; // 4 byte * 45
|
||||
static constexpr uint32 sawWaveOffset = 364; // 4 byte * 45
|
||||
static constexpr uint32 triangleWaveOffset = 544; // 4 byte * 45
|
||||
static constexpr uint32 waveshapeType = 0; // 1 byte
|
||||
static constexpr uint32 sineWaveOffset = 1; // 1 byte * 45
|
||||
static constexpr uint32 squareWaveOffset = 46; // 1 byte * 45
|
||||
static constexpr uint32 sawWaveOffset = 91; // 1 byte * 45
|
||||
static constexpr uint32 triangleWaveOffset = 136; // 1 byte * 45
|
||||
|
||||
static constexpr uint32 totalDataSize = triangleWaveOffset + (4 * 45);
|
||||
static constexpr uint32 totalDataSize = triangleWaveOffset + 45;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WaveshapeProgram)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue