mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 07:12:02 +00:00
Added support for libOPNMIDI Playing device
This commit is contained in:
parent
46942cb27f
commit
6308fb311b
9 changed files with 4691 additions and 3 deletions
|
@ -645,6 +645,9 @@ if( NOT SEND_ANON_STATS )
|
|||
add_definitions( -DNO_SEND_STATS )
|
||||
endif()
|
||||
|
||||
# OPLMIDI needs for USE_LEGACY_EMULATOR macro to be correctly built
|
||||
add_definitions(-DUSE_LEGACY_EMULATOR)
|
||||
|
||||
# Project files should be aware of the header files. We can GLOB these since
|
||||
# there's generally a new cpp for every header so this file will get changed
|
||||
if( WIN32 )
|
||||
|
@ -667,6 +670,7 @@ file( GLOB HEADER_FILES
|
|||
intermission/*.h
|
||||
menu/*.h
|
||||
sound/adlmidi/*.h*
|
||||
sound/opnmidi/*.h*
|
||||
sound/oplsynth/*.h
|
||||
sound/oplsynth/dosbox/*.h
|
||||
posix/*.h
|
||||
|
@ -863,6 +867,14 @@ set( FASTMATH_SOURCES
|
|||
sound/adlmidi/adlmidi_private.cpp
|
||||
sound/adlmidi/dbopl.cpp
|
||||
sound/adlmidi/nukedopl3.c
|
||||
sound/opnmidi/opnmidi.cpp
|
||||
sound/opnmidi/opnmidi_load.cpp
|
||||
sound/opnmidi/opnmidi_midiplay.cpp
|
||||
sound/opnmidi/opnmidi_opn2.cpp
|
||||
sound/opnmidi/opnmidi_private.cpp
|
||||
sound/opnmidi/opnmidi_mus2mid.c
|
||||
sound/opnmidi/opnmidi_xmi2mid.c
|
||||
sound/opnmidi/Ym2612_ChipEmu.cpp
|
||||
)
|
||||
|
||||
set (PCH_SOURCES
|
||||
|
@ -1171,6 +1183,7 @@ set (PCH_SOURCES
|
|||
sound/mididevices/music_adlmidi_mididevice.cpp
|
||||
sound/mididevices/music_opldumper_mididevice.cpp
|
||||
sound/mididevices/music_opl_mididevice.cpp
|
||||
sound/mididevices/music_opnmidi_mididevice.cpp
|
||||
sound/mididevices/music_timiditypp_mididevice.cpp
|
||||
sound/mididevices/music_fluidsynth_mididevice.cpp
|
||||
sound/mididevices/music_softsynth_mididevice.cpp
|
||||
|
|
|
@ -335,6 +335,25 @@ protected:
|
|||
};
|
||||
|
||||
|
||||
class OPNMIDIDevice : public SoftSynthMIDIDevice
|
||||
{
|
||||
struct OPN2_MIDIPlayer *Renderer;
|
||||
TArray<int16_t> shortbuffer;
|
||||
public:
|
||||
OPNMIDIDevice(const char *args);
|
||||
~OPNMIDIDevice();
|
||||
|
||||
int Open(MidiCallback, void *userdata);
|
||||
int GetDeviceType() const override { return MDEV_OPN; }
|
||||
|
||||
protected:
|
||||
|
||||
void HandleEvent(int status, int parm1, int parm2);
|
||||
void HandleLongEvent(const uint8_t *data, int len);
|
||||
void ComputeOutput(float *buffer, int len);
|
||||
};
|
||||
|
||||
|
||||
// Base class for streaming MUS and MIDI files ------------------------------
|
||||
|
||||
enum
|
||||
|
|
|
@ -163,6 +163,7 @@ enum EMidiDevice
|
|||
MDEV_GUS = 5,
|
||||
MDEV_WILDMIDI = 6,
|
||||
MDEV_ADL = 7,
|
||||
MDEV_OPN = 8,
|
||||
|
||||
MDEV_COUNT
|
||||
};
|
||||
|
|
175
src/sound/mididevices/music_opnmidi_mididevice.cpp
Normal file
175
src/sound/mididevices/music_opnmidi_mididevice.cpp
Normal file
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
** music_opnmidi_mididevice.cpp
|
||||
** Provides access to libOPNMIDI as a generic MIDI device.
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2008 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include "i_musicinterns.h"
|
||||
#include "templates.h"
|
||||
#include "doomdef.h"
|
||||
#include "m_swap.h"
|
||||
#include "w_wad.h"
|
||||
#include "v_text.h"
|
||||
#include "opnmidi/opnmidi.h"
|
||||
#include "opnmidi/default_bank/xg_opn_bank.h"
|
||||
#include <errno.h>
|
||||
|
||||
enum
|
||||
{
|
||||
ME_NOTEOFF = 0x80,
|
||||
ME_NOTEON = 0x90,
|
||||
ME_KEYPRESSURE = 0xA0,
|
||||
ME_CONTROLCHANGE = 0xB0,
|
||||
ME_PROGRAM = 0xC0,
|
||||
ME_CHANNELPRESSURE = 0xD0,
|
||||
ME_PITCHWHEEL = 0xE0
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OPNMIDIDevice Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
OPNMIDIDevice::OPNMIDIDevice(const char *args)
|
||||
:SoftSynthMIDIDevice(44100)
|
||||
{
|
||||
Renderer = opn2_init(44100); // todo: make it configurable
|
||||
if (Renderer != nullptr)
|
||||
{
|
||||
opn2_openBankData(Renderer, g_gm_opn2_bank, sizeof(g_gm_opn2_bank));
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OPNMIDIDevice Destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
OPNMIDIDevice::~OPNMIDIDevice()
|
||||
{
|
||||
Close();
|
||||
if (Renderer != nullptr)
|
||||
{
|
||||
opn2_close(Renderer);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OPNMIDIDevice :: Open
|
||||
//
|
||||
// Returns 0 on success.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int OPNMIDIDevice::Open(MidiCallback callback, void *userdata)
|
||||
{
|
||||
int ret = OpenStream(2, 0, callback, userdata);
|
||||
if (ret == 0)
|
||||
{
|
||||
opn2_rt_resetState(Renderer);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OPNMIDIDevice :: HandleEvent
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void OPNMIDIDevice::HandleEvent(int status, int parm1, int parm2)
|
||||
{
|
||||
int command = status & 0xF0;
|
||||
int chan = status & 0x0F;
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case ME_NOTEON:
|
||||
opn2_rt_noteOn(Renderer, chan, parm1, parm2);
|
||||
break;
|
||||
|
||||
case ME_NOTEOFF:
|
||||
opn2_rt_noteOff(Renderer, chan, parm1);
|
||||
break;
|
||||
|
||||
case ME_KEYPRESSURE:
|
||||
opn2_rt_noteAfterTouch(Renderer, chan, parm1, parm2);
|
||||
break;
|
||||
|
||||
case ME_CONTROLCHANGE:
|
||||
opn2_rt_controllerChange(Renderer, chan, parm1, parm2);
|
||||
break;
|
||||
|
||||
case ME_PROGRAM:
|
||||
opn2_rt_patchChange(Renderer, chan, parm1);
|
||||
break;
|
||||
|
||||
case ME_CHANNELPRESSURE:
|
||||
opn2_rt_channelAfterTouch(Renderer, chan, parm1);
|
||||
break;
|
||||
|
||||
case ME_PITCHWHEEL:
|
||||
opn2_rt_pitchBendML(Renderer, chan, parm2, parm1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OPNMIDIDevice :: HandleLongEvent
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void OPNMIDIDevice::HandleLongEvent(const uint8_t *data, int len)
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OPNMIDIDevice :: ComputeOutput
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void OPNMIDIDevice::ComputeOutput(float *buffer, int len)
|
||||
{
|
||||
if ((int)shortbuffer.Size() < len*2) shortbuffer.Resize(len*2);
|
||||
auto result = opn2_generate(Renderer, len*2, &shortbuffer[0]);
|
||||
for(int i=0; i<result; i++)
|
||||
{
|
||||
buffer[i] = shortbuffer[i] * (5.f/32768.f);
|
||||
}
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@
|
|||
static uint32_t nummididevices;
|
||||
static bool nummididevicesset;
|
||||
|
||||
#define NUM_DEF_DEVICES 6
|
||||
#define NUM_DEF_DEVICES 7
|
||||
|
||||
static void AddDefaultMidiDevices(FOptionValues *opt)
|
||||
{
|
||||
|
@ -67,6 +67,8 @@ static void AddDefaultMidiDevices(FOptionValues *opt)
|
|||
pair[4].Value = -3.0;
|
||||
pair[5].Text = "libADL";
|
||||
pair[5].Value = -7.0;
|
||||
pair[6].Text = "libOPN";
|
||||
pair[6].Value = -8.0;
|
||||
|
||||
}
|
||||
|
||||
|
@ -201,6 +203,7 @@ CCMD (snd_listmididevices)
|
|||
MIDIOUTCAPS caps;
|
||||
MMRESULT res;
|
||||
|
||||
PrintMidiDevice(-8, "libOPN", MIDIDEV_FMSYNTH, 0);
|
||||
PrintMidiDevice(-7, "libADL", MIDIDEV_FMSYNTH, 0);
|
||||
PrintMidiDevice (-6, "WildMidi", MIDIDEV_SWSYNTH, 0);
|
||||
PrintMidiDevice (-5, "FluidSynth", MIDIDEV_SWSYNTH, 0);
|
||||
|
@ -230,8 +233,8 @@ CCMD (snd_listmididevices)
|
|||
|
||||
CUSTOM_CVAR(Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
{
|
||||
if (self < -7)
|
||||
self = -7;
|
||||
if (self < -8)
|
||||
self = -8;
|
||||
else if (self > -2)
|
||||
self = -2;
|
||||
else
|
||||
|
@ -245,6 +248,7 @@ void I_BuildMIDIMenuList (FOptionValues *opt)
|
|||
|
||||
CCMD (snd_listmididevices)
|
||||
{
|
||||
Printf("%s-8. libOPN\n", -7 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
||||
Printf("%s-7. libADL\n", -6 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
||||
Printf("%s-6. WildMidi\n", -6 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
||||
Printf("%s-5. FluidSynth\n", -5 == snd_mididevice ? TEXTCOLOR_BOLD : "");
|
||||
|
|
|
@ -166,6 +166,7 @@ EMidiDevice MIDIStreamer::SelectMIDIDevice(EMidiDevice device)
|
|||
case -5: return MDEV_FLUIDSYNTH;
|
||||
case -6: return MDEV_WILDMIDI;
|
||||
case -7: return MDEV_ADL;
|
||||
case -8: return MDEV_OPN;
|
||||
default:
|
||||
#ifdef _WIN32
|
||||
return MDEV_MMAPI;
|
||||
|
@ -205,6 +206,10 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype, int samplerate)
|
|||
dev = new ADLMIDIDevice(Args);
|
||||
break;
|
||||
|
||||
case MDEV_OPN:
|
||||
dev = new OPNMIDIDevice(Args);
|
||||
break;
|
||||
|
||||
case MDEV_MMAPI:
|
||||
|
||||
#ifdef _WIN32
|
||||
|
|
25
src/sound/opnmidi/default_bank/wopn2hpp.sh
Executable file
25
src/sound/opnmidi/default_bank/wopn2hpp.sh
Executable file
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
|
||||
output="xg_opn_bank.h"
|
||||
|
||||
out()
|
||||
{
|
||||
printf "${1}" >> $output
|
||||
}
|
||||
|
||||
truncate -s 0 $output
|
||||
|
||||
out "/*===============================================================*\n"
|
||||
out " This file is automatically generated by wopn2hpp.sh script\n"
|
||||
out " PLEASE DON'T EDIT THIS DIRECTLY. Edit the gm.wonp file first,\n"
|
||||
out " and then run a wopn2hpp.sh script to generate this file again\n"
|
||||
out " *===============================================================*/\n\n"
|
||||
out "static unsigned char g_gm_opn2_bank[] = \n"
|
||||
out "{\n"
|
||||
hexdump -ve '12/1 "0x%02x, " "\n"' xg.wopn >> $output
|
||||
out "0x00\n"
|
||||
out "};\n"
|
||||
out "\n"
|
||||
|
||||
sed -i "s/0x /0x00/g" $output
|
||||
|
BIN
src/sound/opnmidi/default_bank/xg.wopn
Normal file
BIN
src/sound/opnmidi/default_bank/xg.wopn
Normal file
Binary file not shown.
4446
src/sound/opnmidi/default_bank/xg_opn_bank.h
Normal file
4446
src/sound/opnmidi/default_bank/xg_opn_bank.h
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue