- made the sound decoding interface DLL friendly and added compile switches to the MIDI players so that different licenses can be uses as compile target.

This commit is contained in:
Christoph Oelckers 2020-01-02 12:43:37 +01:00
parent 77a20ea7d1
commit f442d2dc54
22 changed files with 197 additions and 46 deletions

View file

@ -171,7 +171,7 @@ struct MemoryReader : public FileInterface
if (len < 0) len = 0;
memcpy(buff, mData + mPos, len);
mPos += len;
return len / size;
return len;
}
long seek(long offset, int whence) override
{
@ -216,7 +216,7 @@ struct VectorReader : public MemoryReader
mLength = (long)mVector.size();
mPos = 0;
}
VectorReader(uint8_t* data, size_t size)
VectorReader(const uint8_t* data, size_t size)
{
mVector.resize(size);
memcpy(mVector.data(), data, size);

View file

@ -58,6 +58,18 @@ int OPLio::Init(int core, uint32_t numchips, bool stereo, bool initopl3)
uint32_t i;
IsOPL3 = (core == 1 || core == 2 || core == 3);
using CoreInit = OPLEmul* (*)(bool);
static CoreInit inits[] =
{
YM3812Create,
DBOPLCreate,
JavaOPLCreate,
NukedOPL3Create,
};
if (core < 0) core = 0;
if (core > 3) core = 3;
memset(chips, 0, sizeof(chips));
if (IsOPL3)
{
@ -65,7 +77,7 @@ int OPLio::Init(int core, uint32_t numchips, bool stereo, bool initopl3)
}
for (i = 0; i < numchips; ++i)
{
OPLEmul *chip = IsOPL3 ? (core == 1 ? DBOPLCreate(stereo) : (core == 2 ? JavaOPLCreate(stereo) : NukedOPL3Create(stereo))) : YM3812Create(stereo);
OPLEmul* chip = inits[core](stereo);
if (chip == NULL)
{
break;

View file

@ -33,6 +33,7 @@
*/
#include "zmusic/zmusic_internal.h"
#include "sndfile_decoder.h"
#include "mpg123_decoder.h"
@ -115,3 +116,29 @@ short* dumb_decode_vorbis(int outlen, const void* oggstream, int sizebytes)
return samples;
}
DLL_EXPORT struct SoundDecoder* CreateDecoder(const uint8_t* data, size_t size, bool isstatic)
{
MusicIO::FileInterface* reader;
if (isstatic) reader = new MusicIO::MemoryReader(data, (long)size);
else reader = new MusicIO::VectorReader(data, size);
auto res = SoundDecoder::CreateDecoder(reader);
if (!res) reader->close();
return res;
}
DLL_EXPORT void SoundDecoder_GetInfo(struct SoundDecoder* decoder, int* samplerate, ChannelConfig* chans, SampleType* type)
{
if (decoder) decoder->getInfo(samplerate, chans, type);
else if (samplerate) *samplerate = 0;
}
DLL_EXPORT size_t SoundDecoder_Read(struct SoundDecoder* decoder, void* buffer, size_t length)
{
if (decoder) return decoder->read((char*)buffer, length);
else return 0;
}
DLL_EXPORT void SoundDecoder_Close(struct SoundDecoder* decoder)
{
if (decoder) delete decoder;
}

View file

@ -36,7 +36,10 @@
#include <stdlib.h>
#include "zmusic/zmusic_internal.h"
#include "mididevice.h"
#ifdef HAVE_ADL
#include "adlmidi.h"
ADLConfig adlConfig;
@ -267,4 +270,10 @@ MIDIDevice *CreateADLMIDIDevice(const char *Args)
return new ADLMIDIDevice(&config);
}
#else
MIDIDevice* CreateADLMIDIDevice(const char* Args)
{
throw std::runtime_error("ADL device not supported in this configuration");
}
#endif

View file

@ -37,6 +37,7 @@
#include <mutex>
#include <stdio.h>
#include <stdlib.h>
#include "zmusic/zmusic_internal.h"
#include "mididevice.h"
#include "zmusic/mus2midi.h"
@ -687,5 +688,12 @@ MIDIDevice *CreateFluidSynthMIDIDevice(int samplerate, const char *Args)
Fluid_SetupConfig(Args, fluid_patchset, true);
return new FluidSynthMIDIDevice(samplerate, fluid_patchset, musicCallbacks.Fluid_MessageFunc);
}
#else
MIDIDevice* CreateFluidSynthMIDIDevice(int samplerate, const char* Args)
{
throw std::runtime_error("FlidSynth device not supported in this configuration");
}
#endif // HAVE_FLUIDSYNTH

View file

@ -35,8 +35,11 @@
// HEADER FILES ------------------------------------------------------------
#include "zmusic/zmusic_internal.h"
#include "mididevice.h"
#include "zmusic/mus2midi.h"
#ifdef HAVE_OPL
#include "oplsynth/opl.h"
#include "oplsynth/opl_mus_player.h"
@ -324,3 +327,10 @@ MIDIDevice* CreateOplMIDIDevice(const char *Args)
if (Args != NULL && *Args >= '0' && *Args < '4') core = *Args - '0';
return new OPLMIDIDevice(core);
}
#else
MIDIDevice* CreateOplMIDIDevice(const char* Args)
{
throw std::runtime_error("OPL device not supported in this configuration");
}
#endif

View file

@ -35,6 +35,9 @@
// HEADER FILES ------------------------------------------------------------
#include "mididevice.h"
#include "zmusic/zmusic_internal.h"
#ifdef HAVE_OPN
#include "opnmidi.h"
OpnConfig opnConfig;
@ -245,4 +248,9 @@ MIDIDevice *CreateOPNMIDIDevice(const char *Args)
return new OPNMIDIDevice(bank);
}
#else
MIDIDevice* CreateOPNMIDIDevice(const char* Args)
{
throw std::runtime_error("OPN device not supported in this configuration");
}
#endif

View file

@ -35,8 +35,11 @@
// HEADER FILES ------------------------------------------------------------
#include <stdlib.h>
#include "mididevice.h"
#include "zmusic/zmusic_internal.h"
#ifdef HAVE_GUS
#include "timidity/timidity.h"
#include "timidity/playmidi.h"
#include "timidity/instrum.h"
@ -294,10 +297,16 @@ bool GUS_SetupConfig(const char* args)
return true;
}
MIDIDevice *CreateTimidityMIDIDevice(const char *Args, int samplerate)
#
MIDIDevice* CreateTimidityMIDIDevice(const char* Args, int samplerate)
{
GUS_SetupConfig(Args);
return new TimidityMIDIDevice(samplerate);
}
#else
MIDIDevice* CreateTimidityMIDIDevice(const char* Args, int samplerate)
{
throw std::runtime_error("GUS device not supported in this configuration");
}
#endif

View file

@ -33,6 +33,9 @@
*/
#include "mididevice.h"
#include "zmusic/zmusic_internal.h"
#ifdef HAVE_TIMIDITY
#include "timiditypp/timidity.h"
#include "timiditypp/instrum.h"
@ -231,3 +234,9 @@ MIDIDevice *CreateTimidityPPMIDIDevice(const char *Args, int samplerate)
return new TimidityPPMIDIDevice(samplerate);
}
#else
MIDIDevice* CreateTimidityPPMIDIDevice(const char* Args, int samplerate)
{
throw std::runtime_error("Timidity++ device not supported in this configuration");
}
#endif

View file

@ -35,6 +35,10 @@
// HEADER FILES ------------------------------------------------------------
#include "mididevice.h"
#include "zmusic/zmusic_internal.h"
#ifdef HAVE_WILDMIDI
#include "wildmidi/wildmidi_lib.h"
// MACROS ------------------------------------------------------------------
@ -275,3 +279,9 @@ MIDIDevice *CreateWildMIDIDevice(const char *Args, int samplerate)
return new WildMIDIDevice(samplerate);
}
#else
MIDIDevice* CreateWildMIDIDevice(const char* Args, int samplerate)
{
throw std::runtime_error("WildMidi device not supported in this configuration");
}
#endif

View file

@ -287,11 +287,9 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype, int samplerate)
#endif
// Intentional fall-through for systems without standard midi support
#ifdef HAVE_FLUIDSYNTH
case MDEV_FLUIDSYNTH:
dev = CreateFluidSynthMIDIDevice(samplerate, Args.c_str());
break;
#endif // HAVE_FLUIDSYNTH
case MDEV_OPL:
dev = CreateOplMIDIDevice(Args.c_str());
@ -322,6 +320,8 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype, int samplerate)
#ifdef HAVE_SYSTEM_MIDI
else if (!checked[MDEV_STANDARD]) devtype = MDEV_STANDARD;
#endif
else if (!checked[MDEV_ADL]) devtype = MDEV_ADL;
else if (!checked[MDEV_OPN]) devtype = MDEV_OPN;
else if (!checked[MDEV_OPL]) devtype = MDEV_OPL;
if (devtype == MDEV_DEFAULT)
@ -334,13 +334,15 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype, int samplerate)
if (selectedDevice != requestedDevice && (selectedDevice != lastSelectedDevice || requestedDevice != lastRequestedDevice))
{
static const char *devnames[] = {
"Windows Default",
"System Default",
"OPL",
"",
"Timidity++",
"FluidSynth",
"GUS",
"WildMidi"
"WildMidi",
"ADL",
"OPN",
};
lastRequestedDevice = requestedDevice;

View file

@ -338,6 +338,12 @@ void FindLoopTags(MusicIO::FileInterface *fr, uint32_t *start, bool *startass, u
FindOggComments(fr, start, startass, end, endass);
}
DLL_EXPORT void FindLoopTags(const uint8_t* data, size_t size, uint32_t* start, bool* startass, uint32_t* end, bool* endass)
{
MusicIO::FileInterface* reader = new MusicIO::MemoryReader(data, (long)size);
FindLoopTags(reader, start, startass, end, endass);
reader->close();
}
//==========================================================================
//

View file

@ -3,7 +3,7 @@
#include <string>
#include <vector>
#include <memory>
#include "zmusic.h"
#include "zmusic_internal.h"
#include "../../libraries/music_common/fileio.h"
// Note: Bools here are stored as ints to allow having a simpler interface.

View file

@ -1,19 +1,8 @@
#pragma once
#include "../../music_common/fileio.h"
#include "zmusic_internal.h"
#include <vector>
enum SampleType
{
SampleType_UInt8,
SampleType_Int16
};
enum ChannelConfig
{
ChannelConfig_Mono,
ChannelConfig_Stereo
};
struct SoundDecoder
{
static SoundDecoder* CreateDecoder(MusicIO::FileInterface* reader);
@ -37,4 +26,3 @@ protected:
SoundDecoder(const SoundDecoder &rhs) = delete;
SoundDecoder& operator=(const SoundDecoder &rhs) = delete;
};

View file

@ -59,6 +59,17 @@ struct SoundStreamInfo
int mNumChannels; // If mNumChannels is negative, 16 bit integer format is used instead of floating point.
};
enum SampleType
{
SampleType_UInt8,
SampleType_Int16
};
enum ChannelConfig
{
ChannelConfig_Mono,
ChannelConfig_Stereo
};
enum EIntConfigKey
{
zmusic_adl_chips_count,
@ -217,8 +228,10 @@ struct Callbacks
#ifndef ZMUSIC_INTERNAL
#define DLL_IMPORT // _declspec(dllimport)
// Note that the internal 'class' definitions are not C compatible!
typedef struct { int zm1; } *ZMusic_MidiSource;
typedef struct { int zm2; } *ZMusic_MusicStream;
struct SoundDecoder;
#endif
#ifdef __cplusplus
@ -262,11 +275,21 @@ extern "C"
DLL_IMPORT void ZMusic_GetStreamInfo(ZMusic_MusicStream song, SoundStreamInfo *info);
// 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.
DLL_IMPORT bool ChangeMusicSettingInt(EIntConfigKey key, ZMusic_MusicStream song, int value, int* pRealValue = nullptr);
DLL_IMPORT bool ChangeMusicSettingFloat(EFloatConfigKey key, ZMusic_MusicStream song, float value, float* pRealValue = nullptr);
DLL_IMPORT bool ChangeMusicSettingInt(EIntConfigKey key, ZMusic_MusicStream song, int value, int* pRealValue);
DLL_IMPORT bool ChangeMusicSettingFloat(EFloatConfigKey key, ZMusic_MusicStream song, float value, float* pRealValue);
DLL_IMPORT bool ChangeMusicSettingString(EStringConfigKey key, ZMusic_MusicStream song, const char* value);
DLL_IMPORT const char *ZMusic_GetStats(ZMusic_MusicStream song);
DLL_IMPORT struct SoundDecoder* CreateDecoder(const uint8_t* data, size_t size, bool isstatic);
DLL_IMPORT void SoundDecoder_GetInfo(struct SoundDecoder* decoder, int* samplerate, ChannelConfig* chans, SampleType* type);
DLL_IMPORT size_t SoundDecoder_Read(struct SoundDecoder* decoder, void* buffer, size_t length);
DLL_IMPORT void SoundDecoder_Close(struct SoundDecoder* decoder);
DLL_IMPORT void FindLoopTags(const uint8_t* data, size_t size, uint32_t* start, bool* startass, uint32_t* end, bool* endass);
// The rest of the decoder interface is only useful for streaming music.
#ifdef __cplusplus
}

View file

@ -6,6 +6,36 @@
typedef class MIDISource *ZMusic_MidiSource;
typedef class MusInfo *ZMusic_MusicStream;
// Some MIDI backends are not compatible with LGPLv2, so with this #define the support level can be set.
// License can be:
// 0: LGPLv2. FluidSynth and GUS only.
// 1: GPLv2. Adds Timidity++ and OPL.
// 2: GPLv3. Adds ADL, OPN and WildMidi.
//
// Default is GPLv3. Most Open Source games can comply with this.
// The notable exceptions are the Build engine games and Descent which are under a no profit clause.
// For these games LGPLv2 is the only viable choice.
#ifndef LICENSE
#define LICENSE 2
#endif
// Devices under a permissive license, or at most LGPLv2+
#define HAVE_GUS
// FluidSynth is a configuration option
#if LICENSE >= 1
#define HAVE_TIMIDITY
#define HAVE_OPL
#endif
#if LICENSE >= 2
// MIDI Devices that cannot be licensed as LGPLv2.
#define HAVE_ADL
#define HAVE_OPN
#define HAVE_WILDMIDI
#endif
#include "zmusic.h"
#include "../../music_common/fileio.h"

View file

@ -39,7 +39,6 @@
#include "i_module.h"
#include "cmdlib.h"
#include "zmusic/sounddecoder.h"
#include "c_dispatch.h"
#include "i_music.h"

View file

@ -35,8 +35,10 @@
#ifndef __I_SOUND__
#define __I_SOUND__
#include <vector>
#include "i_soundinternal.h"
#include "utility/zstring.h"
#include "zmusic/zmusic.h"
class FileReader;
struct FSoundChan;

View file

@ -6,7 +6,6 @@
#include "vectors.h"
#include "tarray.h"
#include "zmusic/sounddecoder.h"
#include "tflags.h"
enum EChanFlag
@ -139,9 +138,6 @@ struct FISoundChannel
EChanFlags ChanFlags;
};
void FindLoopTags(MusicIO::FileInterface *fr, uint32_t *start, bool *startass, uint32_t *end, bool *endass);
class SoundStream;

View file

@ -43,8 +43,6 @@
#include "i_module.h"
#include "cmdlib.h"
#include "m_fixed.h"
#include "zmusic/sounddecoder.h"
#include "filereadermusicinterface.h"
const char *GetSampleTypeName(SampleType type);
@ -1099,18 +1097,14 @@ std::pair<SoundHandle,bool> OpenALSoundRenderer::LoadSound(uint8_t *sfxdata, int
/* Only downmix to mono if we can't spatialize multi-channel sounds. */
monoize = monoize && !AL.SOFT_source_spatialize;
auto mreader = new MusicIO::MemoryReader(sfxdata, length);
FindLoopTags(mreader, &loop_start, &startass, &loop_end, &endass);
mreader->seek(0, SEEK_SET);
std::unique_ptr<SoundDecoder> decoder(SoundDecoder::CreateDecoder(mreader));
FindLoopTags(sfxdata, length, &loop_start, &startass, &loop_end, &endass);
auto decoder = CreateDecoder(sfxdata, length, true);
if (!decoder)
{
delete mreader;
return std::make_pair(retval, true);
}
// the decode will take ownership of the reader here.
decoder->getInfo(&srate, &chans, &type);
SoundDecoder_GetInfo(decoder, &srate, &chans, &type);
int samplesize = 1;
if (chans == ChannelConfig_Mono || monoize)
{
@ -1125,12 +1119,24 @@ std::pair<SoundHandle,bool> OpenALSoundRenderer::LoadSound(uint8_t *sfxdata, int
if (format == AL_NONE)
{
SoundDecoder_Close(decoder);
Printf("Unsupported audio format: %s, %s\n", GetChannelConfigName(chans),
GetSampleTypeName(type));
return std::make_pair(retval, true);
}
auto data = decoder->readAll();
std::vector<uint8_t> data;
unsigned total = 0;
unsigned got;
data.resize(total + 32768);
while ((got = (unsigned)SoundDecoder_Read(decoder, (char*)&data[total], data.size() - total)) > 0)
{
total += got;
data.resize(total * 2);
}
data.resize(total);
SoundDecoder_Close(decoder);
if(chans != ChannelConfig_Mono && monoize)
{

View file

@ -53,9 +53,7 @@
#include "i_soundfont.h"
#include "s_music.h"
#include "doomstat.h"
#include "streamsources/streamsource.h"
#include "filereadermusicinterface.h"
#include "../libraries/zmusic/midisources/midisource.h"

View file

@ -49,7 +49,6 @@
#include "vm.h"
#include "i_system.h"
#include "s_music.h"
#include "mididevices/mididevice.h"
// MACROS ------------------------------------------------------------------