]> code.delx.au - virtualtones/blob - pianoinstrument.cpp
Fixed octave display
[virtualtones] / pianoinstrument.cpp
1 // pianoinstrument.cpp - A piano simulator
2 // Written by James Bunton <james@delx.net.au>
3 // Licensed under the GPL, see COPYING.txt for more details
4
5
6 #include "pianoinstrument.h"
7
8 using namespace Qt;
9
10
11 PianoInstrument::PianoInstrument(QWidget *parent)
12 : Instrument(parent)
13 {
14 background.load("piano.png");
15
16 memset(oldNotes, 0, sizeof(oldNotes));
17 memset(notes, 0, sizeof(notes));
18
19 noteStart = 48;
20
21 emitSounds();
22 }
23
24 PianoInstrument::~PianoInstrument()
25 {
26
27 }
28
29 QString PianoInstrument::generateHelp()
30 {
31 QString help;
32 help +=
33
34 "<html>"
35
36 "Playing the keyboard:"
37 "<ul>"
38 "<li>You can change the octave using the &quot;Base Octave&quot; box above. Middle C is the third octave</li>"
39 "<li>The keys - qwertyui are the top row white keys</li>"
40 "<li>The keys - 23 567 9 are the top row black keys</li>"
41 "<li>The keys - zxcvbnm, are the bottom row white keys</li>"
42 "<li>The keys - sd ghj l are the bottom row black keys</li>"
43 "<li>When you push a key, the note it corresponds to is highlighted</li>"
44 "</ul>"
45
46 "</html>"
47 ;
48 return help;
49 }
50
51
52 void PianoInstrument::paintEvent(QPaintEvent *)
53 {
54 QPainter paint(this);
55
56 paint.drawPixmap(0, 0, background);
57
58 paint.setPen(Qt::red);
59
60 const int topBlackY = 38;
61 const int topWhiteY = 70;
62 const int botBlackY = 38 + 110;
63 const int botWhiteY = 70 + 110;
64 const int w = 10;
65 const int h = 10;
66
67 if(notes[0] == true) {
68 paint.drawEllipse(6, topWhiteY, w, h);
69 }
70 if(notes[1] == true) {
71 paint.drawEllipse(15, topBlackY, w, h);
72 }
73 if(notes[2] == true) {
74 paint.drawEllipse(29, topWhiteY, w, h);
75 }
76 if(notes[3] == true) {
77 paint.drawEllipse(45, topBlackY, w, h);
78 }
79 if(notes[4] == true) {
80 paint.drawEllipse(52, topWhiteY, w, h);
81 }
82 if(notes[5] == true) {
83 paint.drawEllipse(75, topWhiteY, w, h);
84 }
85 if(notes[6] == true) {
86 paint.drawEllipse(85, topBlackY, w, h);
87 }
88 if(notes[7] == true) {
89 paint.drawEllipse(97, topWhiteY, w, h);
90 }
91 if(notes[8] == true) {
92 paint.drawEllipse(113, topBlackY, w, h);
93 }
94 if(notes[9] == true) {
95 paint.drawEllipse(120, topWhiteY, w, h);
96 }
97 if(notes[10] == true) {
98 paint.drawEllipse(136, topBlackY, w, h);
99 }
100 if(notes[11] == true) {
101 paint.drawEllipse(143, topWhiteY, w, h);
102 }
103 if(notes[12] == true) {
104 paint.drawEllipse(166, topWhiteY, w, h);
105 paint.drawEllipse(6, botWhiteY, w, h);
106 }
107 if(notes[13] == true) {
108 paint.drawEllipse(176, topBlackY, w, h);
109 paint.drawEllipse(15, botBlackY, w, h);
110 }
111 if(notes[14] == true) {
112 paint.drawEllipse(29, botWhiteY, w, h);
113 }
114 if(notes[15] == true) {
115 paint.drawEllipse(45, botBlackY, w, h);
116 }
117 if(notes[16] == true) {
118 paint.drawEllipse(52, botWhiteY, w, h);
119 }
120 if(notes[17] == true) {
121 paint.drawEllipse(75, botWhiteY, w, h);
122 }
123 if(notes[18] == true) {
124 paint.drawEllipse(85, botBlackY, w, h);
125 }
126 if(notes[19] == true) {
127 paint.drawEllipse(97, botWhiteY, w, h);
128 }
129 if(notes[20] == true) {
130 paint.drawEllipse(113, botBlackY, w, h);
131 }
132 if(notes[21] == true) {
133 paint.drawEllipse(120, botWhiteY, w, h);
134 }
135 if(notes[22] == true) {
136 paint.drawEllipse(136, botBlackY, w, h);
137 }
138 if(notes[23] == true) {
139 paint.drawEllipse(143, botWhiteY, w, h);
140 }
141 if(notes[24] == true) {
142 paint.drawEllipse(166, botWhiteY, w, h);
143 }
144 if(notes[25] == true) {
145 paint.drawEllipse(176, botBlackY, w, h);
146 }
147
148 }
149
150
151 void PianoInstrument::keyPressEvent(QKeyEvent *e)
152 {
153 if(e->isAutoRepeat() == true) {
154 e->ignore();
155 return;
156 }
157
158 // Make a copy of the old notes so we know what's changed
159 copyArray(notes, oldNotes);
160
161 switch(e->key()) {
162
163 /* First row of keys */
164 case Key_Q:
165 notes[0] = true;
166 break;
167 case Key_2:
168 notes[1] = true;
169 break;
170 case Key_W:
171 notes[2] = true;
172 break;
173 case Key_3:
174 notes[3] = true;
175 break;
176 case Key_E:
177 notes[4] = true;
178 break;
179 case Key_R:
180 notes[5] = true;
181 break;
182 case Key_5:
183 notes[6] = true;
184 break;
185 case Key_T:
186 notes[7] = true;
187 break;
188 case Key_6:
189 notes[8] = true;
190 break;
191 case Key_Y:
192 notes[9] = true;
193 break;
194 case Key_7:
195 notes[10] = true;
196 break;
197 case Key_U:
198 notes[11] = true;
199 break;
200 case Key_I:
201 notes[12] = true;
202 break;
203 case Key_9:
204 notes[13] = true;
205 break;
206
207 /* Second row of keys */
208 case Key_Z:
209 notes[12] = true;
210 break;
211 case Key_S:
212 notes[13] = true;
213 break;
214 case Key_X:
215 notes[14] = true;
216 break;
217 case Key_D:
218 notes[15] = true;
219 break;
220 case Key_C:
221 notes[16] = true;
222 break;
223 case Key_V:
224 notes[17] = true;
225 break;
226 case Key_G:
227 notes[18] = true;
228 break;
229 case Key_B:
230 notes[19] = true;
231 break;
232 case Key_H:
233 notes[20] = true;
234 break;
235 case Key_N:
236 notes[21] = true;
237 break;
238 case Key_J:
239 notes[22] = true;
240 break;
241 case Key_M:
242 notes[23] = true;
243 break;
244 case Key_Comma:
245 notes[24] = true;
246 break;
247 case Key_L:
248 notes[25] = true;
249 break;
250 default:
251 e->ignore();
252 return;
253 }
254 e->accept();
255 emitSounds();
256 }
257
258 void PianoInstrument::keyReleaseEvent(QKeyEvent *e)
259 {
260 if(e->isAutoRepeat() == true) {
261 e->ignore();
262 return;
263 }
264
265 // Make a copy of the old notes so we know what's changed
266 copyArray(notes, oldNotes);
267
268 switch(e->key()) {
269
270 /* First row of keys */
271 case Key_Q:
272 notes[0] = false;
273 break;
274 case Key_2:
275 notes[1] = false;
276 break;
277 case Key_W:
278 notes[2] = false;
279 break;
280 case Key_3:
281 notes[3] = false;
282 break;
283 case Key_E:
284 notes[4] = false;
285 break;
286 case Key_R:
287 notes[5] = false;
288 break;
289 case Key_5:
290 notes[6] = false;
291 break;
292 case Key_T:
293 notes[7] = false;
294 break;
295 case Key_6:
296 notes[8] = false;
297 break;
298 case Key_Y:
299 notes[9] = false;
300 break;
301 case Key_7:
302 notes[10] = false;
303 break;
304 case Key_U:
305 notes[11] = false;
306 break;
307 case Key_I:
308 notes[12] = false;
309 break;
310 case Key_9:
311 notes[13] = false;
312 break;
313
314 /* Second row of keys */
315 case Key_Z:
316 notes[12] = false;
317 break;
318 case Key_S:
319 notes[13] = false;
320 break;
321 case Key_X:
322 notes[14] = false;
323 break;
324 case Key_D:
325 notes[15] = false;
326 break;
327 case Key_C:
328 notes[16] = false;
329 break;
330 case Key_V:
331 notes[17] = false;
332 break;
333 case Key_G:
334 notes[18] = false;
335 break;
336 case Key_B:
337 notes[19] = false;
338 break;
339 case Key_H:
340 notes[20] = false;
341 break;
342 case Key_N:
343 notes[21] = false;
344 break;
345 case Key_J:
346 notes[22] = false;
347 break;
348 case Key_M:
349 notes[23] = false;
350 break;
351 case Key_Comma:
352 notes[24] = false;
353 break;
354 case Key_L:
355 notes[25] = false;
356 break;
357 default:
358 e->ignore();
359 return;
360 }
361 e->accept();
362 emitSounds();
363 }
364
365 void PianoInstrument::copyArray(bool source[26], bool dest[26])
366 {
367 for(int i = 0; i < 26; i++) {
368 dest[i] = source[i];
369 }
370 }
371
372 void PianoInstrument::emitSounds()
373 {
374 for(int i = 0; i < 26; i++) {
375 if(notes[i] == oldNotes[i]) continue;
376
377 if(notes[i] == false)
378 emit stopNote(i + noteStart);
379 else {
380 emit playNote(i + noteStart, 120, 0);
381 }
382 }
383
384 repaint();
385 }