From 7468c0f36df150d4c1735e5cacce79f78875ea55 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 28 Sep 2019 23:17:16 +0200 Subject: [PATCH] - 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.) --- libraries/music_common/fileio.h | 338 ++++++++++++++++++ libraries/timidity/instrum.cpp | 9 +- libraries/timidity/instrum_font.cpp | 3 +- libraries/timidity/instrum_sf2.cpp | 3 +- libraries/timidity/timidity.cpp | 5 +- libraries/timidity/timidity/instrum.h | 7 +- libraries/timidity/timidity/sf2.h | 5 +- libraries/timidity/timidity/timidity.h | 4 +- libraries/timidity/timidity/timidity_file.h | 142 -------- libraries/timidityplus/common.cpp | 10 +- libraries/timidityplus/configfile.cpp | 4 +- libraries/timidityplus/instrum.cpp | 5 +- libraries/timidityplus/sffile.cpp | 30 +- libraries/timidityplus/smplfile.cpp | 38 +- libraries/timidityplus/sndfont.cpp | 2 +- libraries/timidityplus/timiditypp/common.h | 21 +- libraries/timidityplus/timiditypp/instrum.h | 34 +- .../timidityplus/timiditypp/timidity_file.h | 140 -------- libraries/wildmidi/file_io.cpp | 5 +- libraries/wildmidi/wildmidi/file_io.h | 4 +- libraries/wildmidi/wildmidi/wildmidi_file.h | 146 -------- libraries/wildmidi/wildmidi/wildmidi_lib.h | 6 +- .../mididevices/music_timidity_mididevice.cpp | 9 +- .../music_wavewriter_mididevice.cpp | 25 +- libraries/zmusic/zmusic/midiconfig.h | 7 +- src/sound/music/i_soundfont.cpp | 66 +--- src/sound/music/i_soundfont.h | 63 ++-- src/sound/music/music_midi_base.cpp | 7 + 28 files changed, 504 insertions(+), 634 deletions(-) create mode 100644 libraries/music_common/fileio.h delete mode 100644 libraries/timidity/timidity/timidity_file.h delete mode 100644 libraries/timidityplus/timiditypp/timidity_file.h delete mode 100644 libraries/wildmidi/wildmidi/wildmidi_file.h diff --git a/libraries/music_common/fileio.h b/libraries/music_common/fileio.h new file mode 100644 index 000000000..74d6672fa --- /dev/null +++ b/libraries/music_common/fileio.h @@ -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 +#include +#include + +#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(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 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); + } +}; + + + +} \ No newline at end of file diff --git a/libraries/timidity/instrum.cpp b/libraries/timidity/instrum.cpp index 35d8ee580..bd6224cc4 100644 --- a/libraries/timidity/instrum.cpp +++ b/libraries/timidity/instrum.cpp @@ -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; diff --git a/libraries/timidity/instrum_font.cpp b/libraries/timidity/instrum_font.cpp index cddaf41c9..2bbe8d8b3 100644 --- a/libraries/timidity/instrum_font.cpp +++ b/libraries/timidity/instrum_font.cpp @@ -3,7 +3,6 @@ #include #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) { diff --git a/libraries/timidity/instrum_sf2.cpp b/libraries/timidity/instrum_sf2.cpp index b3a2121a0..555106196 100644 --- a/libraries/timidity/instrum_sf2.cpp +++ b/libraries/timidity/instrum_sf2.cpp @@ -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) diff --git a/libraries/timidity/timidity.cpp b/libraries/timidity/timidity.cpp index 7224cf609..1608dd92e 100644 --- a/libraries/timidity/timidity.cpp +++ b/libraries/timidity/timidity.cpp @@ -28,7 +28,6 @@ #include #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")) diff --git a/libraries/timidity/timidity/instrum.h b/libraries/timidity/timidity/instrum.h index c8c806abc..b3fe93140 100644 --- a/libraries/timidity/timidity/instrum.h +++ b/libraries/timidity/timidity/instrum.h @@ -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); } diff --git a/libraries/timidity/timidity/sf2.h b/libraries/timidity/timidity/sf2.h index 2f161cda9..6a781d923 100644 --- a/libraries/timidity/timidity/sf2.h +++ b/libraries/timidity/timidity/sf2.h @@ -1,9 +1,12 @@ #pragma once #include +#include "../../music_common/fileio.h" + namespace Timidity { typedef uint16_t SFGenerator; -struct timidity_file; + +using timidity_file = MusicIO::FileInterface; struct SFRange { diff --git a/libraries/timidity/timidity/timidity.h b/libraries/timidity/timidity/timidity.h index 6215bd2e0..877d2d419 100644 --- a/libraries/timidity/timidity/timidity.h +++ b/libraries/timidity/timidity/timidity.h @@ -22,11 +22,11 @@ #include #include -#include "timidity_file.h" +#include "../../music_common/fileio.h" namespace Timidity { - struct timidity_file; + using timidity_file = MusicIO::FileInterface; /* diff --git a/libraries/timidity/timidity/timidity_file.h b/libraries/timidity/timidity/timidity_file.h deleted file mode 100644 index f9b111631..000000000 --- a/libraries/timidity/timidity/timidity_file.h +++ /dev/null @@ -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 -#include -#include - -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 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 - -} diff --git a/libraries/timidityplus/common.cpp b/libraries/timidityplus/common.cpp index 0f5cdc4f0..ce275c16b 100644 --- a/libraries/timidityplus/common.cpp +++ b/libraries/timidityplus/common.cpp @@ -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); diff --git a/libraries/timidityplus/configfile.cpp b/libraries/timidityplus/configfile.cpp index fbb852dd5..1fc0cb941 100644 --- a/libraries/timidityplus/configfile.cpp +++ b/libraries/timidityplus/configfile.cpp @@ -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")) { diff --git a/libraries/timidityplus/instrum.cpp b/libraries/timidityplus/instrum.cpp index b4566a5ba..b133af280 100644 --- a/libraries/timidityplus/instrum.cpp +++ b/libraries/timidityplus/instrum.cpp @@ -27,6 +27,7 @@ #include #include +#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; diff --git a/libraries/timidityplus/sffile.cpp b/libraries/timidityplus/sffile.cpp index 7fadad3e7..254f0bfac 100644 --- a/libraries/timidityplus/sffile.cpp +++ b/libraries/timidityplus/sffile.cpp @@ -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; diff --git a/libraries/timidityplus/smplfile.cpp b/libraries/timidityplus/smplfile.cpp index e3b96650b..2480dd450 100644 --- a/libraries/timidityplus/smplfile.cpp +++ b/libraries/timidityplus/smplfile.cpp @@ -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; diff --git a/libraries/timidityplus/sndfont.cpp b/libraries/timidityplus/sndfont.cpp index 60e577c52..13223efca 100644 --- a/libraries/timidityplus/sndfont.cpp +++ b/libraries/timidityplus/sndfont.cpp @@ -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; diff --git a/libraries/timidityplus/timiditypp/common.h b/libraries/timidityplus/timiditypp/common.h index a999f5041..1c6116b7c 100644 --- a/libraries/timidityplus/timiditypp/common.h +++ b/libraries/timidityplus/timiditypp/common.h @@ -27,34 +27,37 @@ #include #include #include -#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(); diff --git a/libraries/timidityplus/timiditypp/instrum.h b/libraries/timidityplus/timiditypp/instrum.h index 6b96a0a3a..b09a7b0f1 100644 --- a/libraries/timidityplus/timiditypp/instrum.h +++ b/libraries/timidityplus/timiditypp/instrum.h @@ -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 diff --git a/libraries/timidityplus/timiditypp/timidity_file.h b/libraries/timidityplus/timiditypp/timidity_file.h deleted file mode 100644 index 38c085635..000000000 --- a/libraries/timidityplus/timiditypp/timidity_file.h +++ /dev/null @@ -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 -#include -#include - -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 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 - -} diff --git a/libraries/wildmidi/file_io.cpp b/libraries/wildmidi/file_io.cpp index ebdfc5f46..ac7dfac15 100644 --- a/libraries/wildmidi/file_io.cpp +++ b/libraries/wildmidi/file_io.cpp @@ -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) { diff --git a/libraries/wildmidi/wildmidi/file_io.h b/libraries/wildmidi/wildmidi/file_io.h index 01fb6260e..84971c310 100644 --- a/libraries/wildmidi/wildmidi/file_io.h +++ b/libraries/wildmidi/wildmidi/file_io.h @@ -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 */ diff --git a/libraries/wildmidi/wildmidi/wildmidi_file.h b/libraries/wildmidi/wildmidi/wildmidi_file.h deleted file mode 100644 index aae9c98c1..000000000 --- a/libraries/wildmidi/wildmidi/wildmidi_file.h +++ /dev/null @@ -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 - . - */ - -#pragma once -#include -#include -#include - -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 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 - -} - diff --git a/libraries/wildmidi/wildmidi/wildmidi_lib.h b/libraries/wildmidi/wildmidi/wildmidi_lib.h index 4737bafbe..39c544a9d 100644 --- a/libraries/wildmidi/wildmidi/wildmidi_lib.h +++ b/libraries/wildmidi/wildmidi/wildmidi_lib.h @@ -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; diff --git a/libraries/zmusic/mididevices/music_timidity_mididevice.cpp b/libraries/zmusic/mididevices/music_timidity_mididevice.cpp index 7d718f8c6..f56aa0651 100644 --- a/libraries/zmusic/mididevices/music_timidity_mididevice.cpp +++ b/libraries/zmusic/mididevices/music_timidity_mididevice.cpp @@ -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; diff --git a/libraries/zmusic/mididevices/music_wavewriter_mididevice.cpp b/libraries/zmusic/mididevices/music_wavewriter_mididevice.cpp index 17066cbce..fcb0caf13 100644 --- a/libraries/zmusic/mididevices/music_wavewriter_mididevice.cpp +++ b/libraries/zmusic/mididevices/music_wavewriter_mididevice.cpp @@ -37,6 +37,7 @@ #include "mididevice.h" #include "zmusic/m_swap.h" +#include "../music_common/fileio.h" #include // 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(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 diff --git a/libraries/zmusic/zmusic/midiconfig.h b/libraries/zmusic/zmusic/midiconfig.h index 2f61c7baf..b49dbac0a 100644 --- a/libraries/zmusic/zmusic/midiconfig.h +++ b/libraries/zmusic/zmusic/midiconfig.h @@ -3,6 +3,7 @@ #include #include #include +#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 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. diff --git a/src/sound/music/i_soundfont.cpp b/src/sound/music/i_soundfont.cpp index d6b4ac065..feb378437 100644 --- a/src/sound/music/i_soundfont.cpp +++ b/src/sound/music/i_soundfont.cpp @@ -50,38 +50,6 @@ FSoundFontManager sfmanager; -template -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 -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; - 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(name); + return open_interface(name); } -struct Timidity::timidity_file* FSoundFontReader::open_timidity_file(const char* name) -{ - return open_interface(name); -} - -struct WildMidi::wildmidi_file* FSoundFontReader::open_wildmidi_file(const char* name) -{ - return open_interface(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; diff --git a/src/sound/music/i_soundfont.h b/src/sound/music/i_soundfont.h index a214801d1..d53418873 100644 --- a/src/sound/music/i_soundfont.h +++ b/src/sound/music/i_soundfont.h @@ -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 - 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); diff --git a/src/sound/music/music_midi_base.cpp b/src/sound/music/music_midi_base.cpp index 13e2d5584..6ecdb5b47 100644 --- a/src/sound/music/music_midi_base.cpp +++ b/src/sound/music/music_midi_base.cpp @@ -31,6 +31,13 @@ ** */ +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#include +#include +#endif + #include "i_musicinterns.h" #include "c_dispatch.h"