- hooked up a few more CVARs and other values the music backend needs to know about and moved the MusInfo base class into zmusic.

This commit is contained in:
Christoph Oelckers 2019-09-30 01:34:16 +02:00
parent 7c27cd0c57
commit 2c33e47988
21 changed files with 228 additions and 283 deletions

View file

@ -33,7 +33,7 @@
#include <algorithm> #include <algorithm>
#include <stdio.h> #include <stdio.h>
#include "zmusic/mpg123_decoder.h" #include "mpg123_decoder.h"
#include "i_module.h" #include "i_module.h"
#ifdef HAVE_MPG123 #ifdef HAVE_MPG123

View file

@ -1,7 +1,7 @@
#ifndef MPG123_DECODER_H #ifndef MPG123_DECODER_H
#define MPG123_DECODER_H #define MPG123_DECODER_H
#include "sounddecoder.h" #include "zmusic/sounddecoder.h"
#ifdef HAVE_MPG123 #ifdef HAVE_MPG123

View file

@ -32,7 +32,7 @@
*/ */
#include <algorithm> #include <algorithm>
#include "zmusic/sndfile_decoder.h" #include "sndfile_decoder.h"
#include "i_module.h" #include "i_module.h"
#ifdef HAVE_SNDFILE #ifdef HAVE_SNDFILE

View file

@ -1,7 +1,7 @@
#ifndef SNDFILE_DECODER_H #ifndef SNDFILE_DECODER_H
#define SNDFILE_DECODER_H #define SNDFILE_DECODER_H
#include "sounddecoder.h" #include "zmusic/sounddecoder.h"
#ifdef HAVE_SNDFILE #ifdef HAVE_SNDFILE

View file

@ -33,8 +33,8 @@
*/ */
#include "zmusic/sndfile_decoder.h" #include "sndfile_decoder.h"
#include "zmusic/mpg123_decoder.h" #include "mpg123_decoder.h"
SoundDecoder *SoundDecoder::CreateDecoder(MusicIO::FileInterface *reader) SoundDecoder *SoundDecoder::CreateDecoder(MusicIO::FileInterface *reader)
{ {

View file

@ -38,6 +38,7 @@
#include "../../libraries/dumb/include/dumb.h" #include "../../libraries/dumb/include/dumb.h"
#include "zmusic.h" #include "zmusic.h"
#include "musinfo.h"
#include "midiconfig.h" #include "midiconfig.h"
struct Dummy struct Dummy
@ -46,13 +47,9 @@ struct Dummy
void ChangeSettingNum(const char*, double) {} void ChangeSettingNum(const char*, double) {}
void ChangeSettingString(const char*, const char*) {} void ChangeSettingString(const char*, const char*) {}
}; };
static Dummy* currSong;
//extern MusInfo *CurrSong; #define devType() ((currSong)? (currSong)->GetDeviceType() : MDEV_DEFAULT)
int devType()
{
/*if (CurrSong) return CurrSong->GetDeviceType();
else*/ return MDEV_DEFAULT;
}
MiscConfig miscConfig; MiscConfig miscConfig;
Callbacks musicCallbacks; Callbacks musicCallbacks;
@ -147,7 +144,7 @@ using namespace ZMusic;
// //
//========================================================================== //==========================================================================
bool ChangeMusicSetting(ZMusic::EIntConfigKey key, int value, int *pRealValue) bool ChangeMusicSetting(ZMusic::EIntConfigKey key, MusInfo *currSong, int value, int *pRealValue)
{ {
switch (key) switch (key)
{ {
@ -452,11 +449,20 @@ bool ChangeMusicSetting(ZMusic::EIntConfigKey key, int value, int *pRealValue)
case mod_autochip_scan_threshold: case mod_autochip_scan_threshold:
ChangeAndReturn(dumbConfig.mod_autochip_scan_threshold, value, pRealValue); ChangeAndReturn(dumbConfig.mod_autochip_scan_threshold, value, pRealValue);
return false; return false;
case snd_mididevice:
miscConfig.snd_mididevice = value;
return false;
case snd_outputrate:
miscConfig.snd_outputrate = value;
return false;
} }
return false; return false;
} }
bool ChangeMusicSetting(ZMusic::EFloatConfigKey key, float value, float *pRealValue) bool ChangeMusicSetting(ZMusic::EFloatConfigKey key, MusInfo* currSong, float value, float *pRealValue)
{ {
switch (key) switch (key)
{ {
@ -588,11 +594,24 @@ bool ChangeMusicSetting(ZMusic::EFloatConfigKey key, float value, float *pRealVa
if (value < 0) value = 0; if (value < 0) value = 0;
ChangeAndReturn(dumbConfig.mod_dumb_mastervolume, value, pRealValue); ChangeAndReturn(dumbConfig.mod_dumb_mastervolume, value, pRealValue);
return false; return false;
case snd_musicvolume:
miscConfig.snd_musicvolume = value;
return false;
case relative_volume:
miscConfig.relative_volume = value;
return false;
case snd_mastervolume:
miscConfig.snd_mastervolume = value;
return false;
} }
return false; return false;
} }
bool ChangeMusicSetting(ZMusic::EStringConfigKey key, const char *value) bool ChangeMusicSetting(ZMusic::EStringConfigKey key, MusInfo* currSong, const char *value)
{ {
switch (key) switch (key)
{ {

View file

@ -138,7 +138,12 @@ struct MiscConfig
{ {
int snd_midiprecache; int snd_midiprecache;
float gme_stereodepth; float gme_stereodepth;
int snd_streambuffersize; int snd_streambuffersize = 64;
int snd_mididevice;
int snd_outputrate = 44100;
float snd_musicvolume = 1.f;
float relative_volume = 1.f;
float snd_mastervolume = 1.f;
}; };
extern ADLConfig adlConfig; extern ADLConfig adlConfig;

View file

@ -0,0 +1,40 @@
#pragma once
#include "mididefs.h"
// The base music class. Everything is derived from this --------------------
class MusInfo
{
public:
MusInfo() = default;
virtual ~MusInfo() {}
virtual void MusicVolumeChanged() {} // snd_musicvolume changed
virtual void Play (bool looping, int subsong) = 0;
virtual void Pause () = 0;
virtual void Resume () = 0;
virtual void Stop () = 0;
virtual bool IsPlaying () = 0;
virtual bool IsMIDI() const { return false; }
virtual bool IsValid () const = 0;
virtual bool SetPosition(unsigned int ms) { return false; }
virtual bool SetSubsong (int subsong) { return false; }
virtual void Update() {}
virtual int GetDeviceType() const { return MDEV_DEFAULT; } // MDEV_DEFAULT stands in for anything that cannot change playback parameters which needs a restart.
virtual std::string GetStats() { return "No stats available for this song"; }
virtual MusInfo* GetWaveDumper(const char* filename, int rate) { return nullptr; }
virtual void ChangeSettingInt(const char* setting, int value) {} // FluidSynth settings
virtual void ChangeSettingNum(const char* setting, double value) {} // "
virtual void ChangeSettingString(const char* setting, const char* value) {} // "
virtual bool ServiceStream(void *buff, int len) { return false; }
virtual SoundStreamInfo GetStreamInfo() const { return { 0,0,0 }; }
enum EState
{
STATE_Stopped,
STATE_Playing,
STATE_Paused
} m_Status = STATE_Stopped;
bool m_Looping = false;
bool m_NotStartedYet = false; // Song has been created but not yet played
};

View file

@ -69,6 +69,9 @@ enum EIntConfigKey
snd_streambuffersize, snd_streambuffersize,
snd_mididevice,
snd_outputrate,
NUM_INT_CONFIGS NUM_INT_CONFIGS
}; };
@ -90,6 +93,10 @@ enum EFloatConfigKey
gme_stereodepth, gme_stereodepth,
mod_dumb_mastervolume, mod_dumb_mastervolume,
snd_musicvolume,
relative_volume,
snd_mastervolume,
NUM_FLOAT_CONFIGS NUM_FLOAT_CONFIGS
}; };
@ -147,8 +154,9 @@ class MIDISource; // abstract for the client
EMIDIType IdentifyMIDIType(uint32_t *id, int size); EMIDIType IdentifyMIDIType(uint32_t *id, int size);
MIDISource *CreateMIDISource(const uint8_t *data, size_t length, EMIDIType miditype); MIDISource *CreateMIDISource(const uint8_t *data, size_t length, EMIDIType miditype);
class MusInfo;
// Configuration interface. The return value specifies if a music restart is needed. // Configuration interface. The return value specifies if a music restart is needed.
// RealValue should be written back to the CVAR or whatever other method the client uses to store configuration state. // RealValue should be written back to the CVAR or whatever other method the client uses to store configuration state.
bool ChangeMusicSetting(ZMusic::EIntConfigKey key, int value, int *pRealValue = nullptr); bool ChangeMusicSetting(ZMusic::EIntConfigKey key, MusInfo *song, int value, int *pRealValue = nullptr);
bool ChangeMusicSetting(ZMusic::EFloatConfigKey key, float value, float *pRealValue = nullptr); bool ChangeMusicSetting(ZMusic::EFloatConfigKey key, MusInfo* song, float value, float *pRealValue = nullptr);
bool ChangeMusicSetting(ZMusic::EStringConfigKey key, const char *value); bool ChangeMusicSetting(ZMusic::EStringConfigKey key, MusInfo* song, const char *value);

View file

@ -41,8 +41,7 @@
#include "i_module.h" #include "i_module.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "zmusic/mpg123_decoder.h" #include "zmusic/sounddecoder.h"
#include "zmusic/sndfile_decoder.h"
#include "c_dispatch.h" #include "c_dispatch.h"
#include "i_music.h" #include "i_music.h"
@ -51,6 +50,7 @@
#include "c_cvars.h" #include "c_cvars.h"
#include "stats.h" #include "stats.h"
#include "s_music.h" #include "s_music.h"
#include "zmusic/zmusic.h"
EXTERN_CVAR (Float, snd_sfxvolume) EXTERN_CVAR (Float, snd_sfxvolume)
EXTERN_CVAR (Float, snd_musicvolume) EXTERN_CVAR (Float, snd_musicvolume)
@ -93,6 +93,8 @@ CUSTOM_CVAR(Float, snd_mastervolume, 1.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVA
self = 0.f; self = 0.f;
else if (self > 1.f) else if (self > 1.f)
self = 1.f; self = 1.f;
ChangeMusicSetting(ZMusic::snd_mastervolume, nullptr, self);
snd_sfxvolume.Callback(); snd_sfxvolume.Callback();
snd_musicvolume.Callback(); snd_musicvolume.Callback();
} }

View file

@ -119,16 +119,7 @@ void FindLoopTags(MusicIO::FileInterface *fr, uint32_t *start, bool *startass, u
const char *GetSampleTypeName(enum SampleType type); const char *GetSampleTypeName(enum SampleType type);
const char *GetChannelConfigName(enum ChannelConfig chan); const char *GetChannelConfigName(enum ChannelConfig chan);
class MusInfo;
class SoundStream; class SoundStream;
struct MusPlayingInfo
{
FString name;
MusInfo *handle;
int baseorder;
bool loop;
};

View file

@ -51,6 +51,7 @@
#include "i_soundfont.h" #include "i_soundfont.h"
#include "s_music.h" #include "s_music.h"
#include "zmusic/zmusic.h" #include "zmusic/zmusic.h"
#include "zmusic/musinfo.h"
#include "streamsources/streamsource.h" #include "streamsources/streamsource.h"
#include "filereadermusicinterface.h" #include "filereadermusicinterface.h"
#include "../libraries/zmusic/midisources/midisource.h" #include "../libraries/zmusic/midisources/midisource.h"
@ -70,6 +71,7 @@
extern int MUSHeaderSearch(const uint8_t *head, int len); extern int MUSHeaderSearch(const uint8_t *head, int len);
void I_InitSoundFonts(); void I_InitSoundFonts();
extern "C" void dumb_exit(); extern "C" void dumb_exit();
extern MusPlayingInfo mus_playing;
EXTERN_CVAR (Int, snd_samplerate) EXTERN_CVAR (Int, snd_samplerate)
EXTERN_CVAR (Int, snd_mididevice) EXTERN_CVAR (Int, snd_mididevice)
@ -80,8 +82,6 @@ static bool ungzip(uint8_t *data, int size, std::vector<uint8_t> &newdata);
MusInfo *currSong; MusInfo *currSong;
int nomusic = 0; int nomusic = 0;
float relative_volume = 1.f;
float saved_relative_volume = 1.0f; // this could be used to implement an ACS FadeMusic function
//========================================================================== //==========================================================================
// //
@ -99,15 +99,16 @@ CUSTOM_CVAR (Float, snd_musicvolume, 0.5f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
else else
{ {
// Set general music volume. // Set general music volume.
ChangeMusicSetting(ZMusic::snd_musicvolume, nullptr, self);
if (GSnd != nullptr) if (GSnd != nullptr)
{ {
GSnd->SetMusicVolume(clamp<float>(self * relative_volume * snd_mastervolume, 0, 1)); GSnd->SetMusicVolume(clamp<float>(self * relative_volume * snd_mastervolume, 0, 1));
} }
// For music not implemented through the digital sound system, // For music not implemented through the digital sound system,
// let them know about the change. // let them know about the change.
if (currSong != nullptr) if (mus_playing.handle != nullptr)
{ {
currSong->MusicVolumeChanged(); mus_playing.handle->MusicVolumeChanged();
} }
else else
{ // If the music was stopped because volume was 0, start it now. { // If the music was stopped because volume was 0, start it now.
@ -287,101 +288,6 @@ void I_ShutdownMusic(bool onexit)
} }
} }
//==========================================================================
//
//
//
//==========================================================================
MusInfo::MusInfo()
: m_Status(STATE_Stopped), m_Looping(false), m_NotStartedYet(true)
{
}
MusInfo::~MusInfo ()
{
if (currSong == this) currSong = nullptr;
}
//==========================================================================
//
// starts playing this song
//
//==========================================================================
void MusInfo::Start(bool loop, float rel_vol, int subsong)
{
if (rel_vol > 0.f)
{
float factor = relative_volume / saved_relative_volume;
saved_relative_volume = rel_vol;
relative_volume = saved_relative_volume * factor;
}
Stop ();
Play (loop, subsong);
m_NotStartedYet = false;
if (m_Status == MusInfo::STATE_Playing)
currSong = this;
else
currSong = nullptr;
// Notify the sound system of the changed relative volume
snd_musicvolume.Callback();
}
//==========================================================================
//
//
//
//==========================================================================
bool MusInfo::SetPosition (unsigned int ms)
{
return false;
}
bool MusInfo::IsMIDI() const
{
return false;
}
bool MusInfo::SetSubsong (int subsong)
{
return false;
}
void MusInfo::Update ()
{
}
void MusInfo::MusicVolumeChanged()
{
}
void MusInfo::ChangeSettingInt(const char *, int)
{
}
void MusInfo::ChangeSettingNum(const char *, double)
{
}
void MusInfo::ChangeSettingString(const char *, const char *)
{
}
FString MusInfo::GetStats()
{
return "No stats available for this song";
}
MusInfo *MusInfo::GetWaveDumper(const char *filename, int rate)
{
return nullptr;
}
//========================================================================== //==========================================================================
// //
// identify a music lump's type and set up a player for it // identify a music lump's type and set up a player for it
@ -648,6 +554,13 @@ void I_UpdateMusic()
} }
} }
void I_SetRelativeVolume(float vol)
{
relative_volume = (float)vol;
ChangeMusicSetting(ZMusic::relative_volume, nullptr, (float)vol);
snd_musicvolume.Callback();
}
//========================================================================== //==========================================================================
// //
// Sets relative music volume. Takes $musicvolume in SNDINFO into consideration // Sets relative music volume. Takes $musicvolume in SNDINFO into consideration
@ -657,8 +570,7 @@ void I_UpdateMusic()
void I_SetMusicVolume (double factor) void I_SetMusicVolume (double factor)
{ {
factor = clamp(factor, 0., 2.0); factor = clamp(factor, 0., 2.0);
relative_volume = saved_relative_volume * float(factor); I_SetRelativeVolume(factor);
snd_musicvolume.Callback();
} }
//========================================================================== //==========================================================================
@ -671,8 +583,7 @@ CCMD(testmusicvol)
{ {
if (argv.argc() > 1) if (argv.argc() > 1)
{ {
relative_volume = (float)strtod(argv[1], nullptr); I_SetRelativeVolume((float)strtod(argv[1], nullptr));
snd_musicvolume.Callback();
} }
else else
Printf("Current relative volume is %1.2f\n", relative_volume); Printf("Current relative volume is %1.2f\n", relative_volume);
@ -686,9 +597,9 @@ CCMD(testmusicvol)
ADD_STAT(music) ADD_STAT(music)
{ {
if (currSong != nullptr) if (mus_playing.handle != nullptr)
{ {
return currSong->GetStats(); return FString(mus_playing.handle->GetStats().c_str());
} }
return "No song playing"; return "No song playing";
} }

View file

@ -50,6 +50,7 @@ void I_BuildMIDIMenuList (FOptionValues *);
void I_UpdateMusic (); void I_UpdateMusic ();
// Volume. // Volume.
void I_SetRelativeVolume(float);
void I_SetMusicVolume (double volume); void I_SetMusicVolume (double volume);
// Registers a song handle to song data. // Registers a song handle to song data.
@ -58,44 +59,6 @@ struct MidiDeviceSetting;
MusInfo *I_RegisterSong (MusicIO::FileInterface *reader, MidiDeviceSetting *device); MusInfo *I_RegisterSong (MusicIO::FileInterface *reader, MidiDeviceSetting *device);
MusInfo *I_RegisterCDSong (int track, int cdid = 0); MusInfo *I_RegisterCDSong (int track, int cdid = 0);
// The base music class. Everything is derived from this --------------------
class MusInfo
{
public:
MusInfo ();
virtual ~MusInfo ();
virtual void MusicVolumeChanged(); // snd_musicvolume changed
virtual void Play (bool looping, int subsong) = 0;
virtual void Pause () = 0;
virtual void Resume () = 0;
virtual void Stop () = 0;
virtual bool IsPlaying () = 0;
virtual bool IsMIDI () const;
virtual bool IsValid () const = 0;
virtual bool SetPosition (unsigned int ms);
virtual bool SetSubsong (int subsong);
virtual void Update();
virtual int GetDeviceType() const { return MDEV_DEFAULT; } // MDEV_DEFAULT stands in for anything that cannot change playback parameters which needs a restart.
virtual FString GetStats();
virtual MusInfo *GetWaveDumper(const char *filename, int rate);
virtual void ChangeSettingInt(const char *setting, int value); // FluidSynth settings
virtual void ChangeSettingNum(const char *setting, double value); // "
virtual void ChangeSettingString(const char *setting, const char *value); // "
virtual bool ServiceStream(void *buff, int len) { return false; }
virtual SoundStreamInfo GetStreamInfo() const { return { 0,0,0 }; }
void Start(bool loop, float rel_vol = -1.f, int subsong = 0);
enum EState
{
STATE_Stopped,
STATE_Playing,
STATE_Paused
} m_Status;
bool m_Looping;
bool m_NotStartedYet; // Song has been created but not yet played
};
extern int nomusic; extern int nomusic;
#endif //__I_MUSIC_H__ #endif //__I_MUSIC_H__

View file

@ -13,7 +13,6 @@
void I_InitMusicWin32 (); void I_InitMusicWin32 ();
extern float relative_volume;
class MIDISource; class MIDISource;
class MIDIDevice; class MIDIDevice;
class OPLmusicFile; class OPLmusicFile;

View file

@ -35,8 +35,10 @@
#include "i_musicinterns.h" #include "i_musicinterns.h"
#include "c_cvars.h" #include "c_cvars.h"
#include "s_music.h"
#include "zmusic/zmusic.h" #include "zmusic/zmusic.h"
extern MusPlayingInfo mus_playing;
//========================================================================== //==========================================================================
// //
@ -46,19 +48,19 @@
#define FORWARD_CVAR(key) \ #define FORWARD_CVAR(key) \
decltype(*self) newval; \ decltype(*self) newval; \
auto ret = ChangeMusicSetting(ZMusic::key, *self, &newval); \ auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle, *self, &newval); \
self = (decltype(*self))newval; \ self = (decltype(*self))newval; \
if (ret) MIDIDeviceChanged(-1, true); if (ret) S_MIDIDeviceChanged(-1, true);
#define FORWARD_BOOL_CVAR(key) \ #define FORWARD_BOOL_CVAR(key) \
int newval; \ int newval; \
auto ret = ChangeMusicSetting(ZMusic::key, *self, &newval); \ auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle,*self, &newval); \
self = !!newval; \ self = !!newval; \
if (ret) MIDIDeviceChanged(-1, true); if (ret) S_MIDIDeviceChanged(-1, true);
#define FORWARD_STRING_CVAR(key) \ #define FORWARD_STRING_CVAR(key) \
auto ret = ChangeMusicSetting(ZMusic::key, *self); \ auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle,*self); \
if (ret) MIDIDeviceChanged(-1, true); if (ret) S_MIDIDeviceChanged(-1, true);
CUSTOM_CVAR(Int, adl_chips_count, 6, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) CUSTOM_CVAR(Int, adl_chips_count, 6, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)

View file

@ -43,6 +43,7 @@
#include "v_text.h" #include "v_text.h"
#include "menu/menu.h" #include "menu/menu.h"
#include "zmusic/zmusic.h"
#include "s_music.h" #include "s_music.h"
static uint32_t nummididevices; static uint32_t nummididevices;
@ -70,43 +71,6 @@ static void AddDefaultMidiDevices(FOptionValues *opt)
} }
extern MusPlayingInfo mus_playing;
void MIDIDeviceChanged(int newdev, bool force)
{
static int oldmididev = INT_MIN;
// If a song is playing, move it to the new device.
if (oldmididev != newdev || force)
{
if (currSong != NULL && currSong->IsMIDI())
{
MusInfo *song = currSong;
if (song->m_Status == MusInfo::STATE_Playing)
{
if (song->GetDeviceType() == MDEV_FLUIDSYNTH && force)
{
// FluidSynth must reload the song to change the patch set.
auto mi = mus_playing;
S_StopMusic(true);
S_ChangeMusic(mi.name, mi.baseorder, mi.loop);
}
else
{
song->Stop();
song->Start(song->m_Looping);
}
}
}
else
{
S_MIDIDeviceChanged();
}
}
// 'force'
if (!force) oldmididev = newdev;
}
#define DEF_MIDIDEV -5 #define DEF_MIDIDEV -5
#ifdef _WIN32 #ifdef _WIN32
@ -115,8 +79,6 @@ void MIDIDeviceChanged(int newdev, bool force)
#include <windows.h> #include <windows.h>
#include <mmsystem.h> #include <mmsystem.h>
unsigned mididevice;
CUSTOM_CVAR (Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CUSTOM_CVAR (Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{ {
if (!nummididevicesset) if (!nummididevicesset)
@ -133,8 +95,8 @@ CUSTOM_CVAR (Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
return; return;
} }
else if (self == -1) self = DEF_MIDIDEV; else if (self == -1) self = DEF_MIDIDEV;
mididevice = MAX<int>(0, self); ChangeMusicSetting(ZMusic::snd_mididevice, nullptr, self);
MIDIDeviceChanged(self); S_MIDIDeviceChanged(self, false);
} }
void I_InitMusicWin32 () void I_InitMusicWin32 ()
@ -244,7 +206,10 @@ CUSTOM_CVAR(Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
else if (self > -2) else if (self > -2)
self = -2; self = -2;
else else
MIDIDeviceChanged(self); {
ChangeMusicSetting(ZMusic::snd_mididevice, nullptr, self);
S_MIDIDeviceChanged(self, false);
}
} }
void I_BuildMIDIMenuList (FOptionValues *opt) void I_BuildMIDIMenuList (FOptionValues *opt)

View file

@ -31,7 +31,9 @@
** **
*/ */
#include "i_musicinterns.h" #include "zmusic/musinfo.h"
#include "zmusic/zmusic.h"
#include "zmusic/m_swap.h"
#include "i_cd.h" #include "i_cd.h"

View file

@ -35,36 +35,20 @@
// HEADER FILES ------------------------------------------------------------ // HEADER FILES ------------------------------------------------------------
#include "i_musicinterns.h" #include "zmusic/musinfo.h"
#include "templates.h"
#include "doomerrors.h"
#include "v_text.h"
#include "mididevices/mididevice.h" #include "mididevices/mididevice.h"
#include "midisources/midisource.h" #include "midisources/midisource.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
#define MAX_TIME (1000000/10) // Send out 1/10 of a sec of events at a time. enum
{
MAX_TIME = (1000000/10) // Send out 1/10 of a sec of events at a time.
// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- };
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void WriteVarLen (TArray<uint8_t> &file, uint32_t value);
// EXTERNAL DATA DECLARATIONS ---------------------------------------------- // EXTERNAL DATA DECLARATIONS ----------------------------------------------
EXTERN_CVAR(Bool, snd_midiprecache);
EXTERN_CVAR(Float, snd_musicvolume)
EXTERN_CVAR(Int, snd_mididevice)
#ifdef _WIN32
extern unsigned mididevice;
#endif
// PRIVATE DATA DEFINITIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
@ -86,7 +70,7 @@ public:
bool IsValid() const override; bool IsValid() const override;
bool SetSubsong(int subsong) override; bool SetSubsong(int subsong) override;
void Update() override; void Update() override;
FString GetStats() override; std::string GetStats() override;
void ChangeSettingInt(const char* setting, int value) override; void ChangeSettingInt(const char* setting, int value) override;
void ChangeSettingNum(const char* setting, double value) override; void ChangeSettingNum(const char* setting, double value) override;
void ChangeSettingString(const char* setting, const char* value) override; void ChangeSettingString(const char* setting, const char* value) override;
@ -229,7 +213,7 @@ EMidiDevice MIDIStreamer::SelectMIDIDevice(EMidiDevice device)
{ {
return device; return device;
} }
switch (snd_mididevice) switch (miscConfig.snd_mididevice)
{ {
case -1: return MDEV_SNDSYS; case -1: return MDEV_SNDSYS;
case -2: return MDEV_TIMIDITY; case -2: return MDEV_TIMIDITY;
@ -285,7 +269,7 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype, int samplerate)
case MDEV_MMAPI: case MDEV_MMAPI:
#ifdef _WIN32 #ifdef _WIN32
dev = CreateWinMIDIDevice(mididevice); dev = CreateWinMIDIDevice(std::max(0, miscConfig.snd_mididevice));
break; break;
#endif #endif
// Intentional fall-through for non-Windows systems. // Intentional fall-through for non-Windows systems.
@ -312,7 +296,7 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype, int samplerate)
} }
catch (std::runtime_error &err) catch (std::runtime_error &err)
{ {
DPrintf(DMSG_WARNING, "%s\n", err.what()); //DPrintf(DMSG_WARNING, "%s\n", err.what());
checked[devtype] = true; checked[devtype] = true;
devtype = MDEV_DEFAULT; devtype = MDEV_DEFAULT;
// Opening the requested device did not work out so choose another one. // Opening the requested device did not work out so choose another one.
@ -327,8 +311,8 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype, int samplerate)
if (devtype == MDEV_DEFAULT) if (devtype == MDEV_DEFAULT)
{ {
Printf("Failed to play music: Unable to open any MIDI Device.\n"); std::string message = std::string(err.what()) + "\n\nFailed to play music: Unable to open any MIDI Device.";
return nullptr; throw std::runtime_error(message);
} }
} }
} }
@ -346,7 +330,8 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype, int samplerate)
lastRequestedDevice = requestedDevice; lastRequestedDevice = requestedDevice;
lastSelectedDevice = selectedDevice; lastSelectedDevice = selectedDevice;
Printf(TEXTCOLOR_RED "Unable to create " TEXTCOLOR_ORANGE "%s" TEXTCOLOR_RED " MIDI device. Falling back to " TEXTCOLOR_ORANGE "%s\n", devnames[requestedDevice], devnames[selectedDevice]); if (musicCallbacks.Fluid_MessageFunc)
musicCallbacks.Fluid_MessageFunc("Unable to create %s MIDI device. Falling back to %s\n", devnames[requestedDevice], devnames[selectedDevice]);
} }
return dev; return dev;
} }
@ -367,7 +352,7 @@ void MIDIStreamer::Play(bool looping, int subsong)
m_Looping = looping; m_Looping = looping;
source->SetMIDISubsong(subsong); source->SetMIDISubsong(subsong);
devtype = SelectMIDIDevice(DeviceType); devtype = SelectMIDIDevice(DeviceType);
MIDI.reset(CreateMIDIDevice(devtype, (int)GSnd->GetOutputRate())); MIDI.reset(CreateMIDIDevice(devtype, miscConfig.snd_outputrate));
InitPlayback(); InitPlayback();
} }
@ -603,8 +588,9 @@ void MIDIStreamer::MusicVolumeChanged()
{ {
if (MIDI != NULL && MIDI->FakeVolume()) if (MIDI != NULL && MIDI->FakeVolume())
{ {
float realvolume = clamp<float>(snd_musicvolume * relative_volume * snd_mastervolume, 0.f, 1.f); float realvolume = miscConfig.snd_musicvolume * miscConfig.relative_volume * miscConfig.snd_mastervolume;
Volume = clamp<uint32_t>((uint32_t)(realvolume * 65535.f), 0, 65535); if (realvolume < 0 || realvolume > 1) realvolume = 1;
Volume = (uint32_t)(realvolume * 65535.f);
} }
else else
{ {
@ -843,7 +829,7 @@ int MIDIStreamer::FillBuffer(int buffer_num, int max_events, uint32_t max_time)
{ {
// Be more responsive when unpausing by only playing each buffer // Be more responsive when unpausing by only playing each buffer
// for a third of the maximum time. // for a third of the maximum time.
events[0] = MAX<uint32_t>(1, (max_time / 3) * source->getDivision() / source->getTempo()); events[0] = std::max<uint32_t>(1, (max_time / 3) * source->getDivision() / source->getTempo());
events[1] = 0; events[1] = 0;
events[2] = MEVENT_NOP << 24; events[2] = MEVENT_NOP << 24;
events += 3; events += 3;
@ -956,14 +942,13 @@ int MIDIStreamer::GetDeviceType() const
// //
//========================================================================== //==========================================================================
FString MIDIStreamer::GetStats() std::string MIDIStreamer::GetStats()
{ {
if (MIDI == NULL) if (MIDI == NULL)
{ {
return "No MIDI device in use."; return "No MIDI device in use.";
} }
auto s = MIDI->GetStats(); return MIDI->GetStats();
return s.c_str();
} }
//========================================================================== //==========================================================================

View file

@ -32,7 +32,7 @@
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
*/ */
#include "i_musicinterns.h" #include "zmusic/musinfo.h"
#include "streamsources/streamsource.h" #include "streamsources/streamsource.h"
class StreamSong : public MusInfo class StreamSong : public MusInfo
@ -48,7 +48,7 @@ public:
bool IsValid () const override { return m_Source != nullptr; } bool IsValid () const override { return m_Source != nullptr; }
bool SetPosition (unsigned int pos) override; bool SetPosition (unsigned int pos) override;
bool SetSubsong (int subsong) override; bool SetSubsong (int subsong) override;
FString GetStats() override; std::string GetStats() override;
void ChangeSettingInt(const char *name, int value) override { if (m_Source) m_Source->ChangeSettingInt(name, value); } void ChangeSettingInt(const char *name, int value) override { if (m_Source) m_Source->ChangeSettingInt(name, value); }
void ChangeSettingNum(const char *name, double value) override { if (m_Source) m_Source->ChangeSettingNum(name, value); } void ChangeSettingNum(const char *name, double value) override { if (m_Source) m_Source->ChangeSettingNum(name, value); }
void ChangeSettingString(const char *name, const char *value) override { if(m_Source) m_Source->ChangeSettingString(name, value); } void ChangeSettingString(const char *name, const char *value) override { if(m_Source) m_Source->ChangeSettingString(name, value); }
@ -140,18 +140,18 @@ bool StreamSong::SetSubsong(int subsong)
return m_Source->SetSubsong(subsong); return m_Source->SetSubsong(subsong);
} }
FString StreamSong::GetStats() std::string StreamSong::GetStats()
{ {
FString s1, s2; std::string s1, s2;
if (m_Source != NULL) if (m_Source != NULL)
{ {
auto stat = m_Source->GetStats(); auto stat = m_Source->GetStats();
s2 = stat.c_str(); s2 = stat.c_str();
} }
if (s1.IsEmpty() && s2.IsEmpty()) return "No song loaded\n"; if (s1.empty() && s2.empty()) return "No song loaded\n";
if (s1.IsEmpty()) return s2; if (s1.empty()) return s2;
if (s2.IsEmpty()) return s1; if (s2.empty()) return s1;
return FStringf("%s\n%s", s1.GetChars(), s2.GetChars()); return s1 + "\n" + s2;
} }
bool StreamSong::ServiceStream (void *buff, int len) bool StreamSong::ServiceStream (void *buff, int len)

View file

@ -86,6 +86,7 @@
#include "atterm.h" #include "atterm.h"
#include "s_music.h" #include "s_music.h"
#include "filereadermusicinterface.h" #include "filereadermusicinterface.h"
#include "zmusic/musinfo.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -102,6 +103,8 @@ static bool MusicPaused; // whether music is paused
MusPlayingInfo mus_playing; // music currently being played MusPlayingInfo mus_playing; // music currently being played
static FString LastSong; // last music that was played static FString LastSong; // last music that was played
static FPlayList *PlayList; static FPlayList *PlayList;
float relative_volume = 1.f;
float saved_relative_volume = 1.0f; // this could be used to implement an ACS FadeMusic function
DEFINE_GLOBAL_NAMED(mus_playing, musplaying); DEFINE_GLOBAL_NAMED(mus_playing, musplaying);
DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, name); DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, name);
@ -199,6 +202,30 @@ void S_StopStream()
} }
} }
//==========================================================================
//
// starts playing this song
//
//==========================================================================
static void S_StartMusicPlaying(MusInfo* song, bool loop, float rel_vol, int subsong)
{
if (rel_vol > 0.f)
{
float factor = relative_volume / saved_relative_volume;
saved_relative_volume = rel_vol;
I_SetRelativeVolume(saved_relative_volume * factor);
}
song->Stop();
song->Play(loop, subsong);
song->m_NotStartedYet = false;
// Notify the sound system of the changed relative volume
snd_musicvolume.Callback();
}
//========================================================================== //==========================================================================
// //
// S_PauseSound // S_PauseSound
@ -530,7 +557,7 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
{ // play it { // play it
try try
{ {
mus_playing.handle->Start(looping, S_GetMusicVolume(musicname), order); S_StartMusicPlaying(mus_playing.handle, looping, S_GetMusicVolume(musicname), order);
S_CreateStream(); S_CreateStream();
mus_playing.baseorder = order; mus_playing.baseorder = order;
} }
@ -577,21 +604,36 @@ void S_RestartMusic ()
// //
//========================================================================== //==========================================================================
void S_MIDIDeviceChanged()
{
if (mus_playing.handle != nullptr && mus_playing.handle->IsMIDI())
{
try
{
mus_playing.handle->Start(mus_playing.loop, -1, mus_playing.baseorder);
S_CreateStream();
}
catch (const std::runtime_error& err)
{
Printf("Unable to restart music %s: %s\n", mus_playing.name.GetChars(), err.what());
}
void S_MIDIDeviceChanged(int newdev, bool force)
{
static int oldmididev = INT_MIN;
// If a song is playing, move it to the new device.
if (oldmididev != newdev || force)
{
if (mus_playing.handle != nullptr && mus_playing.handle->IsMIDI())
{
MusInfo* song = mus_playing.handle;
if (song->m_Status == MusInfo::STATE_Playing)
{
if (song->GetDeviceType() == MDEV_FLUIDSYNTH && force)
{
// FluidSynth must reload the song to change the patch set.
auto mi = mus_playing;
S_StopMusic(true);
S_ChangeMusic(mi.name, mi.baseorder, mi.loop);
}
else
{
song->Stop();
S_StartMusicPlaying(song, song->m_Looping, -1, 0);
}
}
}
} }
// 'force'
if (!force) oldmididev = newdev;
} }
//========================================================================== //==========================================================================

View file

@ -51,8 +51,7 @@ bool S_ChangeMusic (const char *music_name, int order=0, bool looping=true, bool
bool S_ChangeCDMusic (int track, unsigned int id=0, bool looping=true); bool S_ChangeCDMusic (int track, unsigned int id=0, bool looping=true);
void S_RestartMusic (); void S_RestartMusic ();
void S_MIDIDeviceChanged(int newdev, bool force);
void S_MIDIDeviceChanged();
int S_GetMusic (const char **name); int S_GetMusic (const char **name);
@ -80,4 +79,16 @@ typedef TMap<FName, MidiDeviceSetting> MidiDeviceMap;
extern MusicAliasMap MusicAliases; extern MusicAliasMap MusicAliases;
extern MidiDeviceMap MidiDevices; extern MidiDeviceMap MidiDevices;
class MusInfo;
struct MusPlayingInfo
{
FString name;
MusInfo* handle;
int baseorder;
bool loop;
};
extern float relative_volume, saved_relative_volume;
#endif #endif