Merge commit '115d1cb182168bb2c8c29a3650dfc33b08e3e6cb'

This commit is contained in:
Christoph Oelckers 2019-09-23 15:21:43 +02:00
commit 66c9f0902b
51 changed files with 767 additions and 280 deletions

View file

@ -385,6 +385,7 @@ endif()
set( LZMA_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries/lzma/C" )
set( ADL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries/adlmidi" )
set( OPN_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries/opnmidi" )
set( TIMIDITYPP_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries/timidityplus" )
if( NOT CMAKE_CROSSCOMPILING )
if( NOT CROSS_EXPORTS )
@ -408,6 +409,7 @@ add_subdirectory( libraries/dumb )
add_subdirectory( libraries/gdtoa )
add_subdirectory( libraries/adlmidi )
add_subdirectory( libraries/opnmidi )
add_subdirectory( libraries/timidityplus )
add_subdirectory( wadsrc )
add_subdirectory( wadsrc_bm )
add_subdirectory( wadsrc_lights )

View file

@ -0,0 +1,36 @@
cmake_minimum_required( VERSION 2.8.7 )
make_release_only()
if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter -fomit-frame-pointer" )
endif()
set (CMAKE_C_FLAGS ${CMAKE_C_FLAGS} ${ZD_FASTMATH_FLAG})
include_directories( timiditypp )
add_library( timidityplus STATIC
fft4g.cpp
reverb.cpp
common.cpp
configfile.cpp
effect.cpp
filter.cpp
freq.cpp
instrum.cpp
mblock.cpp
mix.cpp
playmidi.cpp
quantity.cpp
readmidic.cpp
recache.cpp
resample.cpp
sbkconv.cpp
sffile.cpp
sfitem.cpp
smplfile.cpp
sndfont.cpp
tables.cpp
)
target_link_libraries( timidityplus )

View file

@ -23,11 +23,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include "m_random.h"
#include "common.h"
#include "controls.h"
namespace TimidityPlus
{
@ -113,80 +114,70 @@ int string_to_7bit_range(const char *string_, int *start, int *end)
}
static FRandom pr_rnd;
double GenRand_Real1()
{
return rand() * (1. / RAND_MAX);
}
int int_rand(int n)
{
return (int)pr_rnd.GenRand_Real1() * n;
return (int)GenRand_Real1() * n;
}
double flt_rand()
{
return (int)pr_rnd.GenRand_Real1();
return (int)GenRand_Real1();
}
struct timidity_file *open_file(const char *name, FSoundFontReader *sfreader)
struct timidity_file *open_file(const char *name, SoundFontReaderInterface *sfreader)
{
FileReader fr;
FString filename;
if (name == nullptr)
{
fr = sfreader->OpenMainConfigFile();
filename = sfreader->basePath() + "timidity.cfg";
}
else
{
auto res = sfreader->LookupFile(name);
fr = std::move(res.first);
filename = res.second;
}
if (!fr.isOpen()) return nullptr;
auto tf = new timidity_file;
tf->url = std::move(fr);
tf->filename = filename.GetChars();
return tf;
return sfreader->open_timidityplus_file(name);
}
/* This closes files opened with open_file */
void tf_close(struct timidity_file *tf)
{
tf->url.Close();
delete tf;
}
/* This is meant for skipping a few bytes. */
void skip(struct timidity_file *tf, size_t len)
{
tf->url.Seek((long)len, FileReader::SeekCur);
}
char *tf_gets(char *buff, int n, struct timidity_file *tf)
{
return tf->url.Gets(buff, n);
tf_seek(tf, (long)len, SEEK_CUR);
}
int tf_getc(struct timidity_file *tf)
{
unsigned char c;
auto read = tf->url.Read(&c, 1);
auto read = tf_read(&c, 1, 1, tf);
return read == 0 ? EOF : c;
}
long tf_read(void *buff, int32_t size, int32_t nitems, struct timidity_file *tf)
void default_ctl_cmsg(int type, int verbosity_level, const char* fmt, ...)
{
return (long)tf->url.Read(buff, size * nitems) / size;
if (verbosity_level >= VERB_DEBUG) return; // Don't waste time on diagnostics.
char buffer[2048];
va_list args;
va_start(args, fmt);
switch (type)
{
case CMSG_ERROR:
vprintf("Error: %s\n", args);
break;
case CMSG_WARNING:
vprintf("Warning: %s\n", args);
break;
case CMSG_INFO:
vprintf("Info: %s\n", args);
break;
}
}
long tf_seek(struct timidity_file *tf, long offset, int whence)
{
return (long)tf->url.Seek(offset, (FileReader::ESeek)whence);
}
long tf_tell(struct timidity_file *tf)
{
return (long)tf->url.Tell();
}
// Allow hosting applications to capture the messages and deal with them themselves.
void (*ctl_cmsg)(int type, int verbosity_level, const char* fmt, ...) = default_ctl_cmsg;
}

View file

@ -26,7 +26,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "common.h"
#include "instrum.h"
#include "quantity.h"
#include "cmdlib.h"
namespace TimidityPlus
@ -642,8 +641,9 @@ int Instruments::read_config_file(const char *name, int self, int allow_missing_
init_mblock(&varbuf);
if (!self)
{
basedir = strdup_mblock(&varbuf, tf->filename.c_str());
FixPathSeperator((char*)basedir);
char *c = strdup_mblock(&varbuf, tf->filename.c_str());
basedir = c;
for (; *c; c++) if (*c == '\\') *c = '/';
sep = (char*)strrchr(basedir, '/');
}
else
@ -1397,7 +1397,7 @@ int Instruments::read_config_file(const char *name, int self, int allow_missing_
continue;
}
for (i = 1; i < words; i++)
sfreader->AddPath(w[i]);
sfreader->timidityplus_add_path(w[i]);
}
else if (!strcmp(w[0], "source") || !strcmp(w[0], "trysource"))
{

View file

@ -210,11 +210,6 @@ void Effect::do_effect(int32_t *buf, int32_t count)
effect_left_right_delay(buf, count);
}
uint32_t Effect::frand(void)
{
return rng.GenRand32();
}
int32_t Effect::my_mod(int32_t x, int32_t n)
{
if (x >= n)

View file

@ -36,6 +36,7 @@
#include "common.h"
#include "filter.h"
#include "sysdep.h"
namespace TimidityPlus
{

View file

@ -52,16 +52,13 @@ Instruments::Instruments()
memcpy(layer_items, static_layer_items, sizeof(layer_items));
}
bool Instruments::load(const char *config)
bool Instruments::load(SoundFontReaderInterface *sf)
{
sfreader = sfmanager.OpenSoundFont(config, SF_SF2 | SF_GUS);
if (sfreader == nullptr) return false;
sfreader = sf;
if (read_config_file(nullptr, 0, 0) == RC_OK)
{
init_load_soundfont();
set_default_instrument();
configFileName = config;
return true;
}
return false;

View file

@ -32,15 +32,10 @@
#include "resample.h"
#include "mix.h"
#include "optcode.h"
#include "c_cvars.h"
CUSTOM_CVAR(Float, min_sustain_time, 5000, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 0) self = 0;
}
namespace TimidityPlus
{
extern float min_sustain_time;
#define FROM_FINAL_VOLUME(a) (a)

View file

@ -22,10 +22,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <mutex>
#include "timidity.h"
#include "common.h"
#include "instrum.h"
@ -35,10 +35,8 @@
#include "reverb.h"
#include "freq.h"
#include "quantity.h"
#include "c_cvars.h"
#include "tables.h"
#include "effect.h"
#include "i_musicinterns.h"
namespace TimidityPlus
@ -59,6 +57,7 @@ namespace TimidityPlus
float timidity_drum_power = 1.f;
int timidity_key_adjust = 0;
float timidity_tempo_adjust = 1.f;
float min_sustain_time = 5000;
// The following options have no generic use and are only meaningful for some SYSEX events not normally found in common MIDIs.
// For now they are kept as unchanging global variables
@ -69,136 +68,7 @@ namespace TimidityPlus
static bool opt_tva_release = false;
static bool opt_insertion_effect = false;
static bool opt_delay_control = false;
}
template<class T> void ChangeVarSync(T&var, T value)
{
std::lock_guard<std::mutex> lock(TimidityPlus::CvarCritSec);
var = value;
}
CUSTOM_CVAR(Bool, timidity_modulation_wheel, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_modulation_wheel, *self);
}
CUSTOM_CVAR(Bool, timidity_portamento, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_portamento, *self);
}
/*
* reverb=0 no reverb 0
* reverb=1 old reverb 1
* reverb=1,n set reverb level to n (-1 to -127)
* reverb=2 "global" old reverb 2
* reverb=2,n set reverb level to n (-1 to -127) - 128
* reverb=3 new reverb 3
* reverb=3,n set reverb level to n (-1 to -127) - 256
* reverb=4 "global" new reverb 4
* reverb=4,n set reverb level to n (-1 to -127) - 384
*/
EXTERN_CVAR(Int, timidity_reverb_level)
EXTERN_CVAR(Int, timidity_reverb)
static void SetReverb()
{
int value = 0;
int mode = timidity_reverb;
int level = timidity_reverb_level;
if (mode == 0 || level == 0) value = mode;
else value = (mode - 1) * -128 - level;
ChangeVarSync(TimidityPlus::timidity_reverb, value);
}
CUSTOM_CVAR(Int, timidity_reverb, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 0 || self > 4) self = 0;
else SetReverb();
}
CUSTOM_CVAR(Int, timidity_reverb_level, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 0 || self > 127) self = 0;
else SetReverb();
}
CUSTOM_CVAR(Int, timidity_chorus, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_chorus, *self);
}
CUSTOM_CVAR(Bool, timidity_surround_chorus, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_TIMIDITY)
{
MIDIDeviceChanged(-1, true);
}
ChangeVarSync(TimidityPlus::timidity_surround_chorus, *self);
}
CUSTOM_CVAR(Bool, timidity_channel_pressure, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_channel_pressure, *self);
}
CUSTOM_CVAR(Int, timidity_lpf_def, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_lpf_def, *self);
}
CUSTOM_CVAR(Bool, timidity_temper_control, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_temper_control, *self);
}
CUSTOM_CVAR(Bool, timidity_modulation_envelope, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_modulation_envelope, *self);
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_TIMIDITY)
{
MIDIDeviceChanged(-1, true);
}
}
CUSTOM_CVAR(Bool, timidity_overlap_voice_allow, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_overlap_voice_allow, *self);
}
CUSTOM_CVAR(Bool, timidity_drum_effect, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_drum_effect, *self);
}
CUSTOM_CVAR(Bool, timidity_pan_delay, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_pan_delay, *self);
}
CUSTOM_CVAR(Float, timidity_drum_power, 1.0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) /* coef. of drum amplitude */
{
if (self < 0) self = 0;
else if (self > MAX_AMPLIFICATION/100.f) self = MAX_AMPLIFICATION/100.f;
ChangeVarSync(TimidityPlus::timidity_drum_power, *self);
}
CUSTOM_CVAR(Int, timidity_key_adjust, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < -24) self = -24;
else if (self > 24) self = 24;
ChangeVarSync(TimidityPlus::timidity_key_adjust, *self);
}
// For testing mainly.
CUSTOM_CVAR(Float, timidity_tempo_adjust, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 0.25) self = 0.25;
else if (self > 10) self = 10;
ChangeVarSync(TimidityPlus::timidity_tempo_adjust, *self);
}
namespace TimidityPlus
{
// These two variables need to remain global or things will get messy because they get accessed from non-class code.
int32_t control_ratio = 22;

View file

@ -27,26 +27,34 @@
#include <string>
#include <vector>
#include <stdint.h>
#include "files.h"
#include "i_soundfont.h"
#include "timidity_file.h"
namespace TimidityPlus
{
struct timidity_file
inline char* tf_gets(char* buff, int n, struct timidity_file* tf)
{
FileReader url;
std::string filename;
};
return tf->gets(buff, n);
}
extern struct timidity_file *open_file(const char *name, FSoundFontReader *);
inline long tf_read(void* buff, int32_t size, int32_t nitems, struct timidity_file* tf)
{
return (long)tf->read(buff, size, nitems);
}
inline long tf_seek(struct timidity_file* tf, long offset, int whence)
{
return (long)tf->seek(offset, whence);
}
inline long tf_tell(struct timidity_file* tf)
{
return (long)tf->tell();
}
extern struct timidity_file *open_file(const char *name, SoundFontReaderInterface *);
extern void tf_close(struct timidity_file *tf);
extern void skip(struct timidity_file *tf, size_t len);
extern char *tf_gets(char *buff, int n, struct timidity_file *tf);
int tf_getc(struct timidity_file *tf);
extern long tf_read(void *buff, int32_t size, int32_t nitems, struct timidity_file *tf);
extern long tf_seek(struct timidity_file *tf, long offset, int whence);
extern long tf_tell(struct timidity_file *tf);
extern int int_rand(int n); /* random [0..n-1] */
double flt_rand();

View file

@ -52,7 +52,7 @@ inline bool RC_IS_SKIP_FILE(int rc)
}
void ctl_cmsg(int type, int verbosity_level, const char *fmt, ...);
extern void (*ctl_cmsg)(int type, int verbosity_level, const char* fmt, ...);
}

View file

@ -1,7 +1,6 @@
#pragma once
#include <stdint.h>
#include "m_random.h"
#include "timidity.h"
@ -14,7 +13,6 @@ class Effect
{
void effect_left_right_delay(int32_t *, int32_t);
void init_mtrand(void);
uint32_t frand(void);
int32_t my_mod(int32_t, int32_t);
int turn_counter = 0, tc = 0;
@ -22,7 +20,6 @@ class Effect
double rate0 = 0, rate1 = 0, dr = 0;
int32_t prev[AUDIO_BUFFER_SIZE * 2] = { 0 };
FRandom rng;
Reverb *reverb;
public:

View file

@ -31,7 +31,6 @@
#include "sflayer.h"
#include "sfitem.h"
class FSoundFontReader;
namespace TimidityPlus
{
@ -233,7 +232,7 @@ struct SampleImporter;
class Instruments
{
std::string configFileName;
FSoundFontReader *sfreader;
SoundFontReaderInterface *sfreader;
ToneBank standard_tonebank, standard_drumset;
@ -462,7 +461,7 @@ class Instruments
public:
Instruments();
bool load(const char *config);
bool load(SoundFontReaderInterface *);
~Instruments();
const ToneBank *toneBank(int i) const
@ -556,12 +555,6 @@ public:
{
set_default_instrument(def_instr_name);
}
bool checkConfig(const char *filename)
{
return configFileName.compare(filename) == 0;
}
};

View file

@ -28,7 +28,7 @@
#include <stdint.h> // int types are defined here
#include "m_swap.h"
#include "t_swap.h"
namespace TimidityPlus
{

View file

@ -0,0 +1,255 @@
//
// DESCRIPTION:
// Endianess handling, swapping 16bit and 32bit.
//
//-----------------------------------------------------------------------------
#ifndef __M_SWAP_H__
#define __M_SWAP_H__
#include <stdlib.h>
// Endianess handling.
// WAD files are stored little endian.
#ifdef __APPLE__
#include <libkern/OSByteOrder.h>
inline short LittleShort(short x)
{
return (short)OSSwapLittleToHostInt16((uint16_t)x);
}
inline unsigned short LittleShort(unsigned short x)
{
return OSSwapLittleToHostInt16(x);
}
inline short LittleShort(int x)
{
return OSSwapLittleToHostInt16((uint16_t)x);
}
inline unsigned short LittleShort(unsigned int x)
{
return OSSwapLittleToHostInt16((uint16_t)x);
}
inline int LittleLong(int x)
{
return OSSwapLittleToHostInt32((uint32_t)x);
}
inline unsigned int LittleLong(unsigned int x)
{
return OSSwapLittleToHostInt32(x);
}
inline short BigShort(short x)
{
return (short)OSSwapBigToHostInt16((uint16_t)x);
}
inline unsigned short BigShort(unsigned short x)
{
return OSSwapBigToHostInt16(x);
}
inline int BigLong(int x)
{
return OSSwapBigToHostInt32((uint32_t)x);
}
inline unsigned int BigLong(unsigned int x)
{
return OSSwapBigToHostInt32(x);
}
#elif defined __BIG_ENDIAN__
// Swap 16bit, that is, MSB and LSB byte.
// No masking with 0xFF should be necessary.
inline short LittleShort (short x)
{
return (short)((((unsigned short)x)>>8) | (((unsigned short)x)<<8));
}
inline unsigned short LittleShort (unsigned short x)
{
return (unsigned short)((x>>8) | (x<<8));
}
inline short LittleShort (int x)
{
return LittleShort((short)x);
}
inline unsigned short LittleShort (unsigned int x)
{
return LittleShort((unsigned short)x);
}
// Swapping 32bit.
inline unsigned int LittleLong (unsigned int x)
{
return (unsigned int)(
(x>>24)
| ((x>>8) & 0xff00)
| ((x<<8) & 0xff0000)
| (x<<24));
}
inline int LittleLong (int x)
{
return (int)(
(((unsigned int)x)>>24)
| ((((unsigned int)x)>>8) & 0xff00)
| ((((unsigned int)x)<<8) & 0xff0000)
| (((unsigned int)x)<<24));
}
inline short BigShort(short x)
{
return x;
}
inline unsigned short BigShort(unsigned short x)
{
return x;
}
inline unsigned int BigLong(unsigned int x)
{
return x;
}
inline int BigLong(int x)
{
return x;
}
#else
inline short LittleShort(short x)
{
return x;
}
inline unsigned short LittleShort(unsigned short x)
{
return x;
}
inline unsigned int LittleLong(unsigned int x)
{
return x;
}
inline int LittleLong(int x)
{
return x;
}
#ifdef _MSC_VER
inline short BigShort(short x)
{
return (short)_byteswap_ushort((unsigned short)x);
}
inline unsigned short BigShort(unsigned short x)
{
return _byteswap_ushort(x);
}
inline int BigLong(int x)
{
return (int)_byteswap_ulong((unsigned long)x);
}
inline unsigned int BigLong(unsigned int x)
{
return (unsigned int)_byteswap_ulong((unsigned long)x);
}
#pragma warning (default: 4035)
#else
inline short BigShort (short x)
{
return (short)((((unsigned short)x)>>8) | (((unsigned short)x)<<8));
}
inline unsigned short BigShort (unsigned short x)
{
return (unsigned short)((x>>8) | (x<<8));
}
inline unsigned int BigLong (unsigned int x)
{
return (unsigned int)(
(x>>24)
| ((x>>8) & 0xff00)
| ((x<<8) & 0xff0000)
| (x<<24));
}
inline int BigLong (int x)
{
return (int)(
(((unsigned int)x)>>24)
| ((((unsigned int)x)>>8) & 0xff00)
| ((((unsigned int)x)<<8) & 0xff0000)
| (((unsigned int)x)<<24));
}
#endif
#endif // __BIG_ENDIAN__
// These may be destructive so they should create errors
unsigned long BigLong(unsigned long) = delete;
long BigLong(long) = delete;
unsigned long LittleLong(unsigned long) = delete;
long LittleLong(long) = delete;
// Data accessors, since some data is highly likely to be unaligned.
#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__)
inline int GetShort(const unsigned char *foo)
{
return *(const short *)foo;
}
inline int GetInt(const unsigned char *foo)
{
return *(const int *)foo;
}
#else
inline int GetShort(const unsigned char *foo)
{
return short(foo[0] | (foo[1] << 8));
}
inline int GetInt(const unsigned char *foo)
{
return int(foo[0] | (foo[1] << 8) | (foo[2] << 16) | (foo[3] << 24));
}
#endif
inline int GetBigInt(const unsigned char *foo)
{
return int((foo[0] << 24) | (foo[1] << 16) | (foo[2] << 8) | foo[3]);
}
#ifdef __BIG_ENDIAN__
inline int GetNativeInt(const unsigned char *foo)
{
return GetBigInt(foo);
}
#else
inline int GetNativeInt(const unsigned char *foo)
{
return GetInt(foo);
}
#endif
#endif // __M_SWAP_H__

View file

@ -30,6 +30,7 @@
#include "controls.h"
#include "mblock.h"
#include <mutex>
#include <stdint.h>
#ifdef _MSC_VER
@ -124,6 +125,7 @@
namespace TimidityPlus
{
extern std::mutex CvarCritSec;
extern bool timidity_modulation_wheel;
extern bool timidity_portamento;
extern int timidity_reverb;
@ -139,6 +141,8 @@ extern bool timidity_pan_delay;
extern float timidity_drum_power;
extern int timidity_key_adjust;
extern float timidity_tempo_adjust;
extern float min_sustain_time;
extern int timidity_lpf_def;
extern int32_t playback_rate;
extern int32_t control_ratio; // derived from playback_rate

View file

@ -0,0 +1,133 @@
/*
TiMidity++ -- File interface for the pure sequencer.
Copyright (C) 2019 Christoph Oelckers
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#pragma once
#include <stdio.h>
#include <vector>
#include <string>
namespace TimidityPlus
{
struct timidity_file
{
std::string filename;
virtual ~timidity_file() {}
virtual char* gets(char* buff, int n) = 0;
virtual long read(void* buff, int32_t size, int32_t nitems) = 0;
virtual long seek(long offset, int whence) = 0;
virtual long tell() = 0;
};
class SoundFontReaderInterface
{
public:
virtual struct timidity_file* open_timidityplus_file(const char* fn) = 0;
virtual void timidityplus_add_path(const char* path) = 0;
};
// A minimalistic sound font reader interface. Normally this should be replaced with something better tied into the host application.
#ifdef USE_BASE_INTERFACE
// Base version of timidity_file using stdio's FILE.
struct timidity_file_FILE : public timidity_file
{
FILE* f = nullptr;
~timidity_file_FILE()
{
if (f) fclose(f);
}
char* gets(char* buff, int n) override
{
if (!f) return nullptr;
return fgets(buff, n, f);
}
long read(void* buff, int32_t size, int32_t nitems) override
{
if (!f) return 0;
return (long)fread(buff, size, nitems, f);
}
long seek(long offset, int whence) override
{
if (!f) return 0;
return fseek(f, offset, whence);
}
long tell() override
{
if (!f) return 0;
return ftell(f);
}
};
class BaseSoundFontReader : public SoundFontReaderInterface
{
std::vector<std::string> paths;
bool IsAbsPath(const char *name)
{
if (name[0] == '/' || name[0] == '\\') return true;
#ifdef _WIN32
/* [A-Za-z]: (for Windows) */
if (isalpha(name[0]) && name[1] == ':') return true;
#endif /* _WIN32 */
return 0;
}
struct timidity_file* open_timidityplus_file(const char* fn)
{
FILE *f = nullptr;
std::string fullname;
if (!fn)
{
f = fopen("timidity.cfg", "rt");
fullname = "timidity.cfg";
}
else
{
if (!IsAbsPath(fn))
{
for(int i = (int)paths.size()-1; i>=0; i--)
{
fullname = paths[i] + fn;
f = fopen(fullname.c_str(), "rt");
break;
}
}
if (!f) f = fopen(fn, "rt");
}
if (!f) return nullptr;
auto tf = new timidity_file_FILE;
tf->f = f;
tf->filename = fullname;
return tf;
}
void timidityplus_add_path(const char* path)
{
std::string p = path;
if (p.back() != '/' && p.back() != '\\') p += '/'; // always let it end with a slash.
paths.push_back(p);
}
};
#endif
}

View file

@ -468,7 +468,7 @@ set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_L
if (HAVE_VULKAN)
set( ZDOOM_LIBS ${ZDOOM_LIBS} "glslang" "SPIRV" "OGLCompiler")
endif()
include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" "${ADL_INCLUDE_DIR}" "${OPN_INCLUDE_DIR}" )
include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" "${ADL_INCLUDE_DIR}" "${OPN_INCLUDE_DIR}" "${TIMIDITYPP_INCLUDE_DIR}" )
if( ${HAVE_VM_JIT} )
add_definitions( -DHAVE_VM_JIT )
@ -694,7 +694,6 @@ file( GLOB HEADER_FILES
sound/oplsynth/dosbox/*.h
sound/thirdparty/*.h
sound/timidity/*.h
sound/timiditypp/*.h
sound/wildmidi/*.h
rendering/*.h
rendering/2d/*.h
@ -846,8 +845,6 @@ set( FASTMATH_SOURCES
sound/music/music_midi_base.cpp
sound/backend/oalsound.cpp
sound/backend/sndfile_decoder.cpp
sound/timiditypp/fft4g.cpp
sound/timiditypp/reverb.cpp
gamedata/textures/hires/hqnx/init.cpp
gamedata/textures/hires/hqnx/hq2x.cpp
gamedata/textures/hires/hqnx/hq3x.cpp
@ -1232,25 +1229,6 @@ set (PCH_SOURCES
sound/timidity/playmidi.cpp
sound/timidity/resample.cpp
sound/timidity/timidity.cpp
sound/timiditypp/common.cpp
sound/timiditypp/configfile.cpp
sound/timiditypp/effect.cpp
sound/timiditypp/filter.cpp
sound/timiditypp/freq.cpp
sound/timiditypp/instrum.cpp
sound/timiditypp/mblock.cpp
sound/timiditypp/mix.cpp
sound/timiditypp/playmidi.cpp
sound/timiditypp/quantity.cpp
sound/timiditypp/readmidic.cpp
sound/timiditypp/recache.cpp
sound/timiditypp/resample.cpp
sound/timiditypp/sbkconv.cpp
sound/timiditypp/sffile.cpp
sound/timiditypp/sfitem.cpp
sound/timiditypp/smplfile.cpp
sound/timiditypp/sndfont.cpp
sound/timiditypp/tables.cpp
sound/wildmidi/file_io.cpp
sound/wildmidi/gus_pat.cpp
sound/wildmidi/reverb.cpp
@ -1352,7 +1330,7 @@ if( UNIX )
endif()
endif()
target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa dumb lzma adl opn )
target_link_libraries( zdoom ${ZDOOM_LIBS} gdtoa dumb lzma adl opn timidityplus )
include_directories( .
g_statusbar
@ -1484,7 +1462,6 @@ source_group("Audio Files\\Backend" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_
source_group("Audio Files\\OPL Synth" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sound/oplsynth/.+")
source_group("Audio Files\\OPL Synth\\DOSBox" FILES sound/oplsynth/dosbox/opl.cpp sound/oplsynth/dosbox/opl.h)
source_group("Audio Files\\Timidity" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sound/timidity/.+")
source_group("Audio Files\\Timiditypp" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sound/timiditypp/.+")
source_group("Audio Files\\WildMidi" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sound/wildmidi/.+")
source_group("Audio Files\\MIDI Devices" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sound/mididevices/.+")
source_group("Audio Files\\MIDI Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sound/midisources/.+")

View file

@ -37,14 +37,187 @@
#include "i_musicinterns.h"
#include "v_text.h"
#include "doomerrors.h"
#include "i_soundfont.h"
#include "timiditypp/timidity.h"
#include "timiditypp/instrum.h"
#include "timiditypp/playmidi.h"
//==========================================================================
//
// Error printing override to redirect to the internal console instead of stdout.
//
//==========================================================================
static void gzdoom_ctl_cmsg(int type, int verbosity_level, const char* fmt, ...)
{
if (verbosity_level >= TimidityPlus::VERB_DEBUG) return; // Don't waste time on diagnostics.
va_list args;
va_start(args, fmt);
FString msg;
msg.VFormat(fmt, args);
va_end(args);
switch (type)
{
case TimidityPlus::CMSG_ERROR:
Printf(TEXTCOLOR_RED "%s\n", msg.GetChars());
break;
case TimidityPlus::CMSG_WARNING:
Printf(TEXTCOLOR_YELLOW "%s\n", msg.GetChars());
break;
case TimidityPlus::CMSG_INFO:
DPrintf(DMSG_SPAMMY, "%s\n", msg.GetChars());
break;
}
}
//==========================================================================
//
// CVar interface to configurable parameters
//
//==========================================================================
template<class T> void ChangeVarSync(T& var, T value)
{
std::lock_guard<std::mutex> lock(TimidityPlus::CvarCritSec);
var = value;
}
CUSTOM_CVAR(Bool, timidity_modulation_wheel, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_modulation_wheel, *self);
}
CUSTOM_CVAR(Bool, timidity_portamento, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_portamento, *self);
}
/*
* reverb=0 no reverb 0
* reverb=1 old reverb 1
* reverb=1,n set reverb level to n (-1 to -127)
* reverb=2 "global" old reverb 2
* reverb=2,n set reverb level to n (-1 to -127) - 128
* reverb=3 new reverb 3
* reverb=3,n set reverb level to n (-1 to -127) - 256
* reverb=4 "global" new reverb 4
* reverb=4,n set reverb level to n (-1 to -127) - 384
*/
EXTERN_CVAR(Int, timidity_reverb_level)
EXTERN_CVAR(Int, timidity_reverb)
static void SetReverb()
{
int value = 0;
int mode = timidity_reverb;
int level = timidity_reverb_level;
if (mode == 0 || level == 0) value = mode;
else value = (mode - 1) * -128 - level;
ChangeVarSync(TimidityPlus::timidity_reverb, value);
}
CUSTOM_CVAR(Int, timidity_reverb, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 0 || self > 4) self = 0;
else SetReverb();
}
CUSTOM_CVAR(Int, timidity_reverb_level, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 0 || self > 127) self = 0;
else SetReverb();
}
CUSTOM_CVAR(Int, timidity_chorus, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_chorus, *self);
}
CUSTOM_CVAR(Bool, timidity_surround_chorus, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_TIMIDITY)
{
MIDIDeviceChanged(-1, true);
}
ChangeVarSync(TimidityPlus::timidity_surround_chorus, *self);
}
CUSTOM_CVAR(Bool, timidity_channel_pressure, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_channel_pressure, *self);
}
CUSTOM_CVAR(Int, timidity_lpf_def, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_lpf_def, *self);
}
CUSTOM_CVAR(Bool, timidity_temper_control, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_temper_control, *self);
}
CUSTOM_CVAR(Bool, timidity_modulation_envelope, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_modulation_envelope, *self);
if (currSong != nullptr && currSong->GetDeviceType() == MDEV_TIMIDITY)
{
MIDIDeviceChanged(-1, true);
}
}
CUSTOM_CVAR(Bool, timidity_overlap_voice_allow, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_overlap_voice_allow, *self);
}
CUSTOM_CVAR(Bool, timidity_drum_effect, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_drum_effect, *self);
}
CUSTOM_CVAR(Bool, timidity_pan_delay, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
ChangeVarSync(TimidityPlus::timidity_pan_delay, *self);
}
CUSTOM_CVAR(Float, timidity_drum_power, 1.0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) /* coef. of drum amplitude */
{
if (self < 0) self = 0;
else if (self > MAX_AMPLIFICATION / 100.f) self = MAX_AMPLIFICATION / 100.f;
ChangeVarSync(TimidityPlus::timidity_drum_power, *self);
}
CUSTOM_CVAR(Int, timidity_key_adjust, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < -24) self = -24;
else if (self > 24) self = 24;
ChangeVarSync(TimidityPlus::timidity_key_adjust, *self);
}
// For testing mainly.
CUSTOM_CVAR(Float, timidity_tempo_adjust, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 0.25) self = 0.25;
else if (self > 10) self = 10;
ChangeVarSync(TimidityPlus::timidity_tempo_adjust, *self);
}
CUSTOM_CVAR(Float, min_sustain_time, 5000, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 0) self = 0;
ChangeVarSync(TimidityPlus::min_sustain_time, *self);
}
class TimidityPPMIDIDevice : public SoftSynthMIDIDevice
{
static TimidityPlus::Instruments *instruments;
static FString configName;
int sampletime;
public:
TimidityPPMIDIDevice(const char *args, int samplerate);
@ -70,6 +243,7 @@ protected:
void ComputeOutput(float *buffer, int len);
};
TimidityPlus::Instruments *TimidityPPMIDIDevice::instruments;
FString TimidityPPMIDIDevice::configName;
// Config file to use
CUSTOM_CVAR(String, timidity_config, "gzdoom", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
@ -95,20 +269,25 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args, int samplerate)
if (args == NULL || *args == 0) args = timidity_config;
Renderer = nullptr;
if (instruments != nullptr && !instruments->checkConfig(args))
if (instruments != nullptr && configName.CompareNoCase(args)) // Only load instruments if they have changed from the last played song.
{
delete instruments;
instruments = nullptr;
}
TimidityPlus::ctl_cmsg = gzdoom_ctl_cmsg;
TimidityPlus::set_playback_rate(SampleRate);
if (instruments == nullptr)
{
instruments = new TimidityPlus::Instruments;
if (!instruments->load(args))
auto sfreader = sfmanager.OpenSoundFont(args, SF_SF2 | SF_GUS);
if (sfreader != nullptr)
{
delete instruments;
instruments = nullptr;
instruments = new TimidityPlus::Instruments;
if (!instruments->load(sfreader))
{
delete instruments;
instruments = nullptr;
}
}
}
if (instruments != nullptr)
@ -225,30 +404,3 @@ void TimidityPP_Shutdown()
TimidityPlus::free_gauss_table();
TimidityPlus::free_global_mblock();
}
void TimidityPlus::ctl_cmsg(int type, int verbosity_level, const char *fmt, ...)
{
if (verbosity_level >= VERB_DEBUG) return; // Don't waste time on diagnostics.
va_list args;
va_start(args, fmt);
FString msg;
msg.VFormat(fmt, args);
va_end(args);
switch (type)
{
case CMSG_ERROR:
Printf(TEXTCOLOR_RED "%s\n", msg.GetChars());
break;
case CMSG_WARNING:
Printf(TEXTCOLOR_YELLOW "%s\n", msg.GetChars());
break;
case CMSG_INFO:
DPrintf(DMSG_SPAMMY, "%s\n", msg.GetChars());
break;
}
}

View file

@ -35,13 +35,42 @@
#include <ctype.h>
#include <assert.h>
#include "i_soundfont.h"
#include "i_soundinternal.h"
#include "cmdlib.h"
#include "i_system.h"
#include "gameconfigfile.h"
#include "resourcefiles/resourcefile.h"
#include "timiditypp/common.h"
FSoundFontManager sfmanager;
struct timidity_file_FileReader : public TimidityPlus::timidity_file
{
FileReader fr;
char* gets(char* buff, int n) override
{
if (!fr.isOpen()) return nullptr;
return fr.Gets(buff, n);
}
long read(void* buff, int32_t size, int32_t nitems) override
{
if (!fr.isOpen()) return 0;
return (long)fr.Read(buff, size * nitems) / size;
}
long seek(long offset, int whence) override
{
if (!fr.isOpen()) return 0;
return (long)fr.Seek(offset, (FileReader::ESeek)whence);
}
long tell() override
{
if (!fr.isOpen()) return 0;
return (long)fr.Tell();
}
};
//==========================================================================
//
// returns both a file reader and the full name of the looked up file
@ -97,6 +126,44 @@ int FSoundFontReader::pathcmp(const char *p1, const char *p2)
return mCaseSensitivePaths? strcmp(p1, p2) : stricmp(p1, p2);
}
FileReader FSoundFontReader::Open(const char *name, std::string& filename)
{
FileReader fr;
if (name == nullptr)
{
fr = OpenMainConfigFile();
filename = MainConfigFileName();
}
else
{
auto res = LookupFile(name);
fr = std::move(res.first);
filename = res.second;
}
return fr;
}
//==========================================================================
//
// This is the interface function for Timidity++
//
//==========================================================================
struct TimidityPlus::timidity_file* FSoundFontReader::open_timidityplus_file(const char* name)
{
std::string filename;
FileReader fr = Open(name, filename);
if (!fr.isOpen()) return nullptr;
auto tf = new timidity_file_FileReader;
tf->fr = std::move(fr);
tf->filename = std::move(filename);
return tf;
}
//==========================================================================
//
// Note that the file type has already been checked

View file

@ -3,6 +3,7 @@
#include "doomtype.h"
#include "w_wad.h"
#include "files.h"
#include "timiditypp/timidity_file.h"
enum
{
@ -26,7 +27,7 @@ struct FSoundFontInfo
//
//==========================================================================
class FSoundFontReader
class FSoundFontReader : public TimidityPlus::SoundFontReaderInterface
{
protected:
// This is only doable for loose config files that get set as sound fonts. All other cases read from a contained environment where this does not apply.
@ -44,6 +45,11 @@ public:
virtual ~FSoundFontReader() {}
virtual FileReader OpenMainConfigFile() = 0; // this is special because it needs to be synthesized for .sf files and set some restrictions for patch sets
virtual FString MainConfigFileName()
{
return basePath() + "timidity.cfg";
}
virtual FileReader OpenFile(const char *name) = 0;
std::pair<FileReader , FString> LookupFile(const char *name);
void AddPath(const char *str);
@ -51,6 +57,13 @@ public:
{
return ""; // archived patch sets do not use paths
}
virtual FileReader Open(const char* name, std::string &filename);
virtual struct TimidityPlus::timidity_file* open_timidityplus_file(const char* name);
virtual void timidityplus_add_path(const char* name)
{
return AddPath(name);
}
};
//==========================================================================

View file

@ -36,6 +36,7 @@
#include "i_musicinterns.h"
#include "v_text.h"
#include "timidity.h"
#include "i_soundfont.h"
CUSTOM_CVAR(String, midi_config, "gzdoom", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{