From 9b61ee9618d8d674c8ee37f323374d2bceee3c7d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 6 Mar 2018 22:41:27 +0100 Subject: [PATCH] - fixed: The MIDI wave writer set the sample rate to save at too late. This was done after the players had already been created. To ensure that everything gets set properly it is necessary to pass the desired sample rate to the device's constructor and let it make sure that a proper sample rate gets set. --- src/sound/i_musicinterns.h | 22 ++++++---------- .../music_fluidsynth_mididevice.cpp | 8 ++---- .../mididevices/music_opl_mididevice.cpp | 2 +- .../music_softsynth_mididevice.cpp | 5 ++-- .../mididevices/music_timidity_mididevice.cpp | 4 +-- .../music_timiditypp_mididevice.cpp | 25 ++++++------------- .../music_wavewriter_mididevice.cpp | 9 +++---- .../mididevices/music_wildmidi_mididevice.cpp | 12 ++------- src/sound/musicformats/music_midistream.cpp | 16 ++++++------ 9 files changed, 37 insertions(+), 66 deletions(-) diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index b4269aaba..9679fec93 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -88,7 +88,7 @@ public: #ifdef _WIN32 MIDIDevice *CreateWinMIDIDevice(int mididevice); #endif -MIDIDevice *CreateTimidityPPMIDIDevice(const char *args); +MIDIDevice *CreateTimidityPPMIDIDevice(const char *args, int samplerate); void TimidityPP_Shutdown(); // Base class for software synthesizer MIDI output devices ------------------ @@ -97,7 +97,7 @@ class SoftSynthMIDIDevice : public MIDIDevice { friend class MIDIWaveWriter; public: - SoftSynthMIDIDevice(); + SoftSynthMIDIDevice(int samplerate, int minrate = 1, int maxrate = 1000000 /* something higher than any valid value */); ~SoftSynthMIDIDevice(); void Close(); @@ -131,10 +131,6 @@ protected: int OpenStream(int chunks, int flags, MidiCallback, void *userdata); static bool FillStream(SoundStream *stream, void *buff, int len, void *userdata); virtual bool ServiceStream (void *buff, int numbytes); - virtual void SetSampleRate(int rate) - { - if (rate > 11025) { SampleRate = rate; } - } int GetSampleRate() const { return SampleRate; } virtual void HandleEvent(int status, int parm1, int parm2) = 0; @@ -152,7 +148,6 @@ public: void Close(); int GetTechnology() const; FString GetStats(); - virtual void SetSampleRate(int rate) { } // cannot be changed. protected: void CalcTickRate(); @@ -182,14 +177,13 @@ namespace Timidity { struct Renderer; } class TimidityMIDIDevice : public SoftSynthMIDIDevice { public: - TimidityMIDIDevice(const char *args); + TimidityMIDIDevice(const char *args, int samplerate); ~TimidityMIDIDevice(); int Open(MidiCallback, void *userdata); void PrecacheInstruments(const uint16_t *instruments, int count); FString GetStats(); int GetDeviceType() const override { return MDEV_GUS; } - virtual void SetSampleRate(int rate) { if (rate >= 11025 && rate < 65535) SampleRate = rate; } protected: Timidity::Renderer *Renderer; @@ -204,7 +198,7 @@ protected: class MIDIWaveWriter : public SoftSynthMIDIDevice { public: - MIDIWaveWriter(const char *filename, MIDIDevice *devtouse, int rate); + MIDIWaveWriter(const char *filename, MIDIDevice *devtouse); ~MIDIWaveWriter(); int Resume(); int Open(MidiCallback cb, void *userdata) @@ -235,14 +229,13 @@ protected: class WildMIDIDevice : public SoftSynthMIDIDevice { public: - WildMIDIDevice(const char *args); + WildMIDIDevice(const char *args, int samplerate); ~WildMIDIDevice(); int Open(MidiCallback, void *userdata); void PrecacheInstruments(const uint16_t *instruments, int count); FString GetStats(); int GetDeviceType() const override { return MDEV_WILDMIDI; } - virtual void SetSampleRate(int rate) { if (rate >= 11025 && SampleRate < rate) SampleRate = rate; } protected: WildMidi_Renderer *Renderer; @@ -268,7 +261,7 @@ struct fluid_synth_t; class FluidSynthMIDIDevice : public SoftSynthMIDIDevice { public: - FluidSynthMIDIDevice(const char *args); + FluidSynthMIDIDevice(const char *args, int samplerate); ~FluidSynthMIDIDevice(); int Open(MidiCallback, void *userdata); @@ -277,7 +270,6 @@ public: void FluidSettingNum(const char *setting, double value); void FluidSettingStr(const char *setting, const char *value); int GetDeviceType() const override { return MDEV_FLUIDSYNTH; } - virtual void SetSampleRate(int rate) { if (rate >= 22050 && rate <= 96000) SampleRate = rate; } protected: void HandleEvent(int status, int parm1, int parm2); @@ -382,7 +374,7 @@ protected: static EMidiDevice SelectMIDIDevice(EMidiDevice devtype); - MIDIDevice *CreateMIDIDevice(EMidiDevice devtype); + MIDIDevice *CreateMIDIDevice(EMidiDevice devtype, int samplerate); static void Callback(void *userdata); diff --git a/src/sound/mididevices/music_fluidsynth_mididevice.cpp b/src/sound/mididevices/music_fluidsynth_mididevice.cpp index 05ed27532..97282299f 100644 --- a/src/sound/mididevices/music_fluidsynth_mididevice.cpp +++ b/src/sound/mididevices/music_fluidsynth_mididevice.cpp @@ -274,7 +274,8 @@ CUSTOM_CVAR(Int, fluid_chorus_type, FLUID_CHORUS_DEFAULT_TYPE, CVAR_ARCHIVE|CVAR // //========================================================================== -FluidSynthMIDIDevice::FluidSynthMIDIDevice(const char *args) +FluidSynthMIDIDevice::FluidSynthMIDIDevice(const char *args, int samplerate) + : SoftSynthMIDIDevice(samplerate <= 0? fluid_samplerate : samplerate, 22050, 96000) { FluidSynth = NULL; FluidSettings = NULL; @@ -290,11 +291,6 @@ FluidSynthMIDIDevice::FluidSynthMIDIDevice(const char *args) printf("Failed to create FluidSettings.\n"); return; } - SampleRate = fluid_samplerate; - if (SampleRate < 22050 || SampleRate > 96000) - { // Match sample rate to SFX rate - SampleRate = clamp((int)GSnd->GetOutputRate(), 22050, 96000); - } fluid_settings_setnum(FluidSettings, "synth.sample-rate", SampleRate); fluid_settings_setnum(FluidSettings, "synth.gain", fluid_gain); fluid_settings_setint(FluidSettings, "synth.reverb.active", fluid_reverb); diff --git a/src/sound/mididevices/music_opl_mididevice.cpp b/src/sound/mididevices/music_opl_mididevice.cpp index 72ae555a8..a37358520 100644 --- a/src/sound/mididevices/music_opl_mididevice.cpp +++ b/src/sound/mididevices/music_opl_mididevice.cpp @@ -79,6 +79,7 @@ CVAR(Bool, opl_fullpan, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); //========================================================================== OPLMIDIDevice::OPLMIDIDevice(const char *args) + : SoftSynthMIDIDevice((int)OPL_SAMPLE_RATE) { OPL_SetCore(args); FullPan = opl_fullpan; @@ -88,7 +89,6 @@ OPLMIDIDevice::OPLMIDIDevice(const char *args) data.Read(filehdr, 8); if (memcmp(filehdr, "#OPL_II#", 8)) I_Error("Corrupt GENMIDI lump"); data.Read(OPLinstruments, sizeof(GenMidiInstrument) * GENMIDI_NUM_TOTAL); - SampleRate = (int)OPL_SAMPLE_RATE; } //========================================================================== diff --git a/src/sound/mididevices/music_softsynth_mididevice.cpp b/src/sound/mididevices/music_softsynth_mididevice.cpp index ae46e31d3..ccee4bd27 100644 --- a/src/sound/mididevices/music_softsynth_mididevice.cpp +++ b/src/sound/mididevices/music_softsynth_mididevice.cpp @@ -68,14 +68,15 @@ CVAR(Bool, synth_watch, false, 0) // //========================================================================== -SoftSynthMIDIDevice::SoftSynthMIDIDevice() +SoftSynthMIDIDevice::SoftSynthMIDIDevice(int samplerate, int minrate, int maxrate) { Stream = NULL; Tempo = 0; Division = 0; Events = NULL; Started = false; - SampleRate = GSnd != NULL ? (int)GSnd->GetOutputRate() : 44100; + SampleRate = samplerate; + if (SampleRate < minrate || SampleRate > maxrate) SampleRate = GSnd != NULL ? clamp((int)GSnd->GetOutputRate(), minrate, maxrate) : 44100; } //========================================================================== diff --git a/src/sound/mididevices/music_timidity_mididevice.cpp b/src/sound/mididevices/music_timidity_mididevice.cpp index 675fee126..c8454f811 100644 --- a/src/sound/mididevices/music_timidity_mididevice.cpp +++ b/src/sound/mididevices/music_timidity_mididevice.cpp @@ -66,9 +66,9 @@ // //========================================================================== -TimidityMIDIDevice::TimidityMIDIDevice(const char *args) +TimidityMIDIDevice::TimidityMIDIDevice(const char *args, int samplerate) + : SoftSynthMIDIDevice(samplerate, 11025, 65535) { - Renderer = nullptr; Renderer = new Timidity::Renderer((float)SampleRate, args); } diff --git a/src/sound/mididevices/music_timiditypp_mididevice.cpp b/src/sound/mididevices/music_timiditypp_mididevice.cpp index c299dddae..40205840f 100644 --- a/src/sound/mididevices/music_timiditypp_mididevice.cpp +++ b/src/sound/mididevices/music_timiditypp_mididevice.cpp @@ -53,7 +53,7 @@ class TimidityPPMIDIDevice : public SoftSynthMIDIDevice static TimidityPlus::Instruments *instruments; int sampletime; public: - TimidityPPMIDIDevice(const char *args); + TimidityPPMIDIDevice(const char *args, int samplerate); ~TimidityPPMIDIDevice(); int Open(MidiCallback, void *userdata); @@ -65,10 +65,6 @@ public: if (instruments != nullptr) delete instruments; instruments = nullptr; } - virtual void SetSampleRate(int rate) - { - if (rate >= 4000 && SampleRate < rate) SampleRate = rate; - } double test[3] = { 0, 0, 0 }; @@ -91,13 +87,7 @@ CUSTOM_CVAR(String, timidity_config, "timidity.cfg", CVAR_ARCHIVE | CVAR_GLOBALC } -CUSTOM_CVAR (Int, timidity_frequency, 44100, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -{ // Clamp frequency to Timidity's limits - if (self < 4000) - self = 4000; - else if (self > 65000) - self = 65000; -} +CVAR (Int, timidity_frequency, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) //========================================================================== // @@ -105,7 +95,8 @@ CUSTOM_CVAR (Int, timidity_frequency, 44100, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // //========================================================================== -TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) +TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args, int samplerate) + :SoftSynthMIDIDevice(samplerate <= 0? timidity_frequency : samplerate, 4000, 65000) { if (args == NULL || *args == 0) args = timidity_config; @@ -115,8 +106,8 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) delete instruments; instruments = nullptr; } - TimidityPlus::set_playback_rate(timidity_frequency); - SampleRate = timidity_frequency; + TimidityPlus::set_playback_rate(SampleRate); + if (instruments == nullptr) { instruments = new TimidityPlus::Instruments; @@ -229,9 +220,9 @@ void TimidityPPMIDIDevice::ComputeOutput(float *buffer, int len) // //========================================================================== -MIDIDevice *CreateTimidityPPMIDIDevice(const char *args) +MIDIDevice *CreateTimidityPPMIDIDevice(const char *args, int samplerate) { - return new TimidityPPMIDIDevice(args); + return new TimidityPPMIDIDevice(args, samplerate); } void TimidityPP_Shutdown() diff --git a/src/sound/mididevices/music_wavewriter_mididevice.cpp b/src/sound/mididevices/music_wavewriter_mididevice.cpp index ddf5bb3bb..1f109aea2 100644 --- a/src/sound/mididevices/music_wavewriter_mididevice.cpp +++ b/src/sound/mididevices/music_wavewriter_mididevice.cpp @@ -87,7 +87,8 @@ struct FmtChunk // //========================================================================== -MIDIWaveWriter::MIDIWaveWriter(const char *filename, MIDIDevice *playdevice, int rate) +MIDIWaveWriter::MIDIWaveWriter(const char *filename, MIDIDevice *playdevice) + : SoftSynthMIDIDevice(playDevice->GetSampleRate()) { File = FileWriter::Open(filename); playDevice = (SoftSynthMIDIDevice*) playdevice; @@ -102,15 +103,13 @@ MIDIWaveWriter::MIDIWaveWriter(const char *filename, MIDIDevice *playdevice, int if (4*3 != File->Write(work, 4 * 3)) goto fail; - playDevice->SetSampleRate(rate); playDevice->CalcTickRate(); - rate = playDevice->GetSampleRate(); // read back what the device made of it. fmt.ChunkID = MAKE_ID('f','m','t',' '); fmt.ChunkLen = LittleLong(uint32_t(sizeof(fmt) - 8)); fmt.FormatTag = LittleShort(0xFFFE); // WAVE_FORMAT_EXTENSIBLE fmt.Channels = LittleShort(2); - fmt.SamplesPerSec = LittleLong(rate); - fmt.AvgBytesPerSec = LittleLong(rate * 8); + fmt.SamplesPerSec = LittleLong(SampleRate); + fmt.AvgBytesPerSec = LittleLong(SampleRate * 8); fmt.BlockAlign = LittleShort(8); fmt.BitsPerSample = LittleShort(32); fmt.ExtensionSize = LittleShort(2 + 4 + 16); diff --git a/src/sound/mididevices/music_wildmidi_mididevice.cpp b/src/sound/mididevices/music_wildmidi_mididevice.cpp index 2a71f1c7e..fe3571389 100644 --- a/src/sound/mididevices/music_wildmidi_mididevice.cpp +++ b/src/sound/mididevices/music_wildmidi_mididevice.cpp @@ -89,19 +89,11 @@ CUSTOM_CVAR(Bool, wildmidi_enhanced_resampling, true, CVAR_ARCHIVE | CVAR_GLOBAL // //========================================================================== -WildMIDIDevice::WildMIDIDevice(const char *args) +WildMIDIDevice::WildMIDIDevice(const char *args, int samplerate) + :SoftSynthMIDIDevice(samplerate <= 0? wildmidi_frequency : samplerate, 11025, 65535) { Renderer = NULL; - if (wildmidi_frequency > 0) - { - SampleRate = clamp(*wildmidi_frequency, 11025, 65535); - } - else - { // If nothing is set, use the active device's output rate. - SampleRate = (int)GSnd->GetOutputRate(); - } - if (args == NULL || *args == 0) args = wildmidi_config; if (CurrentConfig.CompareNoCase(args) != 0 || SampleRate != WildMidi_GetSampleRate()) diff --git a/src/sound/musicformats/music_midistream.cpp b/src/sound/musicformats/music_midistream.cpp index eea204910..2b4e1c34e 100644 --- a/src/sound/musicformats/music_midistream.cpp +++ b/src/sound/musicformats/music_midistream.cpp @@ -182,7 +182,7 @@ EMidiDevice MIDIStreamer::SelectMIDIDevice(EMidiDevice device) static EMidiDevice lastRequestedDevice, lastSelectedDevice; -MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) +MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype, int samplerate) { bool checked[MDEV_COUNT] = { false }; @@ -197,7 +197,7 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) switch (devtype) { case MDEV_GUS: - dev = new TimidityMIDIDevice(Args); + dev = new TimidityMIDIDevice(Args, samplerate); break; case MDEV_MMAPI: @@ -208,7 +208,7 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) // Intentional fall-through for non-Windows systems. case MDEV_FLUIDSYNTH: - dev = new FluidSynthMIDIDevice(Args); + dev = new FluidSynthMIDIDevice(Args, samplerate); break; case MDEV_OPL: @@ -216,11 +216,11 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) break; case MDEV_TIMIDITY: - dev = CreateTimidityPPMIDIDevice(Args); + dev = CreateTimidityPPMIDIDevice(Args, samplerate); break; case MDEV_WILDMIDI: - dev = new WildMIDIDevice(Args); + dev = new WildMIDIDevice(Args, samplerate); break; default: @@ -284,7 +284,7 @@ void MIDIStreamer::Play(bool looping, int subsong) m_Looping = looping; source->SetMIDISubsong(subsong); devtype = SelectMIDIDevice(DeviceType); - MIDI = CreateMIDIDevice(devtype); + MIDI = CreateMIDIDevice(devtype, 0); InitPlayback(); } @@ -319,8 +319,8 @@ bool MIDIStreamer::DumpWave(const char *filename, int subsong, int samplerate) assert(MIDI == NULL); auto devtype = SelectMIDIDevice(DeviceType); - MIDI = CreateMIDIDevice(devtype); - MIDI = new MIDIWaveWriter(filename, MIDI, samplerate); + MIDI = CreateMIDIDevice(devtype, samplerate); + MIDI = new MIDIWaveWriter(filename, MIDI); return InitPlayback(); }