-
Notifications
You must be signed in to change notification settings - Fork 0
/
WaveGenerator.cpp
126 lines (109 loc) · 3.63 KB
/
WaveGenerator.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#define OLC_PGE_APPLICATION
#include "olcPixelGameEngine.h"
#include "olcPGEX_PanZoom.h"
#include "wavegen.h"
class WaveGenerator : public olc::PixelGameEngine
{
private:
olc::panzoom pz;
int nMode = 0;
int nHarmonics = 10;
double dFrequency = 0.001;
double dAmplitude = 1.0;
double dScale = 240.0;
olc::vi2d vScreenTL;
olc::vi2d vScreenBR;
public:
WaveGenerator()
{
sAppName = "Wave Generator";
}
bool OnUserCreate() override
{
vScreenTL = { 0, 0 };
vScreenBR = { ScreenWidth(), ScreenHeight() };
pz.Create(this);
pz.SetOffset({ -(double)ScreenWidth() / 2.0, -(double)ScreenHeight() / 2.0 });
return true;
}
bool OnUserUpdate(float fElapsedTime) override
{
Clear(0);
// app inputs
if (GetKey(olc::K1).bPressed) nMode = 0;
if (GetKey(olc::K2).bPressed) nMode = 1;
if (GetKey(olc::K3).bPressed) nMode = 2;
if (GetKey(olc::K4).bPressed) nMode = 3;
if (GetKey(olc::UP).bHeld) dAmplitude += dAmplitude * 1.0 * fElapsedTime;
if (GetKey(olc::DOWN).bHeld) dAmplitude -= dAmplitude * 1.0 * fElapsedTime;
if (GetKey(olc::LEFT).bHeld) dFrequency -= dFrequency * 1.0 * fElapsedTime;
if (GetKey(olc::RIGHT).bHeld) dFrequency += dFrequency * 1.0 * fElapsedTime;
if (GetKey(olc::NP_ADD).bPressed) nHarmonics++;
if (GetKey(olc::NP_SUB).bPressed) nHarmonics--;
// clamp
if (nHarmonics < 1) nHarmonics = 1;
// panzoom inputs
if (GetMouse(0).bPressed) pz.StartPan();
if (GetMouse(0).bReleased) pz.StopPan();
if (GetMouseWheel() > 0 || GetKey(olc::Q).bHeld) pz.ZoomIn(1.1f);
if (GetMouseWheel() < 0 || GetKey(olc::A).bHeld) pz.ZoomOut(0.9f);
pz.Update(fElapsedTime);
// determine range to generate
olc::vd2d vWorldTL, vWorldBR;
pz.ScreenToWorld(vScreenTL, vWorldTL);
pz.ScreenToWorld(vScreenBR, vWorldBR);
// draw axes
olc::vd2d axisXL, axisXR, axisYT, axisYB;
olc::vi2d sAxisXL, sAxisXR, sAxisYT, sAxisYB;
axisXL = { vWorldTL.x, 0.0 };
axisXR = { vWorldBR.x, 0.0 };
axisYT = { 0.0, vWorldTL.y };
axisYB = { 0.0, vWorldBR.y };
pz.WorldToScreen(axisXL, sAxisXL);
pz.WorldToScreen(axisXR, sAxisXR);
pz.WorldToScreen(axisYT, sAxisYT);
pz.WorldToScreen(axisYB, sAxisYB);
DrawLine(sAxisXL, sAxisXR, olc::DARK_GREY);
DrawLine(sAxisYT, sAxisYB, olc::DARK_GREY);
// generate and draw function
olc::vd2d vScreenPosPrev;
for (double x = vWorldTL.x; x < vWorldBR.x; x++)
{
double y = 0.0;
switch (nMode)
{
case 0: y = wavegen::Sine(dFrequency, x, dAmplitude); break;
case 1: y = wavegen::Sawtooth(dFrequency, x, dAmplitude, nHarmonics); break;
case 2: y = wavegen::Square(dFrequency, x, dAmplitude, nHarmonics); break;
case 3: y = wavegen::Triangle(dFrequency, x, dAmplitude, nHarmonics); break;
}
olc::vd2d vWorldPos = { x, y * dScale };
olc::vi2d vScreenPos;
pz.WorldToScreen(vWorldPos, vScreenPos);
if (x != vWorldTL.x)
DrawLine(vScreenPosPrev, vScreenPos);
vScreenPosPrev = vScreenPos;
}
// draw ui
std::string sFunctionName;
switch (nMode)
{
case 0: sFunctionName = "Sine"; break;
case 1: sFunctionName = "Sawtooth"; break;
case 2: sFunctionName = "Square"; break;
case 3: sFunctionName = "Triangle"; break;
}
DrawString({ 5, 5 }, "Function: " + sFunctionName);
DrawString({ 5, 20 }, "Frequency: " + std::to_string(dFrequency * 1000.0));
DrawString({ 5, 35 }, "Amplitude: " + std::to_string(dAmplitude));
DrawString({ 5, 50 }, "Harmonics: " + std::to_string(nHarmonics));
return !(GetKey(olc::ESCAPE).bPressed);
}
};
int main()
{
WaveGenerator app;
app.Construct(1280, 720, 1, 1);
app.Start();
return 0;
}