- consolidated the different file access interfaces in the backends into one shared version.

This was getting a bit unwieldy. The include path setup is not perfect yet, that's work for later.
(It's about time we're getting C++20 with modules so that this include path madness can be put to an end.)
This commit is contained in:
Christoph Oelckers 2019-09-28 23:17:16 +02:00
parent d94b63b486
commit 7468c0f36d
28 changed files with 504 additions and 634 deletions

View file

@ -0,0 +1,338 @@
/*
The common sound font reader interface. Used by GUS, Timidity++ and WildMidi
backends for reading sound font configurations.
The FileInterface is also used by streaming sound formats.
Copyright (C) 2019 Christoph Oelckers
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser 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>
#if defined _WIN32 && !defined _WINDOWS_ // only define this if windows.h is not included.
// I'd rather not include Windows.h for just this. This header is not supposed to pollute everything it touches.
extern "C" __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned CodePage, unsigned long dwFlags, const char* lpMultiByteStr, int cbMultiByte, const wchar_t* lpWideCharStr, int cchWideChar);
enum
{
CP_UTF8 = 65001
};
#endif
namespace MusicIO
{
//==========================================================================
//
// This class defines a common file wrapper interface which allows these
// libraries to work with any kind of file access API, e.g. stdio (provided below),
// Win32, POSIX, iostream or custom implementations (like GZDoom's FileReader.)
//
//==========================================================================
struct FileInterface
{
std::string filename;
// It's really too bad that the using code requires long instead of size_t.
// Fortunately 2GB files are unlikely to come by here.
virtual ~FileInterface() {}
virtual char* gets(char* buff, int n) = 0;
virtual long read(void* buff, int32_t size, int32_t nitems) = 0;
long read(void* buff, int32_t size) { return read(buff, 1, size); }
virtual long seek(long offset, int whence) = 0;
virtual long tell() = 0;
virtual void close() = 0;
};
//==========================================================================
//
// Inplementation of the FileInterface for stdio's FILE*.
//
//==========================================================================
struct StdioFileReader : public FileInterface
{
FILE* f = nullptr;
~StdioFileReader()
{
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);
}
void close() override
{
if (f) fclose(f);
delete this;
}
};
//==========================================================================
//
// Inplementation of the FileInterface for a block of memory
//
//==========================================================================
struct MemoryReader : public FileInterface
{
const uint8_t *mData;
const long mLength;
long mPos;
MemoryReader(const uint8_t *data, long length)
: mData(data), mLength(length), mPos(0)
{
}
char* gets(char* strbuf, int len) override
{
if (len > mLength - mPos) len = mLength - mPos;
if (len <= 0) return NULL;
char *p = strbuf;
while (len > 1)
{
if (mData[mPos] == 0)
{
mPos++;
break;
}
if (mData[mPos] != '\r')
{
*p++ = mData[mPos];
len--;
if (mData[mPos] == '\n')
{
mPos++;
break;
}
}
mPos++;
}
if (p == strbuf) return nullptr;
*p++ = 0;
return strbuf;
}
long read(void* buff, int32_t size, int32_t nitems) override
{
long len = long(size) * nitems;
if (len > mLength - mPos) len = mLength - mPos;
if (len < 0) len = 0;
memcpy(buff, mData + mPos, len);
mPos += len;
return len / size;
}
long seek(long offset, int whence) override
{
switch (whence)
{
case SEEK_CUR:
offset += mPos;
break;
case SEEK_END:
offset += mLength;
break;
}
if (offset < 0 || offset > mLength) return -1;
mPos = offset;
return 0;
}
long tell() override
{
return mPos;
}
void close() override
{
delete this;
}
};
//==========================================================================
//
// The follpwing two functions are needed to allow using UTF-8 in the file interface.
// fopen on Windows is only safe for ASCII,
//
//==========================================================================
#ifdef _WIN32
inline std::wstring wideString(const char *filename)
{
std::wstring filePathW;
auto len = strlen(filename);
filePathW.resize(len);
int newSize = MultiByteToWideChar(CP_UTF8, 0, filename, (int)len, const_cast<wchar_t*>(filePathW.c_str()), (int)len);
filePathW.resize(newSize);
return filePathW;
}
#endif
inline FILE* utf8_fopen(const char* filename, const char *mode)
{
#ifndef _WIN32
return fopen(filename, "wb");
#else
auto fn = wideString(filename);
auto mo = wideString(mode);
return _wfopen(fn.c_str(), mo.c_str());
#endif
}
//==========================================================================
//
// This class providea a framework for reading sound fonts.
// This is needed when the sound font data is not read from
// the file system. e.g. zipped GUS patch sets.
//
//==========================================================================
class SoundFontReaderInterface
{
public:
virtual ~SoundFontReaderInterface() {}
virtual struct FileInterface* open_file(const char* fn) = 0;
virtual void add_search_path(const char* path) = 0;
};
//==========================================================================
//
// A basic sound font reader for reading data from the file system.
//
//==========================================================================
class FileSystemSoundFontReader : public SoundFontReaderInterface
{
protected:
std::vector<std::string> mPaths;
std::string mBaseFile;
bool mAllowAbsolutePaths;
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;
}
public:
FileSystemSoundFontReader(const char *configfilename, bool allowabs = false)
{
// Note that this does not add the directory the base file is in to the search path!
// The caller of this has to do it themselves!
mBaseFile = configfilename;
mAllowAbsolutePaths = allowabs;
}
struct FileInterface* open_file(const char* fn) override
{
FILE *f = nullptr;
std::string fullname;
if (!fn)
{
f = utf8_fopen(mBaseFile.c_str(), "rt");
fullname = mBaseFile;
}
else
{
if (!IsAbsPath(fn))
{
for(int i = (int)mPaths.size()-1; i>=0; i--)
{
fullname = mPaths[i] + fn;
f = utf8_fopen(fullname.c_str(), "rt");
break;
}
}
if (!f) f = fopen(fn, "rt");
}
if (!f) return nullptr;
auto tf = new StdioFileReader;
tf->f = f;
tf->filename = fullname;
return tf;
}
void add_search_path(const char* path) override
{
std::string p = path;
if (p.back() != '/' && p.back() != '\\') p += '/'; // always let it end with a slash.
mPaths.push_back(p);
}
};
//==========================================================================
//
// This reader exists to trick Timidity config readers into accepting
// a loose SF2 file by providing a fake config pointing to the given file.
//
//==========================================================================
class SF2Reader : public FileSystemSoundFontReader
{
std::string mMainConfigForSF2;
public:
SF2Reader(const char *filename)
: FileSystemSoundFontReader(filename)
{
mMainConfigForSF2 = "soundfont \"" + mBaseFile + "\"\n";
}
struct FileInterface* open_file(const char* fn) override
{
if (fn == nullptr)
{
return new MemoryReader((uint8_t*)mMainConfigForSF2.c_str(), (long)mMainConfigForSF2.length());
}
else return FileSystemSoundFontReader::open_file(fn);
}
};
}

View file

@ -32,7 +32,6 @@
#include "timidity.h"
#include "gf1patch.h"
#include "timidity_file.h"
#include "t_swap.h"
#include "common.h"
@ -164,18 +163,18 @@ Instrument *Renderer::load_instrument(const char *name, int percussion,
if (!name || reader == nullptr) return nullptr;
/* Open patch file */
auto fp = reader->open_timidity_file(name);
auto fp = reader->open_file(name);
if (!fp)
{
/* Try with various extensions */
std::string tmp = name;
tmp += ".pat";
fp = reader->open_timidity_file(tmp.c_str());
fp = reader->open_file(tmp.c_str());
if (!fp)
{
#ifndef _WIN32 // Windows isn't case-sensitive.
std::transform(tmp.begin(), tmp.end(), tmp.begin(), [](unsigned char c){ return toupper(c); } );
fp = reader->open_timidity_file(tmp.c_str());
fp = reader->open_file(tmp.c_str());
if (!fp)
#endif
{
@ -680,7 +679,7 @@ void Instruments::free_instruments()
}
}
Instruments::Instruments(SoundFontReaderInterface *reader)
Instruments::Instruments(MusicIO::SoundFontReaderInterface *reader)
{
sfreader = reader;
tonebank[0] = new ToneBank;

View file

@ -3,7 +3,6 @@
#include <memory>
#include "timidity.h"
#include "timidity_file.h"
#include "common.h"
#include "instrum.h"
#include "sf2.h"
@ -57,7 +56,7 @@ void Instruments::font_add(const char *filename, int load_order)
}
else
{
auto fp = sfreader->open_timidity_file(filename);
auto fp = sfreader->open_file(filename);
if (fp)
{

View file

@ -8,7 +8,6 @@
#include "t_swap.h"
#include "timidity.h"
#include "timidity_file.h"
#include "common.h"
#include "instrum.h"
#include "playmidi.h"
@ -1506,7 +1505,7 @@ void SFFile::ApplyGeneratorsToRegion(SFGenComposite *gen, SFSample *sfsamp, Rend
void SFFile::LoadSample(Renderer *song, SFSample *sample)
{
auto fp = song->instruments->sfreader->open_timidity_file(Filename.c_str());
auto fp = song->instruments->sfreader->open_file(Filename.c_str());
uint32_t i;
if (!fp)

View file

@ -28,7 +28,6 @@
#include <string.h>
#include "timidity.h"
#include "timidity_file.h"
#include "common.h"
#include "instrum.h"
#include "playmidi.h"
@ -188,7 +187,7 @@ int Instruments::read_config_file(const char *name)
printMessage(CMSG_ERROR, VERB_NORMAL, "Timidity: Probable source loop in configuration files\n");
return (-1);
}
auto fp = sfreader->open_timidity_file(name);
auto fp = sfreader->open_file(name);
if (!fp)
{
printMessage(CMSG_ERROR, VERB_NORMAL, "Timidity: Unable to open config file\n");
@ -400,7 +399,7 @@ int Instruments::read_config_file(const char *name)
for (i = 1; i < words; i++)
{
// Q: How does this deal with relative paths? In this form it just does not work.
sfreader->timidity_add_path(w[i]);
sfreader->add_search_path(w[i]);
}
}
else if (!strcmp(w[0], "source"))

View file

@ -1,4 +1,7 @@
#pragma once
#include "../../music_common/fileio.h"
namespace Timidity
{
/*
@ -164,13 +167,13 @@ public:
class Instruments
{
public:
SoundFontReaderInterface *sfreader;
MusicIO::SoundFontReaderInterface *sfreader;
ToneBank* tonebank[MAXBANK] = {};
ToneBank* drumset[MAXBANK] = {};
FontFile* Fonts = nullptr;
std::string def_instr_name;
Instruments(SoundFontReaderInterface* reader);
Instruments(MusicIO::SoundFontReaderInterface* reader);
~Instruments();
int LoadConfig() { return read_config_file(nullptr); }

View file

@ -1,9 +1,12 @@
#pragma once
#include <vector>
#include "../../music_common/fileio.h"
namespace Timidity
{
typedef uint16_t SFGenerator;
struct timidity_file;
using timidity_file = MusicIO::FileInterface;
struct SFRange
{

View file

@ -22,11 +22,11 @@
#include <stdint.h>
#include <string>
#include "timidity_file.h"
#include "../../music_common/fileio.h"
namespace Timidity
{
struct timidity_file;
using timidity_file = MusicIO::FileInterface;
/*

View file

@ -1,142 +0,0 @@
/*
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 Lesser 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 Timidity
{
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;
long read(void* buff, int32_t size) { return read(buff, 1, size); }
virtual long seek(long offset, int whence) = 0;
virtual long tell() = 0;
virtual void close() = 0;
};
class SoundFontReaderInterface
{
public:
virtual ~SoundFontReaderInterface() {}
virtual struct timidity_file* open_timidity_file(const char* fn) = 0;
virtual void timidity_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.
#if 1//def 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);
}
void close()
{
if (f) fclose(f);
delete this;
}
};
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;
}
public:
struct timidity_file* open_timidity_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 timidity_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

@ -129,24 +129,24 @@ double flt_rand()
return (int)GenRand_Real1();
}
struct timidity_file *open_file(const char *name, SoundFontReaderInterface *sfreader)
timidity_file *open_file(const char *name, MusicIO::SoundFontReaderInterface *sfreader)
{
return sfreader->open_timidityplus_file(name);
return sfreader->open_file(name);
}
/* This closes files opened with open_file */
void tf_close(struct timidity_file *tf)
void tf_close(timidity_file *tf)
{
if (tf) tf->close();
}
/* This is meant for skipping a few bytes. */
void skip(struct timidity_file *tf, size_t len)
void skip(timidity_file *tf, size_t len)
{
tf_seek(tf, (long)len, SEEK_CUR);
}
int tf_getc(struct timidity_file *tf)
int tf_getc(timidity_file *tf)
{
unsigned char c;
auto read = tf_read(&c, 1, 1, tf);

View file

@ -615,7 +615,7 @@ char *Instruments::expand_variables(char *string, MBlockList *varbuf, const char
int Instruments::read_config_file(const char *name, int self, int allow_missing_file)
{
struct timidity_file *tf;
timidity_file *tf;
char buf[1024], *tmp, *w[MAXWORDS + 1], *cp;
ToneBank *bank = NULL;
int i, j, k, line = 0, words, errcnt = 0;
@ -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->timidityplus_add_path(w[i]);
sfreader->add_search_path(w[i]);
}
else if (!strcmp(w[0], "source") || !strcmp(w[0], "trysource"))
{

View file

@ -27,6 +27,7 @@
#include <math.h>
#include <string.h>
#include "../music_common/fileio.h"
#include "timidity.h"
#include "common.h"
#include "instrum.h"
@ -52,7 +53,7 @@ Instruments::Instruments()
memcpy(layer_items, static_layer_items, sizeof(layer_items));
}
bool Instruments::load(SoundFontReaderInterface *sf)
bool Instruments::load(MusicIO::SoundFontReaderInterface *sf)
{
sfreader = sf;
if (read_config_file(nullptr, 0, 0) == RC_OK)
@ -578,7 +579,7 @@ Instrument *Instruments::load_gus_instrument(char *name, ToneBank *bank, int dr,
ToneBankElement *tone;
int amp, note_to_use, panning, strip_envelope, strip_loop, strip_tail;
Instrument *ip;
struct timidity_file *tf;
timidity_file *tf;
uint8_t tmp[1024], fractions;
Sample *sp;
int i, j, noluck = 0;

View file

@ -64,7 +64,7 @@ namespace TimidityPlus
#define NEW(type,nums) (type*)safe_malloc(sizeof(type) * (nums))
static int READCHUNK(SFChunk *vp, struct timidity_file *tf)
static int READCHUNK(SFChunk *vp, timidity_file *tf)
{
if (tf_read(vp, 8, 1, tf) != 1)
return -1;
@ -72,7 +72,7 @@ static int READCHUNK(SFChunk *vp, struct timidity_file *tf)
return 1;
}
static int READDW(uint32_t *vp, struct timidity_file *tf)
static int READDW(uint32_t *vp, timidity_file *tf)
{
if (tf_read(vp, 4, 1, tf) != 1)
return -1;
@ -80,7 +80,7 @@ static int READDW(uint32_t *vp, struct timidity_file *tf)
return 1;
}
static int READW(uint16_t *vp, struct timidity_file *tf)
static int READW(uint16_t *vp, timidity_file *tf)
{
if (tf_read(vp, 2, 1, tf) != 1)
return -1;
@ -88,7 +88,7 @@ static int READW(uint16_t *vp, struct timidity_file *tf)
return 1;
}
static int READSTR(char *str, struct timidity_file *tf)
static int READSTR(char *str, timidity_file *tf)
{
int n;
@ -140,7 +140,7 @@ enum {
* load a soundfont file
*================================================================*/
int Instruments::load_soundfont(SFInfo *sf, struct timidity_file *fd)
int Instruments::load_soundfont(SFInfo *sf, timidity_file *fd)
{
SFChunk chunk;
@ -272,7 +272,7 @@ int Instruments::chunkid(char *id)
* process a list chunk
*================================================================*/
int Instruments::process_list(int size, SFInfo *sf, struct timidity_file *fd)
int Instruments::process_list(int size, SFInfo *sf, timidity_file *fd)
{
SFChunk chunk;
@ -299,7 +299,7 @@ int Instruments::process_list(int size, SFInfo *sf, struct timidity_file *fd)
* process info list
*================================================================*/
int Instruments::process_info(int size, SFInfo *sf, struct timidity_file *fd)
int Instruments::process_info(int size, SFInfo *sf, timidity_file *fd)
{
sf->infopos = tf_tell(fd);
sf->infosize = size;
@ -347,7 +347,7 @@ int Instruments::process_info(int size, SFInfo *sf, struct timidity_file *fd)
* process sample data list
*================================================================*/
int Instruments::process_sdta(int size, SFInfo *sf, struct timidity_file *fd)
int Instruments::process_sdta(int size, SFInfo *sf, timidity_file *fd)
{
while (size > 0) {
SFChunk chunk;
@ -384,7 +384,7 @@ int Instruments::process_sdta(int size, SFInfo *sf, struct timidity_file *fd)
* process preset data list
*================================================================*/
int Instruments::process_pdta(int size, SFInfo *sf, struct timidity_file *fd)
int Instruments::process_pdta(int size, SFInfo *sf, timidity_file *fd)
{
while (size > 0) {
SFChunk chunk;
@ -434,7 +434,7 @@ int Instruments::process_pdta(int size, SFInfo *sf, struct timidity_file *fd)
* store sample name list; sf1 only
*----------------------------------------------------------------*/
void Instruments::load_sample_names(int size, SFInfo *sf, struct timidity_file *fd)
void Instruments::load_sample_names(int size, SFInfo *sf, timidity_file *fd)
{
int i, nsamples;
if (sf->version > 1) {
@ -466,7 +466,7 @@ void Instruments::load_sample_names(int size, SFInfo *sf, struct timidity_file *
* preset header list
*----------------------------------------------------------------*/
void Instruments::load_preset_header(int size, SFInfo *sf, struct timidity_file *fd)
void Instruments::load_preset_header(int size, SFInfo *sf, timidity_file *fd)
{
int i;
@ -491,7 +491,7 @@ void Instruments::load_preset_header(int size, SFInfo *sf, struct timidity_file
* instrument header list
*----------------------------------------------------------------*/
void Instruments::load_inst_header(int size, SFInfo *sf, struct timidity_file *fd)
void Instruments::load_inst_header(int size, SFInfo *sf, timidity_file *fd)
{
int i;
@ -515,7 +515,7 @@ void Instruments::load_inst_header(int size, SFInfo *sf, struct timidity_file *f
* load preset/instrument bag list on the private table
*----------------------------------------------------------------*/
void Instruments::load_bag(int size, SFBags *bagp, struct timidity_file *fd)
void Instruments::load_bag(int size, SFBags *bagp, timidity_file *fd)
{
int i;
@ -533,7 +533,7 @@ void Instruments::load_bag(int size, SFBags *bagp, struct timidity_file *fd)
* load preset/instrument generator list on the private table
*----------------------------------------------------------------*/
void Instruments::load_gen(int size, SFBags *bagp, struct timidity_file *fd)
void Instruments::load_gen(int size, SFBags *bagp, timidity_file *fd)
{
int i;
@ -551,7 +551,7 @@ void Instruments::load_gen(int size, SFBags *bagp, struct timidity_file *fd)
* load sample info list
*----------------------------------------------------------------*/
void Instruments::load_sample_info(int size, SFInfo *sf, struct timidity_file *fd)
void Instruments::load_sample_info(int size, SFInfo *sf, timidity_file *fd)
{
int i;
int in_rom;

View file

@ -248,7 +248,7 @@ static void apply_GeneralInstrumentInfo(int samples, Sample *sample, const Gener
#define SAMPLE_BIG_ENDIAN (1 << 0)
#define SAMPLE_8BIT_UNSIGNED (1 << 1)
static int read_sample_data(int32_t flags, struct timidity_file *tf, int bits, int samples, int frames, sample_t **sdata);
static int read_sample_data(int32_t flags, timidity_file *tf, int bits, int samples, int frames, sample_t **sdata);
/*************** WAV Importer ***************/
@ -269,13 +269,13 @@ typedef struct {
int32_t loop_dwStart, loop_dwEnd, loop_dwFraction;
} WAVSamplerChunk;
static int read_WAVFormatChunk(struct timidity_file *tf, WAVFormatChunk *fmt, int psize);
static int read_WAVSamplerChunk(struct timidity_file *tf, WAVSamplerChunk *smpl, int psize);
static int read_WAVInstrumentChunk(struct timidity_file *tf, GeneralInstrumentInfo *inst, int psize);
static int read_WAVFormatChunk(timidity_file *tf, WAVFormatChunk *fmt, int psize);
static int read_WAVSamplerChunk(timidity_file *tf, WAVSamplerChunk *smpl, int psize);
static int read_WAVInstrumentChunk(timidity_file *tf, GeneralInstrumentInfo *inst, int psize);
int Instruments::import_wave_discriminant(char *sample_file)
{
struct timidity_file *tf;
timidity_file *tf;
char buf[12];
if ((tf = open_file(sample_file, sfreader)) == NULL)
@ -295,7 +295,7 @@ int Instruments::import_wave_discriminant(char *sample_file)
int Instruments::import_wave_load(char *sample_file, Instrument *inst)
{
struct timidity_file *tf;
timidity_file *tf;
union {
int32_t i[3];
char c[12];
@ -424,7 +424,7 @@ int Instruments::import_wave_load(char *sample_file, Instrument *inst)
return (state != 2);
}
static int read_WAVFormatChunk(struct timidity_file *tf, WAVFormatChunk *fmt, int csize)
static int read_WAVFormatChunk(timidity_file *tf, WAVFormatChunk *fmt, int csize)
{
int32_t tmplong;
int16_t tmpshort;
@ -443,7 +443,7 @@ static int read_WAVFormatChunk(struct timidity_file *tf, WAVFormatChunk *fmt, in
return 0;
}
static int read_WAVSamplerChunk(struct timidity_file *tf, WAVSamplerChunk *smpl, int psize)
static int read_WAVSamplerChunk(timidity_file *tf, WAVSamplerChunk *smpl, int psize)
{
int32_t tmplong;
int i, loopCount, cbSamplerData, dwPlayCount;
@ -495,7 +495,7 @@ static int read_WAVSamplerChunk(struct timidity_file *tf, WAVSamplerChunk *smpl,
return 0;
}
static int read_WAVInstrumentChunk(struct timidity_file *tf, GeneralInstrumentInfo *inst, int psize)
static int read_WAVInstrumentChunk(timidity_file *tf, GeneralInstrumentInfo *inst, int psize)
{
int8_t tmpchar;
@ -542,13 +542,13 @@ typedef struct {
uint32_t position;
} AIFFMarkerData;
static int read_AIFFInstumentChunk(struct timidity_file *tf, GeneralInstrumentInfo *inst, AIFFLoopInfo *loop, int csize);
static int read_AIFFMarkerChunk(struct timidity_file *tf, AIFFMarkerData **markers, int csize);
static int read_AIFFInstumentChunk(timidity_file *tf, GeneralInstrumentInfo *inst, AIFFLoopInfo *loop, int csize);
static int read_AIFFMarkerChunk(timidity_file *tf, AIFFMarkerData **markers, int csize);
static int AIFFGetMarkerPosition(int16_t id, const AIFFMarkerData *markers, uint32_t *position);
int Instruments::import_aiff_discriminant(char *sample_file)
{
struct timidity_file *tf;
timidity_file *tf;
char buf[12];
if ((tf = open_file(sample_file, sfreader)) == NULL)
@ -576,7 +576,7 @@ int Instruments::import_aiff_discriminant(char *sample_file)
int Instruments::import_aiff_load(char *sample_file, Instrument *inst)
{
struct timidity_file *tf;
timidity_file *tf;
union {
int32_t i[3];
char c[12];
@ -733,7 +733,7 @@ int Instruments::import_aiff_load(char *sample_file, Instrument *inst)
return 0;
}
int Instruments::read_AIFFCommonChunk(struct timidity_file *tf, AIFFCommonChunk *comm, int csize, int compressed)
int Instruments::read_AIFFCommonChunk(timidity_file *tf, AIFFCommonChunk *comm, int csize, int compressed)
{
int32_t tmplong;
int16_t tmpshort;
@ -775,7 +775,7 @@ int Instruments::import_aiff_load(char *sample_file, Instrument *inst)
return 0;
}
int Instruments::read_AIFFSoundDataChunk(struct timidity_file *tf, AIFFSoundDataChunk *sound, int csize, int mode)
int Instruments::read_AIFFSoundDataChunk(timidity_file *tf, AIFFSoundDataChunk *sound, int csize, int mode)
{
int32_t tmplong;
uint32_t offset, blockSize;
@ -809,7 +809,7 @@ int Instruments::read_AIFFSoundDataChunk(struct timidity_file *tf, AIFFSoundData
return 0;
}
int Instruments::read_AIFFSoundData(struct timidity_file *tf, Instrument *inst, AIFFCommonChunk *common)
int Instruments::read_AIFFSoundData(timidity_file *tf, Instrument *inst, AIFFCommonChunk *common)
{
int i, samples;
Sample *sample;
@ -834,7 +834,7 @@ int Instruments::read_AIFFSoundData(struct timidity_file *tf, Instrument *inst,
return 0;
}
static int read_AIFFInstumentChunk(struct timidity_file *tf, GeneralInstrumentInfo *inst, AIFFLoopInfo *loop, int csize)
static int read_AIFFInstumentChunk(timidity_file *tf, GeneralInstrumentInfo *inst, AIFFLoopInfo *loop, int csize)
{
int8_t tmpchar;
int16_t tmpshort;
@ -867,7 +867,7 @@ static int read_AIFFInstumentChunk(struct timidity_file *tf, GeneralInstrumentIn
return 0;
}
static int read_AIFFMarkerChunk(struct timidity_file *tf, AIFFMarkerData **markers, int csize)
static int read_AIFFMarkerChunk(timidity_file *tf, AIFFMarkerData **markers, int csize)
{
int32_t tmplong;
int16_t tmpshort;
@ -940,7 +940,7 @@ static int AIFFGetMarkerPosition(int16_t id, const AIFFMarkerData *markers, uint
for(j = 0; j < (block_frame_count * (fch)); i++)
#define BLOCK_READ_END } } }
static int read_sample_data(int32_t flags, struct timidity_file *tf, int bits, int channels, int frames, sample_t **sdata)
static int read_sample_data(int32_t flags, timidity_file *tf, int bits, int channels, int frames, sample_t **sdata)
{
int i, block_frame_count;

View file

@ -123,7 +123,7 @@ struct SFOrder {
((int)(((unsigned)bank ^ (unsigned)preset ^ (unsigned)keynote) % INSTHASHSIZE))
struct SFInsts {
struct timidity_file *tf;
timidity_file *tf;
char *fname;
int8_t def_order, def_cutoff_allowed, def_resonance_allowed;
uint16_t version, minorversion;

View file

@ -27,34 +27,37 @@
#include <string>
#include <vector>
#include <stdint.h>
#include "timidity_file.h"
#include "../../music_common/fileio.h"
namespace TimidityPlus
{
inline char* tf_gets(char* buff, int n, struct timidity_file* tf)
using timidity_file = MusicIO::FileInterface;
inline char* tf_gets(char* buff, int n, timidity_file* tf)
{
return tf->gets(buff, n);
}
inline long tf_read(void* buff, int32_t size, int32_t nitems, struct timidity_file* tf)
inline long tf_read(void* buff, int32_t size, int32_t nitems, timidity_file* tf)
{
return (long)tf->read(buff, size, nitems);
}
inline long tf_seek(struct timidity_file* tf, long offset, int whence)
inline long tf_seek(timidity_file* tf, long offset, int whence)
{
return (long)tf->seek(offset, whence);
}
inline long tf_tell(struct timidity_file* tf)
inline long tf_tell(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);
int tf_getc(struct timidity_file *tf);
extern timidity_file *open_file(const char *name, MusicIO::SoundFontReaderInterface *);
extern void tf_close(timidity_file *tf);
extern void skip(timidity_file *tf, size_t len);
int tf_getc(timidity_file *tf);
extern int int_rand(int n); /* random [0..n-1] */
double flt_rand();

View file

@ -30,10 +30,12 @@
#include "sffile.h"
#include "sflayer.h"
#include "sfitem.h"
#include "../../music_common/fileio.h"
namespace TimidityPlus
{
using timidity_file = MusicIO::FileInterface;
enum
{
@ -232,7 +234,7 @@ struct SampleImporter;
class Instruments
{
std::string configFileName;
SoundFontReaderInterface *sfreader;
MusicIO::SoundFontReaderInterface *sfreader;
ToneBank standard_tonebank, standard_drumset;
@ -384,9 +386,9 @@ class Instruments
int import_wave_load(char *sample_file, Instrument *inst);
int import_aiff_discriminant(char *sample_file);
int import_aiff_load(char *sample_file, Instrument *inst);
int read_AIFFCommonChunk(struct timidity_file *tf, AIFFCommonChunk *comm, int csize, int compressed);
int read_AIFFSoundData(struct timidity_file *tf, Instrument *inst, AIFFCommonChunk *common);
int read_AIFFSoundDataChunk(struct timidity_file *tf, AIFFSoundDataChunk *sound, int csize, int mode);
int read_AIFFCommonChunk(timidity_file *tf, AIFFCommonChunk *comm, int csize, int compressed);
int read_AIFFSoundData(timidity_file *tf, Instrument *inst, AIFFCommonChunk *common);
int read_AIFFSoundDataChunk(timidity_file *tf, AIFFSoundDataChunk *sound, int csize, int mode);
// sndfont.cpp
@ -440,20 +442,20 @@ class Instruments
// sffile.cpp
int chunkid(char *id);
int process_list(int size, SFInfo *sf, struct timidity_file *fd);
int process_info(int size, SFInfo *sf, struct timidity_file *fd);
int process_sdta(int size, SFInfo *sf, struct timidity_file *fd);
int process_pdta(int size, SFInfo *sf, struct timidity_file *fd);
void load_sample_names(int size, SFInfo *sf, struct timidity_file *fd);
void load_preset_header(int size, SFInfo *sf, struct timidity_file *fd);
void load_inst_header(int size, SFInfo *sf, struct timidity_file *fd);
void load_bag(int size, SFBags *bagp, struct timidity_file *fd);
void load_gen(int size, SFBags *bagp, struct timidity_file *fd);
void load_sample_info(int size, SFInfo *sf, struct timidity_file *fd);
int process_list(int size, SFInfo *sf, timidity_file *fd);
int process_info(int size, SFInfo *sf, timidity_file *fd);
int process_sdta(int size, SFInfo *sf, timidity_file *fd);
int process_pdta(int size, SFInfo *sf, timidity_file *fd);
void load_sample_names(int size, SFInfo *sf, timidity_file *fd);
void load_preset_header(int size, SFInfo *sf, timidity_file *fd);
void load_inst_header(int size, SFInfo *sf, timidity_file *fd);
void load_bag(int size, SFBags *bagp, timidity_file *fd);
void load_gen(int size, SFBags *bagp, timidity_file *fd);
void load_sample_info(int size, SFInfo *sf, timidity_file *fd);
void convert_layers(SFInfo *sf);
void generate_layers(SFHeader *hdr, SFHeader *next, SFBags *bags);
void free_layer(SFHeader *hdr);
int load_soundfont(SFInfo *sf, struct timidity_file *fd);
int load_soundfont(SFInfo *sf, timidity_file *fd);
void free_soundfont(SFInfo *sf);
void correct_samples(SFInfo *sf);
@ -461,7 +463,7 @@ class Instruments
public:
Instruments();
bool load(SoundFontReaderInterface *);
bool load(MusicIO::SoundFontReaderInterface *);
~Instruments();
const ToneBank *toneBank(int i) const

View file

@ -1,140 +0,0 @@
/*
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;
virtual void close() = 0;
};
class SoundFontReaderInterface
{
public:
virtual ~SoundFontReaderInterface() {}
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);
}
void close()
{
if (f) fclose(f);
delete this;
}
};
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

@ -39,7 +39,6 @@
#include "wm_error.h"
#include "file_io.h"
#include "wildmidi_file.h"
namespace WildMidi
@ -47,9 +46,9 @@ namespace WildMidi
static const int WM_MAXFILESIZE = 0x1fffffff;
unsigned char *_WM_BufferFile(SoundFontReaderInterface *reader, const char *filename, unsigned long int *size, std::string *fullname)
unsigned char *_WM_BufferFile(MusicIO::SoundFontReaderInterface *reader, const char *filename, unsigned long int *size, std::string *fullname)
{
auto fp = reader->open_wildmidi_file(filename);
auto fp = reader->open_file(filename);
if (!fp)
{

View file

@ -27,11 +27,11 @@
#ifndef __FILE_IO_H
#define __FILE_IO_H
#include "wildmidi_file.h"
#include "../../music_common/fileio.h"
namespace WildMidi
{
unsigned char *_WM_BufferFile(SoundFontReaderInterface *reader, const char *filename, unsigned long int *size, std::string *fullname = nullptr);
unsigned char *_WM_BufferFile(MusicIO::SoundFontReaderInterface *reader, const char *filename, unsigned long int *size, std::string *fullname = nullptr);
}
#endif /* __FILE_IO_H */

View file

@ -1,146 +0,0 @@
/*
wildmidi_file.h
Midi Wavetable Processing library
Copyright (C) 2019 Christoph Oelckers
WildMIDI is free software: you can redistribute and/or modify the player
under the terms of the GNU General Public License and you can redistribute
and/or modify the library under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, either version 3 of
the licenses, or(at your option) any later version.
WildMIDI 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 and
the GNU Lesser General Public License for more details.
You should have received a copy of the GNU General Public License and the
GNU Lesser General Public License along with WildMIDI. If not, see
<http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdio.h>
#include <vector>
#include <string>
namespace WildMidi
{
struct wildmidi_file
{
std::string filename;
virtual ~wildmidi_file() {}
virtual char* gets(char* buff, int n) = 0;
virtual long read(void* buff, int32_t size, int32_t nitems) = 0;
long read(void* buff, int32_t size) { return read(buff, 1, size); }
virtual long seek(long offset, int whence) = 0;
virtual long tell() = 0;
virtual void close() = 0;
};
class SoundFontReaderInterface
{
public:
virtual ~SoundFontReaderInterface() {}
virtual struct wildmidi_file* open_wildmidi_file(const char* fn) = 0;
virtual void wildmidi_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 wildmidi_file_FILE : public wildmidi_file
{
FILE* f = nullptr;
~wildmidi_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);
}
void close()
{
if (f) fclose(f);
delete this;
}
};
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 wildmidi_file* open_wildmidi_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 wildmidi_file_FILE;
tf->f = f;
tf->filename = fullname;
return tf;
}
void wildmidi_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

@ -27,6 +27,8 @@
#ifndef WILDMIDI_LIB_H
#define WILDMIDI_LIB_H
#include "../../music_common/fileio.h"
namespace WildMidi
{
enum EMixerOptions
@ -55,7 +57,7 @@ typedef void midi;
struct Instruments
{
SoundFontReaderInterface *sfreader;
MusicIO::SoundFontReaderInterface *sfreader;
struct _patch *patch[128] = {};
float reverb_room_width = 16.875f;
@ -70,7 +72,7 @@ struct Instruments
unsigned short int _WM_SampleRate; // WildMidi makes the sample rate a property of the patches, not the renderer. Meaning that the instruments need to be reloaded when it changes... :?
Instruments(SoundFontReaderInterface *reader, int samplerate)
Instruments(MusicIO::SoundFontReaderInterface *reader, int samplerate)
{
sfreader = reader;
_WM_SampleRate = samplerate;

View file

@ -38,8 +38,7 @@
#include "timidity/timidity.h"
#include "timidity/playmidi.h"
#include "timidity/instrum.h"
#define USE_BASE_INTERFACE
#include "timidity/timidity_file.h"
#include "../../music_common/fileio.h"
// MACROS ------------------------------------------------------------------
@ -96,16 +95,16 @@ void TimidityMIDIDevice::LoadInstruments(GUSConfig *config)
std::string ultradir = getenv("ULTRADIR");
if (ultradir.length() || config->gus_patchdir.length() != 0)
{
auto psreader = new Timidity::BaseSoundFontReader;
auto psreader = new MusicIO::FileSystemSoundFontReader("");
// The GUS put its patches in %ULTRADIR%/MIDI so we can try that
if (ultradir.length())
{
ultradir += "/midi";
psreader->timidity_add_path(ultradir.c_str());
psreader->add_search_path(ultradir.c_str());
}
// Load DMXGUS lump and patches from gus_patchdir
if (config->gus_patchdir.length() != 0) psreader->timidity_add_path(config->gus_patchdir.c_str());
if (config->gus_patchdir.length() != 0) psreader->add_search_path(config->gus_patchdir.c_str());
config->instruments.reset(new Timidity::Instruments(psreader));
bool success = config->instruments->LoadDMXGUS(config->gus_memsize, (const char*)config->dmxgus.data(), config->dmxgus.size()) >= 0;

View file

@ -37,6 +37,7 @@
#include "mididevice.h"
#include "zmusic/m_swap.h"
#include "../music_common/fileio.h"
#include <errno.h>
// MACROS ------------------------------------------------------------------
@ -75,28 +76,6 @@ struct FmtChunk
// PUBLIC DATA DEFINITIONS -------------------------------------------------
// CODE --------------------------------------------------------------------
#ifdef _WIN32
// I'd rather not include Windows.h for just this.
extern "C" __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned CodePage, unsigned long dwFlags, const char* lpMultiByteStr, int cbMultiByte, const wchar_t* lpWideCharStr, int cchWideChar);
#endif
static FILE* my_fopen(const char* filename)
{
#ifndef _WIN32
return fopen(filename, "wb");
#else
// This is supposed to handle UTF-8 which Windows does not support with fopen. :(
const int CP_UTF8 = 65001;
std::wstring filePathW;
auto len = strlen(filename);
filePathW.resize(len);
int newSize = MultiByteToWideChar(CP_UTF8, 0, filename, (int)len, const_cast<wchar_t*>(filePathW.c_str()), (int)len);
filePathW.resize(newSize);
return _wfopen(filePathW.c_str(), L"wb");
#endif
}
//==========================================================================
//
@ -107,7 +86,7 @@ static FILE* my_fopen(const char* filename)
MIDIWaveWriter::MIDIWaveWriter(const char *filename, SoftSynthMIDIDevice *playdevice)
: SoftSynthMIDIDevice(playdevice->GetSampleRate())
{
File = my_fopen(filename);
File = MusicIO::utf8_fopen(filename, "wt");
playDevice = playdevice;
if (File != nullptr)
{ // Write wave header

View file

@ -3,6 +3,7 @@
#include <string>
#include <vector>
#include <memory>
#include "../../libraries/music_common/fileio.h"
struct ADLConfig
{
@ -68,7 +69,7 @@ struct GUSConfig
int gus_memsize = 0;
void (*errorfunc)(int type, int verbosity_level, const char* fmt, ...) = nullptr;
Timidity::SoundFontReaderInterface *reader;
MusicIO::SoundFontReaderInterface *reader;
std::string readerName;
std::vector<uint8_t> dmxgus; // can contain the contents of a DMXGUS lump that may be used as the instrument set. In this case gus_patchdir must point to the location of the GUS data.
std::string gus_patchdir;
@ -90,7 +91,7 @@ struct TimidityConfig
{
void (*errorfunc)(int type, int verbosity_level, const char* fmt, ...) = nullptr;
TimidityPlus::SoundFontReaderInterface* reader;
MusicIO::SoundFontReaderInterface* reader;
std::string readerName;
// These next two fields are for caching the instruments for repeated use. The GUS device will work without them being cached in the config but it'd require reloading the instruments each time.
@ -113,7 +114,7 @@ struct WildMidiConfig
bool enhanced_resampling = true;
void (*errorfunc)(const char* wmfmt, va_list args) = nullptr;
WildMidi::SoundFontReaderInterface* reader;
MusicIO::SoundFontReaderInterface* reader;
std::string readerName;
// These next two fields are for caching the instruments for repeated use. The GUS device will work without them being cached in the config but it'd require reloading the instruments each time.

View file

@ -50,38 +50,6 @@
FSoundFontManager sfmanager;
template<class base>
struct file_interface : public base
{
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();
}
void close()
{
delete this;
}
};
//==========================================================================
//
// returns both a file reader and the full name of the looked up file
@ -166,42 +134,29 @@ FileReader FSoundFontReader::Open(const char *name, std::string& filename)
//
//==========================================================================
template<class interface>
interface* FSoundFontReader::open_interface(const char* name)
MusicIO::FileInterface* FSoundFontReader::open_interface(const char* name)
{
std::string filename;
FileReader fr = Open(name, filename);
if (!fr.isOpen()) return nullptr;
auto tf = new file_interface<interface>;
tf->fr = std::move(fr);
tf->filename = std::move(filename);
return tf;
auto fri = new FileReaderMusicInterface(fr);
fri->filename = std::move(filename);
return fri;
}
//==========================================================================
//
// The file interfaces for the different MIDI renderers
// They are all the same except for the class names.
// The file interface for the backend
//
//==========================================================================
struct TimidityPlus::timidity_file* FSoundFontReader::open_timidityplus_file(const char* name)
struct MusicIO::FileInterface* FSoundFontReader::open_file(const char* name)
{
return open_interface<TimidityPlus::timidity_file>(name);
return open_interface(name);
}
struct Timidity::timidity_file* FSoundFontReader::open_timidity_file(const char* name)
{
return open_interface<Timidity::timidity_file>(name);
}
struct WildMidi::wildmidi_file* FSoundFontReader::open_wildmidi_file(const char* name)
{
return open_interface<WildMidi::wildmidi_file>(name);
}
//==========================================================================
//
@ -323,16 +278,9 @@ FPatchSetReader::FPatchSetReader(const char *filename)
}
}
FPatchSetReader::FPatchSetReader(FileReader &reader)
{
// This constructor is for reading DMXGUS
mAllowAbsolutePaths = true;
dmxgus = std::move(reader);
}
FileReader FPatchSetReader::OpenMainConfigFile()
{
if (dmxgus.isOpen()) return std::move(dmxgus);
FileReader fr;
fr.OpenFile(mFullPathToConfig);
return fr;

View file

@ -3,9 +3,7 @@
#include "doomtype.h"
#include "w_wad.h"
#include "files.h"
#include "../libraries/timidityplus/timiditypp/timidity_file.h"
#include "../libraries/timidity/timidity/timidity_file.h"
#include "../libraries/wildmidi/wildmidi/wildmidi_file.h"
#include "../libraries/music_common/fileio.h"
enum
{
@ -23,13 +21,48 @@ struct FSoundFontInfo
int type;
};
struct FileReaderMusicInterface : public MusicIO::FileInterface
{
FileReader fr;
FileReaderMusicInterface(FileReader& fr_in)
{
fr = std::move(fr_in);
}
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();
}
void close()
{
delete this;
}
};
//==========================================================================
//
//
//
//==========================================================================
class FSoundFontReader : public TimidityPlus::SoundFontReaderInterface, public Timidity::SoundFontReaderInterface, public WildMidi::SoundFontReaderInterface
class FSoundFontReader : public MusicIO::SoundFontReaderInterface
// Yes, it's 3 copies of essentially the same interface, but since we want to keep the 3 renderers as isolated modules we have to pull in their own implementations here.
{
protected:
@ -64,28 +97,13 @@ public:
virtual FileReader Open(const char* name, std::string &filename);
// Timidity++ interface
struct TimidityPlus::timidity_file* open_timidityplus_file(const char* name) override;
void timidityplus_add_path(const char* name) override
struct MusicIO::FileInterface* open_file(const char* name) override;
void add_search_path(const char* name) override
{
return AddPath(name);
}
// Timidity(GUS) interface - essentially the same but different namespace
virtual struct Timidity::timidity_file* open_timidity_file(const char* name) override;
virtual void timidity_add_path(const char* name) override
{
return AddPath(name);
}
// WildMidi interface - essentially the same again but yet another namespace
virtual struct WildMidi::wildmidi_file* open_wildmidi_file(const char* name) override;
virtual void wildmidi_add_path(const char* name) override
{
return AddPath(name);
}
template<class interface>
interface* open_interface(const char* name);
MusicIO::FileInterface* open_interface(const char* name);
};
@ -154,7 +172,6 @@ class FPatchSetReader : public FSoundFontReader
{
FString mBasePath;
FString mFullPathToConfig;
FileReader dmxgus;
public:
FPatchSetReader(FileReader &reader);

View file

@ -31,6 +31,13 @@
**
*/
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#endif
#include "i_musicinterns.h"
#include "c_dispatch.h"