Skip to content

Commit

Permalink
Initial Emu de MIDI commit
Browse files Browse the repository at this point in the history
  • Loading branch information
dashodanger committed Oct 23, 2024
1 parent dd8464f commit 6d8643f
Show file tree
Hide file tree
Showing 37 changed files with 5,868 additions and 4 deletions.
2 changes: 2 additions & 0 deletions docs/licenses/License Attribution.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ AlmostEquals Google Test Framework Component - Copyright (c) 2005 Google, Inc.

Blasphemer (various assets) - Copyright (c) 2021 Contributors to the Blasphemer project

Emu de MIDI library - Copyright (C) 2004 Mitsutaka Okazaki

FMMIDI library - Copyright (c) 2003-2006 yuno

Freedoom (various assets) - Copyright (c) 2001-2019 Contributors to the Freedoom project
Expand Down
1 change: 1 addition & 0 deletions libraries/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ else()
add_subdirectory(gl4es)
endif()
add_subdirectory(hmm)
add_subdirectory(libemidi)
add_subdirectory(libRAD)
add_subdirectory(libvwad)
add_subdirectory(lua)
Expand Down
18 changes: 18 additions & 0 deletions libraries/libemidi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
##########################################
# Emu de MIDI
##########################################

add_library(libemidi
source/CEnvelope.cpp
source/device/emu2413.c
source/device/emu2212.c
source/device/emu2149.c
source/CMIDIModule.cpp
source/CSccDevice.cpp
source/CPSGDrum.cpp
source/CMIDIMessage.cpp
source/COpllDevice.cpp
source/CSMFPlay.cpp
)

target_include_directories(libemidi PUBLIC ./source)
17 changes: 17 additions & 0 deletions libraries/libemidi/license.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Copyright (C) Mitsutaka Okazaki 2004

This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from
the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
132 changes: 132 additions & 0 deletions libraries/libemidi/source/CEnvelope.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#include "CEnvelope.hpp"

#if defined(_MSC_VER)
#if defined(_DEBUG)
#define new new (_CLIENT_BLOCK, __FILE__, __LINE__)
#endif
#endif

using namespace dsa;

#define GETA_BITS 20
#define MAX_CNT (1 << (GETA_BITS + 8))

uint32_t CEnvelope::_CalcSpeed(uint32_t ms)
{
if (ms == 0)
return MAX_CNT;
else
return (MAX_CNT / (ms * m_clock / 1000)) * m_rate;
}

CEnvelope::CEnvelope(uint32_t ch) : m_ch(ch)
{
m_ci = new ChannelInfo[ch];
}

CEnvelope::~CEnvelope()
{
delete[] m_ci;
}

void CEnvelope::Reset(uint32_t clock, uint32_t rate)
{
m_rate = rate;
m_clock = clock;
m_cnt = 0;
m_inc = (MAX_CNT / m_clock) * m_rate;
for (uint32_t ch = 0; ch < m_ch; ch++)
{
m_ci[ch].value = 0;
m_ci[ch].speed = 0;
m_ci[ch].state = FINISH;
}
}

bool CEnvelope::Update()
{

m_cnt += m_inc;
if (m_cnt < MAX_CNT)
return false;
m_cnt &= 0xFFFFFFF;

for (uint32_t ch = 0; ch < m_ch; ch++)
{

switch (m_ci[ch].state)
{
case ATTACK:
if (m_ci[ch].speed + m_ci[ch].value < MAX_CNT)
m_ci[ch].value += m_ci[ch].speed;
else
{
m_ci[ch].value = MAX_CNT;
m_ci[ch].speed = _CalcSpeed(m_ci[ch].param.dr);
m_ci[ch].state = DECAY;
}
break;
case DECAY:
if ((m_ci[ch].value > m_ci[ch].speed) && (m_ci[ch].value > (uint32_t)m_ci[ch].param.sl << GETA_BITS))
{
m_ci[ch].value -= m_ci[ch].speed;
}
else
{
m_ci[ch].speed = _CalcSpeed(m_ci[ch].param.sr);
m_ci[ch].value = (uint32_t)m_ci[ch].param.sl << GETA_BITS;
m_ci[ch].state = SUSTINE;
}
break;
case SUSTINE:
if ((m_ci[ch].speed > m_ci[ch].value))
{
m_ci[ch].value = 0;
m_ci[ch].state = FINISH;
}
else
{
m_ci[ch].value -= m_ci[ch].speed;
}
break;
case RELEASE:
if ((m_ci[ch].speed > m_ci[ch].value))
{
m_ci[ch].value = 0;
m_ci[ch].state = FINISH;
}
else
{
m_ci[ch].value -= m_ci[ch].speed;
}
break;
default:
break;
}
}

return true;
}

void CEnvelope::KeyOn(uint32_t ch)
{
m_ci[ch].value = 0;
m_ci[ch].speed = _CalcSpeed(m_ci[ch].param.ar);
m_ci[ch].state = ATTACK;
}

void CEnvelope::KeyOff(uint32_t ch)
{
m_ci[ch].state = RELEASE;
m_ci[ch].speed = _CalcSpeed(m_ci[ch].param.rr);
}

void CEnvelope::SetParam(uint32_t ch, const Param &param)
{
m_ci[ch].param = param;
}

uint32_t CEnvelope::GetValue(uint32_t ch) const
{
return m_ci[ch].value >> GETA_BITS;
}
54 changes: 54 additions & 0 deletions libraries/libemidi/source/CEnvelope.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#ifndef __CENVELOPE_HPP__
#define __CENVELOPE_HPP__

#include <stdint.h>

namespace dsa
{

class CEnvelope
{
public:
enum EnvState
{
SETTLE,
ATTACK,
DECAY,
SUSTINE,
RELEASE,
FINISH
};
struct Param
{
uint32_t ar, dr, sl, sr, rr;
};
struct ChannelInfo
{
EnvState state;
uint32_t speed;
uint32_t value;
Param param;
};

private:
uint32_t m_ch;
ChannelInfo *m_ci;
uint32_t m_clock;
uint32_t m_rate;
uint32_t m_cnt;
uint32_t m_inc;
uint32_t _CalcSpeed(uint32_t ms);

public:
CEnvelope(uint32_t ch);
~CEnvelope();
void Reset(uint32_t clock = 44100, uint32_t rate = 60);
void KeyOn(uint32_t ch);
void KeyOff(uint32_t ch);
bool Update();
void SetParam(uint32_t ch, const Param &param);
uint32_t GetValue(uint32_t ch) const;
};

} // namespace dsa
#endif
46 changes: 46 additions & 0 deletions libraries/libemidi/source/CMIDIMessage.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "CMIDIMessage.hpp"

using namespace dsa;

CMIDIMsg::CMIDIMsg(MsgType type, int ch, uint8_t data1, uint8_t data2 )
: m_type(type), m_ch(ch), m_data1(data1), m_data2(data2)
{
}

CMIDIMsg &CMIDIMsg::operator=(const CMIDIMsg &arg)
{
m_type = arg.m_type;
m_ch = arg.m_ch;
m_data1 = arg.m_data1;
m_data2 = arg.m_data2;
return (*this);
}

CMIDIMsg::CMIDIMsg(const CMIDIMsg &arg)
{
m_type = arg.m_type;
m_ch = arg.m_ch;
m_data1 = arg.m_data1;
m_data2 = arg.m_data2;
}

CMIDIMsg::~CMIDIMsg()
{
}

const char *CMIDIMsg::c_str() const
{
const char *text[] = {// CANNEL
"NOTE_OFF", "NOTE_ON", "POLYPHONIC_KEY_PRESSURE", "CONTROL_CHANGE", "PROGRAM_CHANGE",
"CHANNEL_PRESSURE", "PITCH_BEND_CHANGE",
// MODE
"ALL_SOUND_OFF", "RESET_ALL_CONTROLLERS", "LOCAL_CONTROL", "ALL_NOTES_OFF", "OMNI_OFF",
"OMNI_ON", "POLYPHONIC_OPERATION", "MONOPHONIC_OPERATION",
// SYSTEM
"SYSTEM_EXCLUSIVE", "MTC_QUARTER_FRAME", "SONG_POSITION_POINTER", "SONG_SELECT",
"TUNE_REQUEST",
// REALTIME
"REALTIME_CLOCK", "REALTIME_TICK", "REALTIME_START", "REALTIME_CONTINUE", "REALTIME_STOP",
"REALTIME_ACTIVE_SENSE", "REALTIME_SYSTEM_RESET", "UNKNOWN_MESSAGE"};
return text[m_type];
}
65 changes: 65 additions & 0 deletions libraries/libemidi/source/CMIDIMessage.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#ifndef __MIDI_MESSAGE_HPP__
#define __MIDI_MESSAGE_HPP__
#include <stdint.h>
#include <string.h>

#include <deque>
#include <string>

namespace dsa
{

// MIDI Msgs (Channel or exclusive Msg)
class CMIDIMsg
{
public:
enum MsgType
{
// CHANNEL Msg
NOTE_OFF = 0, // 8n #note #velo
NOTE_ON, // 9n #note #velo
POLYPHONIC_KEY_PRESSURE, // An #note #data
CONTROL_CHANGE, // Bn #ctrl #data
PROGRAM_CHANGE, // Cn #data
CHANNEL_PRESSURE, // Dn #data
PITCH_BEND_CHANGE, // En #data #data
// MODE Msg
ALL_SOUND_OFF, // Bn 78 00
RESET_ALL_CONTROLLERS, // Bn 79 00
LOCAL_CONTROL, // Bn 7A #data
ALL_NOTES_OFF, // Bn 7B 00
OMNI_OFF, // Bn 7C 00
OMNI_ON, // Bn 7D 00
POLYPHONIC_OPERATION, // Bn 7E 00
MONOPHONIC_OPERATION, // Bn 7F 00
// SYSTEM Msg
SYSTEM_EXCLUSIVE, // F0 ... F7
MTC_QUARTER_FRAME, // F1 #data
SONG_POSITION_POINTER, // F2 #data #data
SONG_SELECT, // F3 #data
TUNE_REQUEST, // F6
// REALTIME Msg
REALTIME_CLOCK, // F8
REALTIME_TICK, // F9
REALTIME_START, // FA
REALTIME_CONTINUE, // FB
REALTIME_STOP, // FC
REALTIME_ACTIVE_SENSE, // FE
REALTIME_SYSTEM_RESET, // FF
UNKNOWN_MESSAGE
};

MsgType m_type; // The Msg identifier
uint32_t m_ch; // The channel
uint8_t m_data1;
uint8_t m_data2;
CMIDIMsg(MsgType type = UNKNOWN_MESSAGE, int ch = 0, uint8_t data1 = 0, uint8_t data2 = 0);
CMIDIMsg(const CMIDIMsg &);
~CMIDIMsg();
CMIDIMsg &operator=(const CMIDIMsg &arg);
const char *c_str() const;
};

} // namespace dsa

#endif
Loading

0 comments on commit 6d8643f

Please sign in to comment.