- something can be heard.

This doesn't pipe the audio through OpenAL yet but the fundamentals for further progress are done.
This commit is contained in:
Christoph Oelckers 2018-02-20 20:50:01 +01:00
parent 5ce3b00b90
commit a8283ffdd6
8 changed files with 73 additions and 64 deletions

View file

@ -44,11 +44,15 @@
#include "version.h" #include "version.h"
#include "tmpfileplus.h" #include "tmpfileplus.h"
#include "m_misc.h" #include "m_misc.h"
#include "v_text.h"
#include "timiditypp/timidity.h"
#include "timiditypp/instrum.h"
class TimidityPPMIDIDevice : public SoftSynthMIDIDevice class TimidityPPMIDIDevice : public SoftSynthMIDIDevice
{ {
TArray<uint8_t> midi; TArray<uint8_t> midi;
FString CurrentConfig; static TimidityPlus::Instruments *instruments;
public: public:
TimidityPPMIDIDevice(const char *args); TimidityPPMIDIDevice(const char *args);
~TimidityPPMIDIDevice(); ~TimidityPPMIDIDevice();
@ -67,9 +71,10 @@ protected:
void HandleLongEvent(const uint8_t *data, int len); void HandleLongEvent(const uint8_t *data, int len);
void ComputeOutput(float *buffer, int len); void ComputeOutput(float *buffer, int len);
}; };
TimidityPlus::Instruments *TimidityPPMIDIDevice::instruments;
// Config file to use // Config file to use
CVAR(String, timidity_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(String, timidity_config, "timidity.cfg", CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
// added because Timidity's output is rather loud. // added because Timidity's output is rather loud.
CUSTOM_CVAR (Float, timidity_mastervolume, 1.0f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CUSTOM_CVAR (Float, timidity_mastervolume, 1.0f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
@ -101,14 +106,19 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args)
{ {
if (args == NULL || *args == 0) args = timidity_config; if (args == NULL || *args == 0) args = timidity_config;
if (CurrentConfig.CompareNoCase(args) != 0) if (instruments != nullptr && !instruments->checkConfig(args))
{ {
// reload instruments delete instruments;
// if (!reload_inst()) CurrentConfig = "";
} }
if (CurrentConfig.IsNotEmpty()) instruments = new TimidityPlus::Instruments;
if (!instruments->load(args))
{ {
//Renderer = new TimidityPlus::Player(timidity_frequency, args); delete instruments;
instruments = nullptr;
}
if (instruments != nullptr)
{
//Renderer = new TimidityPlus::Player(timidity_frequency, instruments);
} }
} }
@ -136,11 +146,19 @@ TimidityPPMIDIDevice::~TimidityPPMIDIDevice ()
// //
//========================================================================== //==========================================================================
namespace TimidityPlus
{
int load_midi_file(FileReader *fr, TimidityPlus::Instruments *inst);
void run_midi(int samples);
void timidity_close();
}
bool TimidityPPMIDIDevice::Preprocess(MIDIStreamer *song, bool looping) bool TimidityPPMIDIDevice::Preprocess(MIDIStreamer *song, bool looping)
{ {
// Write MIDI song to temporary file // Write MIDI song to temporary file
song->CreateSMF(midi, looping ? 0 : 1); song->CreateSMF(midi, looping ? 0 : 1);
return midi.Size() > 0; MemoryReader fr((char*)&midi[0], midi.Size());
return !TimidityPlus::load_midi_file(&fr, instruments);
} }
//========================================================================== //==========================================================================
@ -148,21 +166,16 @@ bool TimidityPPMIDIDevice::Preprocess(MIDIStreamer *song, bool looping)
// TimidityPPMIDIDevice :: Open // TimidityPPMIDIDevice :: Open
// //
//========================================================================== //==========================================================================
namespace TimidityPlus
{
int load_midi_file(FileReader *fr);
void run_midi(int samples);
void timidity_close();
}
int TimidityPPMIDIDevice::Open(MidiCallback callback, void *userdata) int TimidityPPMIDIDevice::Open(MidiCallback callback, void *userdata)
{ {
// No instruments loaded means we cannot play...
if (instruments == nullptr) return 0;
int ret = OpenStream(2, 0, callback, userdata); int ret = OpenStream(2, 0, callback, userdata);
if (ret == 0) if (ret == 0)
{ {
//Renderer->Reset(); //Renderer->Reset();
MemoryReader fr((char*)&midi[0], midi.Size());
return !TimidityPlus::load_midi_file(&fr);
} }
return ret; return ret;
} }
@ -217,8 +230,10 @@ void TimidityPPMIDIDevice::HandleLongEvent(const uint8_t *data, int len)
void TimidityPPMIDIDevice::ComputeOutput(float *buffer, int len) void TimidityPPMIDIDevice::ComputeOutput(float *buffer, int len)
{ {
Printf("Committing slice\n");
TimidityPlus::run_midi(len / 8); // bytes to samples TimidityPlus::run_midi(len / 8); // bytes to samples
memset(buffer, len, 0); // to do memset(buffer, len, 0); // to do
Printf("Done\n");
//Renderer->ComputeOutput(buffer, len); //Renderer->ComputeOutput(buffer, len);
} }
@ -242,3 +257,30 @@ MIDIDevice *CreateTimidityPPMIDIDevice(const char *args)
{ {
return new TimidityPPMIDIDevice(args); return new TimidityPPMIDIDevice(args);
} }
void TimidityPlus::ctl_cmsg(int type, int verbosity_level, const char *fmt, ...)
{
if (verbosity_level >= VERB_DEBUG) return; // Don't waste time on diagnostics.
va_list args;
va_start(args, fmt);
FString msg;
msg.VFormat(fmt, args);
va_end(args);
switch (type)
{
case CMSG_ERROR:
Printf(TEXTCOLOR_RED "%s\n", msg.GetChars());
break;
case CMSG_WARNING:
Printf(TEXTCOLOR_YELLOW "%s\n", msg.GetChars());
break;
case CMSG_INFO:
DPrintf(DMSG_SPAMMY, "%s\n", msg.GetChars());
break;
}
}

View file

@ -134,7 +134,6 @@ double flt_rand()
PathList::PathList() PathList::PathList()
{ {
paths.push_back("./");
} }
/* This adds a directory to the path list */ /* This adds a directory to the path list */
@ -234,9 +233,11 @@ std::pair<FileReader *, std::string> PathList::openFile(const char *name, bool i
s += '/'; s += '/';
} }
s += name; s += name;
auto fr = tryOpenPath(name, ismainfile); auto fr = tryOpenPath(s.c_str(), ismainfile);
if (fr!= nullptr) return std::make_pair(fr, s); if (fr!= nullptr) return std::make_pair(fr, s);
} }
auto fr = tryOpenPath(name, ismainfile);
if (fr != nullptr) return std::make_pair(fr, name);
} }
else else
{ {
@ -254,13 +255,11 @@ std::pair<FileReader *, std::string> PathList::openFile(const char *name, bool i
int PathList::isAbsPath(const char *name) int PathList::isAbsPath(const char *name)
{ {
if (name[0] == '/') if (name[0] == '/') return 1;
return 1;
#ifdef _WIN32 #ifdef _WIN32
/* [A-Za-z]: (for Windows) */ /* [A-Za-z]: (for Windows) */
if (isalpha(name[0]) && name[1] == ':') if (isalpha(name[0]) && name[1] == ':') return 1;
return 1;
#endif /* _WIN32 */ #endif /* _WIN32 */
return 0; return 0;
} }

View file

@ -29,6 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "common.h" #include "common.h"
#include "instrum.h" #include "instrum.h"
#include "quantity.h" #include "quantity.h"
#include "cmdlib.h"
@ -646,6 +647,7 @@ int Instruments::read_config_file(const char *name, int self, int allow_missing_
if (!self) if (!self)
{ {
basedir = strdup_mblock(&varbuf, tf->filename.c_str()); basedir = strdup_mblock(&varbuf, tf->filename.c_str());
FixPathSeperator((char*)basedir);
sep = (char*)strrchr(basedir, '/'); sep = (char*)strrchr(basedir, '/');
} }
else else

View file

@ -51,27 +51,8 @@ inline bool RC_IS_SKIP_FILE(int rc)
return ((rc) == RC_QUIT || (rc) == RC_ERROR || (rc) == RC_STOP || (rc) == RC_TUNE_END); return ((rc) == RC_QUIT || (rc) == RC_ERROR || (rc) == RC_STOP || (rc) == RC_TUNE_END);
} }
inline void ctl_cmsg(int type, int verbosity_level, const char *fmt, ...)
{
/* todo:
CMSG_ERROR: I_Error(...)
CMSG_WARNING, VERB_NORMAL: Printf(TEXTCOLOR_YELLOW
CMSG_WARNING, VERB_VERBOSE: DPrintf(DMSG_SPAMMY
void ctl_cmsg(int type, int verbosity_level, const char *fmt, ...);
CMSG_INFO, VERB_DEBUG/VERB_NOISY: ignore
/*
#ifdef _WIN32
char buf[1024];
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
I_DebugPrint(buf);
#endif
*/
}
} }

View file

@ -54,7 +54,7 @@ Instruments::Instruments()
bool Instruments::load(const char *config) bool Instruments::load(const char *config)
{ {
if (read_config_file(config, 0, 0, true)) if (read_config_file(config, 0, 0, true) == RC_OK)
{ {
init_load_soundfont(); init_load_soundfont();
set_default_instrument(); set_default_instrument();
@ -617,13 +617,10 @@ Instrument *Instruments::load_gus_instrument(char *name, ToneBank *bank, int dr,
} }
/* Open patch file */ /* Open patch file */
if (!(tf = open_file(name, false, pathlist))) { if (!(tf = open_file(name, false, pathlist))) {
#ifdef PATCH_EXT_LIST
int name_len, ext_len; int name_len, ext_len;
static const char *patch_ext[] = PATCH_EXT_LIST; static const char *patch_ext[] = { ".pat", 0 };
#endif
noluck = 1; noluck = 1;
#ifdef PATCH_EXT_LIST
name_len = (int)strlen(name); name_len = (int)strlen(name);
/* Try with various extensions */ /* Try with various extensions */
for (i = 0; patch_ext[i]; i++) { for (i = 0; patch_ext[i]; i++) {
@ -641,7 +638,6 @@ Instrument *Instruments::load_gus_instrument(char *name, ToneBank *bank, int dr,
} }
} }
} }
#endif
} }
if (noluck) { if (noluck) {
ctl_cmsg(CMSG_ERROR, VERB_NORMAL, ctl_cmsg(CMSG_ERROR, VERB_NORMAL,

View file

@ -1855,6 +1855,7 @@ void Player::finish_note(int i)
void Player::set_envelope_time(int ch, int val, int stage) void Player::set_envelope_time(int ch, int val, int stage)
{ {
val = val & 0x7F; val = val & 0x7F;
#if 0
switch(stage) { switch(stage) {
case EG_ATTACK: /* Attack */ case EG_ATTACK: /* Attack */
//ctl_cmsg(CMSG_INFO,VERB_NOISY,"Attack Time (CH:%d VALUE:%d)", ch, val); //ctl_cmsg(CMSG_INFO,VERB_NOISY,"Attack Time (CH:%d VALUE:%d)", ch, val);
@ -1868,6 +1869,7 @@ void Player::set_envelope_time(int ch, int val, int stage)
default: default:
//ctl_cmsg(CMSG_INFO,VERB_NOISY,"? Time (CH:%d VALUE:%d)", ch, val); //ctl_cmsg(CMSG_INFO,VERB_NOISY,"? Time (CH:%d VALUE:%d)", ch, val);
} }
#endif
channel[ch].envelope_rate[stage] = val; channel[ch].envelope_rate[stage] = val;
} }
@ -3382,8 +3384,8 @@ void Player::process_sysex_event(int ev, int ch, int val, int b)
case 0x23: /* Insertion Effect ON/OFF */ case 0x23: /* Insertion Effect ON/OFF */
if(!opt_insertion_effect) {break;} if(!opt_insertion_effect) {break;}
if(channel[ch].insertion_effect != val) { if(channel[ch].insertion_effect != val) {
if(val) {//ctl_cmsg(CMSG_INFO,VERB_NOISY,"EFX ON (CH:%d)",ch);} //if(val) {//ctl_cmsg(CMSG_INFO,VERB_NOISY,"EFX ON (CH:%d)",ch);}
else {//ctl_cmsg(CMSG_INFO,VERB_NOISY,"EFX OFF (CH:%d)",ch);} //else {//ctl_cmsg(CMSG_INFO,VERB_NOISY,"EFX OFF (CH:%d)",ch);}
} }
channel[ch].insertion_effect = val; channel[ch].insertion_effect = val;
break; break;

View file

@ -1562,7 +1562,7 @@ int load_midi_file(FileReader *fr, TimidityPlus::Instruments *inst)
void Player::run_midi(int samples) void Player::run_midi(int samples)
{ {
auto time = current_event->time + samples; auto time = current_event->time + samples;
while (current_event->time < samples) while (current_event->time < time)
{ {
if (play_event(current_event) != RC_OK) if (play_event(current_event) != RC_OK)
return; return;

View file

@ -71,19 +71,6 @@ typedef struct _ChannelBitMask
# define TIM_FSCALENEG(a,b) ((a) * (1.0 / (double)(1<<(b)))) # define TIM_FSCALENEG(a,b) ((a) * (1.0 / (double)(1<<(b))))
#ifdef _WIN32
#undef PATCH_EXT_LIST
#define PATCH_EXT_LIST { ".pat", 0 }
#endif
#define PATH_SEP '/'
#define PATH_STRING "/"
#define IS_PATH_SEP(c) ((c) == PATH_SEP)
#define NLS "\n"
#ifndef M_PI #ifndef M_PI
#define M_PI 3.14159265358979323846 #define M_PI 3.14159265358979323846
#endif /* M_PI */ #endif /* M_PI */