Added support for multiple music tracks in FT mode.

Note that taba3 is not currently played as it needs multiball support.
Issue #129.
This commit is contained in:
Muzychenko Andrey 2022-05-20 19:32:09 +03:00
parent 97aea20586
commit e283a643b3
7 changed files with 63 additions and 26 deletions

View File

@ -4,6 +4,7 @@
#include "control.h" #include "control.h"
#include "loader.h" #include "loader.h"
#include "midi.h"
#include "pb.h" #include "pb.h"
#include "pinball.h" #include "pinball.h"
#include "render.h" #include "render.h"
@ -448,6 +449,8 @@ int TPinballTable::Message(int code, float value)
auto time = loader::play_sound(SoundIndex1); auto time = loader::play_sound(SoundIndex1);
LightShowTimer = timer::set(time, this, LightShow_timeout); LightShowTimer = timer::set(time, this, LightShow_timeout);
} }
midi::play_track(midi::track1);
break; break;
case 1018: case 1018:
if (ReplayTimer) if (ReplayTimer)

View File

@ -1,6 +1,7 @@
#include "pch.h" #include "pch.h"
#include "control.h" #include "control.h"
#include "midi.h"
#include "pb.h" #include "pb.h"
#include "pinball.h" #include "pinball.h"
#include "TBlocker.h" #include "TBlocker.h"
@ -967,6 +968,8 @@ void control::table_set_flag_lights()
void control::table_set_multiball() void control::table_set_multiball()
{ {
info_text_box->Display(pinball::get_rc_string(16, 0), 2.0); info_text_box->Display(pinball::get_rc_string(16, 0), 2.0);
if (midi::get_active_track() != midi::track3)
midi::play_track(midi::track3);
} }
void control::table_bump_ball_sink_lock() void control::table_bump_ball_sink_lock()
@ -2572,6 +2575,8 @@ void control::BallDrainControl(int code, TPinballComponent* caller)
{ {
lite200->Message(20, 0.0); lite200->Message(20, 0.0);
lite199->Message(20, 0.0); lite199->Message(20, 0.0);
if (midi::get_active_track() != midi::track1)
midi::play_track(midi::track1);
} }
if (light_on(&control_lite200_tag)) if (light_on(&control_lite200_tag))
{ {
@ -3102,6 +3107,8 @@ void control::GameoverController(int code, TPinballComponent* caller)
flip1->Message(1022, 0.0); flip1->Message(1022, 0.0);
flip2->Message(1022, 0.0); flip2->Message(1022, 0.0);
mission_text_box->MessageField = 0; mission_text_box->MessageField = 0;
if (midi::get_active_track() != midi::track1)
midi::play_track(midi::track1);
return; return;
} }
if (code != 67) if (code != 67)
@ -4008,6 +4015,8 @@ void control::SelectMissionController(int code, TPinballComponent* caller)
int addedScore = SpecialAddScore(mission_select_scores[scoreId]); int addedScore = SpecialAddScore(mission_select_scores[scoreId]);
snprintf(Buffer, sizeof Buffer, pinball::get_rc_string(77, 0), addedScore); snprintf(Buffer, sizeof Buffer, pinball::get_rc_string(77, 0), addedScore);
mission_text_box->Display(Buffer, 4.0); mission_text_box->Display(Buffer, 4.0);
if (midi::get_active_track() != midi::track2)
midi::play_track(midi::track2);
} }
return; return;
} }
@ -4121,6 +4130,8 @@ void control::SelectMissionController(int code, TPinballComponent* caller)
return; return;
} }
case 66: case 66:
if (midi::get_active_track() != midi::track1)
midi::play_track(midi::track1);
lite198->Message(20, 0.0); lite198->Message(20, 0.0);
outer_circle->Message(34, 0.0); outer_circle->Message(34, 0.0);
ramp_tgt_lights->Message(20, 0.0); ramp_tgt_lights->Message(20, 0.0);
@ -4408,6 +4419,8 @@ void control::WaitingDeploymentController(int code, TPinballComponent* caller)
case 66: case 66:
mission_text_box->Clear(); mission_text_box->Clear();
waiting_deployment_flag = 0; waiting_deployment_flag = 0;
if (midi::get_active_track() != midi::track1)
midi::play_track(midi::track1);
break; break;
case 67: case 67:
mission_text_box->Display(pinball::get_rc_string(50, 0), -1.0); mission_text_box->Display(pinball::get_rc_string(50, 0), -1.0);

View File

@ -8,8 +8,8 @@
std::vector<Mix_Music*> midi::LoadedTracks{}; std::vector<Mix_Music*> midi::LoadedTracks{};
Mix_Music *midi::track1, *midi::track2, *midi::track3, *midi::active_track, *midi::NextTrack; Mix_Music *midi::track1, *midi::track2, *midi::track3, *midi::active_track, *midi::NextTrack;
bool midi::SetNextTrackFlag;
int midi::Volume = MIX_MAX_VOLUME; int midi::Volume = MIX_MAX_VOLUME;
bool midi::IsPlaying = false;
constexpr uint32_t FOURCC(uint8_t a, uint8_t b, uint8_t c, uint8_t d) constexpr uint32_t FOURCC(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{ {
@ -31,27 +31,41 @@ int ToVariableLen(uint32_t value, uint32_t& dst)
return count; return count;
} }
int midi::play_pb_theme() void midi::music_play()
{ {
// Todo: add support for tracks 2 and 3 if (!IsPlaying)
return play_track(track1); {
IsPlaying = true;
play_track(NextTrack);
NextTrack = nullptr;
}
} }
int midi::music_stop() void midi::music_stop()
{ {
if (active_track) if (IsPlaying)
{ {
active_track = nullptr; IsPlaying = false;
Mix_HaltMusic(); NextTrack = active_track;
StopPlayback();
} }
}
return true; void midi::StopPlayback()
{
if (active_track != nullptr)
{
Mix_HaltMusic();
active_track = nullptr;
}
} }
int midi::music_init(int volume) int midi::music_init(int volume)
{ {
SetVolume(volume); SetVolume(volume);
active_track = nullptr; active_track = nullptr;
NextTrack = nullptr;
IsPlaying = false;
if (pb::FullTiltMode) if (pb::FullTiltMode)
{ {
@ -78,8 +92,7 @@ int midi::music_init(int volume)
void midi::music_shutdown() void midi::music_shutdown()
{ {
if (active_track) music_stop();
Mix_HaltMusic();
for (auto midi : LoadedTracks) for (auto midi : LoadedTracks)
{ {
@ -105,7 +118,7 @@ Mix_Music* midi::load_track(std::string fileName)
fileName.insert(0, "SOUND"); fileName.insert(0, "SOUND");
} }
// FT has music in two formats, depending on version: MIDI in 16bit, MIDS in 32bit. // FT has music in two formats, depending on game version: MIDI in 16bit, MIDS in 32bit.
// 3DPB music is MIDI only. // 3DPB music is MIDI only.
auto basePath = pinball::make_path_name(fileName); auto basePath = pinball::make_path_name(fileName);
for (int i = 0; i <= 1 && !audio; i++) for (int i = 0; i <= 1 && !audio; i++)
@ -148,15 +161,14 @@ Mix_Music* midi::load_track(std::string fileName)
bool midi::play_track(Mix_Music* midi) bool midi::play_track(Mix_Music* midi)
{ {
music_stop(); StopPlayback();
if (!midi) if (!midi)
return false; return false;
if (SetNextTrackFlag) if (!IsPlaying)
{ {
NextTrack = midi; NextTrack = midi;
SetNextTrackFlag = false; return false;
return true;
} }
if (Mix_PlayMusic(midi, -1)) if (Mix_PlayMusic(midi, -1))
@ -331,7 +343,7 @@ std::vector<uint8_t>* midi::MdsToMidi(std::string file)
while (false); while (false);
delete[] fileBuf; delete[] fileBuf;
if (returnCode && midiOut) if (returnCode && midiOut)
{ {
delete midiOut; delete midiOut;
midiOut = nullptr; midiOut = nullptr;

View File

@ -86,18 +86,27 @@ static_assert(sizeof(midi_track) == 8, "Wrong size of midi_track");
class midi class midi
{ {
public: public:
static int play_pb_theme(); static Mix_Music * track1, * track2, * track3;
static int music_stop(); static void music_play();
static void music_stop();
static int music_init(int volume); static int music_init(int volume);
static void music_shutdown(); static void music_shutdown();
static void SetVolume(int volume); static void SetVolume(int volume);
static bool play_track(Mix_Music* midi);
static Mix_Music* get_active_track()
{
if (active_track == nullptr)
return NextTrack;
else
return active_track;
}
private: private:
static std::vector<Mix_Music*> LoadedTracks; static std::vector<Mix_Music*> LoadedTracks;
static Mix_Music *track1, *track2, *track3, *active_track, *NextTrack; static Mix_Music *active_track, *NextTrack;
static bool SetNextTrackFlag;
static int Volume; static int Volume;
static bool IsPlaying;
static void StopPlayback();
static Mix_Music* load_track(std::string fileName); static Mix_Music* load_track(std::string fileName);
static bool play_track(Mix_Music* midi);
static std::vector<uint8_t>* MdsToMidi(std::string file); static std::vector<uint8_t>* MdsToMidi(std::string file);
}; };

View File

@ -226,7 +226,7 @@ void options::toggle(Menu1 uIDCheckItem)
if (!Options.Music) if (!Options.Music)
midi::music_stop(); midi::music_stop();
else else
midi::play_pb_theme(); midi::music_play();
return; return;
case Menu1::Show_Menu: case Menu1::Show_Menu:
Options.ShowMenu = Options.ShowMenu == 0; Options.ShowMenu = Options.ShowMenu == 0;

View File

@ -232,7 +232,7 @@ void pb::replay_level(bool demoMode)
demo_mode = demoMode; demo_mode = demoMode;
mode_change(GameModes::InGame); mode_change(GameModes::InGame);
if (options::Options.Music) if (options::Options.Music)
midi::play_pb_theme(); midi::music_play();
MainTable->Message(1014, static_cast<float>(options::Options.Players)); MainTable->Message(1014, static_cast<float>(options::Options.Players));
} }
@ -379,7 +379,7 @@ void pb::pause_continue()
pinball::InfoTextBox->Display(text, textTime); pinball::InfoTextBox->Display(text, textTime);
} }
if (options::Options.Music && !winmain::single_step) if (options::Options.Music && !winmain::single_step)
midi::play_pb_theme(); midi::music_play();
Sound::Activate(); Sound::Activate();
} }
} }

View File

@ -813,7 +813,7 @@ int winmain::event_handler(const SDL_Event* event)
activated = true; activated = true;
Sound::Activate(); Sound::Activate();
if (Options.Music && !single_step) if (Options.Music && !single_step)
midi::play_pb_theme(); midi::music_play();
no_time_loss = true; no_time_loss = true;
has_focus = true; has_focus = true;
break; break;