- Fixed compilation with FMOD 4.38+. The removal of hardware voices and EAX was a fairly

major change, so I'm making no provisions for using older FMOD DLLs when compiled with the
  4.38 API. However, sound positioning is still broken like in 4.28, so you are recommended
  to continue building with 4.26. Also, the Freeverb-based DSP unit is no longer present in
  FMOD, so the underwater effect is currently unavailable when using 4.38 until I can figure
  out how to make it work with the SFX Reverb unit instead. (And on that topic, the Freeverb
  DSP was officially only for stereo outputs, so I really shouldn't have been using it in the
  first place.)
- Since I would like to eventually figure out the sound positioning issues with the newer
  FMODs, the following have been added:
  * snd_drawoutput now labels its outputs with the speakers they represent.
  * DCanvas::DrawTextA was added as an alias for DrawText, since the Windows headers #define
    DrawText to a Unicode/non-Unicode variant.
  * The loopsound console command was added to spawn an actor at the player's location and
    have it loop a sound infinitely.
  Hopefully I can figure it out. FMOD's 3D example works, so I assume the problem lies with
  my code, though I don't really know where to begin looking for the problem.

SVN r3350 (trunk)
This commit is contained in:
Randy Heit 2012-02-10 00:53:50 +00:00
commit 68fbd75897
9 changed files with 545 additions and 368 deletions

View file

@ -63,6 +63,10 @@ extern HWND Window;
#include "cmdlib.h"
#include "s_sound.h"
#if FMOD_VERSION > 0x42899 && FMOD_VERSION < 0x43800
#error You are trying to compile with an unsupported version of FMOD.
#endif
// MACROS ------------------------------------------------------------------
// killough 2/21/98: optionally use varying pitched sounds
@ -173,12 +177,12 @@ static const FEnumList OutputNames[] =
{ "ESD", FMOD_OUTPUTTYPE_ESD },
#if FMOD_VERSION >= 0x43400
{ "PulseAudio", FMOD_OUTPUTTYPE_PULSEAUDIO },
{ "Pulse", FMOD_OUTPUTTYPE_PULSEAUDIO },
#endif
{ "SDL", 666 },
// Mac
#if FMOD_VERSION < 0x43000
// Sound Manager support was removed sometime in the 4.29 line.
{ "Sound Manager", FMOD_OUTPUTTYPE_SOUNDMANAGER },
#endif
{ "Core Audio", FMOD_OUTPUTTYPE_COREAUDIO },
@ -238,6 +242,9 @@ static const char *OpenStateNames[] =
"Streaming"
};
const FMODSoundRenderer::spk FMODSoundRenderer::SpeakerNames4[4] = { "L", "R", "BL", "BR" };
const FMODSoundRenderer::spk FMODSoundRenderer::SpeakerNamesMore[8] = { "L", "R", "C", "LFE", "BL", "BR", "SL", "SR" };
// CODE --------------------------------------------------------------------
//==========================================================================
@ -348,7 +355,7 @@ public:
Channel->setSpeakerMix(1, 1, 1, 1, 1, 1, 1, 1);
Channel->setVolume(volume);
// Ensure reverb is disabled.
FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, };
if (FMOD_OK == Channel->getReverbProperties(&reverb))
{
reverb.Room = -10000;
@ -704,7 +711,11 @@ bool FMODSoundRenderer::Init()
}
const char *wrongver = NULL;
#if FMOD_VERSION >= 0x43800
if (version < 0x43800)
#else
if (version < 0x42000)
#endif
{
wrongver = "an old";
}
@ -842,7 +853,14 @@ bool FMODSoundRenderer::Init()
result = Sys->setDriver(driver);
}
result = Sys->getDriver(&driver);
#if FMOD_VERSION >= 0x43700
// We were built with an FMOD that only returns the control panel frequency
result = Sys->getDriverCaps(driver, &Driver_Caps, &Driver_MinFrequency, &speakermode);
Driver_MaxFrequency = Driver_MinFrequency;
#else
// We were built with an FMOD that returns a frequency range
result = Sys->getDriverCaps(driver, &Driver_Caps, &Driver_MinFrequency, &Driver_MaxFrequency, &speakermode);
#endif
if (result != FMOD_OK)
{
Printf(TEXTCOLOR_BLUE"Could not ascertain driver capabilities. Some things may be weird. (Error %d)\n", result);
@ -871,7 +889,9 @@ bool FMODSoundRenderer::Init()
format = eval >= 0 ? FMOD_SOUND_FORMAT(eval) : FMOD_SOUND_FORMAT_PCM16;
eval = Enum_NumForName(ResamplerNames, snd_resampler);
resampler = eval >= 0 ? FMOD_DSP_RESAMPLER(eval) : FMOD_DSP_RESAMPLER_LINEAR;
samplerate = clamp<int>(snd_samplerate, Driver_MinFrequency, Driver_MaxFrequency);
// These represented the frequency limits for hardware channels, which we never used anyway.
// samplerate = clamp<int>(snd_samplerate, Driver_MinFrequency, Driver_MaxFrequency);
samplerate = snd_samplerate;
if (samplerate == 0 || snd_samplerate == 0)
{ // Creative's ASIO drivers report the only supported frequency as 0!
if (FMOD_OK != Sys->getSoftwareFormat(&samplerate, NULL, NULL, NULL, NULL, NULL))
@ -922,7 +942,12 @@ bool FMODSoundRenderer::Init()
initflags = FMOD_INIT_NORMAL;
if (snd_hrtf)
{
// These flags are the same thing, just with different names.
#ifdef FMOD_INIT_SOFTWARE_HRTF
initflags |= FMOD_INIT_SOFTWARE_HRTF;
#else
initflags |= FMOD_INIT_HRTF_LOWPASS;
#endif
}
if (snd_profile)
{
@ -1007,6 +1032,7 @@ bool FMODSoundRenderer::Init()
}
// Create DSP units for underwater effect
#if FMOD_VERSION < 0x43701
result = Sys->createDSPByType(FMOD_DSP_TYPE_LOWPASS, &WaterLP);
if (result != FMOD_OK)
{
@ -1020,6 +1046,9 @@ bool FMODSoundRenderer::Init()
Printf(TEXTCOLOR_BLUE" Could not create underwater reverb unit. (Error %d)\n", result);
}
}
#else
result = FMOD_ERR_UNSUPPORTED;
#endif
// Connect underwater DSP unit between PausableSFX and SFX groups, while
// retaining the connection established by SfxGroup->addGroup().
@ -1066,6 +1095,7 @@ bool FMODSoundRenderer::Init()
WaterLP->setActive(false);
WaterLP->setParameter(FMOD_DSP_LOWPASS_CUTOFF, snd_waterlp);
WaterLP->setParameter(FMOD_DSP_LOWPASS_RESONANCE, 2);
#if FMOD_VERSION < 0x43701
if (WaterReverb != NULL)
{
FMOD::DSPConnection *dry;
@ -1090,6 +1120,7 @@ bool FMODSoundRenderer::Init()
}
}
else
#endif
{
result = sfx_head->addInput(WaterLP, NULL);
}
@ -1209,7 +1240,6 @@ void FMODSoundRenderer::PrintStatus()
int driver;
int samplerate;
int numoutputchannels;
int num2d, num3d, total;
unsigned int bufferlength;
int numbuffers;
@ -1233,12 +1263,6 @@ void FMODSoundRenderer::PrintStatus()
Printf ("Driver: "TEXTCOLOR_GREEN"%d"TEXTCOLOR_NORMAL" ("TEXTCOLOR_ORANGE"%s"TEXTCOLOR_NORMAL")\n", driver, name);
DumpDriverCaps(Driver_Caps, Driver_MinFrequency, Driver_MaxFrequency);
}
if (FMOD_OK == Sys->getHardwareChannels(&num2d, &num3d, &total))
{
Printf (TEXTCOLOR_YELLOW "Hardware 2D channels: "TEXTCOLOR_GREEN"%d\n", num2d);
Printf (TEXTCOLOR_YELLOW "Hardware 3D channels: "TEXTCOLOR_GREEN"%d\n", num3d);
Printf (TEXTCOLOR_YELLOW "Total hardware channels: "TEXTCOLOR_GREEN"%d\n", total);
}
if (FMOD_OK == Sys->getSoftwareFormat(&samplerate, &format, &numoutputchannels, NULL, &resampler, NULL))
{
Printf (TEXTCOLOR_LIGHTBLUE "Software mixer sample rate: "TEXTCOLOR_GREEN"%d\n", samplerate);
@ -1276,15 +1300,6 @@ void FMODSoundRenderer::DumpDriverCaps(FMOD_CAPS caps, int minfrequency, int max
{
Printf("\n");
}
if (caps & FMOD_CAPS_REVERB_EAX2) Printf(TEXTCOLOR_OLIVE " EAX2");
if (caps & FMOD_CAPS_REVERB_EAX3) Printf(TEXTCOLOR_OLIVE " EAX3");
if (caps & FMOD_CAPS_REVERB_EAX4) Printf(TEXTCOLOR_OLIVE " EAX4");
if (caps & FMOD_CAPS_REVERB_EAX5) Printf(TEXTCOLOR_OLIVE " EAX5");
if (caps & FMOD_CAPS_REVERB_I3DL2) Printf(TEXTCOLOR_OLIVE " I3DL2");
if (caps & (FMOD_CAPS_REVERB_EAX2 | FMOD_CAPS_REVERB_EAX3 | FMOD_CAPS_REVERB_EAX4 | FMOD_CAPS_REVERB_EAX5 | FMOD_CAPS_REVERB_I3DL2))
{
Printf("\n");
}
if (caps & FMOD_CAPS_REVERB_LIMITED) Printf("TEXTCOLOR_OLIVE Limited reverb\n");
}
@ -1689,7 +1704,7 @@ FISoundChannel *FMODSoundRenderer::StartSound(SoundHandle sfx, float vol, int pi
}
if (flags & SNDF_NOREVERB)
{
FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, };
if (FMOD_OK == chan->getReverbProperties(&reverb))
{
reverb.Room = -10000;
@ -1809,7 +1824,7 @@ FISoundChannel *FMODSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener *
}
if (flags & SNDF_NOREVERB)
{
FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
FMOD_REVERB_CHANNELPROPERTIES reverb = { 0, };
if (FMOD_OK == chan->getReverbProperties(&reverb))
{
reverb.Room = -10000;
@ -2180,7 +2195,7 @@ void FMODSoundRenderer::UpdateListener(SoundListener *listener)
{
DPrintf ("Reverb Environment %s\n", env->Name);
const_cast<ReverbContainer*>(env)->Modified = false;
Sys->setReverbProperties((FMOD_REVERB_PROPERTIES *)(&env->Properties));
SetSystemReverbProperties(&env->Properties);
PrevEnvironment = env;
if (!SfxReverbHooked)
@ -2567,23 +2582,60 @@ void FMODSoundRenderer::DrawWaveDebug(int mode)
const int window_height = 100;
int window_size;
int numoutchans;
int y;
int y, yy;
const spk *labels;
int labelcount;
if (FMOD_OK != Sys->getSoftwareFormat(NULL, NULL, &numoutchans, NULL, NULL, NULL))
{
return;
}
// Decide on which set of labels to use.
labels = (numoutchans == 4) ? SpeakerNames4 : SpeakerNamesMore;
labelcount = MIN<int>(numoutchans, countof(SpeakerNamesMore));
// Scale all the channel windows so one group fits completely on one row, with
// 16 pixels of padding between each window.
window_size = (screen->GetWidth() - 16) / numoutchans - 16;
float *wavearray = (float*)alloca(MAX(SPECTRUM_SIZE,window_size)*sizeof(float));
y = 16;
y = DrawChannelGroupOutput(SfxGroup, wavearray, window_size, window_height, y, mode);
y = DrawChannelGroupOutput(MusicGroup, wavearray, window_size, window_height, y, mode >> 2);
y = DrawSystemOutput(wavearray, window_size, window_height, y, mode >> 4);
yy = DrawChannelGroupOutput(SfxGroup, wavearray, window_size, window_height, y, mode);
if (y != yy)
{
DrawSpeakerLabels(labels, yy-14, window_size, labelcount);
}
y = DrawChannelGroupOutput(MusicGroup, wavearray, window_size, window_height, yy, mode >> 2);
if (y != yy)
{
DrawSpeakerLabels(labels, y-14, window_size, labelcount);
}
yy = DrawSystemOutput(wavearray, window_size, window_height, y, mode >> 4);
if (y != yy)
{
DrawSpeakerLabels(labels, yy-14, window_size, labelcount);
}
}
//==========================================================================
//
// FMODSoundRenderer :: DrawSpeakerLabels
//
//==========================================================================
void FMODSoundRenderer::DrawSpeakerLabels(const spk *labels, int y, int width, int count)
{
if (labels == NULL)
{
return;
}
for (int i = 0, x = 16; i < count; ++i)
{
screen->DrawText(SmallFont, CR_LIGHTBLUE, x, y, labels[i], TAG_DONE);
x += width + 16;
}
}
//==========================================================================
@ -2716,7 +2768,7 @@ void FMODSoundRenderer::DrawWave(float *wavearray, int x, int y, int width, int
// Draw a box around the oscilloscope.
screen->DrawLine(x - 1, y - 1, x + width, y - 1, -1, MAKEARGB(160, 0, 40, 200));
screen->DrawLine(x + width + 1, y - 1, x + width, y + height, -1, MAKEARGB(160, 0, 40, 200));
screen->DrawLine(x + width, y - 1, x + width, y + height, -1, MAKEARGB(160, 0, 40, 200));
screen->DrawLine(x + width, y + height, x - 1, y + height, -1, MAKEARGB(160, 0, 40, 200));
screen->DrawLine(x - 1, y + height, x - 1, y - 1, -1, MAKEARGB(160, 0, 40, 200));
@ -2823,7 +2875,7 @@ void FMODSoundRenderer::DrawSpectrum(float *spectrumarray, int x, int y, int wid
// Draw a border and dark background for the spectrum.
screen->DrawLine(x - 1, y - 1, x + width, y - 1, -1, MAKEARGB(160, 0, 40, 200));
screen->DrawLine(x + width + 1, y - 1, x + width, y + height, -1, MAKEARGB(160, 0, 40, 200));
screen->DrawLine(x + width, y - 1, x + width, y + height, -1, MAKEARGB(160, 0, 40, 200));
screen->DrawLine(x + width, y + height, x - 1, y + height, -1, MAKEARGB(160, 0, 40, 200));
screen->DrawLine(x - 1, y + height, x - 1, y - 1, -1, MAKEARGB(160, 0, 40, 200));
screen->Dim(MAKERGB(0,0,0), 0.3f, x, y, width, height);
@ -2912,17 +2964,60 @@ short *FMODSoundRenderer::DecodeSample(int outlen, const void *coded, int sizeby
void FMODSoundRenderer::InitCreateSoundExInfo(FMOD_CREATESOUNDEXINFO *exinfo) const
{
#if FMOD_VERSION >= 0x42600
if (ActiveFMODVersion < 0x42600)
{
// This parameter was added for 4.26.00, and trying to pass it to older
// DLLs will fail.
exinfo->cbsize = myoffsetof(FMOD_CREATESOUNDEXINFO, ignoresetfilesystem);
}
else
memset(exinfo, 0, sizeof(*exinfo));
#if FMOD_VERSION >= 0x42600 && FMOD_VERSION < 0x43800
if (ActiveFMODVersion < 0x42600)
{
// This parameter was added for 4.26.00, and trying to pass it to older
// DLLs will fail.
exinfo->cbsize = myoffsetof(FMOD_CREATESOUNDEXINFO, ignoresetfilesystem);
}
else
#endif
{
exinfo->cbsize = sizeof(*exinfo);
}
memset((BYTE *)exinfo + sizeof(exinfo->cbsize), 0, exinfo->cbsize - sizeof(exinfo->cbsize));
{
exinfo->cbsize = sizeof(*exinfo);
}
}
//==========================================================================
//
// FMODSoundRenderer :: SetSystemReverbProperties
//
// Set the global reverb properties.
//
//==========================================================================
FMOD_RESULT FMODSoundRenderer::SetSystemReverbProperties(const REVERB_PROPERTIES *props)
{
#if FMOD_VERSION < 0x43800
return Sys->setReverbProperties((const FMOD_REVERB_PROPERTIES *)props);
#else
// The reverb format changed when hardware mixing support was dropped, because
// all EAX-only properties were removed from the structure.
FMOD_REVERB_PROPERTIES fr;
fr.Instance = props->Instance;
fr.Environment = props->Environment;
fr.EnvDiffusion = props->EnvDiffusion;
fr.Room = props->Room;
fr.RoomHF = props->RoomHF;
fr.RoomLF = props->RoomLF;
fr.DecayTime = props->DecayTime;
fr.DecayHFRatio = props->DecayHFRatio;
fr.DecayLFRatio = props->DecayLFRatio;
fr.Reflections = props->Reflections;
fr.ReflectionsDelay = props->ReflectionsDelay;
fr.Reverb = props->Reverb;
fr.ReverbDelay = props->ReverbDelay;
fr.ModulationTime = props->ModulationTime;
fr.ModulationDepth = props->ModulationDepth;
fr.HFReference = props->HFReference;
fr.LFReference = props->LFReference;
fr.Diffusion = props->Diffusion;
fr.Density = props->Density;
fr.Flags = props->Flags;
return Sys->setReverbProperties(&fr);
#endif
}