1 /*
2 * tracker/PlayerController.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 * PlayerController.cpp
25 * MilkyTracker
26 *
27 * Created by Peter Barth on Tue Mar 15 2005.
28 *
29 */
30
31 #include "PlayerController.h"
32 #include "PlayerMaster.h"
33 #include "MilkyPlay.h"
34 #include "ResamplerMacros.h"
35 #include "PPSystem.h"
36 #include "PlayerCriticalSection.h"
37 #include "ModuleEditor.h"
38
39 class PlayerStatusTracker : public PlayerSTD::StatusEventListener
40 {
41 public:
PlayerStatusTracker(PlayerController & playerController)42 PlayerStatusTracker(PlayerController& playerController) :
43 playerController(playerController)
44 {
45 clearUpdateCommandBuff();
46 }
47
48 // this is being called from the player callback in a serialized fashion
playerTickStarted(PlayerSTD & player,XModule & module)49 virtual void playerTickStarted(PlayerSTD& player, XModule& module)
50 {
51 while (rbReadIndex < rbWriteIndex)
52 {
53 mp_sint32 idx = rbReadIndex & (UPDATEBUFFSIZE-1);
54
55 // handle notes that are played from external source
56 // i.e. keyboard playback
57 switch (updateCommandBuff[idx].code)
58 {
59 case UpdateCommandCodeNote:
60 {
61 UpdateCommandNote* command = reinterpret_cast<UpdateCommandNote*>(&updateCommandBuff[idx]);
62 mp_sint32 note = command->note;
63 if (note)
64 {
65 player.playNote(command->channel, note,
66 command->ins,
67 command->volume);
68 command->note = 0;
69 }
70 break;
71 }
72
73 case UpdateCommandCodeSample:
74 {
75 UpdateCommandSample* command = reinterpret_cast<UpdateCommandSample*>(&updateCommandBuff[idx]);
76 const TXMSample* smp = command->smp;
77 if (smp)
78 {
79 playSampleInternal(player, command->channel, smp, command->currentSamplePlayNote,
80 command->rangeStart, command->rangeEnd);
81 command->smp = NULL;
82 }
83
84 break;
85 }
86
87 }
88 rbReadIndex++;
89 }
90 }
91
patternEndReached(PlayerSTD & player,XModule & module,mp_sint32 & newOrderIndex)92 virtual void patternEndReached(PlayerSTD& player, XModule& module, mp_sint32& newOrderIndex)
93 {
94 handleQueuedPositions(player, newOrderIndex);
95 }
96
playNote(mp_ubyte chn,mp_sint32 note,mp_sint32 ins,mp_sint32 vol)97 void playNote(mp_ubyte chn, mp_sint32 note, mp_sint32 ins, mp_sint32 vol/* = -1*/)
98 {
99 // fill ring buffer with note entries
100 // the callback will query these notes and play them
101 mp_sint32 idx = rbWriteIndex & (UPDATEBUFFSIZE-1);
102 UpdateCommandNote* command = reinterpret_cast<UpdateCommandNote*>(&updateCommandBuff[idx]);
103 command->channel = chn;
104 command->ins = ins;
105 command->volume = vol;
106 command->note = note;
107 // code needs to be filled in last
108 command->code = UpdateCommandCodeNote;
109 rbWriteIndex++;
110 }
111
playSample(mp_ubyte chn,const TXMSample & smp,mp_sint32 currentSamplePlayNote,mp_sint32 rangeStart,mp_sint32 rangeEnd)112 void playSample(mp_ubyte chn, const TXMSample& smp, mp_sint32 currentSamplePlayNote, mp_sint32 rangeStart, mp_sint32 rangeEnd)
113 {
114 // fill ring buffer with sample playback entries
115 mp_sint32 idx = rbWriteIndex & (UPDATEBUFFSIZE-1);
116 UpdateCommandSample* command = reinterpret_cast<UpdateCommandSample*>(&updateCommandBuff[idx]);
117 command->channel = chn;
118 command->currentSamplePlayNote = currentSamplePlayNote;
119 command->rangeStart = rangeStart;
120 command->rangeEnd = rangeEnd;
121 command->smp = &smp;
122 command->code = UpdateCommandCodeSample;
123 rbWriteIndex++;
124 }
125
126 private:
127 PlayerController& playerController;
128
handleQueuedPositions(PlayerSTD & player,mp_sint32 & poscnt)129 void handleQueuedPositions(PlayerSTD& player, mp_sint32& poscnt)
130 {
131 // there is a queued position
132 if (playerController.nextOrderIndexToPlay != -1)
133 {
134 // the new order the queued one
135 poscnt = playerController.nextOrderIndexToPlay;
136 // the queued one becomes invalid
137 playerController.nextOrderIndexToPlay = -1;
138 // we're no longer in pattern play mode...
139 playerController.patternPlay = false;
140 // ... that's why we're going to set the pattern index to -1
141 playerController.patternIndex = -1;
142 player.setPatternToPlay(-1);
143 }
144 // there is a queued pattern
145 else if (playerController.nextPatternIndexToPlay != -1)
146 {
147 // the new pattern index
148 player.setPatternToPlay(playerController.nextPatternIndexToPlay);
149 // we're no in pattern play mode
150 playerController.patternPlay = true;
151 // that's our new pattern
152 playerController.patternIndex = playerController.nextPatternIndexToPlay;
153 // the queued one becomes invalid
154 playerController.nextPatternIndexToPlay = -1;
155 }
156 }
157
playSampleInternal(PlayerSTD & player,mp_ubyte chn,const TXMSample * smp,mp_sint32 currentSamplePlayNote,mp_sint32 rangeStart,mp_sint32 rangeEnd)158 void playSampleInternal(PlayerSTD& player, mp_ubyte chn, const TXMSample* smp, mp_sint32 currentSamplePlayNote,
159 mp_sint32 rangeStart, mp_sint32 rangeEnd)
160 {
161 pp_int32 period = player.getlogperiod(currentSamplePlayNote+1, smp->relnote, smp->finetune) << 8;
162 pp_int32 freq = player.getlogfreq(period);
163
164 player.setFreq(chn,freq);
165 player.setVol(chn, (smp->vol*512)/255);
166 player.setPan(chn, 128);
167
168 player.chninfo[chn].flags |= 0x100; // CHANNEL_FLAGS_UPDATE_IGNORE
169
170 pp_int32 flags = (smp->type >> 2) & 4;
171
172 if (rangeStart == -1 && rangeEnd == -1)
173 {
174 flags |= smp->type & 3;
175
176 if (flags & 3)
177 player.playSample(chn, smp->sample, smp->samplen, 0, 0, false, smp->loopstart, smp->loopstart+smp->looplen, flags);
178 else
179 player.playSample(chn, smp->sample, smp->samplen, 0, 0, false, 0, smp->samplen, flags);
180 }
181 else
182 {
183 if (rangeStart == -1 || rangeEnd == -1)
184 return;
185
186 if (rangeEnd > (signed)smp->samplen)
187 rangeEnd = smp->samplen;
188
189 player.playSample(chn, smp->sample, smp->samplen, rangeStart, 0, false, 0, rangeEnd, flags);
190 }
191 }
192
clearUpdateCommandBuff()193 void clearUpdateCommandBuff()
194 {
195 memset(updateCommandBuff, 0, sizeof(updateCommandBuff));
196 rbReadIndex = rbWriteIndex = 0;
197 }
198
199 enum
200 {
201 // must be 2^n
202 UPDATEBUFFSIZE = 128
203 };
204
205 enum UpdateCommandCodes
206 {
207 UpdateCommandCodeInvalid = 0,
208 UpdateCommandCodeNote,
209 UpdateCommandCodeSample,
210 };
211
212 struct UpdateCommand
213 {
214 mp_ubyte code;
215 mp_uint32 data[8];
216 void* pdata[8];
217 };
218
219 struct UpdateCommandNote
220 {
221 mp_ubyte code;
222 mp_sint32 note;
223 mp_sint32 channel;
224 mp_sint32 ins;
225 mp_sint32 volume;
226 mp_uint32 data[4];
227 void* pdata[8];
228 };
229
230 struct UpdateCommandSample
231 {
232 mp_ubyte code;
233 mp_uint32 currentSamplePlayNote;
234 mp_uint32 rangeStart;
235 mp_uint32 rangeEnd;
236 mp_sint32 channel;
237 mp_uint32 data[4];
238 const TXMSample* smp;
239 void* pdata[7];
240 };
241
242 UpdateCommand updateCommandBuff[UPDATEBUFFSIZE];
243
244 mp_sint32 rbReadIndex;
245 mp_sint32 rbWriteIndex;
246 };
247
assureNotSuspended()248 void PlayerController::assureNotSuspended()
249 {
250 if (mixer->isDevicePaused(player))
251 {
252 mixer->resumeDevice(player);
253 if (suspended)
254 suspended = false;
255 }
256 }
257
reset()258 void PlayerController::reset()
259 {
260 if (!player)
261 return;
262
263 // reset internal player variables (effect memory) and looping information
264 player->BPMCounter = 0;
265 player->reset();
266 // reset mixer channels (stop playing channels)
267 player->resetChannelsFull();
268 }
269
detachDevice()270 bool PlayerController::detachDevice()
271 {
272 if (!mixer->isDeviceRemoved(player))
273 {
274 return mixer->removeDevice(player);
275 }
276 return false;
277 }
278
PlayerController(MasterMixer * mixer,bool fakeScopes)279 PlayerController::PlayerController(MasterMixer* mixer, bool fakeScopes) :
280 mixer(mixer),
281 player(NULL),
282 module(NULL),
283 criticalSection(NULL),
284 playerStatusTracker(new PlayerStatusTracker(*this)),
285 patternPlay(false), playRowOnly(false),
286 patternIndex(-1),
287 nextOrderIndexToPlay(-1),
288 nextPatternIndexToPlay(-1),
289 lastPosition(-1), lastRow(-1),
290 suspended(false),
291 firstRecordChannelCall(true),
292 numPlayerChannels(TrackerConfig::numPlayerChannels),
293 numVirtualChannels(TrackerConfig::numVirtualChannels),
294 totalPlayerChannels(numPlayerChannels + numVirtualChannels + 2),
295 useVirtualChannels(TrackerConfig::useVirtualChannels),
296 multiChannelKeyJazz(true),
297 multiChannelRecord(true),
298 mixerDataCacheSize(fakeScopes ? 0 : 512*2),
299 mixerDataCache(fakeScopes ? NULL : new mp_sint32[mixerDataCacheSize])
300 {
301 criticalSection = new PlayerCriticalSection(*this);
302
303 player = new PlayerSTD(mixer->getSampleRate(), playerStatusTracker);
304 player->setPlayMode(PlayerBase::PlayMode_FastTracker2);
305 player->resetMainVolumeOnStartPlay(false);
306 player->setBufferSize(mixer->getBufferSize());
307
308 currentPlayingChannel = useVirtualChannels ? numPlayerChannels : 0;
309
310 pp_uint32 i;
311
312 for (i = 0; i < sizeof(muteChannels) / sizeof(bool); i++)
313 muteChannels[i] = false;
314
315 for (i = 0; i < sizeof(recordChannels) / sizeof(bool); i++)
316 recordChannels[i] = false;
317
318 for (i = 0; i < sizeof(panning) / sizeof(mp_ubyte); i++)
319 {
320 switch (i & 3)
321 {
322 case 0:
323 panning[i] = 0;
324 break;
325 case 1:
326 panning[i] = 255;
327 break;
328 case 2:
329 panning[i] = 255;
330 break;
331 case 3:
332 panning[i] = 0;
333 break;
334 }
335 }
336 }
337
~PlayerController()338 PlayerController::~PlayerController()
339 {
340 delete[] mixerDataCache;
341
342 if (player)
343 {
344 detachDevice();
345 delete player;
346 }
347
348 delete playerStatusTracker;
349
350 delete criticalSection;
351 }
352
attachModuleEditor(ModuleEditor * moduleEditor)353 void PlayerController::attachModuleEditor(ModuleEditor* moduleEditor)
354 {
355 this->moduleEditor = moduleEditor;
356 this->module = moduleEditor->getModule();
357
358 if (!player)
359 return;
360
361 if (!mixer->isDeviceRemoved(player))
362 mixer->removeDevice(player);
363
364 ASSERT(sizeof(muteChannels)/sizeof(bool) >= (unsigned)totalPlayerChannels);
365
366 player->startPlaying(module, true, 0, 0, totalPlayerChannels, panning, true);
367
368 // restore muting
369 for (mp_sint32 i = 0; i < numPlayerChannels; i++)
370 player->muteChannel(i, muteChannels[i]);
371
372 mixer->addDevice(player);
373 }
374
playSong(mp_sint32 startIndex,mp_sint32 rowPosition,bool * muteChannels)375 void PlayerController::playSong(mp_sint32 startIndex, mp_sint32 rowPosition, bool* muteChannels)
376 {
377 if (!player)
378 return;
379
380 if (!module)
381 return;
382
383 if (!module->isModuleLoaded())
384 return;
385
386 assureNotSuspended();
387
388 if (!suspended)
389 criticalSection->enter(false);
390
391 readjustSpeed();
392
393 reset();
394
395 player->setPatternToPlay(-1);
396 setNextOrderToPlay(-1);
397 setNextPatternToPlay(-1);
398
399 // muting has been reset, restore it
400 for (mp_sint32 i = 0; i < numPlayerChannels; i++)
401 {
402 player->muteChannel(i, muteChannels[i]);
403 this->muteChannels[i] = muteChannels[i];
404 }
405 player->restart(startIndex, rowPosition, false, panning);
406 player->setIdle(false);
407 //resetPlayTimeCounter();
408
409 patternPlay = false;
410 playRowOnly = false;
411 patternIndex = 0;
412
413 criticalSection->leave(false);
414 }
415
playPattern(mp_sint32 index,mp_sint32 songPosition,mp_sint32 rowPosition,bool * muteChannels,bool playRowOnly)416 void PlayerController::playPattern(mp_sint32 index, mp_sint32 songPosition, mp_sint32 rowPosition, bool* muteChannels, bool playRowOnly/* = false*/)
417 {
418 if (!player)
419 return;
420
421 if (!module)
422 return;
423
424 if (!module->isModuleLoaded())
425 return;
426
427 assureNotSuspended();
428
429 if (!suspended)
430 criticalSection->enter(false);
431
432 readjustSpeed();
433
434 reset();
435
436 setCurrentPatternIndex(index);
437 setNextOrderToPlay(-1);
438 setNextPatternToPlay(-1);
439
440 // muting has been reset, restore it
441 for (mp_sint32 i = 0; i < numPlayerChannels; i++)
442 {
443 player->muteChannel(i, muteChannels[i]);
444 this->muteChannels[i] = muteChannels[i];
445 }
446
447 if (rowPosition == -1)
448 {
449 rowPosition = player->getRow();
450 if (rowPosition >= module->phead[index].rows)
451 rowPosition = 0;
452 }
453
454 player->restart(songPosition, rowPosition, false, panning, playRowOnly);
455 player->setIdle(false);
456 //resetPlayTimeCounter();
457
458 patternPlay = true;
459 this->playRowOnly = playRowOnly;
460 patternIndex = index;
461
462 criticalSection->leave(false);
463 }
464
setCurrentPatternIndex(mp_sint32 index)465 void PlayerController::setCurrentPatternIndex(mp_sint32 index)
466 {
467 if (player)
468 player->setPatternToPlay(index);
469 }
470
stop(bool bResetMainVolume)471 void PlayerController::stop(bool bResetMainVolume/* = true*/)
472 {
473 if (!player)
474 return;
475
476 if (!module)
477 return;
478
479 if (!suspended)
480 criticalSection->enter(false);
481
482 if (isPlaying() && !playRowOnly)
483 {
484 lastPosition = player->getOrder();
485 lastRow = player->getRow();
486 wasPlayingPattern = isPlayingPattern();
487 }
488 else
489 {
490 lastPosition = -1;
491 lastRow = -1;
492 wasPlayingPattern = false;
493 }
494
495 patternPlay = false;
496 playRowOnly = false;
497
498 readjustSpeed();
499
500 player->setIdle(true);
501 reset();
502 player->restart(0, 0, true, panning);
503
504 // muting has been reset, restore it
505 for (mp_sint32 i = 0; i < numPlayerChannels; i++)
506 {
507 player->muteChannel(i, muteChannels[i]);
508 this->muteChannels[i] = muteChannels[i];
509 }
510
511 // reset internal variables
512 if (bResetMainVolume)
513 resetMainVolume();
514
515 setNextOrderToPlay(-1);
516 setNextPatternToPlay(-1);
517
518 criticalSection->leave(false);
519 }
520
continuePlaying()521 void PlayerController::continuePlaying()
522 {
523 continuePlaying(true);
524 }
525
continuePlaying(bool assureNotSuspended)526 void PlayerController::continuePlaying(bool assureNotSuspended)
527 {
528 if (lastPosition == -1 || lastRow == -1)
529 return;
530
531 if (!player)
532 return;
533
534 if (!module)
535 return;
536
537 if (!module->isModuleLoaded())
538 return;
539
540 if (assureNotSuspended)
541 this->assureNotSuspended();
542
543 if (!suspended)
544 criticalSection->enter(false);
545
546 readjustSpeed();
547
548 if (wasPlayingPattern)
549 player->setPatternToPlay(patternIndex);
550 else
551 player->setPatternToPlay(-1);
552
553 for (mp_sint32 i = 0; i < numPlayerChannels; i++)
554 player->muteChannel(i, muteChannels[i]);
555
556 player->restart(lastPosition, lastRow, false, panning);
557 player->setIdle(false);
558
559 patternPlay = wasPlayingPattern;
560 playRowOnly = false;
561
562 criticalSection->leave(false);
563 }
564
restartPlaying()565 void PlayerController::restartPlaying()
566 {
567 if (!player)
568 return;
569
570 if (!module)
571 return;
572
573 if (!module->isModuleLoaded())
574 return;
575
576 lastPosition = lastRow = 0;
577 }
578
isPlaying() const579 bool PlayerController::isPlaying() const
580 {
581 if (!player)
582 return false;
583
584 if (!module)
585 return false;
586
587 return player->isPlaying() && (!player->isIdle()) && !player->hasSongHalted();
588 }
589
isPlayingRowOnly() const590 bool PlayerController::isPlayingRowOnly() const
591 {
592 if (!player)
593 return false;
594
595 if (!module)
596 return false;
597
598 return playRowOnly;
599 }
600
isActive() const601 bool PlayerController::isActive() const
602 {
603 if (!player)
604 return false;
605
606 if (!module)
607 return false;
608
609 return player->isPlaying() && (!player->isIdle());
610 }
611
isPlayingPattern(mp_sint32 index) const612 bool PlayerController::isPlayingPattern(mp_sint32 index) const
613 {
614 if (!player)
615 return false;
616
617 if (index < 0)
618 return false;
619
620 if (player->getPatternToPlay() < 0)
621 return false;
622
623 return isPlayingPattern() && (player->getPatternToPlay() == index);
624 }
625
setNextOrderToPlay(mp_sint32 orderIndex)626 void PlayerController::setNextOrderToPlay(mp_sint32 orderIndex)
627 {
628 nextOrderIndexToPlay = orderIndex;
629 if (orderIndex != -1)
630 nextPatternIndexToPlay = -1;
631 }
632
getNextOrderToPlay() const633 mp_sint32 PlayerController::getNextOrderToPlay() const
634 {
635 return nextOrderIndexToPlay;
636 }
637
setNextPatternToPlay(mp_sint32 patternIndex)638 void PlayerController::setNextPatternToPlay(mp_sint32 patternIndex)
639 {
640 nextPatternIndexToPlay = patternIndex;
641 if (patternIndex != -1)
642 nextOrderIndexToPlay = -1;
643 }
644
getNextPatternToPlay() const645 mp_sint32 PlayerController::getNextPatternToPlay() const
646 {
647 return nextPatternIndexToPlay;
648 }
649
pause()650 void PlayerController::pause()
651 {
652 if (player)
653 player->pausePlaying();
654 }
655
unpause()656 void PlayerController::unpause()
657 {
658 if (player)
659 player->resumePlaying();
660 }
661
isPaused() const662 bool PlayerController::isPaused() const
663 {
664 if (player)
665 return player->isPaused();
666
667 return false;
668 }
669
getSpeed(mp_sint32 & BPM,mp_sint32 & speed)670 void PlayerController::getSpeed(mp_sint32& BPM, mp_sint32& speed)
671 {
672 if (player && player->isPlaying())
673 {
674 BPM = player->getTempo();
675 speed = player->getSpeed();
676 }
677 else if (module)
678 {
679 BPM = module->header.speed;
680 speed = module->header.tempo;
681 }
682 else
683 {
684 BPM = 125;
685 speed = 6;
686 }
687 }
688
setSpeed(mp_sint32 BPM,mp_sint32 speed,bool adjustModuleHeader)689 void PlayerController::setSpeed(mp_sint32 BPM, mp_sint32 speed, bool adjustModuleHeader/* = true*/)
690 {
691 if (!player)
692 return;
693
694 if (BPM < 32)
695 BPM = 32;
696 if (BPM > 255)
697 BPM = 255;
698
699 if (speed < 1)
700 speed = 1;
701 if (speed > 31)
702 speed = 31;
703
704 if (player->isPlaying())
705 {
706 player->setTempo(BPM);
707 player->setSpeed(speed);
708 // this is a MUST!!!
709 pp_uint32 bpmRate = player->getbpmrate(BPM);
710 player->adder = bpmRate;
711 }
712
713 if (module && adjustModuleHeader)
714 {
715 module->header.speed = BPM;
716 module->header.tempo = speed;
717 }
718 }
719
readjustSpeed(bool adjustModuleHeader)720 void PlayerController::readjustSpeed(bool adjustModuleHeader/* = true*/)
721 {
722 mp_sint32 speed, bpm;
723 getSpeed(bpm, speed);
724 setSpeed(bpm, speed, adjustModuleHeader);
725 }
726
playSample(const TXMSample & smp,mp_sint32 currentSamplePlayNote,mp_sint32 rangeStart,mp_sint32 rangeEnd)727 void PlayerController::playSample(const TXMSample& smp, mp_sint32 currentSamplePlayNote, mp_sint32 rangeStart/* = -1*/, mp_sint32 rangeEnd/* = -1*/)
728 {
729 if (!player)
730 return;
731
732 assureNotSuspended();
733
734 if (player->isPlaying())
735 {
736 pp_int32 i = numPlayerChannels + numVirtualChannels + 1;
737
738 playerStatusTracker->playSample(i, smp, currentSamplePlayNote, rangeStart, rangeEnd);
739 }
740
741 }
742
stopSample()743 void PlayerController::stopSample()
744 {
745 if (!player)
746 return;
747
748 if (player->isPlaying())
749 {
750 // doesn't seem to be a critical race condition
751 pp_int32 i = numPlayerChannels + numVirtualChannels + 1;
752
753 player->stopSample(i);
754
755 player->chninfo[i].flags &= ~0x100; // CHANNEL_FLAGS_UPDATE_IGNORE
756 }
757
758 }
759
stopInstrument(mp_sint32 insIndex)760 void PlayerController::stopInstrument(mp_sint32 insIndex)
761 {
762 if (!player)
763 return;
764
765 if (player->isPlaying())
766 {
767 // doesn't seem to be a critical race condition
768 for (pp_int32 i = 0; i < numPlayerChannels + numVirtualChannels; i++)
769 {
770 if (player->chninfo[i].ins == insIndex)
771 {
772 player->stopSample(i);
773 player->chninfo[i].flags &= ~0x100; // CHANNEL_FLAGS_UPDATE_IGNORE
774 }
775 }
776 }
777 }
778
playNote(mp_ubyte chn,mp_sint32 note,mp_sint32 i,mp_sint32 vol)779 void PlayerController::playNote(mp_ubyte chn, mp_sint32 note, mp_sint32 i, mp_sint32 vol/* = -1*/)
780 {
781 if (!player)
782 return;
783
784 assureNotSuspended();
785
786 // note playing goes synchronized in the playback callback
787 playerStatusTracker->playNote(chn, note, i, vol);
788 }
789
suspendPlayer(bool bResetMainVolume,bool stopPlaying)790 void PlayerController::suspendPlayer(bool bResetMainVolume/* = true*/, bool stopPlaying/* = true*/)
791 {
792 if (!player || suspended || mixer->isDeviceRemoved(player))
793 return;
794
795 mixer->pauseDevice(player);
796 suspended = true;
797
798 if (stopPlaying)
799 {
800 stopSample();
801 stop(bResetMainVolume);
802 }
803 }
804
resumePlayer(bool continuePlaying)805 void PlayerController::resumePlayer(bool continuePlaying)
806 {
807 if (!player)
808 return;
809
810 if (continuePlaying)
811 this->continuePlaying(!suspended);
812
813 if (suspended)
814 {
815 mixer->resumeDevice(player);
816 suspended = false;
817 }
818 }
819
muteChannel(mp_sint32 c,bool m)820 void PlayerController::muteChannel(mp_sint32 c, bool m)
821 {
822 muteChannels[c] = m;
823
824 if (player)
825 player->muteChannel(c, m);
826 }
827
isChannelMuted(mp_sint32 c)828 bool PlayerController::isChannelMuted(mp_sint32 c)
829 {
830 return muteChannels[c];
831 // do not poll the state from the player it will be resetted when the
832 // player stops playing of a song
833 /*if (player)
834 {
835 if (!player->getPlayerInstance())
836 return false;
837
838 return static_cast<PlayerSTD*>(player->getPlayerInstance())->isChannelMuted(c);
839 }
840
841 return false;*/
842 }
843
recordChannel(mp_sint32 c,bool m)844 void PlayerController::recordChannel(mp_sint32 c, bool m)
845 {
846 recordChannels[c] = m;
847 }
848
isChannelRecording(mp_sint32 c)849 bool PlayerController::isChannelRecording(mp_sint32 c)
850 {
851 return recordChannels[c];
852 }
853
reallocateChannels(mp_sint32 moduleChannels,mp_sint32 virtualChannels)854 void PlayerController::reallocateChannels(mp_sint32 moduleChannels/* = 32*/, mp_sint32 virtualChannels/* = 0*/)
855 {
856
857 // channels might be changed, we need to make sure playing is stopped firstly
858 bool paused = false;
859 if (player && module) {
860 paused = player->isPaused();
861 stop(false);
862 }
863
864 numPlayerChannels = moduleChannels;
865 numVirtualChannels = virtualChannels;
866 totalPlayerChannels = numPlayerChannels + (numVirtualChannels >= 0 ? numVirtualChannels : 0) + 2;
867
868 if (player && module) {
869 // reattaching will cause the desired channels to be allocated
870 attachModuleEditor(moduleEditor);
871 if (paused)
872 player->pausePlaying();
873 continuePlaying();
874 }
875 }
876
setUseVirtualChannels(bool bUseVirtualChannels)877 void PlayerController::setUseVirtualChannels(bool bUseVirtualChannels)
878 {
879 useVirtualChannels = bUseVirtualChannels;
880
881 currentPlayingChannel = useVirtualChannels ? numPlayerChannels : 0;
882 }
883
resetFirstPlayingChannel()884 void PlayerController::resetFirstPlayingChannel()
885 {
886 for (pp_int32 i = 0; i < module->header.channum; i++)
887 {
888 if (recordChannels[i])
889 {
890 currentPlayingChannel = i;
891 break;
892 }
893 }
894 }
895
getNextPlayingChannel(mp_sint32 currentChannel)896 mp_sint32 PlayerController::getNextPlayingChannel(mp_sint32 currentChannel)
897 {
898 // if we're using virtual channels for instrument playback
899 // the virtual channels are located in the range
900 // [numPlayerChannels .. numPlayerChannels + numVirtualChannels]
901 if (useVirtualChannels)
902 {
903 if (currentPlayingChannel < numPlayerChannels)
904 currentPlayingChannel = numPlayerChannels-1;
905
906 mp_sint32 res = currentPlayingChannel++;
907
908 if (currentPlayingChannel >= numPlayerChannels + numVirtualChannels)
909 currentPlayingChannel = numPlayerChannels;
910
911 return res;
912 }
913 // if we're not using virtual channels for instrument playback
914 // just use the module channels and cut notes which are playing
915 else if (multiChannelKeyJazz)
916 {
917 mp_sint32 res = currentPlayingChannel/*++*/;
918 //if (currentPlayingChannel >= module->header.channum)
919 // currentPlayingChannel = 0;
920
921 bool found = false;
922 for (pp_int32 i = currentPlayingChannel+1; i < currentPlayingChannel + 1 + module->header.channum; i++)
923 {
924 pp_int32 c = i % module->header.channum;
925 if (recordChannels[c])
926 {
927 currentPlayingChannel = c;
928 found = true;
929 break;
930 }
931 }
932
933 return found ? res : currentChannel;
934 }
935
936 return currentChannel;
937 }
938
initRecording()939 void PlayerController::initRecording()
940 {
941 firstRecordChannelCall = true;
942 }
943
getNextRecordingChannel(mp_sint32 currentChannel)944 mp_sint32 PlayerController::getNextRecordingChannel(mp_sint32 currentChannel)
945 {
946 if (currentChannel < 0 || currentChannel >= TrackerConfig::MAXCHANNELS)
947 return -1;
948
949 if (firstRecordChannelCall && recordChannels[currentChannel])
950 {
951 firstRecordChannelCall = false;
952 return currentChannel;
953 }
954 else
955 {
956 for (pp_int32 i = currentChannel+1; i < currentChannel + 1 + module->header.channum; i++)
957 {
958 pp_int32 c = i % module->header.channum;
959 if (recordChannels[c])
960 return c;
961 }
962 //return (currentChannel+1)%module->header.channum;
963 }
964 return currentChannel;
965 }
966
getSongMainVolume()967 mp_sint32 PlayerController::getSongMainVolume()
968 {
969 if (!player || !module)
970 return 255;
971
972 return player->getSongMainVolume();
973 }
974
resetMainVolume()975 void PlayerController::resetMainVolume()
976 {
977 if (!player || !module)
978 return;
979
980 player->setSongMainVolume((mp_ubyte)module->header.mainvol);
981 }
982
getPlayTime()983 mp_int64 PlayerController::getPlayTime()
984 {
985 if (!player)
986 return 0;
987
988 float freq = (float)player->getMixFrequency();
989
990 return (mp_int64)(player->getSampleCounter()/freq);
991 }
992
resetPlayTimeCounter()993 void PlayerController::resetPlayTimeCounter()
994 {
995 if (!player)
996 return;
997
998 player->resetSampleCounter();
999 }
1000
setPanning(mp_ubyte chn,mp_ubyte pan)1001 void PlayerController::setPanning(mp_ubyte chn, mp_ubyte pan)
1002 {
1003 if (!player)
1004 return;
1005
1006 panning[chn] = pan;
1007
1008 if (player && player->isPlaying())
1009 {
1010 for (mp_sint32 i = 0; i < TrackerConfig::numPlayerChannels; i++)
1011 player->setPanning((mp_ubyte)i, panning[i]);
1012 }
1013 }
1014
getPosition(mp_sint32 & pos,mp_sint32 & row)1015 void PlayerController::getPosition(mp_sint32& pos, mp_sint32& row)
1016 {
1017 mp_uint32 index = player->getBeatIndexFromSamplePos(getCurrentSamplePosition());
1018 player->getPosition(pos, row, index);
1019 }
1020
getPosition(mp_sint32 & order,mp_sint32 & row,mp_sint32 & ticker)1021 void PlayerController::getPosition(mp_sint32& order, mp_sint32& row, mp_sint32& ticker)
1022 {
1023 mp_uint32 index = player->getBeatIndexFromSamplePos(getCurrentSamplePosition());
1024 player->getPosition(order, row, ticker, index);
1025 }
1026
setPatternPos(mp_sint32 pos,mp_sint32 row)1027 void PlayerController::setPatternPos(mp_sint32 pos, mp_sint32 row)
1028 {
1029 player->setPatternPos(pos, row, false, false);
1030 }
1031
switchPlayMode(PlayModes playMode,bool exactSwitch)1032 void PlayerController::switchPlayMode(PlayModes playMode, bool exactSwitch/* = true*/)
1033 {
1034 if (!player)
1035 return;
1036
1037 switch (playMode)
1038 {
1039 case PlayMode_ProTracker2:
1040 if (exactSwitch)
1041 {
1042 player->enable(PlayerSTD::PlayModeOptionPanningE8x, false);
1043 player->enable(PlayerSTD::PlayModeOptionPanning8xx, false);
1044 player->enable(PlayerSTD::PlayModeOptionForcePTPitchLimit, true);
1045 }
1046 player->setPlayMode(PlayerBase::PlayMode_ProTracker2);
1047 break;
1048 case PlayMode_ProTracker3:
1049 if (exactSwitch)
1050 {
1051 player->enable(PlayerSTD::PlayModeOptionPanningE8x, false);
1052 player->enable(PlayerSTD::PlayModeOptionPanning8xx, false);
1053 player->enable(PlayerSTD::PlayModeOptionForcePTPitchLimit, true);
1054 }
1055 player->setPlayMode(PlayerBase::PlayMode_ProTracker3);
1056 break;
1057 case PlayMode_FastTracker2:
1058 if (exactSwitch)
1059 {
1060 player->enable(PlayerSTD::PlayModeOptionPanningE8x, false);
1061 player->enable(PlayerSTD::PlayModeOptionPanning8xx, true);
1062 player->enable(PlayerSTD::PlayModeOptionForcePTPitchLimit, false);
1063 }
1064 player->setPlayMode(PlayerBase::PlayMode_FastTracker2);
1065 break;
1066
1067 default:
1068 ASSERT(false);
1069 }
1070
1071 //stop();
1072 //continuePlaying();
1073 }
1074
getPlayMode()1075 PlayerController::PlayModes PlayerController::getPlayMode()
1076 {
1077 if (!player)
1078 return PlayMode_Auto;
1079
1080 switch (player->getPlayMode())
1081 {
1082 case PlayerBase::PlayMode_ProTracker2:
1083 return PlayMode_ProTracker2;
1084 case PlayerBase::PlayMode_ProTracker3:
1085 return PlayMode_ProTracker3;
1086 case PlayerBase::PlayMode_FastTracker2:
1087 return PlayMode_FastTracker2;
1088 default:
1089 ASSERT(false);
1090 }
1091
1092 return PlayMode_Auto;
1093 }
1094
enablePlayModeOption(PlayModeOptions option,bool b)1095 void PlayerController::enablePlayModeOption(PlayModeOptions option, bool b)
1096 {
1097 switch (option)
1098 {
1099 case PlayModeOptionPanning8xx:
1100 player->enable(PlayerSTD::PlayModeOptionPanning8xx, b);
1101 break;
1102 case PlayModeOptionPanningE8x:
1103 player->enable(PlayerSTD::PlayModeOptionPanningE8x, b);
1104 break;
1105 case PlayModeOptionForcePTPitchLimit:
1106 player->enable(PlayerSTD::PlayModeOptionForcePTPitchLimit, b);
1107 break;
1108 default:
1109 ASSERT(false);
1110 }
1111 }
1112
isPlayModeOptionEnabled(PlayModeOptions option)1113 bool PlayerController::isPlayModeOptionEnabled(PlayModeOptions option)
1114 {
1115 if (!player)
1116 return false;
1117
1118 switch (option)
1119 {
1120 case PlayModeOptionPanning8xx:
1121 return player->isEnabled(PlayerSTD::PlayModeOptionPanning8xx);
1122 case PlayModeOptionPanningE8x:
1123 return player->isEnabled(PlayerSTD::PlayModeOptionPanningE8x);
1124 case PlayModeOptionForcePTPitchLimit:
1125 return player->isEnabled(PlayerSTD::PlayModeOptionForcePTPitchLimit);
1126 default:
1127 ASSERT(false);
1128 return false;
1129 }
1130 }
1131
getAllNumPlayingChannels()1132 mp_sint32 PlayerController::getAllNumPlayingChannels()
1133 {
1134 if (!player)
1135 return 0;
1136
1137 return player->mixerNumAllocatedChannels;
1138 }
1139
getPlayerNumPlayingChannels()1140 mp_sint32 PlayerController::getPlayerNumPlayingChannels()
1141 {
1142 if (!player)
1143 return 0;
1144
1145 return player->initialNumChannels;
1146 }
1147
getCurrentSamplePosition()1148 mp_sint32 PlayerController::getCurrentSamplePosition()
1149 {
1150 if (mixer && mixer->getAudioDriver())
1151 return mixer->getAudioDriver()->getBufferPos();
1152
1153 return 0;
1154 }
1155
getCurrentBeatIndex()1156 mp_sint32 PlayerController::getCurrentBeatIndex()
1157 {
1158 if (player)
1159 return player->getBeatIndexFromSamplePos(getCurrentSamplePosition());
1160
1161 return 0;
1162 }
1163
isSamplePlaying(const TXMSample & smp,mp_sint32 channel,mp_sint32 & pos,mp_sint32 & vol,mp_sint32 & pan)1164 bool PlayerController::isSamplePlaying(const TXMSample& smp, mp_sint32 channel, mp_sint32& pos, mp_sint32& vol, mp_sint32& pan)
1165 {
1166 if (!player)
1167 return false;
1168
1169 ChannelMixer* mixer = player;
1170
1171 // this rather critical
1172 // maybe someday this entire decision should go into the
1173 // player or mixer class itself, so I don't need to access it here
1174 pp_int32 j = getCurrentBeatIndex();
1175 pos = mixer->channel[channel].timeRecord[j].smppos;
1176
1177 // compare sample from sample editor against sample from current mixer channel
1178 if (pos >= 0 &&
1179 (void*)mixer->channel[channel].timeRecord[j].sample == (void*)smp.sample)
1180 {
1181 vol = (mixer->channel[channel].timeRecord[j].volPan & 0xFFFF) >> 1;
1182 pan = (mixer->channel[channel].timeRecord[j].volPan) >> 16;
1183 return true;
1184 }
1185
1186 return false;
1187 }
1188
isEnvelopePlaying(const TEnvelope & envelope,mp_sint32 envelopeType,mp_sint32 channel,mp_sint32 & pos)1189 bool PlayerController::isEnvelopePlaying(const TEnvelope& envelope, mp_sint32 envelopeType, mp_sint32 channel, mp_sint32& pos)
1190 {
1191 if (!player)
1192 return false;
1193
1194 ChannelMixer* mixer = player;
1195
1196 const PlayerSTD::TPrEnv* env = NULL;
1197
1198 switch (envelopeType)
1199 {
1200 case 0:
1201 env = &player->chninfo[channel].venv;
1202 break;
1203 case 1:
1204 env = &player->chninfo[channel].penv;
1205 break;
1206 }
1207
1208 pp_int32 j = getCurrentBeatIndex();
1209 pos = env->timeRecord[j].pos;
1210
1211 if (env && env->timeRecord[j].envstruc && env->timeRecord[j].envstruc == &envelope)
1212 {
1213
1214 if ((env->timeRecord[j].envstruc->num &&
1215 !(env->timeRecord[j].envstruc->type & 4) &&
1216 pos >= env->timeRecord[j].envstruc->env[env->timeRecord[j].envstruc->num-1][0]) ||
1217 !(mixer->channel[channel].timeRecord[j].volPan & 0xFFFF))
1218 {
1219 pos = -1;
1220 }
1221
1222 return true;
1223 }
1224
1225 return false;
1226 }
1227
isNotePlaying(mp_sint32 ins,mp_sint32 channel,mp_sint32 & note,bool & muted)1228 bool PlayerController::isNotePlaying(mp_sint32 ins, mp_sint32 channel, mp_sint32& note, bool& muted)
1229 {
1230 if (!player)
1231 return false;
1232
1233 const PlayerSTD::TModuleChannel* chnInf = &player->chninfo[channel];
1234
1235 if (player->channel[channel].flags&ChannelMixer::MP_SAMPLE_PLAY)
1236 {
1237 if (chnInf->ins == ins && chnInf->keyon && chnInf->note)
1238 {
1239 muted = (player->channel[channel].flags & ChannelMixer::MP_SAMPLE_MUTE) != 0;
1240 note = chnInf->note;
1241 return true;
1242 }
1243 }
1244
1245 return false;
1246 }
1247
1248 #define FULLMIXER_8BIT_NORMAL_TEMP \
1249 if (sample) { \
1250 sd1 = ((mp_sbyte)sample[smppos])<<8; \
1251 sd2 = ((mp_sbyte)sample[smppos+1])<<8; \
1252 sd1 =((sd1<<12)+(smpposfrac>>4)*(sd2-sd1))>>12; \
1253 y = (sd1*vol)>>9; \
1254 } \
1255 else { \
1256 y = 0; \
1257 } \
1258 fetcher.fetchSampleData(y);
1259
1260 #define FULLMIXER_16BIT_NORMAL_TEMP \
1261 if (sample) { \
1262 sd1 = ((mp_sword*)(sample))[smppos]; \
1263 sd2 = ((mp_sword*)(sample))[smppos+1]; \
1264 sd1 =((sd1<<12)+(smpposfrac>>4)*(sd2-sd1))>>12; \
1265 y = (sd1*vol)>>9; \
1266 } \
1267 else { \
1268 y = 0; \
1269 } \
1270 fetcher.fetchSampleData(y);
1271
grabSampleData(mp_uint32 chnIndex,mp_sint32 count,mp_sint32 fMul,SampleDataFetcher & fetcher)1272 void PlayerController::grabSampleData(mp_uint32 chnIndex, mp_sint32 count, mp_sint32 fMul, SampleDataFetcher& fetcher)
1273 {
1274 if (!player)
1275 return;
1276
1277 if (mixerDataCache && (count * 2 > mixerDataCacheSize))
1278 {
1279 delete[] mixerDataCache;
1280 mixerDataCacheSize = count * 2 * 2;
1281 mixerDataCache = new mp_sint32[mixerDataCacheSize];
1282 }
1283
1284 ChannelMixer* mixer = player;
1285
1286 ChannelMixer::TMixerChannel* chn = &mixer->channel[chnIndex];
1287
1288 pp_int32 j = getCurrentBeatIndex();
1289
1290 if (chn->flags & ChannelMixer::MP_SAMPLE_PLAY)
1291 {
1292 // this is critical
1293 // it might be that the audio thread modifies the data as we are
1294 // accessing it... So in the worst case we're getting a sample
1295 // but the channel state data does belong to another sample already
1296 // in that case we're displaying garbage...
1297 // BUT it's important that we only access sample data
1298 // within the range of the current sample we have
1299 ChannelMixer::TMixerChannel channel;
1300 channel.sample = chn->timeRecord[j].sample;
1301
1302 if (channel.sample == NULL)
1303 goto resort;
1304
1305 channel.smplen = TXMSample::getSampleSizeInSamples((mp_ubyte*)channel.sample);
1306 channel.flags = chn->timeRecord[j].flags;
1307 channel.smppos = chn->timeRecord[j].smppos % channel.smplen;
1308 channel.smpposfrac = chn->timeRecord[j].smpposfrac;
1309 channel.smpadd = chn->timeRecord[j].smpadd;
1310 channel.loopend = channel.loopendcopy = chn->timeRecord[j].loopend % (channel.smplen+1);
1311 channel.loopstart = chn->timeRecord[j].loopstart % (channel.smplen+1);
1312 if (channel.loopstart >= channel.loopend)
1313 channel.flags &= ~3;
1314 channel.vol = chn->timeRecord[j].volPan & 0xFFFF;
1315 channel.pan = chn->timeRecord[j].volPan >> 16;
1316 channel.fixedtimefrac = chn->timeRecord[j].fixedtimefrac;
1317 channel.cutoff = ChannelMixer::MP_INVALID_VALUE;
1318 channel.resonance = ChannelMixer::MP_INVALID_VALUE;
1319 // channel.index = chnIndex; Uncomment this if you like crackly audio
1320 // The scopes (which I assume is what this function is for) are currently
1321 // using channel 33, to avoid interfering with playback
1322
1323 channel.smpadd = (channel.smpadd*fMul) / (!count ? 1 : count);
1324 chn = &channel;
1325
1326 if (mixerDataCache && channel.smpadd <= 65536)
1327 {
1328 memset(mixerDataCache, 0, count*2*sizeof(mp_sint32));
1329
1330 channel.rsmpadd = (mp_sint32)((1.0 / channel.smpadd) * 65536.0);
1331
1332 // we only need the left channel as no panning is involved
1333 channel.finalvoll = (channel.vol*128*256)<<6;
1334 channel.finalvolr = 0;
1335 channel.rampFromVolStepL = channel.rampFromVolStepR = 0;
1336
1337 player->getCurrentResampler()->addChannel(chn, mixerDataCache, count, count);
1338
1339 for (mp_sint32 i = 0; i < count; i++)
1340 fetcher.fetchSampleData(mixerDataCache[i*2]);
1341 }
1342 else
1343 {
1344 pp_int32 vol = chn->vol;
1345 mp_sint32 y;
1346 FULLMIXER_TEMPLATE(FULLMIXER_8BIT_NORMAL_TEMP, FULLMIXER_16BIT_NORMAL_TEMP, 16, 0);
1347 }
1348 }
1349 else
1350 {
1351 resort:
1352 for (mp_sint32 i = 0; i < count; i++)
1353 fetcher.fetchSampleData(0);
1354 }
1355 }
1356
hasSampleData(mp_uint32 chnIndex)1357 bool PlayerController::hasSampleData(mp_uint32 chnIndex)
1358 {
1359 if (!player)
1360 return false;
1361
1362 ChannelMixer* mixer = player;
1363
1364 ChannelMixer::TMixerChannel* chn = &mixer->channel[chnIndex];
1365
1366 pp_int32 j = getCurrentBeatIndex();
1367
1368 return ((chn->timeRecord[j].flags & ChannelMixer::MP_SAMPLE_PLAY) && (chn->timeRecord[j].volPan & 0xFFFF));
1369 }
1370