1 /*
2 * tracker/DialogResample.cpp
3 *
4 * Copyright 2009 Peter Barth
5 *
6 * This file is part of Milkytracker.
7 *
8 * Milkytracker is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Milkytracker is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with Milkytracker. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23 /*
24 * DialogResample.cpp
25 * MilkyTracker
26 *
27 * Created by Peter Barth on 25.10.05.
28 *
29 */
30
31 #include "DialogResample.h"
32 #include "Screen.h"
33 #include "StaticText.h"
34 #include "CheckBox.h"
35 #include "CheckBoxLabel.h"
36 #include "PPUIConfig.h"
37 #include "MessageBoxContainer.h"
38 #include "Font.h"
39 #include "ListBox.h"
40 #include "Seperator.h"
41 #include "XModule.h"
42 #include "ResamplerHelper.h"
43
getc4spd(mp_sint32 relnote,mp_sint32 finetune)44 float getc4spd(mp_sint32 relnote,mp_sint32 finetune)
45 {
46 static const mp_sint32 table[] = {65536,69432,73561,77935,82570,87480,92681,98193,104031,110217,116771,123715,
47 65536,65565,65595,65624,65654,65684,65713,65743,65773,65802,65832,65862,65891,
48 65921,65951,65981,66010,66040,66070,66100,66130,66160,66189,66219,66249,66279,
49 66309,66339,66369,66399,66429,66459,66489,66519,66549,66579,66609,66639,66669,
50 66699,66729,66759,66789,66820,66850,66880,66910,66940,66971,67001,67031,67061,
51 67092,67122,67152,67182,67213,67243,67273,67304,67334,67365,67395,67425,67456,
52 67486,67517,67547,67578,67608,67639,67669,67700,67730,67761,67792,67822,67853,
53 67883,67914,67945,67975,68006,68037,68067,68098,68129,68160,68190,68221,68252,
54 68283,68314,68344,68375,68406,68437,68468,68499,68530,68561,68592,68623,68654,
55 68685,68716,68747,68778,68809,68840,68871,68902,68933,68964,68995,69026,69057,
56 69089,69120,69151,69182,69213,69245,69276,69307,69339,69370,69401};
57
58 mp_sint32 c4spd = 8363;
59 mp_sbyte xmfine = finetune;
60
61 mp_sbyte octave = (relnote+96)/12;
62 mp_sbyte note = (relnote+96)%12;
63
64 mp_sbyte o2 = octave-8;
65
66 if (xmfine<0)
67 {
68 xmfine+=(mp_sbyte)128;
69 note--;
70 if (note<0)
71 {
72 note+=12;
73 o2--;
74 }
75 }
76
77 if (o2>=0)
78 {
79 c4spd<<=o2;
80 }
81 else
82 {
83 c4spd>>=-o2;
84 }
85
86 float f = table[(mp_ubyte)note]*(1.0f/65536.0f) * c4spd;
87 return f * (table[(mp_ubyte)xmfine+12]*(1.0f/65536.0f));
88 }
89
DialogResample(PPScreen * screen,DialogResponder * responder,pp_int32 id)90 DialogResample::DialogResample(PPScreen* screen,
91 DialogResponder* responder,
92 pp_int32 id) :
93 PPDialogBase(),
94 count(0),
95 resamplerHelper(new ResamplerHelper()),
96 interpolationType(1),
97 adjustFtAndRelnote(true)
98 {
99 #ifdef __LOWRES__
100 initDialog(screen, responder, id, "Resample" PPSTR_PERIODS, 290, 142+15+20+16, 26+15, "Ok", "Cancel");
101 #else
102 initDialog(screen, responder, id, "Resample" PPSTR_PERIODS, 290, 142+20+16, 26, "Ok", "Cancel");
103 #endif
104
105 pp_int32 x = getMessageBoxContainer()->getLocation().x;
106
107 pp_int32 width = getMessageBoxContainer()->getSize().width;
108
109 pp_int32 x2 = x;
110 pp_int32 y2 = getMessageBoxContainer()->getControlByID(MESSAGEBOX_STATICTEXT_MAIN_CAPTION)->getLocation().y;
111
112 PPButton* button;
113
114 y2 +=16;
115
116 // enter edit field 1
117 x2 = x + width / 2 - (10*8+35 + 14*8)/2;
118
119 messageBoxContainerGeneric->addControl(new PPStaticText(0, screen, this, PPPoint(x2, y2+2), "Relative note", true));
120
121 x2+=17*8;
122 PPListBox* listBox = new PPListBox(MESSAGEBOX_LISTBOX_VALUE_ONE, screen, this, PPPoint(x2, y2), PPSize(7*8,12), true, true, false);
123 listBox->showSelection(false);
124 listBox->setBorderColor(messageBoxContainerGeneric->getColor());
125 listBox->setMaxEditSize(8);
126 listBoxes[0] = listBox;
127 messageBoxContainerGeneric->addControl(listBox);
128
129 button = new PPButton(MESSAGEBOX_BUTTON_INCREASE_VALUEONE, screen, this, PPPoint(x2 + listBox->getSize().width + 2, y2), PPSize(16, 11));
130 button->setText("+");
131 messageBoxContainerGeneric->addControl(button);
132
133 button = new PPButton(MESSAGEBOX_BUTTON_DECREASE_VALUEONE, screen, this, PPPoint(x2 + listBox->getSize().width + 2 + button->getSize().width + 1, y2), PPSize(16, 11));
134 button->setText("-");
135 messageBoxContainerGeneric->addControl(button);
136
137 y2+=16;
138
139 x2 = x + width / 2 - (10*8+35 + 14*8)/2;
140
141 messageBoxContainerGeneric->addControl(new PPStaticText(0, screen, this, PPPoint(x2, y2+2), "Fine tune", true));
142
143 x2+=17*8;
144 listBox = new PPListBox(MESSAGEBOX_LISTBOX_VALUE_TWO, screen, this, PPPoint(x2, y2), PPSize(7*8,12), true, true, false);
145 listBox->showSelection(false);
146 listBox->setBorderColor(messageBoxContainerGeneric->getColor());
147 listBox->setMaxEditSize(8);
148 listBoxes[1] = listBox;
149 messageBoxContainerGeneric->addControl(listBox);
150
151 button = new PPButton(MESSAGEBOX_BUTTON_INCREASE_VALUETWO, screen, this, PPPoint(x2 + listBox->getSize().width + 2, y2), PPSize(16, 11));
152 button->setText("+");
153 messageBoxContainerGeneric->addControl(button);
154
155 button = new PPButton(MESSAGEBOX_BUTTON_DECREASE_VALUETWO, screen, this, PPPoint(x2 + listBox->getSize().width + 2 + button->getSize().width + 1, y2), PPSize(16, 11));
156 button->setText("-");
157 messageBoxContainerGeneric->addControl(button);
158
159 y2+=16;
160
161 x2 = x + width / 2 - (10*8+35 + 14*8)/2;
162
163 messageBoxContainerGeneric->addControl(new PPStaticText(0, screen, this, PPPoint(x2, y2+2), "C4 speed (Hz)", true));
164
165 x2+=14*8;
166 listBox = new PPListBox(MESSAGEBOX_LISTBOX_VALUE_THREE, screen, this, PPPoint(x2, y2), PPSize(10*8,12), true, true, false);
167 listBox->showSelection(false);
168 listBox->setBorderColor(messageBoxContainerGeneric->getColor());
169 listBox->setMaxEditSize(8);
170 listBoxes[2] = listBox;
171 messageBoxContainerGeneric->addControl(listBox);
172
173 button = new PPButton(MESSAGEBOX_BUTTON_INCREASE_VALUETHREE, screen, this, PPPoint(x2 + listBox->getSize().width + 2, y2), PPSize(16, 11));
174 button->setText("+");
175 messageBoxContainerGeneric->addControl(button);
176
177 button = new PPButton(MESSAGEBOX_BUTTON_DECREASE_VALUETHREE, screen, this, PPPoint(x2 + listBox->getSize().width + 2 + button->getSize().width + 1, y2), PPSize(16, 11));
178 button->setText("-");
179 messageBoxContainerGeneric->addControl(button);
180
181 y2+=16;
182 x2 = x + width / 2 - (10*8+35 + 14*8)/2;
183 messageBoxContainerGeneric->addControl(new PPStaticText(0, screen, this, PPPoint(x2, y2+2), "New size:", true));
184 x2+=18*8;
185 messageBoxContainerGeneric->addControl(new PPStaticText(MESSAGEBOX_STATICTEXT_USER1, screen, this, PPPoint(x2, y2+2), "XXXXXXXX"));
186
187 y2+=16;
188
189 x2 = x + width / 2 - (10*8+35 + 14*8)/2;
190 messageBoxContainerGeneric->addControl(new PPStaticText(0, screen, this, PPPoint(x2, y2+2), "Interpolation:", true));
191
192 x2+=15*8;
193 button = new PPButton(MESSAGEBOX_CONTROL_USER1, screen, this, PPPoint(x2, y2), PPSize(button->getLocation().x + button->getSize().width - x2, 11), false);
194 button->setText(resamplerHelper->getResamplerName(interpolationType, true));
195 button->setColor(messageBoxContainerGeneric->getColor());
196 button->setTextColor(PPUIConfig::getInstance()->getColor(PPUIConfig::ColorStaticText));
197
198 messageBoxContainerGeneric->addControl(button);
199
200 y2+=16;
201
202 x2 = x + width / 2 - (10 * 8 + 35 + 14 * 8) / 2 + 21 * 8;
203 checkBox = new PPCheckBox(MESSAGEBOX_CONTROL_USER2, screen, this, PPPoint(x2, y2 + 1));
204 checkBox->checkIt(adjustFtAndRelnote);
205 messageBoxContainerGeneric->addControl(checkBox);
206
207 x2 -= 21 * 8;
208 messageBoxContainerGeneric->addControl(new PPCheckBoxLabel(0, screen, this, PPPoint(x2, y2 + 2), "Adjust Ft/Rel.Note:", checkBox, true));
209
210 y2+=16;
211
212 #ifdef __LOWRES__
213 pp_int32 height = getMessageBoxContainer()->getSize().height;
214 pp_int32 y = getMessageBoxContainer()->getLocation().y;
215
216 const char buttonTexts[] = {'1','2','3','4','5','6','7','8','9','0','+','-','.','<','>'};
217
218 pp_int32 bWidth = (width - 22*2 - 2*3) / sizeof(buttonTexts);
219 pp_int32 x2_2 = x+4;
220
221 pp_int32 y2_2 = y+height - 4 - 13;
222
223 messageBoxContainerGeneric->addControl(new PPSeperator(0, screen, PPPoint(x2_2-1, y2_2-3), width-2*3, messageBoxContainerGeneric->getColor(), true));
224
225 pp_uint32 i = 0;
226 for (i = 0; i < sizeof(buttonTexts); i++)
227 {
228 button = new PPButton(MESSAGEBOX_BUTTON_KEYS_BASE+i, screen, this, PPPoint(x2_2, y2_2), PPSize(bWidth+1, 13));
229 button->setText(buttonTexts[i]);
230 messageBoxContainerGeneric->addControl(button);
231 x2_2+=bWidth;
232 }
233
234 bWidth = 22;
235
236 button = new PPButton(MESSAGEBOX_BUTTON_KEYS_BASE+i, screen, this, PPPoint(x2_2, y2_2), PPSize(bWidth+1-3, 13));
237 button->setFont(PPFont::getFont(PPFont::FONT_TINY));
238 button->setText("Del");
239 messageBoxContainerGeneric->addControl(button);
240 x2_2+=bWidth-3;
241 i++;
242 button = new PPButton(MESSAGEBOX_BUTTON_KEYS_BASE+i, screen, this, PPPoint(x2_2, y2_2), PPSize(bWidth+1, 13));
243 button->setFont(PPFont::getFont(PPFont::FONT_TINY));
244 button->setText("Back");
245 messageBoxContainerGeneric->addControl(button);
246 #endif
247
248 currentSelectedListBox = 0;
249 relnote = finetune = 0;
250 c4spd = 0.0f;
251 }
252
~DialogResample()253 DialogResample::~DialogResample()
254 {
255 delete resamplerHelper;
256 }
257
show(bool b)258 void DialogResample::show(bool b/* = true*/)
259 {
260 if (b)
261 {
262 currentSelectedListBox = 0;
263 updateListBoxes();
264 listBoxEnterEditState(MESSAGEBOX_LISTBOX_VALUE_ONE);
265
266 PPButton* button = static_cast<PPButton*>(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_CONTROL_USER1));
267 button->setText(resamplerHelper->getResamplerName(interpolationType, true));
268 }
269 PPDialogBase::show(b);
270 }
271
handleEvent(PPObject * sender,PPEvent * event)272 pp_int32 DialogResample::handleEvent(PPObject* sender, PPEvent* event)
273 {
274 if (event->getID() == eKeyDown)
275 {
276 pp_uint16 keyCode = *((pp_uint16*)event->getDataPtr());
277 if (keyCode == VK_TAB)
278 {
279 switchListBox();
280 event->cancel();
281 }
282 }
283 else if (event->getID() == eCommand || event->getID() == eCommandRepeat)
284 {
285 switch (reinterpret_cast<PPControl*>(sender)->getID())
286 {
287 case PP_MESSAGEBOX_BUTTON_YES:
288 {
289 commitChanges();
290 break;
291 }
292
293 case MESSAGEBOX_BUTTON_INCREASE_VALUEONE:
294 {
295 relnote++;
296 toC4Speed();
297 calcSize();
298 updateListBoxes();
299 parentScreen->paintControl(messageBoxContainerGeneric);
300 break;
301 }
302
303 case MESSAGEBOX_BUTTON_DECREASE_VALUEONE:
304 {
305 relnote--;
306 toC4Speed();
307 calcSize();
308 updateListBoxes();
309 parentScreen->paintControl(messageBoxContainerGeneric);
310 break;
311 }
312
313 case MESSAGEBOX_BUTTON_INCREASE_VALUETWO:
314 {
315 finetune++;
316 toC4Speed();
317 calcSize();
318 updateListBoxes();
319 parentScreen->paintControl(messageBoxContainerGeneric);
320 break;
321 }
322
323 case MESSAGEBOX_BUTTON_DECREASE_VALUETWO:
324 {
325 finetune--;
326 toC4Speed();
327 calcSize();
328 updateListBoxes();
329 parentScreen->paintControl(messageBoxContainerGeneric);
330 break;
331 }
332
333 case MESSAGEBOX_BUTTON_INCREASE_VALUETHREE:
334 {
335 c4spd++;
336 fromC4Speed();
337 calcSize();
338 updateListBoxes();
339 parentScreen->paintControl(messageBoxContainerGeneric);
340 break;
341 }
342
343 case MESSAGEBOX_BUTTON_DECREASE_VALUETHREE:
344 {
345 c4spd--;
346 fromC4Speed();
347 calcSize();
348 updateListBoxes();
349 parentScreen->paintControl(messageBoxContainerGeneric);
350 break;
351 }
352
353 case MESSAGEBOX_CONTROL_USER1:
354 {
355 if (event->getID() != eCommand)
356 break;
357
358 interpolationType = (interpolationType + 1) % resamplerHelper->getNumResamplers();
359
360 PPButton* button = static_cast<PPButton*>(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_CONTROL_USER1));
361 button->setText(resamplerHelper->getResamplerName(interpolationType, true));
362 parentScreen->paintControl(messageBoxContainerGeneric);
363 break;
364 }
365
366 case MESSAGEBOX_CONTROL_USER2:
367 {
368 if (event->getID() != eCommand)
369 break;
370
371 this->adjustFtAndRelnote = reinterpret_cast<PPCheckBox*>(sender)->isChecked();
372 break;
373 }
374
375 }
376 }
377 else if (event->getID() == eValueChanged)
378 {
379 switch (reinterpret_cast<PPControl*>(sender)->getID())
380 {
381 case MESSAGEBOX_LISTBOX_VALUE_ONE:
382 {
383 const PPString* str = *(reinterpret_cast<PPString* const*>(event->getDataPtr()));
384 setRelNote((pp_int32)atoi(*str));
385 calcSize();
386 updateListBoxes();
387 parentScreen->paintControl(messageBoxContainerGeneric);
388 break;
389 }
390
391 case MESSAGEBOX_LISTBOX_VALUE_TWO:
392 {
393 const PPString* str = *(reinterpret_cast<PPString* const*>(event->getDataPtr()));
394 setFineTune((pp_int32)atoi(*str));
395 calcSize();
396 updateListBoxes();
397 parentScreen->paintControl(messageBoxContainerGeneric);
398 break;
399 }
400
401 case MESSAGEBOX_LISTBOX_VALUE_THREE:
402 {
403 const PPString* str = *(reinterpret_cast<PPString* const*>(event->getDataPtr()));
404 setC4Speed((float)atof(*str));
405 calcSize();
406 updateListBoxes();
407 parentScreen->paintControl(messageBoxContainerGeneric);
408 break;
409 }
410 }
411 }
412
413 return PPDialogBase::handleEvent(sender, event);
414 }
415
updateListBoxes()416 void DialogResample::updateListBoxes()
417 {
418 updateListBox(MESSAGEBOX_LISTBOX_VALUE_ONE, (float)relnote, 0);
419 updateListBox(MESSAGEBOX_LISTBOX_VALUE_TWO, (float)finetune, 0);
420 updateListBox(MESSAGEBOX_LISTBOX_VALUE_THREE, (float)c4spd, 2);
421
422 PPStaticText* staticText = static_cast<PPStaticText*>(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_STATICTEXT_USER1));
423 staticText->setHexValue(finalSize, 8);
424
425 checkBox->checkIt(adjustFtAndRelnote);
426 }
427
updateListBox(pp_int32 id,float val,pp_int32 numDecimals)428 void DialogResample::updateListBox(pp_int32 id, float val, pp_int32 numDecimals)
429 {
430 char buffer1[100];
431 char buffer2[100];
432
433 sprintf(buffer1, "%%.%if", numDecimals);
434
435 PPListBox* listBox = static_cast<PPListBox*>(messageBoxContainerGeneric->getControlByID(id));
436 if (listBox)
437 {
438 sprintf(buffer2, buffer1, val);
439 listBox->clear();
440 listBox->addItem(buffer2);
441 }
442 }
443
commitChanges()444 void DialogResample::commitChanges()
445 {
446 PPListBox* listBox = static_cast<PPListBox*>(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_LISTBOX_VALUE_ONE));
447 if (listBox)
448 listBox->commitChanges();
449
450 listBox = static_cast<PPListBox*>(messageBoxContainerGeneric->getControlByID(MESSAGEBOX_LISTBOX_VALUE_TWO));
451 if (listBox)
452 listBox->commitChanges();
453 }
454
listBoxEnterEditState(pp_int32 id)455 void DialogResample::listBoxEnterEditState(pp_int32 id)
456 {
457 PPListBox* listBox = static_cast<PPListBox*>(messageBoxContainerGeneric->getControlByID(id));
458 if (listBox)
459 listBox->placeCursorAtEnd();
460 }
461
switchListBox()462 void DialogResample::switchListBox()
463 {
464 if (listBoxes[currentSelectedListBox]->isEditing())
465 listBoxes[currentSelectedListBox]->commitChanges();
466
467 currentSelectedListBox = (currentSelectedListBox+1) % 3;
468
469 listBoxEnterEditState(listBoxes[currentSelectedListBox]->getID());
470 messageBoxContainerGeneric->setFocus(listBoxes[currentSelectedListBox]);
471 parentScreen->paintControl(messageBoxContainerGeneric);
472 }
473
setRelNote(pp_int32 note)474 void DialogResample::setRelNote(pp_int32 note)
475 {
476 relnote = note;
477 toC4Speed();
478
479 if (count < 2)
480 {
481 count++;
482 if (count == 2)
483 originalc4spd = c4spd;
484 }
485 }
486
setFineTune(pp_int32 ft)487 void DialogResample::setFineTune(pp_int32 ft)
488 {
489 finetune = ft;
490 toC4Speed();
491
492 if (count < 2)
493 {
494 count++;
495 if (count == 2)
496 originalc4spd = c4spd;
497 }
498 }
499
setC4Speed(float c4spd)500 void DialogResample::setC4Speed(float c4spd)
501 {
502 this->c4spd = c4spd;
503 fromC4Speed();
504 }
505
setSize(pp_uint32 size)506 void DialogResample::setSize(pp_uint32 size)
507 {
508 this->size = size;
509
510 calcSize();
511 }
512
toC4Speed()513 void DialogResample::toC4Speed()
514 {
515 validate();
516 c4spd = getc4spd(relnote, finetune);
517 validate();
518 }
519
fromC4Speed()520 void DialogResample::fromC4Speed()
521 {
522 validate();
523 mp_sbyte rn, ft;
524 XModule::convertc4spd((mp_uint32)c4spd, &ft, &rn);
525 relnote = rn;
526 finetune = ft;
527 validate();
528 }
529
calcSize()530 void DialogResample::calcSize()
531 {
532 float c4spd = getc4spd(relnote, finetune);
533 float step = originalc4spd / c4spd;
534
535 finalSize = (mp_uint32)(size / step);
536 }
537
validate()538 void DialogResample::validate()
539 {
540 if (relnote > 48)
541 relnote = 48;
542 if (relnote < -48)
543 relnote = -48;
544
545 if (finetune > 127)
546 finetune = 127;
547 if (finetune < -128)
548 finetune = -128;
549
550 if (c4spd < 0)
551 c4spd = 0;
552
553 if (c4spd > 65535*4)
554 c4spd = 65535*4;
555 }
556