zmusic/thirdparty/opnmidi/chips/np2/fmgen_fmgeninl.h
Wohlstand 72c23d98a3 Update libOPNMIDI library to 1.5.0
## 1.5.0   2020-09-28
 * Drum note length expanding is now supported in real-time mode (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!)
 * Added support for OPNA chip with Neko Project II Kai YM2602 emulator usage (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!)
 * Added VGM file dumper which allows to output OPN2 commands into VGM file. (A new MIDI to VGM tool is now created with basing on libOPNMIDI)
 * Fixed an incorrect work of CC-121 (See https://github.com/Wohlstand/libADLMIDI/issues/227 for details)
 * Internality has been refactored and improved
2020-10-04 08:03:44 +02:00

274 lines
4.8 KiB
C++

// ---------------------------------------------------------------------------
// FM Sound Generator
// Copyright (C) cisc 1998, 2003.
// ---------------------------------------------------------------------------
// $Id: fmgeninl.h,v 1.26 2003/06/12 13:14:36 cisc Exp $
#ifndef FM_GEN_INL_H
#define FM_GEN_INL_H
// ---------------------------------------------------------------------------
// 定数その2
//
#define FM_PI 3.14159265358979323846
#define FM_SINEPRESIS 2 // EGとサイン波の精度の差 0(低)-2(高)
#define FM_OPSINBITS 10
#define FM_OPSINENTS (1 << FM_OPSINBITS)
#define FM_EGCBITS 18 // eg の count のシフト値
#define FM_LFOCBITS 14
#ifdef FM_TUNEBUILD
#define FM_PGBITS 2
#define FM_RATIOBITS 0
#else
#define FM_PGBITS 9
#define FM_RATIOBITS 7 // 8-12 くらいまで?
#endif
#define FM_EGBITS 16
//extern int paramcount[];
//#define PARAMCHANGE(i) paramcount[i]++;
#define PARAMCHANGE(i)
namespace FM
{
// ---------------------------------------------------------------------------
// Operator
//
// フィードバックバッファをクリア
inline void Operator::ResetFB()
{
out_ = out2_ = 0;
}
// キーオン
inline void Operator::KeyOn()
{
if (!keyon_)
{
keyon_ = true;
held_ = false;
if (eg_phase_ == off || eg_phase_ == release)
{
#if 1 // libOPNMIDI: experimental SSG-EG
inverted_ = (ssg_type_ & 4) != 0;
inverted_ ^= (ssg_type_ & 2) && ar_ != 62; // try to match polarity with nuked OPN
#else
ssg_phase_ = -1;
#endif
ShiftPhase(attack);
EGUpdate();
in2_ = out_ = out2_ = 0;
pg_count_ = 0;
}
}
}
// キーオフ
inline void Operator::KeyOff()
{
if (keyon_)
{
keyon_ = false;
ShiftPhase(release);
}
}
// オペレータは稼働中か?
inline int Operator::IsOn()
{
return eg_phase_ - off;
}
// Detune (0-7)
inline void Operator::SetDT(uint dt)
{
detune_ = dt * 0x20, param_changed_ = true;
PARAMCHANGE(4);
}
// DT2 (0-3)
inline void Operator::SetDT2(uint dt2)
{
detune2_ = dt2 & 3, param_changed_ = true;
PARAMCHANGE(5);
}
// Multiple (0-15)
inline void Operator::SetMULTI(uint mul)
{
multiple_ = mul, param_changed_ = true;
PARAMCHANGE(6);
}
// Total Level (0-127) (0.75dB step)
inline void Operator::SetTL(uint tl, bool csm)
{
if (!csm)
{
tl_ = tl, param_changed_ = true;
PARAMCHANGE(7);
}
tl_latch_ = tl;
}
// Attack Rate (0-63)
inline void Operator::SetAR(uint ar)
{
ar_ = ar;
param_changed_ = true;
PARAMCHANGE(8);
}
// Decay Rate (0-63)
inline void Operator::SetDR(uint dr)
{
dr_ = dr;
param_changed_ = true;
PARAMCHANGE(9);
}
// Sustain Rate (0-63)
inline void Operator::SetSR(uint sr)
{
sr_ = sr;
param_changed_ = true;
PARAMCHANGE(10);
}
// Sustain Level (0-127)
inline void Operator::SetSL(uint sl)
{
sl_ = sl;
param_changed_ = true;
PARAMCHANGE(11);
}
// Release Rate (0-63)
inline void Operator::SetRR(uint rr)
{
rr_ = rr;
param_changed_ = true;
PARAMCHANGE(12);
}
// Keyscale (0-3)
inline void Operator::SetKS(uint ks)
{
ks_ = ks;
param_changed_ = true;
PARAMCHANGE(13);
}
// SSG-type Envelop (0-15)
inline void Operator::SetSSGEC(uint ssgec)
{
if (ssgec & 8)
ssg_type_ = ssgec;
else
ssg_type_ = 0;
}
inline void Operator::SetAMON(bool amon)
{
amon_ = amon;
param_changed_ = true;
PARAMCHANGE(14);
}
inline void Operator::Mute(bool mute)
{
mute_ = mute;
param_changed_ = true;
PARAMCHANGE(15);
}
inline void Operator::SetMS(uint ms)
{
ms_ = ms;
param_changed_ = true;
PARAMCHANGE(16);
}
// ---------------------------------------------------------------------------
// 4-op Channel
// オペレータの種類 (LFO) を設定
inline void Channel4::SetType(OpType type)
{
for (int i=0; i<4; i++)
op[i].type_ = type;
}
// セルフ・フィードバックレートの設定 (0-7)
inline void Channel4::SetFB(uint feedback)
{
fb = fbtable[feedback];
}
// OPNA 系 LFO の設定
inline void Channel4::SetMS(uint ms)
{
op[0].SetMS(ms);
op[1].SetMS(ms);
op[2].SetMS(ms);
op[3].SetMS(ms);
}
// チャンネル・マスク
inline void Channel4::Mute(bool m)
{
for (int i=0; i<4; i++)
op[i].Mute(m);
}
// 内部パラメータを再計算
inline void Channel4::Refresh()
{
for (int i=0; i<4; i++)
op[i].param_changed_ = true;
PARAMCHANGE(3);
}
inline void Channel4::SetChip(Chip* chip)
{
chip_ = chip;
for (int i=0; i<4; i++)
op[i].SetChip(chip);
}
// ---------------------------------------------------------------------------
//
//
inline void StoreSample(Sample& dest, ISample data)
{
if (sizeof(Sample) == 2)
dest = (Sample) Limit(dest + data, 0x7fff, -0x8000);
else
dest += data;
}
// ---------------------------------------------------------------------------
// AM のレベルを設定
inline void Chip::SetAML(uint l)
{
aml_ = l & (FM_LFOENTS - 1);
}
// PM のレベルを設定
inline void Chip::SetPML(uint l)
{
pml_ = l & (FM_LFOENTS - 1);
}
}
#endif // FM_GEN_INL_H