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