1 /*
2 * Copyright (c) 2009, The MilkyTracker Team.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * - Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * - Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * - Neither the name of the <ORGANIZATION> nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 * PlayerGeneric.cpp
32 * MilkyPlay
33 *
34 * PlayerGeneric is a wrapper that allocates a suiting type of player
35 * for a module while providing the same player interfaces.
36 * Currently there are three types of players: PlayerFAR, PlayerSTD and PlayerIT
37 *
38 */
39 #include "PlayerGeneric.h"
40 #include "MasterMixer.h"
41 #include "XModule.h"
42 #include "AudioDriver_WAVWriter.h"
43 #include "AudioDriverManager.h"
44 #include "PlayerBase.h"
45 #include "PlayerSTD.h"
46 #ifndef MILKYTRACKER
47 #include "PlayerIT.h"
48 #include "PlayerFAR.h"
49 #endif
50
51 #undef __VERBOSE__
52
53 class MixerNotificationListener : public MasterMixer::MasterMixerNotificationListener
54 {
55 private:
56 class PlayerGeneric& player;
57
58 public:
MixerNotificationListener(PlayerGeneric & player)59 MixerNotificationListener(PlayerGeneric& player) :
60 player(player)
61 {
62 }
63
masterMixerNotification(MasterMixer::MasterMixerNotifications notification)64 virtual void masterMixerNotification(MasterMixer::MasterMixerNotifications notification)
65 {
66 player.adjustSettings();
67 }
68 };
69
adjustSettings()70 void PlayerGeneric::adjustSettings()
71 {
72 mp_uint32 bufferSize = mixer->getBufferSize();
73 mp_uint32 sampleRate = mixer->getSampleRate();
74
75 this->bufferSize = bufferSize;
76 this->frequency = sampleRate;
77
78 if (player)
79 {
80 player->setBufferSize(bufferSize);
81 player->adjustFrequency(sampleRate);
82 }
83 }
84
getPreferredPlayerType(XModule * module)85 PlayerBase::PlayerTypes PlayerGeneric::getPreferredPlayerType(XModule* module)
86 {
87 if (module == NULL)
88 return PlayerBase::PlayerType_INVALID;
89
90 switch (module->getType())
91 {
92 case XModule::ModuleType_669:
93 case XModule::ModuleType_FAR:
94 #ifndef MILKYTRACKER
95 return PlayerBase::PlayerType_FAR;
96 break;
97 #endif
98 case XModule::ModuleType_IT:
99 #ifndef MILKYTRACKER
100 return PlayerBase::PlayerType_IT;
101 break;
102 #endif
103 case XModule::ModuleType_UNKNOWN: // just assume our standard player can handle this
104 //case XModule::ModuleType_669:
105 case XModule::ModuleType_AMF:
106 case XModule::ModuleType_AMS:
107 case XModule::ModuleType_CBA:
108 case XModule::ModuleType_DBM:
109 case XModule::ModuleType_DIGI:
110 case XModule::ModuleType_DSM:
111 case XModule::ModuleType_DSm:
112 case XModule::ModuleType_DTM_1:
113 case XModule::ModuleType_DTM_2:
114 case XModule::ModuleType_GDM:
115 case XModule::ModuleType_GMC:
116 case XModule::ModuleType_IMF:
117 case XModule::ModuleType_MDL:
118 case XModule::ModuleType_MOD:
119 case XModule::ModuleType_MTM:
120 case XModule::ModuleType_MXM:
121 case XModule::ModuleType_OKT:
122 case XModule::ModuleType_PLM:
123 case XModule::ModuleType_PSM:
124 case XModule::ModuleType_PTM:
125 case XModule::ModuleType_S3M:
126 case XModule::ModuleType_STM:
127 case XModule::ModuleType_SFX:
128 case XModule::ModuleType_UNI:
129 case XModule::ModuleType_ULT:
130 case XModule::ModuleType_XM:
131 case XModule::ModuleType_NONE:
132 return PlayerBase::PlayerType_Generic;
133 break;
134
135 default:
136 return PlayerBase::PlayerType_INVALID;
137 }
138 }
139
getPreferredPlayer(XModule * module) const140 PlayerBase* PlayerGeneric::getPreferredPlayer(XModule* module) const
141 {
142 switch (getPreferredPlayerType(module))
143 {
144 #ifndef MILKYTRACKER
145 case PlayerBase::PlayerType_FAR:
146 return new PlayerFAR(frequency);
147 case PlayerBase::PlayerType_IT:
148 return new PlayerIT(frequency);
149 #endif
150 case PlayerBase::PlayerType_Generic:
151 return new PlayerSTD(frequency);
152
153 default:
154 return NULL;
155 }
156 }
157
PlayerGeneric(mp_sint32 frequency,AudioDriverInterface * audioDriver)158 PlayerGeneric::PlayerGeneric(mp_sint32 frequency, AudioDriverInterface* audioDriver/* = NULL*/) :
159 mixer(NULL),
160 player(NULL),
161 frequency(frequency),
162 audioDriver(audioDriver),
163 audioDriverName(NULL)
164 {
165 listener = new MixerNotificationListener(*this);
166
167 bufferSize = 0;
168 sampleShift = 0;
169
170 resamplerType = MIXER_NORMAL;
171
172 idle = false;
173 playOneRowOnly = false;
174 paused = false;
175 repeat = false;
176 resetOnStopFlag = false;
177 autoAdjustPeak = false;
178 disableMixing = false;
179 allowFilters = false;
180 #ifdef __FORCEPOWEROFTWOBUFFERSIZE__
181 compensateBufferFlag = true;
182 #else
183 compensateBufferFlag = false;
184 #endif
185 masterVolume = panningSeparation = numMaxVirChannels = 256;
186 resetMainVolumeOnStartPlayFlag = true;
187 playMode = PlayMode_Auto;
188
189 // Special playmode settings
190 options[PlayModeOptionPanning8xx] = true;
191 options[PlayModeOptionPanningE8x] = false;
192 options[PlayModeOptionForcePTPitchLimit] = true;
193
194 AudioDriverManager audioDriverManager;
195 const char* defaultName = audioDriverManager.getPreferredAudioDriver()->getDriverID();
196 if (defaultName)
197 {
198 audioDriverName = new char[strlen(defaultName)+1];
199 strcpy(audioDriverName, defaultName);
200 }
201 }
202
~PlayerGeneric()203 PlayerGeneric::~PlayerGeneric()
204 {
205
206 if (player)
207 {
208 if (mixer && mixer->isActive() && !mixer->isDeviceRemoved(player))
209 mixer->removeDevice(player);
210 delete player;
211 }
212
213 if (mixer)
214 delete mixer;
215
216 delete[] audioDriverName;
217
218 delete listener;
219 }
220
221 // -- wrapping mixer specific stuff ----------------------
setResamplerType(ResamplerTypes type)222 void PlayerGeneric::setResamplerType(ResamplerTypes type)
223 {
224 resamplerType = type;
225 if (player)
226 player->setResamplerType(type);
227 }
228
setResamplerType(bool interpolation,bool ramping)229 void PlayerGeneric::setResamplerType(bool interpolation, bool ramping)
230 {
231 if (interpolation)
232 {
233 if (ramping)
234 resamplerType = MIXER_LERPING_RAMPING;
235 else
236 resamplerType = MIXER_LERPING;
237 }
238 else
239 {
240 if (ramping)
241 resamplerType = MIXER_NORMAL_RAMPING;
242 else
243 resamplerType = MIXER_NORMAL;
244 }
245
246 if (player)
247 player->setResamplerType(resamplerType);
248 }
249
getResamplerType() const250 ChannelMixer::ResamplerTypes PlayerGeneric::getResamplerType() const
251 {
252 if (player)
253 return player->getResamplerType();
254
255 return resamplerType;
256 }
257
setSampleShift(mp_sint32 shift)258 void PlayerGeneric::setSampleShift(mp_sint32 shift)
259 {
260 sampleShift = shift;
261 if (mixer)
262 mixer->setSampleShift(shift);
263 }
264
getSampleShift() const265 mp_sint32 PlayerGeneric::getSampleShift() const
266 {
267 if (mixer)
268 return mixer->getSampleShift();
269
270 return sampleShift;
271 }
272
setPeakAutoAdjust(bool b)273 void PlayerGeneric::setPeakAutoAdjust(bool b)
274 {
275 this->autoAdjustPeak = b;
276 }
277
adjustFrequency(mp_uint32 frequency)278 mp_sint32 PlayerGeneric::adjustFrequency(mp_uint32 frequency)
279 {
280 this->frequency = frequency;
281
282 mp_sint32 res = MP_OK;
283
284 if (mixer)
285 res = mixer->setSampleRate(frequency);
286
287 return res;
288 }
289
getMixFrequency() const290 mp_sint32 PlayerGeneric::getMixFrequency() const
291 {
292 if (player)
293 return player->getMixFrequency();
294
295 return frequency;
296 }
297
beatPacketsToBufferSize(mp_uint32 numBeats)298 mp_sint32 PlayerGeneric::beatPacketsToBufferSize(mp_uint32 numBeats)
299 {
300 return ChannelMixer::beatPacketsToBufferSize(getMixFrequency(), numBeats);
301 }
302
adjustBufferSize(mp_uint32 numBeats)303 mp_sint32 PlayerGeneric::adjustBufferSize(mp_uint32 numBeats)
304 {
305 return setBufferSize(beatPacketsToBufferSize(numBeats));
306 }
307
setBufferSize(mp_uint32 bufferSize)308 mp_sint32 PlayerGeneric::setBufferSize(mp_uint32 bufferSize)
309 {
310 mp_sint32 res = 0;
311
312 this->bufferSize = bufferSize;
313
314 if (mixer)
315 {
316 // If we're told to compensate the samples until we
317 // we reached 2^n buffer sizes
318 if (compensateBufferFlag)
319 {
320 for (mp_uint32 i = 0; i < 16; i++)
321 {
322 if ((unsigned)(1 << i) >= (unsigned)bufferSize)
323 {
324 bufferSize = 1 << i;
325 break;
326 }
327 }
328 }
329
330 res = mixer->setBufferSize(bufferSize);
331 }
332
333 return res;
334 }
335
setPowerOfTwoCompensationFlag(bool b)336 mp_sint32 PlayerGeneric::setPowerOfTwoCompensationFlag(bool b)
337 {
338 if (mixer && compensateBufferFlag != b)
339 {
340 compensateBufferFlag = b;
341 setBufferSize(bufferSize);
342 }
343
344 return MP_OK;
345 }
346
getPowerOfTwoCompensationFlag() const347 bool PlayerGeneric::getPowerOfTwoCompensationFlag() const
348 {
349 return compensateBufferFlag;
350 }
351
getCurrentAudioDriverName() const352 const char* PlayerGeneric::getCurrentAudioDriverName() const
353 {
354 if (mixer)
355 return mixer->getCurrentAudioDriverName();
356
357 return audioDriverName;
358 }
359
setCurrentAudioDriverByName(const char * name)360 bool PlayerGeneric::setCurrentAudioDriverByName(const char* name)
361 {
362 if (name == NULL)
363 return false;
364
365 if (mixer)
366 {
367 bool res = mixer->setCurrentAudioDriverByName(name);
368
369 if (audioDriverName)
370 delete[] audioDriverName;
371
372 const char* curDrvName = getCurrentAudioDriverName();
373 ASSERT(curDrvName);
374 audioDriverName = new char[strlen(curDrvName)+1];
375 strcpy(audioDriverName, curDrvName);
376 return res;
377 }
378
379 AudioDriverManager audioDriverManager;
380 if (audioDriverManager.getAudioDriverByName(name))
381 {
382 if (audioDriverName)
383 delete[] audioDriverName;
384
385 audioDriverName = new char[strlen(name)+1];
386 strcpy(audioDriverName, name);
387 return true;
388 }
389
390 return false;
391 }
392
393
isInitialized() const394 bool PlayerGeneric::isInitialized() const
395 {
396 if (mixer)
397 return mixer->isInitialized();
398
399 return false;
400 }
401
isPlaying() const402 bool PlayerGeneric::isPlaying() const
403 {
404 if (mixer)
405 return mixer->isPlaying();
406
407 return false;
408 }
409
getSampleCounter() const410 mp_int64 PlayerGeneric::getSampleCounter() const
411 {
412 if (player)
413 return player->getSampleCounter();
414
415 return 0;
416 }
417
resetSampleCounter()418 void PlayerGeneric::resetSampleCounter()
419 {
420 if (player)
421 player->resetSampleCounter();
422 }
423
getCurrentSamplePosition() const424 mp_sint32 PlayerGeneric::getCurrentSamplePosition() const
425 {
426 if (mixer && mixer->getAudioDriver())
427 return mixer->getAudioDriver()->getBufferPos();
428
429 return 0;
430 }
431
getCurrentBeatIndex()432 mp_sint32 PlayerGeneric::getCurrentBeatIndex()
433 {
434 if (player)
435 return player->getBeatIndexFromSamplePos(getCurrentSamplePosition());
436
437 return 0;
438 }
439
getCurrentSample(mp_sint32 position,mp_sint32 channel)440 mp_sint32 PlayerGeneric::getCurrentSample(mp_sint32 position, mp_sint32 channel)
441 {
442 if (mixer)
443 return mixer->getCurrentSample(position, channel);
444
445 return 0;
446 }
447
getCurrentSamplePeak(mp_sint32 position,mp_sint32 channel)448 mp_sint32 PlayerGeneric::getCurrentSamplePeak(mp_sint32 position, mp_sint32 channel)
449 {
450 if (mixer)
451 return mixer->getCurrentSamplePeak(position, channel);
452
453 return 0;
454 }
455
resetChannels()456 void PlayerGeneric::resetChannels()
457 {
458 if (player)
459 player->resetChannelsFull();
460 }
461
getNumAllocatedChannels() const462 mp_sint32 PlayerGeneric::getNumAllocatedChannels() const
463 {
464 if (player)
465 return player->getNumAllocatedChannels();
466
467 return 0;
468 }
469
getNumActiveChannels() const470 mp_sint32 PlayerGeneric::getNumActiveChannels() const
471 {
472 if (player)
473 return player->getNumActiveChannels();
474
475 return 0;
476 }
477
478 // -- wrapping player specific stuff ----------------------
setPlayMode(PlayModes mode)479 void PlayerGeneric::setPlayMode(PlayModes mode)
480 {
481 playMode = mode;
482 if (player)
483 player->setPlayMode(mode);
484 }
485
getPlayMode() const486 PlayerGeneric::PlayModes PlayerGeneric::getPlayMode() const
487 {
488 if (player)
489 return player->getPlayMode();
490
491 return playMode;
492 }
493
enable(PlayModeOptions option,bool b)494 void PlayerGeneric::enable(PlayModeOptions option, bool b)
495 {
496 ASSERT(option>=PlayModeOptionFirst && option<PlayModeOptionLast);
497 options[option] = b;
498
499 if (player)
500 player->enable(option, b);
501 }
502
isEnabled(PlayModeOptions option) const503 bool PlayerGeneric::isEnabled(PlayModeOptions option) const
504 {
505 ASSERT(option>=PlayModeOptionFirst && option<PlayModeOptionLast);
506
507 if (!player)
508 return options[option];
509 else
510 return player->isEnabled(option);
511 }
512
restart(mp_uint32 startPosition,mp_uint32 startRow,bool resetMixer,const mp_ubyte * customPanningTable,bool playOneRowOnly)513 void PlayerGeneric::restart(mp_uint32 startPosition/* = 0*/, mp_uint32 startRow/* = 0*/, bool resetMixer/* = true*/, const mp_ubyte* customPanningTable/* = NULL*/, bool playOneRowOnly/* = false*/)
514 {
515 if (player)
516 player->restart(startPosition, startRow, resetMixer, customPanningTable, playOneRowOnly);
517 }
518
reset()519 void PlayerGeneric::reset()
520 {
521 if (player)
522 player->reset();
523 }
524
resetAllSpeed()525 void PlayerGeneric::resetAllSpeed()
526 {
527 if (player)
528 player->resetAllSpeed();
529 }
530
startPlaying(XModule * module,bool repeat,mp_uint32 startPosition,mp_uint32 startRow,mp_sint32 numChannels,const mp_ubyte * customPanningTable,bool idle,mp_sint32 patternIndex,bool playOneRowOnly)531 mp_sint32 PlayerGeneric::startPlaying(XModule* module,
532 bool repeat/* = false*/,
533 mp_uint32 startPosition/* = 0*/,
534 mp_uint32 startRow/* = 0*/,
535 mp_sint32 numChannels/* = -1*/,
536 const mp_ubyte* customPanningTable/* = NULL*/,
537 bool idle/* = false*/,
538 mp_sint32 patternIndex/* = -1*/,
539 bool playOneRowOnly/* = false*/)
540 {
541 this->idle = idle;
542 this->repeat = repeat;
543 this->playOneRowOnly = playOneRowOnly;
544
545 if (mixer == NULL)
546 {
547 mixer = new MasterMixer(frequency, bufferSize, 1, audioDriver);
548 mixer->setMasterMixerNotificationListener(listener);
549 mixer->setSampleShift(sampleShift);
550 if (audioDriver == NULL)
551 mixer->setCurrentAudioDriverByName(audioDriverName);
552 }
553
554 if (!player || player->getType() != getPreferredPlayerType(module))
555 {
556 if (player)
557 {
558 if (!mixer->isDeviceRemoved(player))
559 mixer->removeDevice(player);
560 delete player;
561 }
562
563 player = getPreferredPlayer(module);
564
565 if (player)
566 {
567 // apply our own "state" to the state of the newly allocated player
568 player->resetMainVolumeOnStartPlay(resetMainVolumeOnStartPlayFlag);
569 player->resetOnStop(resetOnStopFlag);
570 player->setBufferSize(bufferSize);
571 player->setResamplerType(resamplerType);
572 player->setMasterVolume(masterVolume);
573 player->setPanningSeparation(panningSeparation);
574 player->setPlayMode(playMode);
575
576 for (mp_sint32 i = PlayModeOptionFirst; i < PlayModeOptionLast; i++)
577 player->enable((PlayModeOptions)i, options[i]);
578
579 player->setDisableMixing(disableMixing);
580 player->setAllowFilters(allowFilters);
581 //if (paused)
582 // player->pausePlaying();
583
584 // adjust number of virtual channels if necessary
585 setNumMaxVirChannels(numMaxVirChannels);
586 }
587 }
588
589 if (player && mixer)
590 {
591 if (!mixer->isDeviceRemoved(player))
592 mixer->removeDevice(player);
593
594 player->startPlaying(module, repeat, startPosition, startRow, numChannels, customPanningTable, idle, patternIndex, playOneRowOnly);
595
596 mixer->addDevice(player);
597
598 if (!mixer->isPlaying())
599 return mixer->start();
600 }
601
602
603 return MP_OK;
604 }
605
setPatternToPlay(mp_sint32 patternIndex)606 void PlayerGeneric::setPatternToPlay(mp_sint32 patternIndex)
607 {
608 if (player)
609 player->setPatternToPlay(patternIndex);
610 }
611
stopPlaying()612 mp_sint32 PlayerGeneric::stopPlaying()
613 {
614 if (player)
615 player->stopPlaying();
616
617 if (mixer)
618 return mixer->stop();
619
620 return MP_OK;
621 }
622
hasSongHalted() const623 bool PlayerGeneric::hasSongHalted() const
624 {
625 if (player)
626 return player->hasSongHalted();
627
628 return true;
629 }
630
setIdle(bool idle)631 void PlayerGeneric::setIdle(bool idle)
632 {
633 this->idle = idle;
634 if (player)
635 player->setIdle(idle);
636 }
637
isIdle() const638 bool PlayerGeneric::isIdle() const
639 {
640 if (player)
641 return player->isIdle();
642
643 return idle;
644 }
645
setRepeat(bool repeat)646 void PlayerGeneric::setRepeat(bool repeat)
647 {
648 this->repeat = repeat;
649 if (player)
650 player->setRepeat(repeat);
651 }
652
isRepeating() const653 bool PlayerGeneric::isRepeating() const
654 {
655 if (player)
656 return player->isRepeating();
657
658 return repeat;
659 }
660
pausePlaying()661 mp_sint32 PlayerGeneric::pausePlaying()
662 {
663 paused = true;
664 if (mixer)
665 return mixer->pause();
666
667 return MP_OK;
668 }
669
resumePlaying()670 mp_sint32 PlayerGeneric::resumePlaying()
671 {
672 if (player && !player->isPlaying())
673 player->resumePlaying();
674
675 if (mixer && mixer->isPaused())
676 return mixer->resume();
677 else if (mixer && !mixer->isPlaying())
678 return mixer->start();
679
680 return MP_OK;
681 }
682
isPaused() const683 bool PlayerGeneric::isPaused() const
684 {
685 if (mixer)
686 return mixer->isPaused();
687
688 return paused;
689 }
690
setDisableMixing(bool b)691 void PlayerGeneric::setDisableMixing(bool b)
692 {
693 disableMixing = b;
694
695 if (player)
696 player->setDisableMixing(disableMixing);
697 }
698
setAllowFilters(bool b)699 void PlayerGeneric::setAllowFilters(bool b)
700 {
701 allowFilters = b;
702
703 if (player)
704 player->setAllowFilters(allowFilters);
705 }
706
getAllowFilters() const707 bool PlayerGeneric::getAllowFilters() const
708 {
709 if (player)
710 return player->getAllowFilters();
711
712 return allowFilters;
713 }
714
715 // volume control
setMasterVolume(mp_sint32 vol)716 void PlayerGeneric::setMasterVolume(mp_sint32 vol)
717 {
718 masterVolume = vol;
719 if (player)
720 player->setMasterVolume(vol);
721 }
722
getMasterVolume() const723 mp_sint32 PlayerGeneric::getMasterVolume() const
724 {
725 if (player)
726 return player->getMasterVolume();
727
728 return masterVolume;
729 }
730
731 // panning control
setPanningSeparation(mp_sint32 separation)732 void PlayerGeneric::setPanningSeparation(mp_sint32 separation)
733 {
734 panningSeparation = separation;
735 if (player)
736 player->setPanningSeparation(separation);
737 }
738
getPanningSeparation() const739 mp_sint32 PlayerGeneric::getPanningSeparation() const
740 {
741 if (player)
742 return player->getPanningSeparation();
743
744 return panningSeparation;
745 }
746
getSongMainVolume() const747 mp_sint32 PlayerGeneric::getSongMainVolume() const
748 {
749 if (player)
750 {
751 mp_uint32 index = player->getBeatIndexFromSamplePos(getCurrentSamplePosition());
752 return player->getSongMainVolume(index);
753 }
754
755 return 255;
756 }
757
getRow() const758 mp_sint32 PlayerGeneric::getRow() const
759 {
760 if (player)
761 {
762 mp_uint32 index = player->getBeatIndexFromSamplePos(getCurrentSamplePosition());
763 return player->getRow(index);
764 }
765
766 return 0;
767 }
768
getOrder() const769 mp_sint32 PlayerGeneric::getOrder() const
770 {
771 if (player)
772 {
773 mp_uint32 index = player->getBeatIndexFromSamplePos(getCurrentSamplePosition());
774 return player->getOrder(index);
775 }
776
777 return 0;
778 }
779
getPosition(mp_sint32 & order,mp_sint32 & row) const780 void PlayerGeneric::getPosition(mp_sint32& order, mp_sint32& row) const
781 {
782 if (player)
783 {
784 mp_uint32 index = player->getBeatIndexFromSamplePos(getCurrentSamplePosition());
785 player->getPosition(order, row, index);
786 return;
787 }
788
789 order = row = 0;
790 }
791
getLastUnvisitedPosition() const792 mp_sint32 PlayerGeneric::getLastUnvisitedPosition() const
793 {
794 if (player)
795 return player->getLastUnvisitedPosition();
796
797 return 0;
798 }
799
getPosition(mp_sint32 & order,mp_sint32 & row,mp_sint32 & ticker) const800 void PlayerGeneric::getPosition(mp_sint32& order, mp_sint32& row, mp_sint32& ticker) const
801 {
802 if (player)
803 {
804 mp_uint32 index = player->getBeatIndexFromSamplePos(getCurrentSamplePosition());
805 player->getPosition(order, row, ticker, index);
806 return;
807 }
808
809 order = row = ticker = 0;
810 }
811
getSyncCount() const812 mp_int64 PlayerGeneric::getSyncCount() const
813 {
814 if (player)
815 return player->getSyncCount();
816
817 return 0;
818 }
819
getSyncSampleCounter() const820 mp_uint32 PlayerGeneric::getSyncSampleCounter() const
821 {
822 if (player)
823 return player->getSyncSampleCounter();
824
825 return 0;
826 }
827
nextPattern()828 void PlayerGeneric::nextPattern()
829 {
830 if (player)
831 player->nextPattern();
832 }
833
lastPattern()834 void PlayerGeneric::lastPattern()
835 {
836 if (player)
837 player->lastPattern();
838 }
839
setPatternPos(mp_uint32 pos,mp_uint32 row,bool resetChannels,bool resetFXMemory)840 void PlayerGeneric::setPatternPos(mp_uint32 pos, mp_uint32 row/* = 0*/, bool resetChannels/* = true*/, bool resetFXMemory/* = true*/)
841 {
842 if (player)
843 player->setPatternPos(pos, row, resetChannels, resetFXMemory);
844 }
845
getTempo() const846 mp_sint32 PlayerGeneric::getTempo() const
847 {
848 if (player)
849 {
850 mp_uint32 index = player->getBeatIndexFromSamplePos(getCurrentSamplePosition());
851 return player->getTempo(index);
852 }
853
854 return 0;
855 }
856
getSpeed() const857 mp_sint32 PlayerGeneric::getSpeed() const
858 {
859 if (player)
860 {
861 mp_uint32 index = player->getBeatIndexFromSamplePos(getCurrentSamplePosition());
862 return player->getSpeed(index);
863 }
864
865 return 0;
866 }
867
resetOnStop(bool b)868 void PlayerGeneric::resetOnStop(bool b)
869 {
870 resetOnStopFlag = b;
871 if (player)
872 player->resetOnStop(b);
873 }
874
resetMainVolumeOnStartPlay(bool b)875 void PlayerGeneric::resetMainVolumeOnStartPlay(bool b)
876 {
877 resetMainVolumeOnStartPlayFlag = b;
878 if (player)
879 player->resetMainVolumeOnStartPlay(b);
880 }
881
882 struct PeakAutoAdjustFilter : public Mixable
883 {
884 mp_uint32 mixerShift;
885 mp_uint32 masterVolume;
886 mp_sint32 lastPeakValue;
887
PeakAutoAdjustFilterPeakAutoAdjustFilter888 PeakAutoAdjustFilter() :
889 mixerShift(0),
890 masterVolume(256),
891 lastPeakValue(0)
892 {
893 }
894
mixPeakAutoAdjustFilter895 virtual void mix(mp_sint32* buffer, mp_uint32 bufferSize)
896 {
897 const mp_sint32* buffer32 = buffer;
898
899 for (mp_uint32 i = 0; i < bufferSize*MP_NUMCHANNELS; i++)
900 {
901 mp_sint32 b = *buffer32++;
902
903 if (abs(b) > lastPeakValue)
904 lastPeakValue = abs(b);
905 }
906 }
907
calculateMasterVolumePeakAutoAdjustFilter908 void calculateMasterVolume()
909 {
910 if (lastPeakValue)
911 {
912 float v = 32768.0f*(1<<mixerShift) / (float)lastPeakValue;
913 masterVolume = (mp_sint32)((float)masterVolume*v);
914 if (masterVolume > 256)
915 masterVolume = 256;
916 }
917 }
918 };
919
920 // export to 16bit stereo WAV
exportToWAV(const SYSCHAR * fileName,XModule * module,mp_sint32 startOrder,mp_sint32 endOrder,const mp_ubyte * mutingArray,mp_uint32 mutingNumChannels,const mp_ubyte * customPanningTable,AudioDriverBase * preferredDriver,mp_sint32 * timingLUT)921 mp_sint32 PlayerGeneric::exportToWAV(const SYSCHAR* fileName, XModule* module,
922 mp_sint32 startOrder/* = 0*/, mp_sint32 endOrder/* = -1*/,
923 const mp_ubyte* mutingArray/* = NULL*/, mp_uint32 mutingNumChannels/* = 0*/,
924 const mp_ubyte* customPanningTable/* = NULL*/,
925 AudioDriverBase* preferredDriver/* = NULL*/,
926 mp_sint32* timingLUT/* = NULL*/)
927 {
928 PlayerBase* player = NULL;
929
930 AudioDriverBase* wavWriter = preferredDriver;
931 bool isWAVWriterDriver = false;
932
933 if (wavWriter == NULL)
934 {
935 wavWriter = new WAVWriter(fileName);
936 isWAVWriterDriver = true;
937
938 if (!static_cast<WAVWriter*>(wavWriter)->isOpen())
939 {
940 delete wavWriter;
941 return MP_DEVICE_ERROR;
942 }
943 }
944
945 MasterMixer mixer(frequency, bufferSize, 1, wavWriter);
946 mixer.setSampleShift(sampleShift);
947 mixer.setDisableMixing(disableMixing);
948
949 player = getPreferredPlayer(module);
950
951 PeakAutoAdjustFilter filter;
952 if (autoAdjustPeak)
953 mixer.setFilterHook(&filter);
954
955 if (player)
956 {
957 player->adjustFrequency(frequency);
958 player->resetOnStop(resetOnStopFlag);
959 player->setBufferSize(bufferSize);
960 player->setResamplerType(resamplerType);
961 player->setMasterVolume(masterVolume);
962 player->setPlayMode(playMode);
963 player->setDisableMixing(disableMixing);
964 player->setAllowFilters(allowFilters);
965 #ifndef MILKYTRACKER
966 if (player->getType() == PlayerBase::PlayerType_IT)
967 {
968 static_cast<PlayerIT*>(player)->setNumMaxVirChannels(numMaxVirChannels);
969 }
970 #endif
971 mixer.addDevice(player);
972 }
973
974 if (player)
975 {
976 if (mutingArray && mutingNumChannels > 0 && mutingNumChannels <= module->header.channum)
977 {
978 for (mp_uint32 i = 0; i < mutingNumChannels; i++)
979 player->muteChannel(i, mutingArray[i] == 1);
980 }
981 player->startPlaying(module, false, startOrder, 0, -1, customPanningTable, false, -1);
982
983 mixer.start();
984 }
985
986 if (endOrder == -1 || endOrder < startOrder || endOrder > module->header.ordnum - 1)
987 endOrder = module->header.ordnum - 1;
988
989 mp_sint32 curOrderPos = startOrder;
990 if (timingLUT)
991 {
992 for (mp_sint32 i = 0; i < module->header.ordnum; i++)
993 timingLUT[i] = -1;
994
995 timingLUT[curOrderPos] = 0;
996 }
997
998 while (!player->hasSongHalted() && player->getOrder(0) <= endOrder)
999 {
1000 wavWriter->advance();
1001
1002 if (player->getOrder(0) != curOrderPos)
1003 {
1004 #ifdef __VERBOSE__
1005 printf("%f\n", (float)wavWriter->getNumPlayedSamples() / (float)getMixFrequency());
1006 #endif
1007 curOrderPos = player->getOrder(0);
1008 if (timingLUT && curOrderPos < module->header.ordnum && timingLUT[curOrderPos] == -1)
1009 timingLUT[curOrderPos] = wavWriter->getNumPlayedSamples();
1010 }
1011 }
1012
1013 player->stopPlaying();
1014
1015 mixer.stop();
1016 // important step, otherwise destruction of the audio driver will cause
1017 // trouble if the mixer instance is removed from this function's stack
1018 // and trys to access the driver which is no longer existant
1019 mixer.closeAudioDevice();
1020
1021 // Sync value
1022 sampleShift = mixer.getSampleShift();
1023 filter.mixerShift = sampleShift;
1024 filter.calculateMasterVolume();
1025 masterVolume = filter.masterVolume;
1026
1027 delete player;
1028
1029 mp_sint32 numWrittenSamples = wavWriter->getNumPlayedSamples();
1030
1031 if (isWAVWriterDriver)
1032 delete wavWriter;
1033
1034 return numWrittenSamples;
1035 }
1036
grabChannelInfo(mp_sint32 chn,TPlayerChannelInfo & channelInfo) const1037 bool PlayerGeneric::grabChannelInfo(mp_sint32 chn, TPlayerChannelInfo& channelInfo) const
1038 {
1039 if (player)
1040 return player->grabChannelInfo(chn, channelInfo);
1041
1042 return false;
1043 }
1044
setNumMaxVirChannels(mp_sint32 max)1045 void PlayerGeneric::setNumMaxVirChannels(mp_sint32 max)
1046 {
1047 numMaxVirChannels = max;
1048 #ifndef MILKYTRACKER
1049 if (player)
1050 {
1051 if (player->getType() == PlayerBase::PlayerType_IT)
1052 {
1053 static_cast<PlayerIT*>(player)->setNumMaxVirChannels(max);
1054 }
1055 }
1056 #endif
1057 }
1058
getNumMaxVirChannels() const1059 mp_sint32 PlayerGeneric::getNumMaxVirChannels() const
1060 {
1061 #ifndef MILKYTRACKER
1062 if (player)
1063 {
1064 if (player->getType() == PlayerBase::PlayerType_IT)
1065 {
1066 return static_cast<PlayerIT*>(player)->getNumMaxVirChannels();
1067 }
1068 }
1069 #endif
1070 return numMaxVirChannels;
1071 }
1072
1073 // milkytracker
setPanning(mp_ubyte chn,mp_ubyte pan)1074 void PlayerGeneric::setPanning(mp_ubyte chn, mp_ubyte pan)
1075 {
1076 if (player)
1077 player->setPanning(chn, pan);
1078 }
1079