mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-09-27 16:57:25 +02:00
71c8c54313
Previously, setting the actual volume of the music was all over the place. Which isn't bad, but when I added being able to press N to mute the music specifically, I should've made it so that there would be a volume variable somewhere that the game looks at if the music is unmuted, and otherwise sets the actual volume to 0 if the game is muted. This resulted in things like #400 and #505 and having to add a bunch of special-cased checks like game.musicmuted and game.completestop. But instead of adding a bunch of special-case code, just make it so there's a central place where Mix_VolumeMusic() actually gets called, and if some piece of code wants to set the music volume, they can set music.musicVolume. But the music handling logic in main.cpp gets the final say on whether to listen to music.musicVolume, or to mute the game entirely. This is how the music handling code should have been from the start (when pressing N to mute the music was added). Fixes #505.
362 lines
8 KiB
C++
362 lines
8 KiB
C++
#define MUSIC_DEFINITION
|
|
#include "Music.h"
|
|
|
|
#include <SDL.h>
|
|
#include <stdio.h>
|
|
|
|
#include "BinaryBlob.h"
|
|
#include "Map.h"
|
|
#include "UtilityClass.h"
|
|
|
|
void songend();
|
|
|
|
void musicclass::init()
|
|
{
|
|
for (size_t i = 0; i < soundTracks.size(); ++i) {
|
|
Mix_FreeChunk(soundTracks[i].sound);
|
|
}
|
|
soundTracks.clear();
|
|
for (size_t i = 0; i < musicTracks.size(); ++i) {
|
|
Mix_FreeMusic(musicTracks[i].m_music);
|
|
}
|
|
musicTracks.clear();
|
|
|
|
musicReadBlob.clear();
|
|
|
|
soundTracks.push_back(SoundTrack( "sounds/jump.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/jump2.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/hurt.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/souleyeminijingle.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/coin.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/save.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crumble.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/vanish.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/blip.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/preteleport.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/teleport.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crew1.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crew2.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crew3.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crew4.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crew5.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crew6.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/terminal.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/gamesaved.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crashing.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/blip2.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/countdown.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/go.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/crash.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/combine.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/newrecord.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/trophy.wav" ));
|
|
soundTracks.push_back(SoundTrack( "sounds/rescue.wav" ));
|
|
|
|
#ifdef VVV_COMPILEMUSIC
|
|
binaryBlob musicWriteBlob;
|
|
#define FOREACH_TRACK(track_name) musicWriteBlob.AddFileToBinaryBlob(track_name);
|
|
TRACK_NAMES
|
|
#undef FOREACH_TRACK
|
|
|
|
musicWriteBlob.writeBinaryBlob("data/BinaryMusic.vvv");
|
|
#endif
|
|
|
|
num_mmmmmm_tracks = 0;
|
|
num_pppppp_tracks = 0;
|
|
|
|
if (!musicReadBlob.unPackBinary("mmmmmm.vvv"))
|
|
{
|
|
mmmmmm = false;
|
|
usingmmmmmm=false;
|
|
bool ohCrap = musicReadBlob.unPackBinary("vvvvvvmusic.vvv");
|
|
SDL_assert(ohCrap && "Music not found!");
|
|
}
|
|
else
|
|
{
|
|
mmmmmm = true;
|
|
usingmmmmmm = true;
|
|
int index;
|
|
SDL_RWops *rw;
|
|
|
|
#define FOREACH_TRACK(track_name) \
|
|
index = musicReadBlob.getIndex(track_name); \
|
|
if (index >= 0 && index < musicReadBlob.max_headers) \
|
|
{ \
|
|
rw = SDL_RWFromMem(musicReadBlob.getAddress(index), musicReadBlob.getSize(index)); \
|
|
if (rw == NULL) \
|
|
{ \
|
|
printf("Unable to read music file header: %s\n", SDL_GetError()); \
|
|
} \
|
|
else \
|
|
{ \
|
|
musicTracks.push_back(MusicTrack( rw )); \
|
|
} \
|
|
}
|
|
|
|
TRACK_NAMES
|
|
|
|
num_mmmmmm_tracks += musicTracks.size();
|
|
|
|
const std::vector<int> extra = musicReadBlob.getExtra();
|
|
for (size_t i = 0; i < extra.size(); i++)
|
|
{
|
|
const int& index = extra[i];
|
|
rw = SDL_RWFromMem(musicReadBlob.getAddress(index), musicReadBlob.getSize(index));
|
|
musicTracks.push_back(MusicTrack( rw ));
|
|
|
|
num_mmmmmm_tracks++;
|
|
}
|
|
|
|
bool ohCrap = musicReadBlob.unPackBinary("vvvvvvmusic.vvv");
|
|
SDL_assert(ohCrap && "Music not found!");
|
|
}
|
|
|
|
int index;
|
|
SDL_RWops *rw;
|
|
|
|
TRACK_NAMES
|
|
|
|
#undef FOREACH_TRACK
|
|
|
|
num_pppppp_tracks += musicTracks.size() - num_mmmmmm_tracks;
|
|
|
|
const std::vector<int> extra = musicReadBlob.getExtra();
|
|
for (size_t i = 0; i < extra.size(); i++)
|
|
{
|
|
const int& index = extra[i];
|
|
rw = SDL_RWFromMem(musicReadBlob.getAddress(index), musicReadBlob.getSize(index));
|
|
musicTracks.push_back(MusicTrack( rw ));
|
|
|
|
num_pppppp_tracks++;
|
|
}
|
|
|
|
safeToProcessMusic= false;
|
|
m_doFadeInVol = false;
|
|
musicVolume = MIX_MAX_VOLUME;
|
|
FadeVolAmountPerFrame = 0;
|
|
|
|
currentsong = 0;
|
|
nicechange = 0;
|
|
nicefade = 0;
|
|
resumesong = 0;
|
|
fadeoutqueuesong = -1;
|
|
dontquickfade = false;
|
|
|
|
songStart = 0;
|
|
songEnd = 0;
|
|
|
|
Mix_HookMusicFinished(&songend);
|
|
|
|
usingmmmmmm = false;
|
|
}
|
|
|
|
void songend()
|
|
{
|
|
extern musicclass music;
|
|
music.songEnd = SDL_GetPerformanceCounter();
|
|
music.currentsong = -1;
|
|
}
|
|
|
|
void musicclass::play(int t, const double position_sec /*= 0.0*/, const int fadein_ms /*= 3000*/)
|
|
{
|
|
if (mmmmmm && usingmmmmmm)
|
|
{
|
|
// Don't conjoin this if-statement with the above one...
|
|
if (num_mmmmmm_tracks > 0)
|
|
{
|
|
t %= num_mmmmmm_tracks;
|
|
}
|
|
}
|
|
else if (num_pppppp_tracks > 0)
|
|
{
|
|
t %= num_pppppp_tracks;
|
|
}
|
|
|
|
if(mmmmmm && !usingmmmmmm)
|
|
{
|
|
t += num_mmmmmm_tracks;
|
|
}
|
|
safeToProcessMusic = true;
|
|
musicVolume = MIX_MAX_VOLUME;
|
|
if (currentsong !=t)
|
|
{
|
|
if (t != -1)
|
|
{
|
|
currentsong = t;
|
|
if (!INBOUNDS_VEC(t, musicTracks))
|
|
{
|
|
puts("play() out-of-bounds!");
|
|
currentsong = -1;
|
|
return;
|
|
}
|
|
if (currentsong == 0 || currentsong == 7 || (!map.custommode && (currentsong == 0+num_pppppp_tracks || currentsong == 7+num_pppppp_tracks)))
|
|
{
|
|
// Level Complete theme, no fade in or repeat
|
|
if(Mix_FadeInMusicPos(musicTracks[t].m_music, 0, 0, position_sec)==-1)
|
|
{
|
|
printf("Mix_FadeInMusicPos: %s\n", Mix_GetError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Mix_FadingMusic() == MIX_FADING_OUT) {
|
|
// We're already fading out
|
|
fadeoutqueuesong = t;
|
|
currentsong = -1;
|
|
if (!dontquickfade)
|
|
Mix_FadeOutMusic(500); // fade out quicker
|
|
else
|
|
dontquickfade = false;
|
|
}
|
|
else if(Mix_FadeInMusicPos(musicTracks[t].m_music, -1, fadein_ms, position_sec)==-1)
|
|
{
|
|
printf("Mix_FadeInMusicPos: %s\n", Mix_GetError());
|
|
}
|
|
}
|
|
|
|
songStart = SDL_GetPerformanceCounter();
|
|
}
|
|
else
|
|
{
|
|
currentsong = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void musicclass::resume(const int fadein_ms /*= 0*/)
|
|
{
|
|
const double offset = static_cast<double>(songEnd - songStart);
|
|
const double frequency = static_cast<double>(SDL_GetPerformanceFrequency());
|
|
|
|
const double position_sec = offset / frequency;
|
|
|
|
play(resumesong, position_sec, fadein_ms);
|
|
}
|
|
|
|
void musicclass::fadein()
|
|
{
|
|
resume(3000); // 3000 ms fadein
|
|
}
|
|
|
|
void musicclass::haltdasmusik()
|
|
{
|
|
Mix_HaltMusic();
|
|
resumesong = currentsong;
|
|
}
|
|
|
|
void musicclass::silencedasmusik()
|
|
{
|
|
musicVolume = 0;
|
|
}
|
|
|
|
void musicclass::fadeMusicVolumeIn(int ms)
|
|
{
|
|
m_doFadeInVol = true;
|
|
FadeVolAmountPerFrame = MIX_MAX_VOLUME / (ms / 33);
|
|
}
|
|
|
|
void musicclass::fadeout()
|
|
{
|
|
Mix_FadeOutMusic(2000);
|
|
resumesong = currentsong;
|
|
}
|
|
|
|
void musicclass::processmusicfadein()
|
|
{
|
|
musicVolume += FadeVolAmountPerFrame;
|
|
if (musicVolume >= MIX_MAX_VOLUME)
|
|
{
|
|
m_doFadeInVol = false;
|
|
}
|
|
}
|
|
|
|
void musicclass::processmusic()
|
|
{
|
|
if(!safeToProcessMusic)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (fadeoutqueuesong != -1 && Mix_PlayingMusic() == 0) {
|
|
play(fadeoutqueuesong);
|
|
fadeoutqueuesong = -1;
|
|
}
|
|
|
|
if (nicefade == 1 && Mix_PlayingMusic() == 0)
|
|
{
|
|
play(nicechange);
|
|
nicechange = -1; nicefade = 0;
|
|
}
|
|
|
|
if(m_doFadeInVol)
|
|
{
|
|
processmusicfadein();
|
|
}
|
|
}
|
|
|
|
|
|
void musicclass::niceplay(int t)
|
|
{
|
|
// important: do nothing if the correct song is playing!
|
|
if((!mmmmmm && currentsong!=t) || (mmmmmm && usingmmmmmm && currentsong!=t) || (mmmmmm && !usingmmmmmm && currentsong!=t+16))
|
|
{
|
|
if(currentsong!=-1)
|
|
{
|
|
dontquickfade = true;
|
|
fadeout();
|
|
}
|
|
nicefade = 1;
|
|
nicechange = t;
|
|
}
|
|
}
|
|
|
|
void musicclass::changemusicarea(int x, int y)
|
|
{
|
|
switch(musicroom(x, y))
|
|
{
|
|
case musicroom(11, 4):
|
|
niceplay(2);
|
|
break;
|
|
|
|
case musicroom(2, 4):
|
|
case musicroom(7, 15):
|
|
niceplay(3);
|
|
break;
|
|
|
|
case musicroom(18, 1):
|
|
case musicroom(15, 0):
|
|
niceplay(12);
|
|
break;
|
|
|
|
case musicroom(0, 0):
|
|
case musicroom(0, 16):
|
|
case musicroom(2, 11):
|
|
case musicroom(7, 9):
|
|
case musicroom(8, 11):
|
|
case musicroom(13, 2):
|
|
case musicroom(17, 12):
|
|
case musicroom(14, 19):
|
|
case musicroom(17, 17):
|
|
niceplay(4);
|
|
break;
|
|
|
|
default:
|
|
niceplay(1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void musicclass::playef(int t)
|
|
{
|
|
if (!INBOUNDS_VEC(t, soundTracks))
|
|
{
|
|
return;
|
|
}
|
|
int channel;
|
|
|
|
channel = Mix_PlayChannel(-1, soundTracks[t].sound, 0);
|
|
if(channel == -1)
|
|
{
|
|
fprintf(stderr, "Unable to play WAV file: %s\n", Mix_GetError());
|
|
}
|
|
}
|