├── gamdx ├── fmgen │ ├── readme.txt │ ├── headers.h │ ├── diag.h │ ├── fmtimer.h │ ├── misc.h │ ├── opm.h │ ├── fmtimer.cpp │ ├── fmgeninl.h │ ├── fmgen.h │ ├── opm.cpp │ └── fmgen.cpp ├── mxdrvg │ ├── so.cpp │ ├── opm_delegate.h │ ├── mxdrvg_depend.h │ ├── opm_delegate.cpp │ └── mxdrvg.h ├── types.h ├── pcm8 │ ├── global.h │ ├── pcm8.h │ ├── x68pcm8.h │ ├── x68pcm8.cpp │ └── pcm8.cpp ├── downsample │ ├── downsample.h │ ├── global.h │ ├── downsample.cpp │ └── lowpass_48.dat └── mame │ └── ym2151.h ├── CMakeLists.txt ├── LICENSE ├── README.md └── src └── mdx2wav.cpp /gamdx/fmgen/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mitsuman/mdx2wav/HEAD/gamdx/fmgen/readme.txt -------------------------------------------------------------------------------- /gamdx/fmgen/headers.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | -------------------------------------------------------------------------------- /gamdx/mxdrvg/so.cpp: -------------------------------------------------------------------------------- 1 | #define MXDRVG_EXPORT 2 | #define MXDRVG_CALLBACK 3 | 4 | volatile unsigned char OpmReg1B; // OPM レジスタ $1B の内容 5 | 6 | #include "mxdrvg_core.h" 7 | 8 | 9 | -------------------------------------------------------------------------------- /gamdx/fmgen/diag.h: -------------------------------------------------------------------------------- 1 | #ifndef incl_diag_h 2 | #define incl_diag_h 3 | 4 | #define LOG0(m) void (0) 5 | #define LOG1(m,a) void (0) 6 | #define LOG2(m,a,b) void (0) 7 | #define LOG3(m,a,b,c) void (0) 8 | #define LOG4(m,a,b,c,d) void (0) 9 | #define LOG5(m,a,b,c,d,e) void (0) 10 | #define LOG6(m,a,b,c,d,e,f) void (0) 11 | #define LOG7(m,a,b,c,d,e,f,g) void (0) 12 | #define LOG8(m,a,b,c,d,e,f,g,h) void (0) 13 | #define LOG9(m,a,b,c,d,e,f,g,h,i) void (0) 14 | 15 | #endif // incl_diag_h 16 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | cmake_minimum_required(VERSION 2.8) 3 | 4 | project(mdx2wav) 5 | 6 | set(CMAKE_C_FLAGS_RELEASE "-Wall -O3") 7 | set(CMAKE_CXX_FLAGS_RELEASE "-Wall -O3") 8 | set(CMAKE_C_FLAGS_DEBUG "-Wall -g") 9 | set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g") 10 | 11 | add_executable(mdx2wav 12 | src/mdx2wav.cpp 13 | gamdx/downsample/downsample.cpp 14 | gamdx/fmgen/fmgen.cpp 15 | gamdx/fmgen/fmtimer.cpp 16 | gamdx/fmgen/opm.cpp 17 | gamdx/mxdrvg/so.cpp 18 | gamdx/mxdrvg/opm_delegate.cpp 19 | gamdx/pcm8/pcm8.cpp 20 | gamdx/pcm8/x68pcm8.cpp 21 | gamdx/mame/ym2151.c 22 | ) 23 | 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 mitsuman 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /gamdx/types.h: -------------------------------------------------------------------------------- 1 | #if !defined(__FMXDRVG_TYPES_H__) 2 | #define __FMXDRVG_TYPES_H__ 3 | 4 | typedef unsigned char uchar; 5 | typedef unsigned short ushort; 6 | typedef unsigned int uint; 7 | typedef unsigned long ulong; 8 | 9 | typedef unsigned char uint8; 10 | typedef unsigned short uint16; 11 | typedef unsigned int uint32; 12 | 13 | typedef signed char sint8; 14 | typedef signed short sint16; 15 | typedef signed int sint32; 16 | 17 | typedef signed char int8; 18 | typedef signed short int16; 19 | typedef signed int int32; 20 | 21 | typedef int16 MXDRVG_SAMPLETYPE; // int16 or int32 22 | 23 | #endif // __FMXDRVG_TYPES_H__ 24 | -------------------------------------------------------------------------------- /gamdx/mxdrvg/opm_delegate.h: -------------------------------------------------------------------------------- 1 | #if !defined(__OPM_DELEGTE__) 2 | #define __OPM_DELEGTE__ 3 | 4 | #include "../types.h" 5 | 6 | class OPM_Delegate { 7 | public: 8 | static OPM_Delegate *getFmgen(); 9 | static OPM_Delegate *getMame(); 10 | typedef void CALLBACK(void); 11 | 12 | virtual ~OPM_Delegate() {} 13 | 14 | // Timer 15 | virtual void Reset() = 0; 16 | virtual bool Count(int32 us) = 0; 17 | virtual int32 GetNextEvent() = 0; 18 | 19 | // OPM 20 | virtual bool Init(uint c, uint r, bool filter = false) = 0; 21 | //virtual void SetLPFCutoff(uint freq) = 0; 22 | virtual void SetReg(uint addr, uint data) = 0; 23 | //virtual uint GetReg(uint addr) = 0; 24 | virtual uint ReadStatus() = 0; 25 | virtual void Mix(short* buffer, int nsamples) = 0; 26 | virtual void SetVolume(int db) = 0; 27 | //virtual void SetChannelMask(uint mask) = 0; 28 | virtual void SetIrqCallback(CALLBACK *callback) = 0; 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /gamdx/pcm8/global.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #if !defined(__FMXDRVG_PCM8_GLOBAL_H__) 8 | #define __FMXDRVG_PCM8_GLOBAL_H__ 9 | 10 | 11 | 12 | #define PCM8_NCH 8 // チャンネル数 13 | 14 | 15 | static int dltLTBL[48+1]= { 16 | 16,17,19,21,23,25,28,31,34,37,41,45,50,55,60,66, 17 | 73,80,88,97,107,118,130,143,157,173,190,209,230,253,279,307, 18 | 337,371,408,449,494,544,598,658,724,796,876,963,1060,1166,1282,1411,1552, 19 | }; 20 | static int DCT[16]= { 21 | -1,-1,-1,-1,2,4,6,8, 22 | -1,-1,-1,-1,2,4,6,8, 23 | }; 24 | 25 | static int ADPCMRATETBL[2][4] = { 26 | 2, 3, 4, 4, 27 | 0, 1, 2, 2, 28 | }; 29 | static int ADPCMRATEADDTBL[8] = { 30 | 46875, 62500, 93750, 125000, 15625*12, 15625*12, 15625*12, 0, 31 | }; 32 | static int PCM8VOLTBL[16] = { 33 | 2,3,4,5,6,8,10,12,16,20,24,32,40,48,64,80, 34 | }; 35 | 36 | 37 | #endif // __FMXDRVG_PCM8_GLOBAL_H__ 38 | 39 | 40 | // [EOF] 41 | -------------------------------------------------------------------------------- /gamdx/downsample/downsample.h: -------------------------------------------------------------------------------- 1 | #if !defined(__FMXDRVG_DOWNSAMPLE_H__) 2 | #define __FMXDRVG_DOWNSAMPLE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define LPF_COL 64 11 | 12 | #include "../types.h" 13 | 14 | namespace X68K 15 | { 16 | typedef MXDRVG_SAMPLETYPE Sample; 17 | typedef int32 ISample; 18 | 19 | class DOWNSAMPLE 20 | { 21 | public: 22 | DOWNSAMPLE(); 23 | ~DOWNSAMPLE() {} 24 | 25 | bool Init(int inrate, int outrate, bool fastmode); 26 | bool SetRate(int inrate, int outrate, bool fastmode); 27 | void Reset(); 28 | 29 | void DownSample(Sample *inbuf, int noutsamples, Sample *outbuf); 30 | int GetInSamplesForDownSample(int noutsamples); 31 | 32 | private: 33 | double inpfirbuf_dummy; 34 | sint16 InpFirBuf0[LPF_COL*2]; 35 | sint16 InpFirBuf1[LPF_COL*2]; 36 | int InpFir_idx; 37 | int LPFidx; 38 | sint16 *LPFp; 39 | int LPFc; 40 | int PreFirRate; 41 | int PostFirRate; 42 | bool FastMode; 43 | 44 | #if 0 45 | int InpInpOpm[2]; 46 | int InpOpm[2]; 47 | int InpInpOpm_prev[2]; 48 | int InpOpm_prev[2]; 49 | int InpInpOpm_prev2[2]; 50 | int InpOpm_prev2[2]; 51 | int OpmHpfInp[2]; 52 | int OpmHpfInp_prev[2]; 53 | int OpmHpfOut[2];; 54 | #endif 55 | 56 | }; 57 | } 58 | 59 | #endif // __FMXDRVG_DOWNSAMPLE_H__ 60 | 61 | // [EOF] 62 | -------------------------------------------------------------------------------- /gamdx/fmgen/fmtimer.h: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // FM sound generator common timer module 3 | // Copyright (C) cisc 1998, 2000. 4 | // --------------------------------------------------------------------------- 5 | // $Id: fmtimer.h,v 1.2 2003/04/22 13:12:53 cisc Exp $ 6 | 7 | #ifndef FM_TIMER_H 8 | #define FM_TIMER_H 9 | 10 | #include "../types.h" 11 | 12 | // --------------------------------------------------------------------------- 13 | 14 | namespace FM 15 | { 16 | class Timer 17 | { 18 | public: 19 | void Reset(); 20 | bool Count(int32 us); 21 | int32 GetNextEvent(); 22 | 23 | protected: 24 | virtual void SetStatus(uint bit) = 0; 25 | virtual void ResetStatus(uint bit) = 0; 26 | 27 | void SetTimerBase(uint clock); 28 | void SetTimerA(uint addr, uint data); 29 | void SetTimerB(uint data); 30 | void SetTimerControl(uint data); 31 | 32 | uint8 status; 33 | uint8 regtc; 34 | 35 | private: 36 | virtual void TimerA() {} 37 | uint8 regta[2]; 38 | 39 | int32 timera, timera_count; 40 | int32 timerb, timerb_count; 41 | int32 timer_step; 42 | }; 43 | 44 | // --------------------------------------------------------------------------- 45 | // 初期化 46 | // 47 | inline void Timer::Reset() 48 | { 49 | timera_count = 0; 50 | timerb_count = 0; 51 | } 52 | 53 | } // namespace FM 54 | 55 | #endif // FM_TIMER_H 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mdx2wav 2 | 3 | mdx2wav is a converter to make raw pcm data from MDX file on Linux. 4 | 5 | MDX is a major sound format of Sharp X68000 in the 1990s. 6 | 7 | ## Usage 8 | 9 | mdx2wav dumps 16bit stereo 44.1kHz pcm data to stdout, so you need to use it with other commands. 10 | 11 | To Play now, 12 | ```shell 13 | mdx2wav xxx.mdx | aplay -f cd 14 | ``` 15 | 16 | To convert to other format, 17 | ```shell 18 | mdx2wav xxx.mdx | ffmpeg -f s16le -ar 44.1k -ac 2 -i - xxx.wav 19 | mdx2wav xxx.mdx | ffmpeg -f s16le -ar 44.1k -ac 2 -i - -ab 192 -f ogg file.ogg 20 | ``` 21 | 22 | ### Options 23 | 24 | ```shell 25 | -d : limit song duration. 0 means nolimit. (default:300) 26 | -e : set ym2151 emulation type, fmgen or mame. (default:fmgen) 27 | -f : enable fadeout. 28 | -l : set loop limit. (default:2) 29 | -m : measure play time as sec. 30 | -r : set sampling rate. (default:44100) 31 | -t : get song title (charset is SHIFT-JIS). 32 | if you need other charset, try following command: 33 | mdx2wav -t xxx.mdx | iconv -f SHIFT-JIS -t utf-8 34 | -v : print version. 35 | -V : verbose, write debug log to stderr. 36 | 37 | ``` 38 | 39 | ## Build 40 | 41 | ```shell 42 | git clone https://github.com/mitsuman/mdx2wav.git 43 | cd mdx2wav 44 | mkdir Release 45 | cd Release 46 | cmake -DCMAKE_BUILD_TYPE=Release .. 47 | make 48 | ``` 49 | -------------------------------------------------------------------------------- /gamdx/fmgen/misc.h: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // misc.h 3 | // Copyright (C) cisc 1998, 1999. 4 | // --------------------------------------------------------------------------- 5 | // $Id: misc.h,v 1.5 2002/05/31 09:45:20 cisc Exp $ 6 | 7 | #ifndef MISC_H 8 | #define MISC_H 9 | 10 | inline int Max(int x, int y) { return (x > y) ? x : y; } 11 | inline int Min(int x, int y) { return (x < y) ? x : y; } 12 | inline int Abs(int x) { return x >= 0 ? x : -x; } 13 | 14 | inline int Limit(int v, int max, int min) 15 | { 16 | return v > max ? max : (v < min ? min : v); 17 | } 18 | 19 | inline unsigned int BSwap(unsigned int a) 20 | { 21 | return (a >> 24) | ((a >> 8) & 0xff00) | ((a << 8) & 0xff0000) | (a << 24); 22 | } 23 | 24 | inline unsigned int NtoBCD(unsigned int a) 25 | { 26 | return ((a / 10) << 4) + (a % 10); 27 | } 28 | 29 | inline unsigned int BCDtoN(unsigned int v) 30 | { 31 | return (v >> 4) * 10 + (v & 15); 32 | } 33 | 34 | 35 | template 36 | inline T gcd(T x, T y) 37 | { 38 | T t; 39 | while (y) 40 | { 41 | t = x % y; 42 | x = y; 43 | y = t; 44 | } 45 | return x; 46 | } 47 | 48 | 49 | template 50 | T bessel0(T x) 51 | { 52 | T p, r, s; 53 | 54 | r = 1.0; 55 | s = 1.0; 56 | p = (x / 2.0) / s; 57 | 58 | while (p > 1.0E-10) 59 | { 60 | r += p * p; 61 | s += 1.0; 62 | p *= (x / 2.0) / s; 63 | } 64 | return r; 65 | } 66 | 67 | 68 | #endif // MISC_H 69 | 70 | -------------------------------------------------------------------------------- /gamdx/mxdrvg/mxdrvg_depend.h: -------------------------------------------------------------------------------- 1 | // MXDRVG.DLL X68000-depend header 2 | // Copyright (C) 2000 GORRY. 3 | 4 | #ifndef __MXDRVG_DEPEND_H__ 5 | #define __MXDRVG_DEPEND_H__ 6 | 7 | typedef unsigned char UBYTE; 8 | typedef unsigned short UWORD; 9 | typedef unsigned long ULONG; 10 | typedef signed char SBYTE; 11 | typedef signed short SWORD; 12 | typedef signed long SLONG; 13 | 14 | typedef long long LONGLONG; 15 | #define TEXT(a) (a) 16 | typedef char TCHAR; 17 | 18 | typedef SWORD MXDRVG_SAMPLETYPE; 19 | typedef MXDRVG_SAMPLETYPE Sample; 20 | 21 | #if !defined(MXDRVG_CALLBACK) 22 | #define MXDRVG_CALLBACK 23 | #endif 24 | 25 | #define FALSE 0 26 | #define TRUE 1 27 | 28 | typedef struct __X68REG { 29 | ULONG d0; 30 | ULONG d1; 31 | ULONG d2; 32 | ULONG d3; 33 | ULONG d4; 34 | ULONG d5; 35 | ULONG d6; 36 | ULONG d7; 37 | UBYTE *a0; 38 | UBYTE *a1; 39 | UBYTE *a2; 40 | UBYTE *a3; 41 | UBYTE *a4; 42 | UBYTE *a5; 43 | UBYTE *a6; 44 | UBYTE *a7; 45 | } X68REG; 46 | 47 | #define SET 255 48 | #define CLR 0 49 | #define GETBWORD(a) ((((UBYTE *)(a))[0]*256)+(((UBYTE *)(a))[1])) 50 | #define GETBLONG(a) ((((UBYTE *)(a))[0]*16777216)+(((UBYTE *)(a))[1]*65536)+(((UBYTE *)(a))[2]*256)+(((UBYTE *)(a))[3])) 51 | #define PUTBWORD(a,b) ((((UBYTE *)(a))[0]=(UBYTE)((b)>> 8)),(((UBYTE *)(a))[1]=(UBYTE)((b)>> 0))) 52 | #define PUTBLONG(a,b) ((((UBYTE *)(a))[0]=(UBYTE)((b)>>24)),(((UBYTE *)(a))[1]=(UBYTE)((b)>>16)), (((UBYTE *)(a))[2]=(UBYTE)((b)>> 8)), (((UBYTE *)(a))[3]=(UBYTE)((b)>> 0))) 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | #endif //__MXDRVG_DEPEND_H__ 64 | -------------------------------------------------------------------------------- /gamdx/pcm8/pcm8.h: -------------------------------------------------------------------------------- 1 | #if !defined(__FMXDRVG_PCM8_H__) 2 | #define __FMXDRVG_PCM8_H__ 3 | 4 | namespace X68K 5 | { 6 | 7 | 8 | class Pcm8 { 9 | static const int TotalVolume = 256; 10 | 11 | int Scale; // 12 | int Pcm; // 16bit PCM Data 13 | int Pcm16Prev; // 16bit,8bitPCMの1つ前のデータ 14 | int InpPcm,InpPcm_prev,OutPcm; // HPF用 16bit PCM Data 15 | int OutInpPcm,OutInpPcm_prev; // HPF用 16 | int AdpcmRate; // 187500(15625*12), 125000(10416.66*12), 93750(7812.5*12), 62500(5208.33*12), 46875(3906.25*12), ... 17 | int RateCounter; 18 | int N1Data; // ADPCM 1サンプルのデータの保存 19 | int N1DataFlag; // 0 or 1 20 | 21 | volatile int Mode; 22 | volatile int Volume; // x/16 23 | volatile int PcmKind; // 0〜4:ADPCM 5:16bitPCM 6:8bitPCM 7:謎 24 | 25 | unsigned char DmaLastValue; 26 | unsigned char AdpcmReg; 27 | 28 | volatile unsigned char *DmaMar; 29 | volatile unsigned int DmaMtc; 30 | volatile unsigned char *DmaBar; 31 | volatile unsigned int DmaBtc; 32 | volatile int DmaOcr; // 0:チェイン動作なし 0x08:アレイチェイン 0x0C:リンクアレイチェイン 33 | 34 | int DmaArrayChainSetNextMtcMar(); 35 | int DmaLinkArrayChainSetNextMtcMar(); 36 | int DmaGetByte(); 37 | void adpcm2pcm(unsigned char adpcm); 38 | void pcm16_2pcm(int pcm16); 39 | 40 | public: 41 | 42 | Pcm8(void); 43 | ~Pcm8() {}; 44 | void Init(); 45 | void Reset(); 46 | 47 | int Out(void *adrs, int mode, int len); 48 | int Aot(void *tbl, int mode, int cnt); 49 | int Lot(void *tbl, int mode); 50 | int SetMode(int mode); 51 | int GetRest(); 52 | int GetMode(); 53 | 54 | int GetPcm22(); 55 | int GetPcm62(); 56 | 57 | }; 58 | 59 | } 60 | 61 | #endif // __FMXDRVG_PCM8_H__ 62 | 63 | // [EOF] 64 | -------------------------------------------------------------------------------- /gamdx/pcm8/x68pcm8.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../types.h" 8 | #include "global.h" 9 | #include "pcm8.h" 10 | 11 | namespace X68K 12 | { 13 | typedef MXDRVG_SAMPLETYPE Sample; 14 | typedef int32 ISample; 15 | 16 | class X68PCM8 17 | { 18 | public: 19 | X68PCM8(); 20 | ~X68PCM8() {} 21 | 22 | bool Init(uint rate); 23 | bool SetRate(uint rate); 24 | void Reset(); 25 | 26 | int Out(int ch, void *adrs, int mode, int len); 27 | void Abort(); 28 | 29 | void Mix(Sample *buffer, int nsamples); 30 | void SetVolume(int db); 31 | void SetChannelMask(uint mask); 32 | 33 | private: 34 | Pcm8 mPcm8[PCM8_NCH]; 35 | uint mMask; 36 | int mVolume; 37 | int mSampleRate; 38 | 39 | sint32 OutInpAdpcm[2]; 40 | sint32 OutInpAdpcm_prev[2]; 41 | sint32 OutInpAdpcm_prev2[2]; 42 | sint32 OutOutAdpcm[2]; 43 | sint32 OutOutAdpcm_prev[2]; 44 | sint32 OutOutAdpcm_prev2[2]; // 高音フィルター2用バッファ 45 | 46 | sint32 OutInpOutAdpcm[2]; 47 | sint32 OutInpOutAdpcm_prev[2]; 48 | sint32 OutInpOutAdpcm_prev2[2]; 49 | sint32 OutOutInpAdpcm[2]; 50 | sint32 OutOutInpAdpcm_prev[2]; // 高音フィルター3用バッファ 51 | 52 | inline void pcmset62500(Sample* buffer, int ndata); 53 | inline void pcmset22050(Sample* buffer, int ndata); 54 | 55 | }; 56 | 57 | inline int Max(int x, int y) { return (x > y) ? x : y; } 58 | inline int Min(int x, int y) { return (x < y) ? x : y; } 59 | inline int Abs(int x) { return x >= 0 ? x : -x; } 60 | 61 | inline int Limit(int v, int max, int min) 62 | { 63 | return v > max ? max : (v < min ? min : v); 64 | } 65 | 66 | inline void StoreSample(Sample& dest, ISample data) 67 | { 68 | if (sizeof(Sample) == 2) 69 | dest = (Sample) Limit(dest + data, 0x7fff, -0x8000); 70 | else 71 | dest += data; 72 | } 73 | 74 | } 75 | 76 | // [EOF] 77 | -------------------------------------------------------------------------------- /gamdx/mame/ym2151.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** File: ym2151.h - header file for software implementation of YM2151 3 | ** FM Operator Type-M(OPM) 4 | ** 5 | ** (c) 1997-2002 Jarek Burczynski (s0246@poczta.onet.pl, bujar@mame.net) 6 | ** Some of the optimizing ideas by Tatsuyuki Satoh 7 | ** 8 | ** Version 2.150 final beta May, 11th 2002 9 | ** 10 | ** 11 | ** I would like to thank following people for making this project possible: 12 | ** 13 | ** Beauty Planets - for making a lot of real YM2151 samples and providing 14 | ** additional informations about the chip. Also for the time spent making 15 | ** the samples and the speed of replying to my endless requests. 16 | ** 17 | ** Shigeharu Isoda - for general help, for taking time to scan his YM2151 18 | ** Japanese Manual first of all, and answering MANY of my questions. 19 | ** 20 | ** Nao - for giving me some info about YM2151 and pointing me to Shigeharu. 21 | ** Also for creating fmemu (which I still use to test the emulator). 22 | ** 23 | ** Aaron Giles and Chris Hardy - they made some samples of one of my favourite 24 | ** arcade games so I could compare it to my emulator. 25 | ** 26 | ** Bryan McPhail and Tim (powerjaw) - for making some samples. 27 | ** 28 | ** Ishmair - for the datasheet and motivation. 29 | */ 30 | 31 | #pragma once 32 | 33 | #ifndef __YM2151_H__ 34 | #define __YM2151_H__ 35 | 36 | typedef void device_t; 37 | typedef short stream_sample_t; 38 | typedef int offs_t; 39 | typedef unsigned char UINT8; 40 | 41 | /* 16- and 8-bit samples (signed) are supported*/ 42 | #define SAMPLE_BITS 16 43 | 44 | typedef stream_sample_t SAMP; 45 | /* 46 | #if (SAMPLE_BITS==16) 47 | typedef INT16 SAMP; 48 | #endif 49 | #if (SAMPLE_BITS==8) 50 | typedef signed char SAMP; 51 | #endif 52 | */ 53 | 54 | /* 55 | ** Initialize YM2151 emulator(s). 56 | ** 57 | ** 'num' is the number of virtual YM2151's to allocate 58 | ** 'clock' is the chip clock in Hz 59 | ** 'rate' is sampling rate 60 | */ 61 | void *ym2151_init(device_t *device, int clock, int rate); 62 | 63 | /* shutdown the YM2151 emulators*/ 64 | void ym2151_shutdown(void *chip); 65 | 66 | /* reset all chip registers for YM2151 number 'num'*/ 67 | void ym2151_reset_chip(void *chip); 68 | 69 | void ym2151_set_volume(void *chip, int db); 70 | 71 | /* 72 | ** Generate samples for one of the YM2151's 73 | ** 74 | ** 'num' is the number of virtual YM2151 75 | ** '*buffers' is a pointer to the buffers: left and right 76 | ** 'length' is the number of samples that should be generated 77 | */ 78 | void ym2151_update_one(void *chip, SAMP *buffers, int length); 79 | 80 | /* write 'v' to register 'r' on YM2151 chip number 'n'*/ 81 | void ym2151_write_reg(void *chip, int r, int v); 82 | 83 | /* read status register on YM2151 chip number 'n'*/ 84 | int ym2151_read_status(void *chip); 85 | 86 | /* set interrupt handler on YM2151 chip number 'n'*/ 87 | void ym2151_set_irq_handler(void *chip, void (*handler)(device_t *device, int irq)); 88 | 89 | /* set port write handler on YM2151 chip number 'n'*/ 90 | void ym2151_set_port_write_handler(void *chip, void (*handler)(device_t *, offs_t, UINT8)); 91 | 92 | #endif /*__YM2151_H__*/ 93 | -------------------------------------------------------------------------------- /gamdx/mxdrvg/opm_delegate.cpp: -------------------------------------------------------------------------------- 1 | #include "opm_delegate.h" 2 | #include "../fmgen/opm.h" 3 | 4 | extern "C" { 5 | #include "../mame/ym2151.h" 6 | } 7 | 8 | class OPMFmgen :public OPM_Delegate { 9 | public: 10 | OPMFmgen() {} 11 | 12 | protected: 13 | virtual ~OPMFmgen() {} 14 | 15 | virtual void Reset() { 16 | OPM.Reset(); 17 | } 18 | 19 | virtual bool Count(int32 us) { 20 | OPM.Count(us); 21 | return true; 22 | } 23 | 24 | virtual int32 GetNextEvent() { 25 | return OPM.GetNextEvent(); 26 | } 27 | 28 | virtual bool Init(uint c, uint r, bool f) { 29 | OPM.Init(c, r, f); 30 | return true; 31 | } 32 | 33 | virtual void SetReg(uint addr, uint data) { 34 | OPM.SetReg(addr, data); 35 | } 36 | 37 | /*virtual uint GetReg(uint addr) { 38 | return OPM.GetReg(addr); 39 | }*/ 40 | 41 | virtual uint ReadStatus() { 42 | return OPM.ReadStatus(); 43 | } 44 | 45 | virtual void Mix(short* buffer, int nsamples) { 46 | OPM.Mix(buffer, nsamples); 47 | } 48 | 49 | virtual void SetVolume(int db) { 50 | OPM.SetVolume(db); 51 | } 52 | 53 | virtual void SetIrqCallback(CALLBACK *cb) { 54 | OPM.callback = cb; 55 | } 56 | 57 | private: 58 | class X68OPM : public FM::OPM { 59 | public: 60 | virtual void Intr(bool irq) { 61 | if (irq) { 62 | if (callback) { 63 | callback(); 64 | } 65 | } 66 | } 67 | CALLBACK *callback; 68 | }; 69 | X68OPM OPM; 70 | }; 71 | 72 | OPM_Delegate *OPM_Delegate::getFmgen() { 73 | return new OPMFmgen(); 74 | } 75 | 76 | class OPMMame :public OPM_Delegate { 77 | public: 78 | OPMMame() {} 79 | 80 | protected: 81 | virtual ~OPMMame() { 82 | ym2151_shutdown(chip); 83 | } 84 | 85 | virtual void Reset() { 86 | ym2151_reset_chip(chip); 87 | } 88 | 89 | virtual bool Count(int32 us) { 90 | return false; 91 | } 92 | 93 | virtual int32 GetNextEvent() { 94 | return 0x100000; 95 | } 96 | 97 | virtual bool Init(uint c, uint r, bool f) { 98 | chip = ym2151_init(this, c, r); 99 | return true; 100 | } 101 | 102 | virtual void SetReg(uint addr, uint data) { 103 | ym2151_write_reg(chip, addr, data); 104 | } 105 | 106 | /*virtual uint GetReg(uint addr) { 107 | return OPM.GetReg(addr); 108 | }*/ 109 | 110 | virtual uint ReadStatus() { 111 | return ym2151_read_status(chip); 112 | } 113 | 114 | virtual void Mix(short* buffer, int nsamples) { 115 | ym2151_update_one(chip, buffer, nsamples); 116 | } 117 | 118 | virtual void SetVolume(int db) { 119 | ym2151_set_volume(chip, db); 120 | } 121 | 122 | static void irqHandler(device_t *device, int irq) { 123 | CALLBACK *cb = ((OPMMame*)device)->callback; 124 | if (cb && irq == 1) { 125 | cb(); 126 | } 127 | } 128 | 129 | virtual void SetIrqCallback(CALLBACK *cb) { 130 | callback = cb; 131 | ym2151_set_irq_handler(chip, irqHandler); 132 | } 133 | 134 | private: 135 | void *chip; 136 | CALLBACK *callback; 137 | }; 138 | 139 | OPM_Delegate *OPM_Delegate::getMame() { 140 | return new OPMMame(); 141 | } 142 | -------------------------------------------------------------------------------- /gamdx/fmgen/opm.h: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // OPM-like Sound Generator 3 | // Copyright (C) cisc 1998, 2003. 4 | // --------------------------------------------------------------------------- 5 | // $Id: opm.h,v 1.14 2003/06/07 08:25:53 cisc Exp $ 6 | 7 | #ifndef FM_OPM_H 8 | #define FM_OPM_H 9 | 10 | #include "fmgen.h" 11 | #include "fmtimer.h" 12 | 13 | // --------------------------------------------------------------------------- 14 | // class OPM 15 | // OPM に良く似た(?)音を生成する音源ユニット 16 | // 17 | // interface: 18 | // bool Init(uint clock, uint rate, bool); 19 | // 初期化.このクラスを使用する前にかならず呼んでおくこと. 20 | // 注意: 線形補完モードは廃止されました 21 | // 22 | // clock: OPM のクロック周波数(Hz) 23 | // 24 | // rate: 生成する PCM の標本周波数(Hz) 25 | // 26 | // 27 | // 返値 初期化に成功すれば true 28 | // 29 | // bool SetRate(uint clock, uint rate, bool) 30 | // クロックや PCM レートを変更する 31 | // 引数等は Init と同様. 32 | // 33 | // void Mix(Sample* dest, int nsamples) 34 | // Stereo PCM データを nsamples 分合成し, dest で始まる配列に 35 | // 加える(加算する) 36 | // ・dest には sample*2 個分の領域が必要 37 | // ・格納形式は L, R, L, R... となる. 38 | // ・あくまで加算なので,あらかじめ配列をゼロクリアする必要がある 39 | // ・FM_SAMPLETYPE が short 型の場合クリッピングが行われる. 40 | // ・この関数は音源内部のタイマーとは独立している. 41 | // Timer は Count と GetNextEvent で操作する必要がある. 42 | // 43 | // void Reset() 44 | // 音源をリセット(初期化)する 45 | // 46 | // void SetReg(uint reg, uint data) 47 | // 音源のレジスタ reg に data を書き込む 48 | // 49 | // uint ReadStatus() 50 | // 音源のステータスレジスタを読み出す 51 | // busy フラグは常に 0 52 | // 53 | // bool Count(uint32 t) 54 | // 音源のタイマーを t [10^(-6) 秒] 進める. 55 | // 音源の内部状態に変化があった時(timer オーバーフロー) 56 | // true を返す 57 | // 58 | // uint32 GetNextEvent() 59 | // 音源のタイマーのどちらかがオーバーフローするまでに必要な 60 | // 時間[μ秒]を返す 61 | // タイマーが停止している場合は 0 を返す. 62 | // 63 | // void SetVolume(int db) 64 | // 各音源の音量を+−方向に調節する.標準値は 0. 65 | // 単位は約 1/2 dB,有効範囲の上限は 20 (10dB) 66 | // 67 | // 仮想関数: 68 | // virtual void Intr(bool irq) 69 | // IRQ 出力に変化があった場合呼ばれる. 70 | // irq = true: IRQ 要求が発生 71 | // irq = false: IRQ 要求が消える 72 | // 73 | namespace FM 74 | { 75 | // YM2151(OPM) ---------------------------------------------------- 76 | class OPM : public Timer 77 | { 78 | public: 79 | OPM(); 80 | ~OPM() {} 81 | 82 | bool Init(uint c, uint r, bool=false); 83 | bool SetRate(uint c, uint r, bool); 84 | void SetLPFCutoff(uint freq); 85 | void Reset(); 86 | 87 | void SetReg(uint addr, uint data); 88 | uint GetReg(uint addr); 89 | uint ReadStatus() { return status & 0x03; } 90 | 91 | void Mix(Sample* buffer, int nsamples); 92 | 93 | void SetVolume(int db); 94 | void SetChannelMask(uint mask); 95 | 96 | private: 97 | virtual void Intr(bool) {} 98 | 99 | private: 100 | enum 101 | { 102 | OPM_LFOENTS = 512, 103 | }; 104 | 105 | void SetStatus(uint bit); 106 | void ResetStatus(uint bit); 107 | void SetParameter(uint addr, uint data); 108 | void TimerA(); 109 | void RebuildTimeTable(); 110 | void MixSub(int activech, ISample**); 111 | void MixSubL(int activech, ISample**); 112 | void LFO(); 113 | uint Noise(); 114 | 115 | int fmvolume; 116 | 117 | uint clock; 118 | uint rate; 119 | uint filter; 120 | 121 | uint pmd; 122 | uint amd; 123 | uint lfocount; 124 | uint lfodcount; 125 | 126 | uint lfo_count_; 127 | uint lfo_count_diff_; 128 | uint lfo_step_; 129 | uint lfo_count_prev_; 130 | 131 | uint lfowaveform; 132 | uint rateratio; 133 | uint noise; 134 | int32 noisecount; 135 | uint32 noisedelta; 136 | 137 | bool interpolation; 138 | uint8 lfofreq; 139 | uint8 status; 140 | uint8 reg01; 141 | 142 | uint8 kc[8]; 143 | uint8 kf[8]; 144 | uint8 pan[8]; 145 | 146 | Channel4 ch[8]; 147 | Chip chip; 148 | 149 | static void BuildLFOTable(); 150 | static int amtable[4][OPM_LFOENTS]; 151 | static int pmtable[4][OPM_LFOENTS]; 152 | 153 | int InpInpOpm[2]; 154 | int InpOpm[2]; 155 | int InpInpOpm_prev[2]; 156 | int InpOpm_prev[2]; 157 | int InpInpOpm_prev2[2]; 158 | int InpOpm_prev2[2]; 159 | int OpmHpfInp[2]; 160 | int OpmHpfInp_prev[2]; 161 | int OpmHpfOut[2];; 162 | 163 | public: 164 | int dbgGetOpOut(int c, int s) { return ch[c].op[s].dbgopout_; } 165 | Channel4* dbgGetCh(int c) { return &ch[c]; } 166 | 167 | }; 168 | } 169 | 170 | #endif // FM_OPM_H 171 | -------------------------------------------------------------------------------- /gamdx/fmgen/fmtimer.cpp: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // FM sound generator common timer module 3 | // Copyright (C) cisc 1998, 2000. 4 | // --------------------------------------------------------------------------- 5 | // $Id: fmtimer.cpp,v 1.1 2000/09/08 13:45:56 cisc Exp $ 6 | 7 | #include "headers.h" 8 | #include "fmtimer.h" 9 | 10 | using namespace FM; 11 | 12 | // --------------------------------------------------------------------------- 13 | // タイマー制御 14 | // 15 | void Timer::SetTimerControl(uint data) 16 | { 17 | uint tmp = regtc ^ data; 18 | regtc = uint8(data); 19 | 20 | if (data & 0x10) 21 | ResetStatus(1); 22 | if (data & 0x20) 23 | ResetStatus(2); 24 | 25 | if (tmp & 0x01) 26 | timera_count = (data & 1) ? timera : 0; 27 | if (tmp & 0x02) 28 | timerb_count = (data & 2) ? timerb : 0; 29 | } 30 | 31 | #if 1 32 | 33 | // --------------------------------------------------------------------------- 34 | // タイマーA 周期設定 35 | // 36 | void Timer::SetTimerA(uint addr, uint data) 37 | { 38 | uint tmp; 39 | regta[addr & 1] = uint8(data); 40 | tmp = (regta[0] << 2) + (regta[1] & 3); 41 | timera = (1024-tmp) * timer_step; 42 | // LOG2("Timer A = %d %d us\n", tmp, timera >> 16); 43 | } 44 | 45 | // --------------------------------------------------------------------------- 46 | // タイマーB 周期設定 47 | // 48 | void Timer::SetTimerB(uint data) 49 | { 50 | timerb = (256-data) * timer_step; 51 | // LOG2("Timer B = %d %d us\n", data, timerb >> 12); 52 | } 53 | 54 | // --------------------------------------------------------------------------- 55 | // タイマー時間処理 56 | // 57 | bool Timer::Count(int32 us) 58 | { 59 | bool event = false; 60 | 61 | if (timera_count) 62 | { 63 | timera_count -= us << 16; 64 | if (timera_count <= 0) 65 | { 66 | event = true; 67 | TimerA(); 68 | 69 | while (timera_count <= 0) 70 | timera_count += timera; 71 | 72 | if (regtc & 4) 73 | SetStatus(1); 74 | } 75 | } 76 | if (timerb_count) 77 | { 78 | timerb_count -= us << 12; 79 | if (timerb_count <= 0) 80 | { 81 | event = true; 82 | while (timerb_count <= 0) 83 | timerb_count += timerb; 84 | 85 | if (regtc & 8) 86 | SetStatus(2); 87 | } 88 | } 89 | return event; 90 | } 91 | 92 | // --------------------------------------------------------------------------- 93 | // 次にタイマーが発生するまでの時間を求める 94 | // 95 | int32 Timer::GetNextEvent() 96 | { 97 | uint32 ta = ((timera_count + 0xffff) >> 16) - 1; 98 | uint32 tb = ((timerb_count + 0xfff) >> 12) - 1; 99 | return (ta < tb ? ta : tb) + 1; 100 | } 101 | 102 | // --------------------------------------------------------------------------- 103 | // タイマー基準値設定 104 | // 105 | void Timer::SetTimerBase(uint clock) 106 | { 107 | timer_step = int32(1000000. * 65536 / clock); 108 | } 109 | 110 | #else 111 | 112 | // --------------------------------------------------------------------------- 113 | // タイマーA 周期設定 114 | // 115 | void Timer::SetTimerA(uint addr, uint data) 116 | { 117 | regta[addr & 1] = uint8(data); 118 | timera = (1024 - ((regta[0] << 2) + (regta[1] & 3))) << 16; 119 | } 120 | 121 | // --------------------------------------------------------------------------- 122 | // タイマーB 周期設定 123 | // 124 | void Timer::SetTimerB(uint data) 125 | { 126 | timerb = (256-data) << (16 + 4); 127 | } 128 | 129 | // --------------------------------------------------------------------------- 130 | // タイマー時間処理 131 | // 132 | bool Timer::Count(int32 us) 133 | { 134 | bool event = false; 135 | 136 | int tick = us * timer_step; 137 | 138 | if (timera_count) 139 | { 140 | timera_count -= tick; 141 | if (timera_count <= 0) 142 | { 143 | event = true; 144 | TimerA(); 145 | 146 | while (timera_count <= 0) 147 | timera_count += timera; 148 | 149 | if (regtc & 4) 150 | SetStatus(1); 151 | } 152 | } 153 | if (timerb_count) 154 | { 155 | timerb_count -= tick; 156 | if (timerb_count <= 0) 157 | { 158 | event = true; 159 | while (timerb_count <= 0) 160 | timerb_count += timerb; 161 | 162 | if (regtc & 8) 163 | SetStatus(2); 164 | } 165 | } 166 | return event; 167 | } 168 | 169 | // --------------------------------------------------------------------------- 170 | // 次にタイマーが発生するまでの時間を求める 171 | // 172 | int32 Timer::GetNextEvent() 173 | { 174 | uint32 ta = timera_count - 1; 175 | uint32 tb = timerb_count - 1; 176 | uint32 t = (ta < tb ? ta : tb) + 1; 177 | 178 | return (t+timer_step-1) / timer_step; 179 | } 180 | 181 | // --------------------------------------------------------------------------- 182 | // タイマー基準値設定 183 | // 184 | void Timer::SetTimerBase(uint clock) 185 | { 186 | timer_step = clock * 1024 / 15625; 187 | } 188 | 189 | #endif 190 | -------------------------------------------------------------------------------- /gamdx/downsample/global.h: -------------------------------------------------------------------------------- 1 | #if !defined(__FMXDRVG_DOWNSAMPLE_GLOBAL_H__) 2 | #define __FMXDRVG_DOWNSAMPLE_GLOBAL_H__ 3 | 4 | #if defined(__GNUC__) 5 | #pragma GCC diagnostic push 6 | #pragma GCC diagnostic ignored "-Wmissing-braces" 7 | #define ALIGNED(x) __attribute__ ((aligned (x))) 8 | #elif defined(_MSC_VER) 9 | #define ALIGNED(x) __declspec(align(x)) 10 | #else 11 | #define ALIGNED(x) 12 | #endif 13 | 14 | #define LPF_ROW_44 441 15 | ALIGNED(8) static int16 LOWPASS_44[LPF_ROW_44][LPF_COL] = { 16 | #include "lowpass_44.dat" 17 | }; 18 | 19 | #define LPF_ROW_48 96 20 | ALIGNED(8) static int16 LOWPASS_48[LPF_ROW_48][LPF_COL] = { 21 | #include "lowpass_48.dat" 22 | }; 23 | 24 | #if defined(__GNUC__) 25 | #pragma GCC diagnostic pop 26 | #endif 27 | 28 | static int LPF_ROW = LPF_ROW_44; 29 | static int16 *LOWPASS = (int16 *)LOWPASS_44; 30 | 31 | 32 | inline void FirMatrix(sint16 *p, sint16 *buf0, sint16 *buf1, sint32 *result) { 33 | sint32 r; 34 | r = (int)buf0[0]*p[0] 35 | +(int)buf0[1]*p[1] 36 | +(int)buf0[2]*p[2] 37 | +(int)buf0[3]*p[3] 38 | +(int)buf0[4]*p[4] 39 | +(int)buf0[5]*p[5] 40 | +(int)buf0[6]*p[6] 41 | +(int)buf0[7]*p[7] 42 | +(int)buf0[8]*p[8] 43 | +(int)buf0[9]*p[9] 44 | +(int)buf0[10]*p[10] 45 | +(int)buf0[11]*p[11] 46 | +(int)buf0[12]*p[12] 47 | +(int)buf0[13]*p[13] 48 | +(int)buf0[14]*p[14] 49 | +(int)buf0[15]*p[15] 50 | +(int)buf0[16]*p[16] 51 | +(int)buf0[17]*p[17] 52 | +(int)buf0[18]*p[18] 53 | +(int)buf0[19]*p[19] 54 | +(int)buf0[20]*p[20] 55 | +(int)buf0[21]*p[21] 56 | +(int)buf0[22]*p[22] 57 | +(int)buf0[23]*p[23] 58 | +(int)buf0[24]*p[24] 59 | +(int)buf0[25]*p[25] 60 | +(int)buf0[26]*p[26] 61 | +(int)buf0[27]*p[27] 62 | +(int)buf0[28]*p[28] 63 | +(int)buf0[29]*p[29] 64 | +(int)buf0[30]*p[30] 65 | +(int)buf0[31]*p[31] 66 | +(int)buf0[32]*p[32] 67 | +(int)buf0[33]*p[33] 68 | +(int)buf0[34]*p[34] 69 | +(int)buf0[35]*p[35] 70 | +(int)buf0[36]*p[36] 71 | +(int)buf0[37]*p[37] 72 | +(int)buf0[38]*p[38] 73 | +(int)buf0[39]*p[39] 74 | +(int)buf0[40]*p[40] 75 | +(int)buf0[41]*p[41] 76 | +(int)buf0[42]*p[42] 77 | +(int)buf0[43]*p[43] 78 | +(int)buf0[44]*p[44] 79 | +(int)buf0[45]*p[45] 80 | +(int)buf0[46]*p[46] 81 | +(int)buf0[47]*p[47] 82 | +(int)buf0[48]*p[48] 83 | +(int)buf0[49]*p[49] 84 | +(int)buf0[50]*p[50] 85 | +(int)buf0[51]*p[51] 86 | +(int)buf0[52]*p[52] 87 | +(int)buf0[53]*p[53] 88 | +(int)buf0[54]*p[54] 89 | +(int)buf0[55]*p[55] 90 | +(int)buf0[56]*p[56] 91 | +(int)buf0[57]*p[57] 92 | +(int)buf0[58]*p[58] 93 | +(int)buf0[59]*p[59] 94 | +(int)buf0[60]*p[60] 95 | +(int)buf0[61]*p[61] 96 | +(int)buf0[62]*p[62] 97 | +(int)buf0[63]*p[63]; 98 | result[0] = r >> (16-1); 99 | r = (int)buf1[0]*p[0] 100 | +(int)buf1[1]*p[1] 101 | +(int)buf1[2]*p[2] 102 | +(int)buf1[3]*p[3] 103 | +(int)buf1[4]*p[4] 104 | +(int)buf1[5]*p[5] 105 | +(int)buf1[6]*p[6] 106 | +(int)buf1[7]*p[7] 107 | +(int)buf1[8]*p[8] 108 | +(int)buf1[9]*p[9] 109 | +(int)buf1[10]*p[10] 110 | +(int)buf1[11]*p[11] 111 | +(int)buf1[12]*p[12] 112 | +(int)buf1[13]*p[13] 113 | +(int)buf1[14]*p[14] 114 | +(int)buf1[15]*p[15] 115 | +(int)buf1[16]*p[16] 116 | +(int)buf1[17]*p[17] 117 | +(int)buf1[18]*p[18] 118 | +(int)buf1[19]*p[19] 119 | +(int)buf1[20]*p[20] 120 | +(int)buf1[21]*p[21] 121 | +(int)buf1[22]*p[22] 122 | +(int)buf1[23]*p[23] 123 | +(int)buf1[24]*p[24] 124 | +(int)buf1[25]*p[25] 125 | +(int)buf1[26]*p[26] 126 | +(int)buf1[27]*p[27] 127 | +(int)buf1[28]*p[28] 128 | +(int)buf1[29]*p[29] 129 | +(int)buf1[30]*p[30] 130 | +(int)buf1[31]*p[31] 131 | +(int)buf1[32]*p[32] 132 | +(int)buf1[33]*p[33] 133 | +(int)buf1[34]*p[34] 134 | +(int)buf1[35]*p[35] 135 | +(int)buf1[36]*p[36] 136 | +(int)buf1[37]*p[37] 137 | +(int)buf1[38]*p[38] 138 | +(int)buf1[39]*p[39] 139 | +(int)buf1[40]*p[40] 140 | +(int)buf1[41]*p[41] 141 | +(int)buf1[42]*p[42] 142 | +(int)buf1[43]*p[43] 143 | +(int)buf1[44]*p[44] 144 | +(int)buf1[45]*p[45] 145 | +(int)buf1[46]*p[46] 146 | +(int)buf1[47]*p[47] 147 | +(int)buf1[48]*p[48] 148 | +(int)buf1[49]*p[49] 149 | +(int)buf1[50]*p[50] 150 | +(int)buf1[51]*p[51] 151 | +(int)buf1[52]*p[52] 152 | +(int)buf1[53]*p[53] 153 | +(int)buf1[54]*p[54] 154 | +(int)buf1[55]*p[55] 155 | +(int)buf1[56]*p[56] 156 | +(int)buf1[57]*p[57] 157 | +(int)buf1[58]*p[58] 158 | +(int)buf1[59]*p[59] 159 | +(int)buf1[60]*p[60] 160 | +(int)buf1[61]*p[61] 161 | +(int)buf1[62]*p[62] 162 | +(int)buf1[63]*p[63]; 163 | result[1] = r >> (16-1); 164 | } 165 | 166 | #endif // __FMXDRVG_DOWNSAMPLE_GLOBAL_H__ 167 | 168 | // [EOF] 169 | -------------------------------------------------------------------------------- /gamdx/downsample/downsample.cpp: -------------------------------------------------------------------------------- 1 | #include "downsample.h" 2 | #include "global.h" 3 | 4 | 5 | namespace X68K 6 | { 7 | 8 | 9 | // --------------------------------------------------------------------------- 10 | // 構築 11 | // 12 | DOWNSAMPLE::DOWNSAMPLE() 13 | { 14 | Init(62500, 62500, true); 15 | } 16 | 17 | // --------------------------------------------------------------------------- 18 | // 初期化 19 | // 20 | bool DOWNSAMPLE::Init(int inrate, int outrate, bool fastmode) 21 | { 22 | SetRate(inrate, outrate, fastmode); 23 | 24 | for (int i=0; i= PostFirRate) { 113 | LPFidx -= PostFirRate; 114 | inbuf++; 115 | inbuf++; 116 | } 117 | } 118 | return; 119 | } 120 | 121 | for (int i=0; i= PostFirRate) { 125 | LPFidx -= PostFirRate; 126 | 127 | --InpFir_idx; 128 | if (InpFir_idx < 0) InpFir_idx = LPF_COL-1; 129 | #if 1 130 | InpFirBuf0[InpFir_idx] = InpFirBuf0[InpFir_idx+LPF_COL] = 131 | (sint16)*(inbuf++); 132 | InpFirBuf1[InpFir_idx] = InpFirBuf1[InpFir_idx+LPF_COL] = 133 | (sint16)*(inbuf++); 134 | #else 135 | OpmHpfInp[0] = ((sint16)*(inbuf++))<<14; 136 | OpmHpfInp[1] = ((sint16)*(inbuf++))<<14; 137 | 138 | OpmHpfOut[0] = OpmHpfInp[0]-OpmHpfInp_prev[0]+ 139 | OpmHpfOut[0]-(OpmHpfOut[0]>>10)-(OpmHpfOut[0]>>12); 140 | OpmHpfOut[1] = OpmHpfInp[1]-OpmHpfInp_prev[1]+ 141 | OpmHpfOut[1]-(OpmHpfOut[1]>>10)-(OpmHpfOut[1]>>12); 142 | 143 | OpmHpfInp_prev[0] = OpmHpfInp[0]; 144 | OpmHpfInp_prev[1] = OpmHpfInp[1]; 145 | 146 | InpInpOpm[0] = OpmHpfOut[0] >> (4+5); 147 | InpInpOpm[1] = OpmHpfOut[1] >> (4+5); 148 | 149 | InpInpOpm[0] = InpInpOpm[0]*29; 150 | InpInpOpm[1] = InpInpOpm[1]*29; 151 | 152 | InpOpm[0] = (InpInpOpm[0] + InpInpOpm_prev[0]+ 153 | InpOpm[0]*70) >> 7; 154 | InpOpm[1] = (InpInpOpm[1] + InpInpOpm_prev[1] + 155 | InpOpm[1]*70) >> 7; 156 | 157 | InpInpOpm_prev[0] = InpInpOpm[0]; 158 | InpInpOpm_prev[1] = InpInpOpm[1]; 159 | 160 | InpFirBuf0[InpFir_idx] = InpFirBuf0[InpFir_idx+LPF_COL] = 161 | InpOpm[0] >> 5; 162 | InpFirBuf1[InpFir_idx] = InpFirBuf1[InpFir_idx+LPF_COL] = 163 | InpOpm[1] >> 5; 164 | #endif 165 | 166 | } 167 | 168 | FirMatrix(LPFp, &InpFirBuf0[InpFir_idx], &InpFirBuf1[InpFir_idx], OutFir); 169 | 170 | if (LPFc) { 171 | LPFp += LPF_COL; 172 | LPFc--; 173 | if (LPFc == 0) { 174 | LPFc = LPF_ROW; 175 | LPFp = (int16 *)LOWPASS; 176 | } 177 | } 178 | 179 | sint32 out; 180 | out = -OutFir[0]; 181 | if ((uint32)(out+32767) > (uint32)(32767*2)) { 182 | if ((sint32)(out+32767) >= (sint32)(32767*2)) { 183 | *(outbuf++) = 32767; 184 | } else { 185 | *(outbuf++) = -32767; 186 | } 187 | } else { 188 | *(outbuf++) = (Sample)out; 189 | } 190 | 191 | out = -OutFir[1]; 192 | if ((uint32)(out+32767) > (uint32)(32767*2)) { 193 | if ((sint32)(out+32767) >= (sint32)(32767*2)) { 194 | *(outbuf++) = 32767; 195 | } else { 196 | *(outbuf++) = -32767; 197 | } 198 | } else { 199 | *(outbuf++) = (Sample)out; 200 | } 201 | } 202 | } 203 | 204 | 205 | // --------------------------------------------------------------------------- 206 | // ダウンサンプル出力数に必要な入力サンプル数を求める 207 | // 208 | int DOWNSAMPLE::GetInSamplesForDownSample(int noutsamples) 209 | { 210 | int n = LPFidx+(noutsamples*PreFirRate); 211 | // return ((n+PostFirRate-1)/PostFirRate); 212 | return (n/PostFirRate); 213 | } 214 | 215 | 216 | // --------------------------------------------------------------------------- 217 | } // namespace X68K 218 | 219 | // [EOF] 220 | -------------------------------------------------------------------------------- /gamdx/fmgen/fmgeninl.h: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // FM Sound Generator 3 | // Copyright (C) cisc 1998, 2003. 4 | // --------------------------------------------------------------------------- 5 | // $Id: fmgeninl.h,v 1.26 2003/06/12 13:14:36 cisc Exp $ 6 | 7 | #ifndef FM_GEN_INL_H 8 | #define FM_GEN_INL_H 9 | 10 | // --------------------------------------------------------------------------- 11 | // 定数その2 12 | // 13 | #define FM_PI 3.14159265358979323846 14 | 15 | #define FM_SINEPRESIS 2 // EGとサイン波の精度の差 0(低)-2(高) 16 | 17 | 18 | #define FM_OPSINBITS 10 19 | #define FM_OPSINENTS (1 << FM_OPSINBITS) 20 | 21 | #define FM_EGCBITS 18 // eg の count のシフト値 22 | #define FM_LFOCBITS 14 23 | 24 | #ifdef FM_TUNEBUILD 25 | #define FM_PGBITS 2 26 | #define FM_RATIOBITS 0 27 | #else 28 | #define FM_PGBITS 9 29 | #define FM_RATIOBITS 7 // 8-12 くらいまで? 30 | #endif 31 | 32 | #define FM_EGBITS 16 33 | 34 | //extern int paramcount[]; 35 | //#define PARAMCHANGE(i) paramcount[i]++; 36 | #define PARAMCHANGE(i) 37 | 38 | namespace FM 39 | { 40 | 41 | // --------------------------------------------------------------------------- 42 | // Operator 43 | // 44 | // フィードバックバッファをクリア 45 | inline void Operator::ResetFB() 46 | { 47 | out_ = out2_ = 0; 48 | } 49 | 50 | // キーオン 51 | inline void Operator::KeyOn() 52 | { 53 | if (!keyon_) 54 | { 55 | keyon_ = true; 56 | if (eg_phase_ == off || eg_phase_ == release) 57 | { 58 | ssg_phase_ = -1; 59 | ShiftPhase(attack); 60 | EGUpdate(); 61 | in2_ = out_ = out2_ = 0; 62 | pg_count_ = 0; 63 | } 64 | } 65 | } 66 | 67 | // キーオフ 68 | inline void Operator::KeyOff() 69 | { 70 | if (keyon_) 71 | { 72 | keyon_ = false; 73 | ShiftPhase(release); 74 | } 75 | } 76 | 77 | // オペレータは稼働中か? 78 | inline int Operator::IsOn() 79 | { 80 | return eg_phase_ - off; 81 | } 82 | 83 | // Detune (0-7) 84 | inline void Operator::SetDT(uint dt) 85 | { 86 | detune_ = dt * 0x20, param_changed_ = true; 87 | PARAMCHANGE(4); 88 | } 89 | 90 | // DT2 (0-3) 91 | inline void Operator::SetDT2(uint dt2) 92 | { 93 | detune2_ = dt2 & 3, param_changed_ = true; 94 | PARAMCHANGE(5); 95 | } 96 | 97 | // Multiple (0-15) 98 | inline void Operator::SetMULTI(uint mul) 99 | { 100 | multiple_ = mul, param_changed_ = true; 101 | PARAMCHANGE(6); 102 | } 103 | 104 | // Total Level (0-127) (0.75dB step) 105 | inline void Operator::SetTL(uint tl, bool csm) 106 | { 107 | if (!csm) 108 | { 109 | tl_ = tl, param_changed_ = true; 110 | PARAMCHANGE(7); 111 | } 112 | tl_latch_ = tl; 113 | } 114 | 115 | // Attack Rate (0-63) 116 | inline void Operator::SetAR(uint ar) 117 | { 118 | ar_ = ar; 119 | param_changed_ = true; 120 | PARAMCHANGE(8); 121 | } 122 | 123 | // Decay Rate (0-63) 124 | inline void Operator::SetDR(uint dr) 125 | { 126 | dr_ = dr; 127 | param_changed_ = true; 128 | PARAMCHANGE(9); 129 | } 130 | 131 | // Sustain Rate (0-63) 132 | inline void Operator::SetSR(uint sr) 133 | { 134 | sr_ = sr; 135 | param_changed_ = true; 136 | PARAMCHANGE(10); 137 | } 138 | 139 | // Sustain Level (0-127) 140 | inline void Operator::SetSL(uint sl) 141 | { 142 | sl_ = sl; 143 | param_changed_ = true; 144 | PARAMCHANGE(11); 145 | } 146 | 147 | // Release Rate (0-63) 148 | inline void Operator::SetRR(uint rr) 149 | { 150 | rr_ = rr; 151 | param_changed_ = true; 152 | PARAMCHANGE(12); 153 | } 154 | 155 | // Keyscale (0-3) 156 | inline void Operator::SetKS(uint ks) 157 | { 158 | ks_ = ks; 159 | param_changed_ = true; 160 | PARAMCHANGE(13); 161 | } 162 | 163 | // SSG-type Envelop (0-15) 164 | inline void Operator::SetSSGEC(uint ssgec) 165 | { 166 | if (ssgec & 8) 167 | ssg_type_ = ssgec; 168 | else 169 | ssg_type_ = 0; 170 | } 171 | 172 | inline void Operator::SetAMON(bool amon) 173 | { 174 | amon_ = amon; 175 | param_changed_ = true; 176 | PARAMCHANGE(14); 177 | } 178 | 179 | inline void Operator::Mute(bool mute) 180 | { 181 | mute_ = mute; 182 | param_changed_ = true; 183 | PARAMCHANGE(15); 184 | } 185 | 186 | inline void Operator::SetMS(uint ms) 187 | { 188 | ms_ = ms; 189 | param_changed_ = true; 190 | PARAMCHANGE(16); 191 | } 192 | 193 | // --------------------------------------------------------------------------- 194 | // 4-op Channel 195 | 196 | // オペレータの種類 (LFO) を設定 197 | inline void Channel4::SetType(OpType type) 198 | { 199 | for (int i=0; i<4; i++) 200 | op[i].type_ = type; 201 | } 202 | 203 | // セルフ・フィードバックレートの設定 (0-7) 204 | inline void Channel4::SetFB(uint feedback) 205 | { 206 | fb = fbtable[feedback]; 207 | } 208 | 209 | // OPNA 系 LFO の設定 210 | inline void Channel4::SetMS(uint ms) 211 | { 212 | op[0].SetMS(ms); 213 | op[1].SetMS(ms); 214 | op[2].SetMS(ms); 215 | op[3].SetMS(ms); 216 | } 217 | 218 | // チャンネル・マスク 219 | inline void Channel4::Mute(bool m) 220 | { 221 | for (int i=0; i<4; i++) 222 | op[i].Mute(m); 223 | } 224 | 225 | // 内部パラメータを再計算 226 | inline void Channel4::Refresh() 227 | { 228 | for (int i=0; i<4; i++) 229 | op[i].param_changed_ = true; 230 | PARAMCHANGE(3); 231 | } 232 | 233 | inline void Channel4::SetChip(Chip* chip) 234 | { 235 | chip_ = chip; 236 | for (int i=0; i<4; i++) 237 | op[i].SetChip(chip); 238 | } 239 | 240 | // --------------------------------------------------------------------------- 241 | // 242 | // 243 | inline void StoreSample(Sample& dest, ISample data) 244 | { 245 | if (sizeof(Sample) == 2) 246 | dest = (Sample) Limit(dest + data, 0x7fff, -0x8000); 247 | else 248 | dest += data; 249 | } 250 | 251 | 252 | // --------------------------------------------------------------------------- 253 | // AM のレベルを設定 254 | inline void Chip::SetAML(uint l) 255 | { 256 | aml_ = l & (FM_LFOENTS - 1); 257 | } 258 | 259 | // PM のレベルを設定 260 | inline void Chip::SetPML(uint l) 261 | { 262 | pml_ = l & (FM_LFOENTS - 1); 263 | } 264 | 265 | 266 | } 267 | 268 | #endif // FM_GEN_INL_H 269 | -------------------------------------------------------------------------------- /gamdx/mxdrvg/mxdrvg.h: -------------------------------------------------------------------------------- 1 | // MXDRVG.DLL header 2 | // Copyright (C) 2000 GORRY. 3 | 4 | #ifndef __MXDRVG_H__ 5 | #define __MXDRVG_H__ 6 | 7 | #include "mxdrvg_depend.h" 8 | 9 | typedef struct tagMXDRVG_WORK_CH { 10 | UBYTE volatile *S0000; // Ptr 11 | UBYTE S0004_b; // PCM bank 12 | UBYTE volatile *S0004; // voice ptr 13 | ULONG S0008; // bend delta 14 | ULONG S000c; // bend offset 15 | UWORD S0010; // D 16 | UWORD S0012; // note+D 17 | UWORD S0014; // note+D+bend+Pitch LFO offset 18 | UBYTE S0016; // flags b3=keyon/off 19 | UBYTE S0017; // flags 20 | UBYTE S0018; // ch 21 | UBYTE S0019; // carrier slot 22 | UBYTE S001a; // len 23 | UBYTE S001b; // gate 24 | UBYTE S001c; // p 25 | UBYTE S001d; // keyon slot 26 | UBYTE S001e; // Q 27 | UBYTE S001f; // Keyon delay 28 | UBYTE S0020; // Keyon delay counter 29 | UBYTE S0021; // PMS/AMS 30 | UBYTE S0022; // v 31 | UBYTE S0023; // v last 32 | UBYTE S0024; // LFO delay 33 | UBYTE S0025; // LFO delay counter 34 | UBYTE volatile *S0026; // Pitch LFO Type 35 | ULONG S002a; // Pitch LFO offset start 36 | ULONG S002e; // Pitch LFO delta start 37 | ULONG S0032; // Pitch LFO delta 38 | ULONG S0036; // Pitch LFO offset 39 | UWORD S003a; // Pitch LFO length (cooked) 40 | UWORD S003c; // Pitch LFO length 41 | UWORD S003e; // Pitch LFO length counter 42 | UBYTE volatile *S0040; // Volume LFO Type 43 | UWORD S0044; // Volume LFO delta start 44 | UWORD S0046; // Volume LFO delta (cooked) 45 | UWORD S0048; // Volume LFO delta 46 | UWORD S004a; // Volume LFO offset 47 | UWORD S004c; // Volume LFO length 48 | UWORD S004e; // Volume LFO length counter 49 | } MXDRVG_WORK_CH; 50 | 51 | typedef struct tagMXDRVG_WORK_GLOBAL { 52 | UWORD L001ba6; 53 | ULONG L001ba8; 54 | UBYTE volatile *L001bac; 55 | UBYTE L001bb4[16]; 56 | UBYTE L001df4; 57 | UBYTE L001df6[16]; 58 | UWORD L001e06; // Channel Mask (true) 59 | UBYTE L001e08; 60 | UBYTE L001e09; 61 | UBYTE L001e0a; 62 | UBYTE L001e0b; 63 | UBYTE L001e0c; // @t 64 | UBYTE L001e0d; 65 | UBYTE L001e0e; 66 | UBYTE L001e10; 67 | UBYTE L001e12; // Paused 68 | UBYTE L001e13; // End 69 | UBYTE L001e14; // Fadeout Offset 70 | UBYTE L001e15; 71 | UBYTE L001e17; // Fadeout Enable 72 | UBYTE L001e18; 73 | UBYTE L001e19; 74 | UWORD L001e1a; // Channel Enable 75 | UWORD L001e1c; // Channel Mask 76 | UWORD L001e1e[2]; // Fadeout Speed 77 | UWORD L001e22; 78 | UBYTE volatile *L001e24; 79 | UBYTE volatile *L001e28; 80 | UBYTE volatile *L001e2c; 81 | UBYTE volatile *L001e30; 82 | UBYTE volatile *L001e34; 83 | UBYTE volatile *L001e38; 84 | ULONG L00220c; 85 | UBYTE volatile *L002218; 86 | UBYTE volatile *L00221c; 87 | ULONG L002220; // L_MDXSIZE 88 | ULONG L002224; // L_PDXSIZE 89 | UBYTE volatile *L002228; // voice data 90 | UBYTE volatile *L00222c; 91 | UBYTE L002230; 92 | UBYTE L002231; 93 | UBYTE L002232; 94 | UBYTE L002233[9]; 95 | UBYTE L00223c[12]; 96 | UBYTE L002245; 97 | UWORD L002246; // loop count 98 | ULONG FATALERROR; 99 | ULONG FATALERRORADR; 100 | ULONG PLAYTIME; // 演奏時間((PLAYTIME*1024/4000)msec == (PLAYTIME*256)μsec) 101 | UBYTE MUSICTIMER; // 演奏時間タイマー定数 102 | UBYTE STOPMUSICTIMER; // 演奏時間タイマー停止 103 | ULONG MEASURETIMELIMIT; // 演奏時間計測中止時間 104 | ULONG SAMPRATE; // サンプリングレート 105 | ULONG INNERSAMPRATE; // サンプリングレート 106 | UBYTE OPMFILTER; // OPMの高域フィルタ 107 | ULONG PLAYSAMPLES; // 生成したサンプル数 108 | } MXDRVG_WORK_GLOBAL; 109 | 110 | typedef struct tagMXDRVG_WORK_KEY { 111 | UBYTE OPT1; 112 | UBYTE OPT2; 113 | UBYTE SHIFT; 114 | UBYTE CTRL; 115 | UBYTE XF3; 116 | UBYTE XF4; 117 | UBYTE XF5; 118 | } MXDRVG_WORK_KEY; 119 | 120 | typedef UBYTE MXDRVG_WORK_OPM[256]; 121 | 122 | typedef void MXDRVG_CALLBACK MXDRVG_CALLBACK_OPMINTFUNC( void ); 123 | 124 | enum { 125 | MXDRVG_WORKADR_FM = 0, // FM8ch+PCM1ch 126 | MXDRVG_WORKADR_PCM, // PCM7ch 127 | MXDRVG_WORKADR_GLOBAL, 128 | MXDRVG_WORKADR_KEY, 129 | MXDRVG_WORKADR_OPM, 130 | MXDRVG_WORKADR_PCM8, 131 | MXDRVG_WORKADR_CREDIT, 132 | MXDRVG_WORKADR_OPMINT, 133 | }; 134 | 135 | enum { 136 | MXDRVG_YM2151TYPE_FMGEN = 0, 137 | MXDRVG_YM2151TYPE_MAME, 138 | }; 139 | 140 | #ifndef MXDRVG_EXPORT 141 | #define MXDRVG_EXPORT 142 | #endif 143 | 144 | #ifdef __cplusplus 145 | extern "C" { 146 | #endif 147 | 148 | #ifndef __MXDRVG_LOADMODULE 149 | 150 | MXDRVG_EXPORT 151 | void MXDRVG_SetEmulationType( 152 | int ym2151type 153 | ); 154 | 155 | MXDRVG_EXPORT 156 | int MXDRVG_Start( 157 | int samprate, 158 | int fastmode, 159 | int mdxbufsize, 160 | int pdxbufsize 161 | ); 162 | 163 | MXDRVG_EXPORT 164 | void MXDRVG_End( 165 | void 166 | ); 167 | 168 | MXDRVG_EXPORT 169 | int MXDRVG_GetPCM( 170 | SWORD *buf, 171 | int len 172 | ); 173 | 174 | MXDRVG_EXPORT 175 | void MXDRVG_SetData( 176 | void *mdx, 177 | ULONG mdxsize, 178 | void *pdx, 179 | ULONG pdxsize 180 | ); 181 | 182 | MXDRVG_EXPORT 183 | void volatile *MXDRVG_GetWork( 184 | int i 185 | ); 186 | 187 | MXDRVG_EXPORT 188 | void MXDRVG( 189 | X68REG *reg 190 | ); 191 | 192 | MXDRVG_EXPORT 193 | ULONG MXDRVG_MeasurePlayTime( 194 | int loop, 195 | int fadeout 196 | ); 197 | 198 | MXDRVG_EXPORT 199 | void MXDRVG_PlayAt( 200 | ULONG playat, 201 | int loop, 202 | int fadeout 203 | ); 204 | 205 | MXDRVG_EXPORT 206 | ULONG MXDRVG_GetPlayAt( 207 | void 208 | ); 209 | 210 | MXDRVG_EXPORT 211 | int MXDRVG_GetTerminated( 212 | void 213 | ); 214 | 215 | MXDRVG_EXPORT 216 | void MXDRVG_TotalVolume( 217 | int vol 218 | ); 219 | 220 | MXDRVG_EXPORT 221 | int MXDRVG_GetTotalVolume( 222 | void 223 | ); 224 | 225 | MXDRVG_EXPORT 226 | void MXDRVG_ChannelMask( 227 | int mask 228 | ); 229 | 230 | MXDRVG_EXPORT 231 | int MXDRVG_GetChannelMask( 232 | void 233 | ); 234 | 235 | #endif // __MXDRVG_LOADMODULE 236 | 237 | #ifdef __cplusplus 238 | } 239 | #endif // __cplusplus 240 | 241 | #define MXDRVG_Call( a ) \ 242 | { \ 243 | X68REG reg; \ 244 | \ 245 | reg.d0 = (a); \ 246 | reg.d1 = 0x00; \ 247 | MXDRVG( ® ); \ 248 | } \ 249 | 250 | 251 | #define MXDRVG_Call_2( a, b ) \ 252 | { \ 253 | X68REG reg; \ 254 | \ 255 | reg.d0 = (a); \ 256 | reg.d1 = (b); \ 257 | MXDRVG( ® ); \ 258 | } \ 259 | 260 | 261 | #define MXDRVG_Replay() MXDRVG_Call( 0x0f ) 262 | #define MXDRVG_Stop() MXDRVG_Call( 0x05 ) 263 | #define MXDRVG_Pause() MXDRVG_Call( 0x06 ) 264 | #define MXDRVG_Cont() MXDRVG_Call( 0x07 ) 265 | #define MXDRVG_Fadeout() MXDRVG_Call_2( 0x0c, 19 ) 266 | #define MXDRVG_Fadeout2(a) MXDRVG_Call_2( 0x0c, (a) ) 267 | 268 | 269 | 270 | #endif //__MXDRVG_H__ 271 | -------------------------------------------------------------------------------- /gamdx/fmgen/fmgen.h: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // FM Sound Generator 3 | // Copyright (C) cisc 1998, 2001. 4 | // --------------------------------------------------------------------------- 5 | // $Id: fmgen.h,v 1.37 2003/08/25 13:33:11 cisc Exp $ 6 | 7 | #ifndef FM_GEN_H 8 | #define FM_GEN_H 9 | 10 | #include "../types.h" 11 | 12 | // --------------------------------------------------------------------------- 13 | // 出力サンプルの型 14 | // 15 | #define FM_SAMPLETYPE MXDRVG_SAMPLETYPE // int16 or int32 16 | 17 | // --------------------------------------------------------------------------- 18 | // 定数その1 19 | // 静的テーブルのサイズ 20 | 21 | #define FM_LFOBITS 8 // 変更不可 22 | #define FM_TLBITS 7 23 | 24 | // --------------------------------------------------------------------------- 25 | 26 | #define FM_TLENTS (1 << FM_TLBITS) 27 | #define FM_LFOENTS (1 << FM_LFOBITS) 28 | #define FM_TLPOS (FM_TLENTS/4) 29 | 30 | // サイン波の精度は 2^(1/256) 31 | #define FM_CLENTS (0x1000 * 2) // sin + TL + LFO 32 | 33 | // --------------------------------------------------------------------------- 34 | 35 | namespace FM 36 | { 37 | // Types ---------------------------------------------------------------- 38 | typedef FM_SAMPLETYPE Sample; 39 | typedef int32 ISample; 40 | 41 | enum OpType { typeN=0, typeM=1 }; 42 | 43 | void StoreSample(ISample& dest, int data); 44 | 45 | class Chip; 46 | 47 | // Operator ------------------------------------------------------------- 48 | class Operator 49 | { 50 | public: 51 | Operator(); 52 | void SetChip(Chip* chip) { chip_ = chip; } 53 | 54 | static void MakeTimeTable(uint ratio); 55 | 56 | ISample Calc(ISample in); 57 | ISample CalcL(ISample in); 58 | ISample CalcFB(uint fb); 59 | ISample CalcFBL(uint fb); 60 | ISample CalcN(uint noise); 61 | void Prepare(); 62 | void KeyOn(); 63 | void KeyOff(); 64 | void Reset(); 65 | void ResetFB(); 66 | int IsOn(); 67 | 68 | void SetDT(uint dt); 69 | void SetDT2(uint dt2); 70 | void SetMULTI(uint multi); 71 | void SetTL(uint tl, bool csm); 72 | void SetKS(uint ks); 73 | void SetAR(uint ar); 74 | void SetDR(uint dr); 75 | void SetSR(uint sr); 76 | void SetRR(uint rr); 77 | void SetSL(uint sl); 78 | void SetSSGEC(uint ssgec); 79 | void SetFNum(uint fnum); 80 | void SetDPBN(uint dp, uint bn); 81 | void SetMode(bool modulator); 82 | void SetAMON(bool on); 83 | void SetMS(uint ms); 84 | void Mute(bool); 85 | 86 | // static void SetAML(uint l); 87 | // static void SetPML(uint l); 88 | 89 | int Out() { return out_; } 90 | 91 | int dbgGetIn2() { return in2_; } 92 | void dbgStopPG() { pg_diff_ = 0; pg_diff_lfo_ = 0; } 93 | 94 | private: 95 | typedef uint32 Counter; 96 | 97 | Chip* chip_; 98 | ISample out_, out2_; 99 | ISample in2_; 100 | 101 | // Phase Generator ------------------------------------------------------ 102 | uint32 PGCalc(); 103 | uint32 PGCalcL(); 104 | 105 | uint dp_; // ΔP 106 | uint detune_; // Detune 107 | uint detune2_; // DT2 108 | uint multiple_; // Multiple 109 | uint32 pg_count_; // Phase 現在値 110 | uint32 pg_diff_; // Phase 差分値 111 | int32 pg_diff_lfo_; // Phase 差分値 >> x 112 | 113 | // Envelop Generator --------------------------------------------------- 114 | enum EGPhase { next, attack, decay, sustain, release, off }; 115 | 116 | void EGCalc(); 117 | void EGStep(); 118 | void ShiftPhase(EGPhase nextphase); 119 | void SSGShiftPhase(int mode); 120 | void SetEGRate(uint); 121 | void EGUpdate(); 122 | int FBCalc(int fb); 123 | ISample LogToLin(uint a); 124 | 125 | 126 | OpType type_; // OP の種類 (M, N...) 127 | uint bn_; // Block/Note 128 | int eg_level_; // EG の出力値 129 | int eg_level_on_next_phase_; // 次の eg_phase_ に移る値 130 | int eg_count_; // EG の次の変移までの時間 131 | int eg_count_diff_; // eg_count_ の差分 132 | int eg_out_; // EG+TL を合わせた出力値 133 | int tl_out_; // TL 分の出力値 134 | // int pm_depth_; // PM depth 135 | // int am_depth_; // AM depth 136 | int eg_rate_; 137 | int eg_curve_count_; 138 | int ssg_offset_; 139 | int ssg_vector_; 140 | int ssg_phase_; 141 | 142 | 143 | uint key_scale_rate_; // key scale rate 144 | EGPhase eg_phase_; 145 | uint* ams_; 146 | uint ms_; 147 | 148 | uint tl_; // Total Level (0-127) 149 | uint tl_latch_; // Total Level Latch (for CSM mode) 150 | uint ar_; // Attack Rate (0-63) 151 | uint dr_; // Decay Rate (0-63) 152 | uint sr_; // Sustain Rate (0-63) 153 | uint sl_; // Sustain Level (0-127) 154 | uint rr_; // Release Rate (0-63) 155 | uint ks_; // Keyscale (0-3) 156 | uint ssg_type_; // SSG-Type Envelop Control 157 | 158 | bool keyon_; 159 | bool amon_; // enable Amplitude Modulation 160 | bool param_changed_; // パラメータが更新された 161 | bool mute_; 162 | 163 | // Tables --------------------------------------------------------------- 164 | static Counter rate_table[16]; 165 | static uint32 multable[4][16]; 166 | 167 | static const uint8 notetable[128]; 168 | static const int8 dttable[256]; 169 | static const int8 decaytable1[64][8]; 170 | static const int decaytable2[16]; 171 | static const int8 attacktable[64][8]; 172 | static const int ssgenvtable[8][2][3][2]; 173 | 174 | static uint sinetable[1024]; 175 | static int32 cltable[FM_CLENTS]; 176 | 177 | static bool tablehasmade; 178 | static void MakeTable(); 179 | 180 | 181 | 182 | // friends -------------------------------------------------------------- 183 | friend class Channel4; 184 | // friend void __stdcall FM_NextPhase(Operator* op); 185 | 186 | public: 187 | int dbgopout_; 188 | int dbgpgout_; 189 | static const int32* dbgGetClTable() { return cltable; } 190 | static const uint* dbgGetSineTable() { return sinetable; } 191 | }; 192 | 193 | // 4-op Channel --------------------------------------------------------- 194 | class Channel4 195 | { 196 | public: 197 | Channel4(); 198 | void SetChip(Chip* chip); 199 | void SetType(OpType type); 200 | 201 | ISample Calc(); 202 | ISample CalcL(); 203 | ISample CalcN(uint noise); 204 | ISample CalcLN(uint noise); 205 | void SetFNum(uint fnum); 206 | void SetFB(uint fb); 207 | void SetKCKF(uint kc, uint kf); 208 | void SetAlgorithm(uint algo); 209 | int Prepare(); 210 | void KeyControl(uint key); 211 | void Reset(); 212 | void SetMS(uint ms); 213 | void Mute(bool); 214 | void Refresh(); 215 | 216 | void dbgStopPG() { for (int i=0; i<4; i++) op[i].dbgStopPG(); } 217 | 218 | private: 219 | static const uint8 fbtable[8]; 220 | uint fb; 221 | int buf[4]; 222 | int* in[3]; // 各 OP の入力ポインタ 223 | int* out[3]; // 各 OP の出力ポインタ 224 | int* pms; 225 | int algo_; 226 | Chip* chip_; 227 | 228 | static void MakeTable(); 229 | 230 | static bool tablehasmade; 231 | static int kftable[64]; 232 | 233 | 234 | public: 235 | Operator op[4]; 236 | }; 237 | 238 | // Chip resource 239 | class Chip 240 | { 241 | public: 242 | Chip(); 243 | void SetRatio(uint ratio); 244 | void SetAML(uint l); 245 | void SetPML(uint l); 246 | void SetPMV(int pmv) { pmv_ = pmv; } 247 | 248 | uint32 GetMulValue(uint dt2, uint mul) { return multable_[dt2][mul]; } 249 | uint GetAML() { return aml_; } 250 | uint GetPML() { return pml_; } 251 | int GetPMV() { return pmv_; } 252 | uint GetRatio() { return ratio_; } 253 | 254 | private: 255 | void MakeTable(); 256 | 257 | uint ratio_; 258 | uint aml_; 259 | uint pml_; 260 | int pmv_; 261 | OpType optype_; 262 | uint32 multable_[4][16]; 263 | }; 264 | } 265 | 266 | #endif // FM_GEN_H 267 | -------------------------------------------------------------------------------- /gamdx/pcm8/x68pcm8.cpp: -------------------------------------------------------------------------------- 1 | #include "x68pcm8.h" 2 | 3 | namespace X68K 4 | { 5 | 6 | 7 | // --------------------------------------------------------------------------- 8 | // 構築 9 | // 10 | X68PCM8::X68PCM8() 11 | { 12 | } 13 | 14 | // --------------------------------------------------------------------------- 15 | // 初期化 16 | // 17 | bool X68PCM8::Init(uint rate) 18 | { 19 | mMask = 0; 20 | mVolume = 256; 21 | for (int i=0; i -192) 93 | mVolume = int(16384.0 * pow(10, db / 40.0)); 94 | else 95 | mVolume = 0; 96 | } 97 | 98 | 99 | // --------------------------------------------------------------------------- 100 | // 62500Hz用ADPCM合成処理 101 | // 102 | inline void X68PCM8::pcmset62500(Sample* buffer, int ndata) { 103 | Sample* limit = buffer + ndata * 2; 104 | for (Sample* dest = buffer; dest < limit; dest+=2) { 105 | OutInpAdpcm[0] = OutInpAdpcm[1] = 0; 106 | 107 | for (int ch=0; ch>1)&1)) & o; 113 | } 114 | } 115 | OutInpAdpcm[0] = (OutInpAdpcm[0] * mVolume) >> 8; 116 | OutInpAdpcm[1] = (OutInpAdpcm[1] * mVolume) >> 8; 117 | 118 | #define LIMITS ((1<<19)-1) 119 | if ((uint32)(OutInpAdpcm[0]+LIMITS) > (uint32)(LIMITS*2)) { 120 | if ((sint32)(OutInpAdpcm[0]+LIMITS) >= (sint32)(LIMITS*2)) { 121 | OutInpAdpcm[0] = LIMITS; 122 | } else { 123 | OutInpAdpcm[0] = -LIMITS; 124 | } 125 | } 126 | if ((uint32)(OutInpAdpcm[1]+LIMITS) > (uint32)(LIMITS*2)) { 127 | if ((sint32)(OutInpAdpcm[1]+LIMITS) >= (sint32)(LIMITS*2)) { 128 | OutInpAdpcm[1] = LIMITS; 129 | } else { 130 | OutInpAdpcm[1] = -LIMITS; 131 | } 132 | } 133 | #undef LIMITS 134 | OutInpAdpcm[0] *= 26; 135 | OutInpAdpcm[1] *= 26; 136 | 137 | OutInpOutAdpcm[0] = ( 138 | OutInpAdpcm[0] + OutInpAdpcm_prev[0] + 139 | OutInpAdpcm_prev[0] + OutInpAdpcm_prev2[0] - 140 | OutInpOutAdpcm_prev[0]*(-1537) - OutInpOutAdpcm_prev2[0]*617 141 | ) >> 10; 142 | OutInpOutAdpcm[1] = ( 143 | OutInpAdpcm[1] + OutInpAdpcm_prev[1] + 144 | OutInpAdpcm_prev[1] + OutInpAdpcm_prev2[1] - 145 | OutInpOutAdpcm_prev[1]*(-1537) - OutInpOutAdpcm_prev2[1]*617 146 | ) >> 10; 147 | 148 | OutInpAdpcm_prev2[0] = OutInpAdpcm_prev[0]; 149 | OutInpAdpcm_prev2[1] = OutInpAdpcm_prev[1]; 150 | OutInpAdpcm_prev[0] = OutInpAdpcm[0]; 151 | OutInpAdpcm_prev[1] = OutInpAdpcm[1]; 152 | OutInpOutAdpcm_prev2[0] = OutInpOutAdpcm_prev[0]; 153 | OutInpOutAdpcm_prev2[1] = OutInpOutAdpcm_prev[1]; 154 | OutInpOutAdpcm_prev[0] = OutInpOutAdpcm[0]; 155 | OutInpOutAdpcm_prev[1] = OutInpOutAdpcm[1]; 156 | 157 | OutOutInpAdpcm[0] = OutInpOutAdpcm[0] * (356); 158 | OutOutInpAdpcm[1] = OutInpOutAdpcm[1] * (356); 159 | OutOutAdpcm[0] = ( 160 | OutOutInpAdpcm[0] + OutOutInpAdpcm_prev[0] - 161 | OutOutAdpcm_prev[0]*(-312) 162 | ) >> 10; 163 | OutOutAdpcm[1] = ( 164 | OutOutInpAdpcm[1] + OutOutInpAdpcm_prev[1] - 165 | OutOutAdpcm_prev[1]*(-312) 166 | ) >> 10; 167 | 168 | OutOutInpAdpcm_prev[0] = OutOutInpAdpcm[0]; 169 | OutOutInpAdpcm_prev[1] = OutOutInpAdpcm[1]; 170 | OutOutAdpcm_prev[0] = OutOutAdpcm[0]; 171 | OutOutAdpcm_prev[1] = OutOutAdpcm[1]; 172 | 173 | // -2048*16〜+2048*16 OPMとADPCMの音量バランス調整 174 | StoreSample(dest[0], (OutOutAdpcm[0]*506) >> (4+9)); 175 | StoreSample(dest[1], (OutOutAdpcm[1]*506) >> (4+9)); 176 | } 177 | } 178 | 179 | 180 | // --------------------------------------------------------------------------- 181 | // 22050Hz用ADPCM合成処理 182 | // 183 | inline void X68PCM8::pcmset22050(Sample* buffer, int ndata) { 184 | Sample* limit = buffer + ndata * 2; 185 | for (Sample* dest = buffer; dest < limit; dest+=2) { 186 | 187 | static int rate=0,rate2=0; 188 | rate2 -= 15625; 189 | if (rate2 < 0) { 190 | rate2 += 22050; 191 | OutInpAdpcm[0] = OutInpAdpcm[1] = 0; 192 | 193 | for (int ch=0; ch>1)&1)) & o; 199 | } 200 | } 201 | OutInpAdpcm[0] = (OutInpAdpcm[0] * mVolume) >> 8; 202 | OutInpAdpcm[1] = (OutInpAdpcm[1] * mVolume) >> 8; 203 | 204 | #define LIMITS ((1<<19)-1) 205 | if ((uint32)(OutInpAdpcm[0]+LIMITS) > (uint32)(LIMITS*2)) { 206 | if ((sint32)(OutInpAdpcm[0]+LIMITS) >= (sint32)(LIMITS*2)) { 207 | OutInpAdpcm[0] = LIMITS; 208 | } else { 209 | OutInpAdpcm[0] = -LIMITS; 210 | } 211 | } 212 | if ((uint32)(OutInpAdpcm[1]+LIMITS) > (uint32)(LIMITS*2)) { 213 | if ((sint32)(OutInpAdpcm[1]+LIMITS) >= (sint32)(LIMITS*2)) { 214 | OutInpAdpcm[1] = LIMITS; 215 | } else { 216 | OutInpAdpcm[1] = -LIMITS; 217 | } 218 | } 219 | #undef LIMITS 220 | 221 | OutInpAdpcm[0] *= 40; 222 | OutInpAdpcm[1] *= 40; 223 | } 224 | OutOutAdpcm[0] = ( 225 | OutInpAdpcm[0] + OutInpAdpcm_prev[0] + 226 | OutInpAdpcm_prev[0] + OutInpAdpcm_prev2[0] - 227 | OutOutAdpcm_prev[0]*(-157) - OutOutAdpcm_prev2[0]*61 228 | ) >> 8; 229 | OutOutAdpcm[1] = ( 230 | OutInpAdpcm[1] + OutInpAdpcm_prev[1] + 231 | OutInpAdpcm_prev[1] + OutInpAdpcm_prev2[1] - 232 | OutOutAdpcm_prev[1]*(-157) - OutOutAdpcm_prev2[1]*61 233 | ) >> 8; 234 | 235 | OutInpAdpcm_prev2[0] = OutInpAdpcm_prev[0]; 236 | OutInpAdpcm_prev2[1] = OutInpAdpcm_prev[1]; 237 | OutInpAdpcm_prev[0] = OutInpAdpcm[0]; 238 | OutInpAdpcm_prev[1] = OutInpAdpcm[1]; 239 | OutInpOutAdpcm_prev2[0] = OutInpOutAdpcm_prev[0]; 240 | OutInpOutAdpcm_prev2[1] = OutInpOutAdpcm_prev[1]; 241 | OutInpOutAdpcm_prev[0] = OutInpOutAdpcm[0]; 242 | OutInpOutAdpcm_prev[1] = OutInpOutAdpcm[1]; 243 | 244 | StoreSample(dest[0], (OutOutAdpcm[0]>>4)); 245 | StoreSample(dest[1], (OutOutAdpcm[1]>>4)); 246 | } 247 | } 248 | 249 | 250 | // --------------------------------------------------------------------------- 251 | // 合成 (stereo) 252 | // 253 | void X68PCM8::Mix(Sample* buffer, int nsamples) 254 | { 255 | if (mSampleRate == 22050) { 256 | pcmset22050(buffer, nsamples); 257 | } else { 258 | pcmset62500(buffer, nsamples); 259 | } 260 | } 261 | 262 | // --------------------------------------------------------------------------- 263 | } // namespace X68K 264 | 265 | // [EOF] 266 | -------------------------------------------------------------------------------- /src/mdx2wav.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../gamdx/mxdrvg/mxdrvg.h" 12 | 13 | #define VERSION "1.0" 14 | 15 | bool verbose = false; 16 | 17 | typedef unsigned char u8; 18 | typedef unsigned int u32; 19 | 20 | const int MAGIC_OFFSET = 10; 21 | 22 | // @param mode 0:tolower, 1:toupper, 2:normal 23 | void strcpy_cnv(char *dst, const char *src, int mode) { 24 | while (int c = *src++) { 25 | *dst++ = 26 | mode == 0 ? tolower(c) : 27 | mode == 1 ? toupper(c) : 28 | c; 29 | } 30 | *dst = 0; 31 | } 32 | 33 | bool read_file(const char *name, int *fsize, u8 **fdata, int offset) { 34 | *fdata = 0; 35 | *fsize = 0; 36 | 37 | int fd = open(name, O_RDONLY); 38 | if (fd == -1) { 39 | if (verbose) { 40 | fprintf(stderr, "cannot open %s\n", name); 41 | } 42 | return false; 43 | } 44 | 45 | struct stat st; 46 | if (fstat(fd, &st) == -1) { 47 | if (verbose) { 48 | fprintf(stderr, "cannot fstat %s\n", name); 49 | } 50 | st.st_size = 128 * 1024; // set tentative file size 51 | } 52 | 53 | int size = st.st_size; 54 | if (size == 0) { 55 | fprintf(stderr, "Invalid file size %s\n", name); 56 | close(fd); 57 | return false; 58 | } 59 | 60 | u8 *data = new u8[size + offset]; 61 | size = read(fd, data + offset, size); 62 | 63 | close(fd); 64 | 65 | *fdata = data; 66 | *fsize = size + offset; 67 | return true; 68 | } 69 | 70 | bool LoadMDX(const char *mdx_name, char *title, int title_len) { 71 | u8 *mdx_buf = 0, *pdx_buf = 0; 72 | int mdx_size = 0, pdx_size = 0; 73 | 74 | // Load MDX file 75 | if (!read_file(mdx_name, &mdx_size, &mdx_buf, MAGIC_OFFSET)) { 76 | fprintf(stderr, "Cannot open/read %s.\n", mdx_name); 77 | return false; 78 | } 79 | 80 | // Skip title. 81 | int pos = MAGIC_OFFSET; 82 | { 83 | char *ptitle = title; 84 | while (pos < mdx_size && --title_len > 0) { 85 | *ptitle++ = mdx_buf[pos]; 86 | if (mdx_buf[pos] == 0x0d && mdx_buf[pos + 1] == 0x0a) 87 | break; 88 | pos++; 89 | } 90 | *ptitle = 0; 91 | } 92 | 93 | while (pos < mdx_size) { 94 | u8 c = mdx_buf[pos++]; 95 | if (c == 0x1a) break; 96 | } 97 | 98 | char *pdx_name = (char*) mdx_buf + pos; 99 | 100 | while (pos < mdx_size) { 101 | u8 c = mdx_buf[pos++]; 102 | if (c == 0) break; 103 | } 104 | 105 | if (pos >= mdx_size) 106 | return false; 107 | 108 | // Get mdx path. 109 | if (*pdx_name) { 110 | char pdx_path[FILENAME_MAX]; 111 | strncpy(pdx_path, mdx_name, sizeof(pdx_path)); 112 | 113 | int pdx_name_start = 0; 114 | for (int i = strlen(pdx_path) - 1; i > 0; i--) { 115 | if (pdx_path[i - 1] == '/') { 116 | pdx_name_start = i; 117 | break; 118 | } 119 | } 120 | 121 | if (pdx_name_start + strlen(pdx_path) + 4 >= sizeof(pdx_path)) { 122 | return false; 123 | } 124 | 125 | // remove .pdx from pdx_name 126 | { 127 | int pdx_name_len = strlen(pdx_name); 128 | if (pdx_name_len > 4) { 129 | if (pdx_name[pdx_name_len - 4] == '.') { 130 | pdx_name[pdx_name_len - 4] = 0; 131 | } 132 | } 133 | } 134 | 135 | // Make pdx path. 136 | for (int i = 0; i < 3 * 2; i++) { 137 | strcpy_cnv(pdx_path + pdx_name_start, pdx_name, i % 3); 138 | strcpy_cnv(pdx_path + pdx_name_start + strlen(pdx_name), ".pdx", i / 3); 139 | if (verbose) { 140 | fprintf(stderr, "try to open pdx:%s\n", pdx_path); 141 | } 142 | if (read_file(pdx_path, &pdx_size, &pdx_buf, MAGIC_OFFSET)) { 143 | break; 144 | } 145 | } 146 | } 147 | 148 | 149 | // Convert mdx to MXDRVG readable structure. 150 | int mdx_body_pos = pos; 151 | 152 | if (verbose) { 153 | fprintf(stderr, "mdx body pos :0x%x\n", mdx_body_pos - MAGIC_OFFSET); 154 | fprintf(stderr, "mdx body size :0x%x\n", mdx_size - mdx_body_pos - MAGIC_OFFSET); 155 | } 156 | 157 | u8 *mdx_head = mdx_buf + mdx_body_pos - MAGIC_OFFSET; 158 | mdx_head[0] = 0x00; 159 | mdx_head[1] = 0x00; 160 | mdx_head[2] = (pdx_buf ? 0 : 0xff); 161 | mdx_head[3] = (pdx_buf ? 0 : 0xff); 162 | mdx_head[4] = 0; 163 | mdx_head[5] = 0x0a; 164 | mdx_head[6] = 0x00; 165 | mdx_head[7] = 0x08; 166 | mdx_head[8] = 0x00; 167 | mdx_head[9] = 0x00; 168 | 169 | if (pdx_buf) { 170 | pdx_buf[0] = 0x00; 171 | pdx_buf[1] = 0x00; 172 | pdx_buf[2] = 0x00; 173 | pdx_buf[3] = 0x00; 174 | pdx_buf[4] = 0x00; 175 | pdx_buf[5] = 0x0a; 176 | pdx_buf[6] = 0x00; 177 | pdx_buf[7] = 0x02; 178 | pdx_buf[8] = 0x00; 179 | pdx_buf[9] = 0x00; 180 | } 181 | 182 | if (verbose) { 183 | fprintf(stderr, "instrument pos:0x%x\n", mdx_body_pos - 10 + (mdx_head[10] << 8) + mdx_head[11]); 184 | } 185 | 186 | MXDRVG_SetData(mdx_head, mdx_size, pdx_buf, pdx_size); 187 | 188 | delete []mdx_buf; 189 | delete []pdx_buf; 190 | 191 | return true; 192 | } 193 | 194 | void version() { 195 | printf( 196 | "mdx2wav version "VERSION"\n" 197 | "Copyright 2014 @__mtm\n" 198 | " based on MDXDRVg V1.50a (C) 2000 GORRY.\n" 199 | " converted from X68k MXDRV music driver version 2.06+17 Rel.X5-S\n" 200 | " (c)1988-92 milk.,K.MAEKAWA, Missy.M, Yatsube\n" 201 | ); 202 | } 203 | 204 | void help() { 205 | printf( 206 | "Usage: mdx2wav [options] \n" 207 | "Convert mdx file to 16bit stereo raw pcm and write it to stdout.\n" 208 | " if you need to convert to other format, use ffmpeg like a following.\n" 209 | " mdx2wav xxx.mdx | ffmpeg -f s16le -ar 44.1k -ac 2 -i - xxx.wav\n" 210 | " if you want to listen now, use aplay like a following.\n" 211 | " mdx2wav xxx.mdx | aplay -f cd\n" 212 | "Options:\n" 213 | " -d : limit song duration. 0 means nolimit. (default:300)\n" 214 | " -e : set ym2151 emulation type, fmgen or mame. (default:fmgen)\n" 215 | " -f : enable fadeout.\n" 216 | " -l : set loop limit. (default:2)\n" 217 | " -m : measure play time as sec.\n" 218 | " -r : set sampling rate. (default:44100)\n" 219 | " -t : get song title (charset is SHIFT-JIS).\n" 220 | " if you need other charset, try following command:\n" 221 | " mdx2wav -t xxx.mdx | iconv -f SHIFT-JIS -t utf-8\n" 222 | " -v : print version.\n" 223 | " -V : verbose, write debug log to stderr.\n" 224 | ); 225 | } 226 | 227 | 228 | 229 | int main(int argc, char **argv) { 230 | int MDX_BUF_SIZE = 256 * 1024; 231 | int PDX_BUF_SIZE = 1024 * 1024; 232 | int SAMPLE_RATE = 44100; 233 | int filter_mode = 0; 234 | 235 | bool measure_play_time = false; 236 | bool get_title = false; 237 | float max_song_duration = 300.0f; 238 | int loop = 2; 239 | int fadeout = 0; 240 | char ym2151_type[8] = "fmgen"; 241 | 242 | int opt; 243 | while ((opt = getopt(argc, argv, "d:e:fl:mr:tvV")) != -1) { 244 | switch (opt) { 245 | case 'd': 246 | max_song_duration = atof(optarg); 247 | break; 248 | case 'e': 249 | strncpy(ym2151_type, optarg, sizeof(ym2151_type)); 250 | break; 251 | case 'f': 252 | fadeout = 1; 253 | break; 254 | case 'l': 255 | loop = atoi(optarg); 256 | break; 257 | case 'm': 258 | measure_play_time = true; 259 | break; 260 | case 'r': 261 | SAMPLE_RATE = atoi(optarg); 262 | break; 263 | case 't': 264 | get_title = true; 265 | break; 266 | case 'v': 267 | version(); 268 | return 0; 269 | case 'V': 270 | verbose = true; 271 | break; 272 | default: 273 | help(); 274 | return 0; 275 | } 276 | } 277 | 278 | int AUDIO_BUF_SAMPLES = SAMPLE_RATE / 100; // 10ms 279 | 280 | const char *mdx_name = argv[optind]; 281 | if (mdx_name == 0 || *mdx_name == 0) { 282 | help(); 283 | return 0; 284 | } 285 | 286 | if (0 == strcmp(ym2151_type, "fmgen")) { 287 | } else if (0 == strcmp(ym2151_type, "mame")) { 288 | MXDRVG_SetEmulationType(MXDRVG_YM2151TYPE_MAME); 289 | } else { 290 | fprintf(stderr, "Invalid ym2151 emulation type: %s.\n", ym2151_type); 291 | return -1; 292 | } 293 | 294 | MXDRVG_Start(SAMPLE_RATE, filter_mode, MDX_BUF_SIZE, PDX_BUF_SIZE); 295 | MXDRVG_TotalVolume(256); 296 | 297 | char title[256]; 298 | 299 | if (!LoadMDX(mdx_name, title, sizeof(title))) { 300 | return -1; 301 | } 302 | 303 | if (get_title) { 304 | printf("%s\n", title); 305 | return 0; 306 | } 307 | 308 | float song_duration = MXDRVG_MeasurePlayTime(loop, fadeout) / 1000.0f; 309 | // Warning: MXDRVG_MeasurePlayTime calls MXDRVG_End internaly, 310 | // thus we need to call MXDRVG_PlayAt due to reset playing status. 311 | MXDRVG_PlayAt(0, loop, fadeout); 312 | 313 | if (measure_play_time) { 314 | printf("%d\n", (int) ceilf(song_duration)); 315 | return 0; 316 | } 317 | 318 | if (verbose) { 319 | fprintf(stderr, "loop:%d fadeout:%d song_duration:%f\n", loop, fadeout, song_duration); 320 | } 321 | 322 | if (max_song_duration < song_duration) { 323 | song_duration = max_song_duration; 324 | } 325 | 326 | short *audio_buf = new short [AUDIO_BUF_SAMPLES * 2]; 327 | 328 | for (int i = 0; song_duration == 0.0f || 1.0f * i * AUDIO_BUF_SAMPLES / SAMPLE_RATE < song_duration; i++) { 329 | if (MXDRVG_GetTerminated()) { 330 | break; 331 | } 332 | 333 | int len = MXDRVG_GetPCM(audio_buf, AUDIO_BUF_SAMPLES); 334 | if (len <= 0) { 335 | break; 336 | } 337 | 338 | 339 | fwrite(audio_buf, len, 4, stdout); 340 | } 341 | 342 | MXDRVG_End(); 343 | 344 | delete []audio_buf; 345 | 346 | if (verbose) { 347 | fprintf(stderr, "completed.\n"); 348 | } 349 | return 0; 350 | } 351 | -------------------------------------------------------------------------------- /gamdx/pcm8/pcm8.cpp: -------------------------------------------------------------------------------- 1 | #include "pcm8.h" 2 | #include "global.h" 3 | 4 | namespace X68K 5 | { 6 | 7 | 8 | inline int MemRead(unsigned char *adrs) { 9 | return *adrs; 10 | } 11 | 12 | 13 | int Pcm8::DmaArrayChainSetNextMtcMar() { 14 | if ( DmaBtc == 0 ) { 15 | return 1; 16 | } 17 | --DmaBtc; 18 | 19 | int mem0,mem1,mem2,mem3,mem4,mem5; 20 | mem0 = MemRead((unsigned char *)DmaBar++); 21 | mem1 = MemRead((unsigned char *)DmaBar++); 22 | mem2 = MemRead((unsigned char *)DmaBar++); 23 | mem3 = MemRead((unsigned char *)DmaBar++); 24 | mem4 = MemRead((unsigned char *)DmaBar++); 25 | mem5 = MemRead((unsigned char *)DmaBar++); 26 | if ((mem0|mem1|mem2|mem3|mem4|mem5) == -1) { 27 | // バスエラー(ベースアドレス/ベースカウンタ) 28 | return 1; 29 | } 30 | DmaMar = (volatile unsigned char *)((mem0<<24)|(mem1<<16)|(mem2<<8)|(mem3)); // MAR 31 | DmaMtc = (mem4<<8)|(mem5); // MTC 32 | 33 | if ( DmaMtc == 0 ) { // MTC == 0 ? 34 | // カウントエラー(メモリアドレス/メモリカウンタ) 35 | return 1; 36 | } 37 | return 0; 38 | } 39 | 40 | 41 | int Pcm8::DmaLinkArrayChainSetNextMtcMar() { 42 | if (DmaBar == (unsigned char *)0) { 43 | return 1; 44 | } 45 | 46 | int mem0,mem1,mem2,mem3,mem4,mem5; 47 | int mem6,mem7,mem8,mem9; 48 | mem0 = MemRead((unsigned char *)DmaBar++); 49 | mem1 = MemRead((unsigned char *)DmaBar++); 50 | mem2 = MemRead((unsigned char *)DmaBar++); 51 | mem3 = MemRead((unsigned char *)DmaBar++); 52 | mem4 = MemRead((unsigned char *)DmaBar++); 53 | mem5 = MemRead((unsigned char *)DmaBar++); 54 | mem6 = MemRead((unsigned char *)DmaBar++); 55 | mem7 = MemRead((unsigned char *)DmaBar++); 56 | mem8 = MemRead((unsigned char *)DmaBar++); 57 | mem9 = MemRead((unsigned char *)DmaBar++); 58 | if ((mem0|mem1|mem2|mem3|mem4|mem5|mem6|mem7|mem8|mem9) == -1) { 59 | // バスエラー(ベースアドレス/ベースカウンタ) 60 | return 1; 61 | } 62 | DmaMar = (volatile unsigned char *)((mem0<<24)|(mem1<<16)|(mem2<<8)|(mem3)); // MAR 63 | DmaMtc = (mem4<<8)|(mem5); // MTC 64 | DmaBar = (volatile unsigned char *)((mem6<<24)|(mem7<<16)|(mem8<<8)|(mem9)); // BAR 65 | 66 | if ( DmaMtc == 0 ) { // MTC == 0 ? 67 | // カウントエラー(メモリアドレス/メモリカウンタ) 68 | return 1; 69 | } 70 | return 0; 71 | } 72 | 73 | 74 | int Pcm8::DmaGetByte() { 75 | if (DmaMtc == 0) { 76 | return 0x80000000; 77 | } 78 | { 79 | int mem; 80 | mem = MemRead((unsigned char *)DmaMar); 81 | if (mem == -1) { 82 | // バスエラー(メモリアドレス/メモリカウンタ) 83 | return 0x80000000; 84 | } 85 | DmaLastValue = mem; 86 | DmaMar += 1; 87 | } 88 | 89 | --DmaMtc; 90 | 91 | // try { 92 | if (DmaMtc == 0) { 93 | if (DmaOcr & 0x08) { // チェイニング動作 94 | if (!(DmaOcr & 0x04)) { // アレイチェイン 95 | if (DmaArrayChainSetNextMtcMar()) { 96 | // throw ""; 97 | } 98 | } else { // リンクアレイチェイン 99 | if (DmaLinkArrayChainSetNextMtcMar()) { 100 | // throw ""; 101 | } 102 | } 103 | } 104 | } 105 | // } catch (void *) { 106 | // } 107 | 108 | return DmaLastValue; 109 | } 110 | 111 | 112 | #define MAXPCMVAL (2047) 113 | static int HPF_shift_tbl[16+1]={ 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4,}; 114 | 115 | 116 | // adpcmを入力して InpPcm の値を変化させる 117 | // -2047<<(4+4) <= InpPcm <= +2047<<(4+4) 118 | void Pcm8::adpcm2pcm(unsigned char adpcm) { 119 | int dltL; 120 | dltL = dltLTBL[Scale]; 121 | dltL = (dltL&(adpcm&4?-1:0)) + ((dltL>>1)&(adpcm&2?-1:0)) + ((dltL>>2)&(adpcm&1?-1:0)) + (dltL>>3); 122 | int sign = adpcm&8?-1:0; 123 | dltL = (dltL^sign)+(sign&1); 124 | Pcm += dltL; 125 | 126 | if ((unsigned int)(Pcm+MAXPCMVAL) > (unsigned int)(MAXPCMVAL*2)) { 127 | if ((int)(Pcm+MAXPCMVAL) >= (int)(MAXPCMVAL*2)) { 128 | Pcm = MAXPCMVAL; 129 | } else { 130 | Pcm = -MAXPCMVAL; 131 | } 132 | } 133 | 134 | InpPcm = (Pcm&(int)0xFFFFFFFC)<<(4+4); 135 | 136 | Scale += DCT[adpcm]; 137 | if ((unsigned int)Scale > (unsigned int)48) { 138 | if ((int)Scale >= (int)48) { 139 | Scale = 48; 140 | } else { 141 | Scale = 0; 142 | } 143 | } 144 | } 145 | 146 | 147 | // pcm16を入力して InpPcm の値を変化させる 148 | // -2047<<(4+4) <= InpPcm <= +2047<<(4+4) 149 | void Pcm8::pcm16_2pcm(int pcm16) { 150 | Pcm += pcm16-Pcm16Prev; 151 | Pcm16Prev = pcm16; 152 | 153 | 154 | if ((unsigned int)(Pcm+MAXPCMVAL) > (unsigned int)(MAXPCMVAL*2)) { 155 | if ((int)(Pcm+MAXPCMVAL) >= (int)(MAXPCMVAL*2)) { 156 | Pcm = MAXPCMVAL; 157 | } else { 158 | Pcm = -MAXPCMVAL; 159 | } 160 | } 161 | 162 | InpPcm = (Pcm&(int)0xFFFFFFFC)<<(4+4); 163 | } 164 | 165 | 166 | // -32768<<4 <= retval <= +32768<<4 167 | int Pcm8::GetPcm22() { 168 | if (AdpcmReg & 0x80) { // ADPCM 停止中 169 | return 0x80000000; 170 | } 171 | RateCounter -= AdpcmRate; 172 | while (RateCounter < 0) { 173 | if (PcmKind == 5) { // 16bitPCM 174 | int dataH,dataL; 175 | dataH = DmaGetByte(); 176 | if (dataH == 0x80000000) { 177 | RateCounter = 0; 178 | AdpcmReg = 0xC7; // ADPCM 停止 179 | return 0x80000000; 180 | } 181 | dataL = DmaGetByte(); 182 | if (dataL == 0x80000000) { 183 | RateCounter = 0; 184 | AdpcmReg = 0xC7; // ADPCM 停止 185 | return 0x80000000; 186 | } 187 | pcm16_2pcm((int)(short)((dataH<<8)|dataL)); // OutPcm に値が入る 188 | } else if (PcmKind == 6) { // 8bitPCM 189 | int data; 190 | data = DmaGetByte(); 191 | if (data == 0x80000000) { 192 | RateCounter = 0; 193 | AdpcmReg = 0xC7; // ADPCM 停止 194 | return 0x80000000; 195 | } 196 | pcm16_2pcm((int)(char)data); // InpPcm に値が入る 197 | } else { 198 | int N10Data; // (N1Data << 4) | N0Data 199 | if (N1DataFlag == 0) { // 次のADPCMデータが内部にない場合 200 | N10Data = DmaGetByte(); // DMA転送(1バイト) 201 | if (N10Data == 0x80000000) { 202 | RateCounter = 0; 203 | AdpcmReg = 0xC7; // ADPCM 停止 204 | return 0x80000000; 205 | } 206 | adpcm2pcm(N10Data & 0x0F); // InpPcm に値が入る 207 | N1Data = (N10Data >> 4) & 0x0F; 208 | N1DataFlag = 1; 209 | } else { 210 | adpcm2pcm(N1Data); // InpPcm に値が入る 211 | N1DataFlag = 0; 212 | } 213 | } 214 | RateCounter += 15625*12; 215 | } 216 | OutPcm = ((InpPcm<<9) - (InpPcm_prev<<9) + 459*OutPcm) >> 9; 217 | InpPcm_prev = InpPcm; 218 | 219 | return ((OutPcm*Volume)>>4); 220 | } 221 | 222 | 223 | // -32768<<4 <= retval <= +32768<<4 224 | int Pcm8::GetPcm62() { 225 | if (AdpcmReg & 0x80) { // ADPCM 停止中 226 | return 0x80000000; 227 | } 228 | RateCounter -= AdpcmRate; 229 | while (RateCounter < 0) { 230 | if (PcmKind == 5) { // 16bitPCM 231 | int dataH,dataL; 232 | dataH = DmaGetByte(); 233 | if (dataH == 0x80000000) { 234 | RateCounter = 0; 235 | AdpcmReg = 0xC7; // ADPCM 停止 236 | return 0x80000000; 237 | } 238 | dataL = DmaGetByte(); 239 | if (dataL == 0x80000000) { 240 | RateCounter = 0; 241 | AdpcmReg = 0xC7; // ADPCM 停止 242 | return 0x80000000; 243 | } 244 | pcm16_2pcm((int)(short)((dataH<<8)|dataL)); // OutPcm に値が入る 245 | } else if (PcmKind == 6) { // 8bitPCM 246 | int data; 247 | data = DmaGetByte(); 248 | if (data == 0x80000000) { 249 | RateCounter = 0; 250 | AdpcmReg = 0xC7; // ADPCM 停止 251 | return 0x80000000; 252 | } 253 | pcm16_2pcm((int)(char)data); // InpPcm に値が入る 254 | } else { 255 | int N10Data; // (N1Data << 4) | N0Data 256 | if (N1DataFlag == 0) { // 次のADPCMデータが内部にない場合 257 | N10Data = DmaGetByte(); // DMA転送(1バイト) 258 | if (N10Data == 0x80000000) { 259 | RateCounter = 0; 260 | AdpcmReg = 0xC7; // ADPCM 停止 261 | return 0x80000000; 262 | } 263 | adpcm2pcm(N10Data & 0x0F); // InpPcm に値が入る 264 | N1Data = (N10Data >> 4) & 0x0F; 265 | N1DataFlag = 1; 266 | } else { 267 | adpcm2pcm(N1Data); // InpPcm に値が入る 268 | N1DataFlag = 0; 269 | } 270 | } 271 | RateCounter += 15625*12*4; 272 | } 273 | OutInpPcm = (InpPcm<<9) - (InpPcm_prev<<9) + OutInpPcm-(OutInpPcm>>5)-(OutInpPcm>>10); 274 | InpPcm_prev = InpPcm; 275 | OutPcm = OutInpPcm - OutInpPcm_prev + OutPcm-(OutPcm>>8)-(OutPcm>>9)-(OutPcm>>12); 276 | OutInpPcm_prev = OutInpPcm; 277 | return ((OutPcm>>9)*Volume)>>4; 278 | } 279 | 280 | 281 | Pcm8::Pcm8(void) { 282 | Mode = 0x00080403; 283 | SetMode(Mode); 284 | } 285 | 286 | 287 | void Pcm8::Init() { 288 | AdpcmReg = 0xC7; // ADPCM動作停止 289 | 290 | Scale = 0; 291 | Pcm = 0; 292 | Pcm16Prev = 0; 293 | InpPcm = InpPcm_prev = OutPcm = 0; 294 | OutInpPcm = OutInpPcm_prev = 0; 295 | AdpcmRate = 15625*12; 296 | RateCounter = 0; 297 | N1Data = 0; 298 | N1DataFlag = 0; 299 | DmaLastValue = 0; 300 | 301 | DmaMar = NULL; 302 | DmaMtc = 0; 303 | DmaBar = NULL; 304 | DmaBtc = 0; 305 | DmaOcr = 0; 306 | } 307 | 308 | 309 | void Pcm8::Reset() { // ADPCM キーオン時の処理 310 | Scale = 0; 311 | Pcm = 0; 312 | Pcm16Prev = 0; 313 | InpPcm = InpPcm_prev = OutPcm = 0; 314 | OutInpPcm = OutInpPcm_prev = 0; 315 | 316 | N1Data = 0; 317 | N1DataFlag = 0; 318 | } 319 | 320 | 321 | int Pcm8::Out(void *adrs, int mode, int len) { 322 | if (len <= 0) { 323 | if (len < 0) { 324 | return GetRest(); 325 | } else { 326 | DmaMtc = 0; 327 | return 0; 328 | } 329 | } 330 | AdpcmReg = 0xC7; // ADPCM 停止 331 | DmaMtc = 0; 332 | DmaMar = (unsigned char *)adrs; 333 | SetMode(mode); 334 | if ((mode&3) != 0) { 335 | DmaMtc = len; 336 | Reset(); 337 | AdpcmReg = 0x47; // ADPCM 動作開始 338 | } 339 | return 0; 340 | } 341 | 342 | 343 | int Pcm8::Aot(void *tbl, int mode, int cnt) { 344 | if (cnt <= 0) { 345 | if (cnt < 0) { 346 | return GetRest(); 347 | } else { 348 | DmaMtc = 0; 349 | return 0; 350 | } 351 | } 352 | AdpcmReg = 0xC7; // ADPCM 停止 353 | DmaMtc = 0; 354 | DmaBar = (unsigned char *)tbl; 355 | DmaBtc = cnt; 356 | SetMode(mode); 357 | if ((mode&3) != 0) { 358 | DmaArrayChainSetNextMtcMar(); 359 | Reset(); 360 | AdpcmReg = 0x47; // ADPCM 動作開始 361 | } 362 | return 0; 363 | } 364 | 365 | 366 | int Pcm8::Lot(void *tbl, int mode) { 367 | AdpcmReg = 0xC7; // ADPCM 停止 368 | DmaMtc = 0; 369 | DmaBar = (unsigned char *)tbl; 370 | SetMode(mode); 371 | if ((mode&3) != 0) { 372 | DmaLinkArrayChainSetNextMtcMar(); 373 | Reset(); 374 | AdpcmReg = 0x47; // ADPCM 動作開始 375 | } 376 | return 0; 377 | } 378 | 379 | 380 | int Pcm8::SetMode(int mode) { 381 | int m; 382 | m = (mode>>16) & 0xFF; 383 | if (m != 0xFF) { 384 | m &= 15; 385 | Volume = PCM8VOLTBL[m]; 386 | Mode = (Mode&0xFF00FFFF)|(m<<16); 387 | } 388 | m = (mode>>8) & 0xFF; 389 | if (m != 0xFF) { 390 | m &= 7; 391 | AdpcmRate = ADPCMRATEADDTBL[m]; 392 | PcmKind = m; 393 | Mode = (Mode&0xFFFF00FF)|(m<<8); 394 | } 395 | m = (mode) & 0xFF; 396 | if (m != 0xFF) { 397 | m &= 3; 398 | if (m == 0) { 399 | AdpcmReg = 0xC7; // ADPCM 停止 400 | DmaMtc = 0; 401 | } else { 402 | Mode = (Mode&0xFFFFFF00)|(m); 403 | } 404 | } 405 | return 0; 406 | } 407 | 408 | 409 | int Pcm8::GetRest() { 410 | if (DmaMtc == 0) { 411 | return 0; 412 | } 413 | if (DmaOcr & 0x08) { // チェイニング動作 414 | if (!(DmaOcr & 0x04)) { // アレイチェイン 415 | return -1; 416 | } else { // リンクアレイチェイン 417 | return -2; 418 | } 419 | } 420 | return DmaMtc; 421 | } 422 | 423 | 424 | int Pcm8::GetMode() { 425 | return Mode; 426 | } 427 | 428 | 429 | } 430 | 431 | // [EOF] 432 | -------------------------------------------------------------------------------- /gamdx/fmgen/opm.cpp: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // OPM interface 3 | // Copyright (C) cisc 1998, 2003. 4 | // --------------------------------------------------------------------------- 5 | // $Id: opm.cpp,v 1.26 2003/08/25 13:53:08 cisc Exp $ 6 | 7 | #include "headers.h" 8 | #include "misc.h" 9 | #include "opm.h" 10 | #include "fmgeninl.h" 11 | 12 | //#define LOGNAME "opm" 13 | 14 | namespace FM 15 | { 16 | 17 | int OPM::amtable[4][OPM_LFOENTS] = { -1, }; 18 | int OPM::pmtable[4][OPM_LFOENTS]; 19 | 20 | // --------------------------------------------------------------------------- 21 | // 構築 22 | // 23 | OPM::OPM() 24 | { 25 | lfo_count_ = 0; 26 | lfo_count_prev_ = ~0; 27 | BuildLFOTable(); 28 | for (int i=0; i<8; i++) 29 | { 30 | ch[i].SetChip(&chip); 31 | ch[i].SetType(typeM); 32 | } 33 | } 34 | 35 | // --------------------------------------------------------------------------- 36 | // 初期化 37 | // 38 | bool OPM::Init(uint c, uint rf, bool f) 39 | { 40 | if (!SetRate(c, rf, f)) 41 | return false; 42 | 43 | Reset(); 44 | 45 | SetVolume(0); 46 | SetChannelMask(0); 47 | return true; 48 | } 49 | 50 | // --------------------------------------------------------------------------- 51 | // 再設定 52 | // 53 | bool OPM::SetRate(uint c, uint r, bool f) 54 | { 55 | clock = c; 56 | rate = r; 57 | filter = f; 58 | 59 | RebuildTimeTable(); 60 | 61 | return true; 62 | } 63 | 64 | // --------------------------------------------------------------------------- 65 | // チャンネルマスクの設定 66 | // 67 | void OPM::SetChannelMask(uint mask) 68 | { 69 | for (int i=0; i<8; i++) 70 | ch[i].Mute(!!(mask & (1 << i))); 71 | } 72 | 73 | // --------------------------------------------------------------------------- 74 | // リセット 75 | // 76 | void OPM::Reset() 77 | { 78 | int i; 79 | for (i=0x0; i<0x100; i++) SetReg(i, 0); 80 | SetReg(0x19, 0x80); 81 | Timer::Reset(); 82 | 83 | status = 0; 84 | noise = 12345; 85 | noisecount = 0; 86 | 87 | for (i=0; i<8; i++) 88 | ch[i].Reset(); 89 | 90 | for (int i=0; i<2; i++) { 91 | InpInpOpm[i] = 0; 92 | InpOpm[i] = 0; 93 | InpInpOpm_prev[i] = 0; 94 | InpOpm_prev[i] = 0; 95 | InpInpOpm_prev2[i] = 0; 96 | InpOpm_prev2[i] = 0; 97 | OpmHpfInp[i] = 0; 98 | OpmHpfInp_prev[i] = 0; 99 | OpmHpfOut[i] = 0; 100 | } 101 | } 102 | 103 | // --------------------------------------------------------------------------- 104 | // 設定に依存するテーブルの作成 105 | // 106 | void OPM::RebuildTimeTable() 107 | { 108 | uint fmclock = clock / 64; 109 | 110 | assert(fmclock < (0x80000000 >> FM_RATIOBITS)); 111 | rateratio = ((fmclock << FM_RATIOBITS) + rate/2) / rate; 112 | SetTimerBase(fmclock); 113 | 114 | // FM::MakeTimeTable(rateratio); 115 | chip.SetRatio(rateratio); 116 | 117 | // lfo_diff_ = 118 | 119 | 120 | // lfodcount = (16 + (lfofreq & 15)) << (lfofreq >> 4); 121 | // lfodcount = lfodcount * rateratio >> FM_RATIOBITS; 122 | } 123 | 124 | // --------------------------------------------------------------------------- 125 | // タイマー A 発生時イベント (CSM) 126 | // 127 | void OPM::TimerA() 128 | { 129 | if (regtc & 0x80) 130 | { 131 | for (int i=0; i<8; i++) 132 | { 133 | ch[i].KeyControl(0); 134 | ch[i].KeyControl(0xf); 135 | } 136 | } 137 | } 138 | 139 | // --------------------------------------------------------------------------- 140 | // 音量設定 141 | // 142 | void OPM::SetVolume(int db) 143 | { 144 | db = Min(db, 20); 145 | if (db > -192) 146 | fmvolume = int(16384.0 * pow(10, db / 40.0)); 147 | else 148 | fmvolume = 0; 149 | } 150 | 151 | // --------------------------------------------------------------------------- 152 | // ステータスフラグ設定 153 | // 154 | void OPM::SetStatus(uint bits) 155 | { 156 | if (!(status & bits)) 157 | { 158 | status |= bits; 159 | Intr(true); 160 | } 161 | } 162 | 163 | // --------------------------------------------------------------------------- 164 | // ステータスフラグ解除 165 | // 166 | void OPM::ResetStatus(uint bits) 167 | { 168 | if (status & bits) 169 | { 170 | status &= ~bits; 171 | if (!status) 172 | Intr(false); 173 | } 174 | } 175 | 176 | // --------------------------------------------------------------------------- 177 | // レジスタアレイにデータを設定 178 | // 179 | void OPM::SetReg(uint addr, uint data) 180 | { 181 | if (addr >= 0x100) 182 | return; 183 | 184 | int c = addr & 7; 185 | switch (addr & 0xff) 186 | { 187 | case 0x01: // TEST (lfo restart) 188 | if (data & 2) 189 | { 190 | lfo_count_ = 0; 191 | lfo_count_prev_ = ~0; 192 | } 193 | reg01 = data; 194 | break; 195 | 196 | case 0x08: // KEYON 197 | if (!(regtc & 0x80)) 198 | ch[data & 7].KeyControl(data >> 3); 199 | else 200 | { 201 | c = data & 7; 202 | if (!(data & 0x08)) ch[c].op[0].KeyOff(); 203 | if (!(data & 0x10)) ch[c].op[1].KeyOff(); 204 | if (!(data & 0x20)) ch[c].op[2].KeyOff(); 205 | if (!(data & 0x40)) ch[c].op[3].KeyOff(); 206 | } 207 | break; 208 | 209 | case 0x10: case 0x11: // CLKA1, CLKA2 210 | SetTimerA(addr, data); 211 | break; 212 | 213 | case 0x12: // CLKB 214 | SetTimerB(data); 215 | break; 216 | 217 | case 0x14: // CSM, TIMER 218 | SetTimerControl(data); 219 | break; 220 | 221 | case 0x18: // LFRQ(lfo freq) 222 | lfofreq = data; 223 | 224 | assert(16-4-FM_RATIOBITS >= 0); 225 | lfo_count_diff_ = 226 | rateratio 227 | * ((16 + (lfofreq & 15)) << (16 - 4 - FM_RATIOBITS)) 228 | / (1 << (15 - (lfofreq >> 4))); 229 | 230 | break; 231 | 232 | case 0x19: // PMD/AMD 233 | (data & 0x80 ? pmd : amd) = data & 0x7f; 234 | break; 235 | 236 | case 0x1b: // CT, W(lfo waveform) 237 | lfowaveform = data & 3; 238 | break; 239 | 240 | // RL, FB, Connect 241 | case 0x20: case 0x21: case 0x22: case 0x23: 242 | case 0x24: case 0x25: case 0x26: case 0x27: 243 | ch[c].SetFB((data >> 3) & 7); 244 | ch[c].SetAlgorithm(data & 7); 245 | pan[c] = (data >> 6) & 3; 246 | break; 247 | 248 | // KC 249 | case 0x28: case 0x29: case 0x2a: case 0x2b: 250 | case 0x2c: case 0x2d: case 0x2e: case 0x2f: 251 | kc[c] = data; 252 | ch[c].SetKCKF(kc[c], kf[c]); 253 | break; 254 | 255 | // KF 256 | case 0x30: case 0x31: case 0x32: case 0x33: 257 | case 0x34: case 0x35: case 0x36: case 0x37: 258 | kf[c] = data >> 2; 259 | ch[c].SetKCKF(kc[c], kf[c]); 260 | break; 261 | 262 | // PMS, AMS 263 | case 0x38: case 0x39: case 0x3a: case 0x3b: 264 | case 0x3c: case 0x3d: case 0x3e: case 0x3f: 265 | ch[c].SetMS((data << 4) | (data >> 4)); 266 | break; 267 | 268 | case 0x0f: // NE/NFRQ (noise) 269 | noisedelta = data; 270 | noisecount = 0; 271 | break; 272 | 273 | default: 274 | if (addr >= 0x40) 275 | OPM::SetParameter(addr, data); 276 | break; 277 | } 278 | } 279 | 280 | 281 | // --------------------------------------------------------------------------- 282 | // パラメータセット 283 | // 284 | void OPM::SetParameter(uint addr, uint data) 285 | { 286 | const static uint8 sltable[16] = 287 | { 288 | 0, 4, 8, 12, 16, 20, 24, 28, 289 | 32, 36, 40, 44, 48, 52, 56, 124, 290 | }; 291 | const static uint8 slottable[4] = { 0, 2, 1, 3 }; 292 | 293 | uint slot = slottable[(addr >> 3) & 3]; 294 | Operator* op = &ch[addr & 7].op[slot]; 295 | 296 | switch ((addr >> 5) & 7) 297 | { 298 | case 2: // 40-5F DT1/MULTI 299 | op->SetDT((data >> 4) & 0x07); 300 | op->SetMULTI(data & 0x0f); 301 | break; 302 | 303 | case 3: // 60-7F TL 304 | op->SetTL(data & 0x7f, (regtc & 0x80) != 0); 305 | break; 306 | 307 | case 4: // 80-9F KS/AR 308 | op->SetKS((data >> 6) & 3); 309 | op->SetAR((data & 0x1f) * 2); 310 | break; 311 | 312 | case 5: // A0-BF DR/AMON(D1R/AMS-EN) 313 | op->SetDR((data & 0x1f) * 2); 314 | op->SetAMON((data & 0x80) != 0); 315 | break; 316 | 317 | case 6: // C0-DF SR(D2R), DT2 318 | op->SetSR((data & 0x1f) * 2); 319 | op->SetDT2((data >> 6) & 3); 320 | break; 321 | 322 | case 7: // E0-FF SL(D1L)/RR 323 | op->SetSL(sltable[(data >> 4) & 15]); 324 | op->SetRR((data & 0x0f) * 4 + 2); 325 | break; 326 | } 327 | } 328 | 329 | // --------------------------------------------------------------------------- 330 | // 331 | // 332 | void OPM::BuildLFOTable() 333 | { 334 | if (amtable[0][0] != -1) 335 | return; 336 | 337 | for (int type=0; type<4; type++) 338 | { 339 | int r = 0; 340 | for (int c=0; c> 15) & 0x1fe; 386 | // fprintf(stderr, "%.8x %.2x\n", lfo_count_, c); 387 | chip.SetPML(pmtable[lfowaveform][c] * pmd / 128 + 0x80); 388 | chip.SetAML(amtable[lfowaveform][c] * amd / 128); 389 | } 390 | } 391 | else 392 | { 393 | if ((lfo_count_ ^ lfo_count_prev_) & ~((1 << 17) - 1)) 394 | { 395 | int c = (rand() / 17) & 0xff; 396 | chip.SetPML((c - 0x80) * pmd / 128 + 0x80); 397 | chip.SetAML(c * amd / 128); 398 | } 399 | } 400 | lfo_count_prev_ = lfo_count_; 401 | lfo_step_++; 402 | if ((lfo_step_ & 7) == 0) 403 | { 404 | lfo_count_ += lfo_count_diff_; 405 | } 406 | } 407 | 408 | inline uint OPM::Noise() 409 | { 410 | noisecount += 2 * rateratio; 411 | if (noisecount >= (32 << FM_RATIOBITS)) 412 | { 413 | int n = 32 - (noisedelta & 0x1f); 414 | if (n == 1) 415 | n = 2; 416 | 417 | noisecount = noisecount - (n << FM_RATIOBITS); 418 | if ((noisedelta & 0x1f) == 0x1f) 419 | noisecount -= FM_RATIOBITS; 420 | noise = (noise >> 1) ^ (noise & 1 ? 0x8408 : 0); 421 | } 422 | return noise; 423 | } 424 | 425 | // --------------------------------------------------------------------------- 426 | // 合成の一部 427 | // 428 | inline void OPM::MixSub(int activech, ISample** idest) 429 | { 430 | if (activech & 0x4000) (*idest[0] = ch[0].Calc()); 431 | if (activech & 0x1000) (*idest[1] += ch[1].Calc()); 432 | if (activech & 0x0400) (*idest[2] += ch[2].Calc()); 433 | if (activech & 0x0100) (*idest[3] += ch[3].Calc()); 434 | if (activech & 0x0040) (*idest[4] += ch[4].Calc()); 435 | if (activech & 0x0010) (*idest[5] += ch[5].Calc()); 436 | if (activech & 0x0004) (*idest[6] += ch[6].Calc()); 437 | if (activech & 0x0001) 438 | { 439 | if (noisedelta & 0x80) 440 | *idest[7] += ch[7].CalcN(Noise()); 441 | else 442 | *idest[7] += ch[7].Calc(); 443 | } 444 | } 445 | 446 | inline void OPM::MixSubL(int activech, ISample** idest) 447 | { 448 | if (activech & 0x4000) (*idest[0] = ch[0].CalcL()); 449 | if (activech & 0x1000) (*idest[1] += ch[1].CalcL()); 450 | if (activech & 0x0400) (*idest[2] += ch[2].CalcL()); 451 | if (activech & 0x0100) (*idest[3] += ch[3].CalcL()); 452 | if (activech & 0x0040) (*idest[4] += ch[4].CalcL()); 453 | if (activech & 0x0010) (*idest[5] += ch[5].CalcL()); 454 | if (activech & 0x0004) (*idest[6] += ch[6].CalcL()); 455 | if (activech & 0x0001) 456 | { 457 | if (noisedelta & 0x80) 458 | *idest[7] += ch[7].CalcLN(Noise()); 459 | else 460 | *idest[7] += ch[7].CalcL(); 461 | } 462 | } 463 | 464 | 465 | // --------------------------------------------------------------------------- 466 | // 合成 (stereo) 467 | // 468 | void OPM::Mix(Sample* buffer, int nsamples) 469 | { 470 | #define IStoSample(s) ((Limit(s, 0xffff, -0x10000) * fmvolume) >> 14) 471 | //#define IStoSample(s) ((s * fmvolume) >> 14) 472 | 473 | // odd bits - active, even bits - lfo 474 | uint activech=0; 475 | for (int i=0; i<8; i++) 476 | activech = (activech << 2) | ch[i].Prepare(); 477 | 478 | if (activech & 0x5555) 479 | { 480 | // LFO 波形初期化ビット = 1 ならば LFO はかからない? 481 | if (reg01 & 0x02) 482 | activech &= 0x5555; 483 | 484 | // Mix 485 | ISample ibuf[8]; 486 | ISample* idest[8]; 487 | idest[0] = &ibuf[pan[0]]; 488 | idest[1] = &ibuf[pan[1]]; 489 | idest[2] = &ibuf[pan[2]]; 490 | idest[3] = &ibuf[pan[3]]; 491 | idest[4] = &ibuf[pan[4]]; 492 | idest[5] = &ibuf[pan[5]]; 493 | idest[6] = &ibuf[pan[6]]; 494 | idest[7] = &ibuf[pan[7]]; 495 | 496 | Sample* limit = buffer + nsamples * 2; 497 | for (Sample* dest = buffer; dest < limit; dest+=2) 498 | { 499 | ibuf[1] = ibuf[2] = ibuf[3] = 0; 500 | if (activech & 0xaaaa) 501 | LFO(), MixSubL(activech, idest); 502 | else 503 | LFO(), MixSub(activech, idest); 504 | 505 | if (filter) 506 | { 507 | OpmHpfInp[0] = IStoSample(ibuf[1] + ibuf[3])<<14; 508 | OpmHpfInp[1] = IStoSample(ibuf[2] + ibuf[3])<<14; 509 | 510 | OpmHpfOut[0] = OpmHpfInp[0]-OpmHpfInp_prev[0]+ 511 | OpmHpfOut[0]-(OpmHpfOut[0]>>10)-(OpmHpfOut[0]>>12); 512 | OpmHpfOut[1] = OpmHpfInp[1]-OpmHpfInp_prev[1]+ 513 | OpmHpfOut[1]-(OpmHpfOut[1]>>10)-(OpmHpfOut[1]>>12); 514 | 515 | OpmHpfInp_prev[0] = OpmHpfInp[0]; 516 | OpmHpfInp_prev[1] = OpmHpfInp[1]; 517 | 518 | InpInpOpm[0] = OpmHpfOut[0] >> (4+5); 519 | InpInpOpm[1] = OpmHpfOut[1] >> (4+5); 520 | 521 | InpInpOpm[0] = InpInpOpm[0]*29; 522 | InpInpOpm[1] = InpInpOpm[1]*29; 523 | 524 | InpOpm[0] = (InpInpOpm[0] + InpInpOpm_prev[0]+ 525 | InpOpm[0]*70) >> 7; 526 | InpOpm[1] = (InpInpOpm[1] + InpInpOpm_prev[1] + 527 | InpOpm[1]*70) >> 7; 528 | 529 | InpInpOpm_prev[0] = InpInpOpm[0]; 530 | InpInpOpm_prev[1] = InpInpOpm[1]; 531 | 532 | StoreSample(dest[0], InpOpm[0] >> 5); 533 | StoreSample(dest[1], InpOpm[1] >> 5); 534 | } 535 | else 536 | { 537 | StoreSample(dest[0], IStoSample(ibuf[1] + ibuf[3])); 538 | StoreSample(dest[1], IStoSample(ibuf[2] + ibuf[3])); 539 | } 540 | } 541 | } 542 | #undef IStoSample 543 | } 544 | 545 | } // namespace FM 546 | 547 | -------------------------------------------------------------------------------- /gamdx/fmgen/fmgen.cpp: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // FM Sound Generator - Core Unit 3 | // Copyright (C) cisc 1998, 2003. 4 | // --------------------------------------------------------------------------- 5 | // $Id: fmgen.cpp,v 1.49 2003/09/02 14:51:04 cisc Exp $ 6 | // --------------------------------------------------------------------------- 7 | // 参考: 8 | // FM sound generator for M.A.M.E., written by Tatsuyuki Satoh. 9 | // 10 | // 謎: 11 | // OPNB の CSM モード(仕様がよくわからない) 12 | // 13 | // 制限: 14 | // ・AR!=31 で SSGEC を使うと波形が実際と異なる可能性あり 15 | // 16 | // 謝辞: 17 | // Tatsuyuki Satoh さん(fm.c) 18 | // Hiromitsu Shioya さん(ADPCM-A) 19 | // DMP-SOFT. さん(OPNB) 20 | // KAJA さん(test program) 21 | // ほか掲示板等で様々なご助言,ご支援をお寄せいただいた皆様に 22 | // --------------------------------------------------------------------------- 23 | 24 | #include "headers.h" 25 | #include "misc.h" 26 | #include "fmgen.h" 27 | #include "fmgeninl.h" 28 | 29 | #define LOGNAME "fmgen" 30 | 31 | // --------------------------------------------------------------------------- 32 | 33 | #define FM_EG_BOTTOM 955 34 | 35 | // --------------------------------------------------------------------------- 36 | // Table/etc 37 | // 38 | namespace FM 39 | { 40 | #if defined(__GNUC__) 41 | #pragma GCC diagnostic push 42 | #pragma GCC diagnostic ignored "-Wmissing-braces" 43 | #endif 44 | 45 | const uint8 Operator::notetable[128] = 46 | { 47 | 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 48 | 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 49 | 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, 50 | 12, 12, 12, 12, 12, 12, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, 51 | 16, 16, 16, 16, 16, 16, 16, 17, 18, 19, 19, 19, 19, 19, 19, 19, 52 | 20, 20, 20, 20, 20, 20, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, 53 | 24, 24, 24, 24, 24, 24, 24, 25, 26, 27, 27, 27, 27, 27, 27, 27, 54 | 28, 28, 28, 28, 28, 28, 28, 29, 30, 31, 31, 31, 31, 31, 31, 31, 55 | }; 56 | 57 | const int8 Operator::dttable[256] = 58 | { 59 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61 | 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 62 | 4, 6, 6, 6, 8, 8, 8, 10, 10, 12, 12, 14, 16, 16, 16, 16, 63 | 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, 64 | 10, 12, 12, 14, 16, 16, 18, 20, 22, 24, 26, 28, 32, 32, 32, 32, 65 | 4, 4, 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, 10, 12, 12, 14, 66 | 16, 16, 18, 20, 22, 24, 26, 28, 32, 34, 38, 40, 44, 44, 44, 44, 67 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69 | 0, 0, 0, 0, -2, -2, -2, -2, -2, -2, -2, -2, -4, -4, -4, -4, 70 | -4, -6, -6, -6, -8, -8, -8,-10,-10,-12,-12,-14,-16,-16,-16,-16, 71 | -2, -2, -2, -2, -4, -4, -4, -4, -4, -6, -6, -6, -8, -8, -8,-10, 72 | -10,-12,-12,-14,-16,-16,-18,-20,-22,-24,-26,-28,-32,-32,-32,-32, 73 | -4, -4, -4, -4, -4, -6, -6, -6, -8, -8, -8,-10,-10,-12,-12,-14, 74 | -16,-16,-18,-20,-22,-24,-26,-28,-32,-34,-38,-40,-44,-44,-44,-44, 75 | }; 76 | 77 | const int8 Operator::decaytable1[64][8] = 78 | { 79 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 81 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 82 | 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 83 | 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 84 | 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 85 | 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 86 | 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 87 | 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 88 | 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 89 | 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 90 | 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 91 | 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 92 | 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 93 | 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 94 | 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 95 | 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 96 | 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 97 | 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 98 | 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 99 | 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 100 | 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 101 | 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 102 | 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 103 | 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 104 | 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 105 | 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 4, 2, 2, 2, 106 | 4, 2, 4, 2, 4, 2, 4, 2, 4, 4, 4, 2, 4, 4, 4, 2, 107 | 4, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 4, 4, 108 | 8, 4, 8, 4, 8, 4, 8, 4, 8, 8, 8, 4, 8, 8, 8, 4, 109 | 16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16, 110 | 16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16, 111 | }; 112 | 113 | const int Operator::decaytable2[16] = 114 | { 115 | 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2047, 2047, 2047, 2047, 2047 116 | }; 117 | 118 | const int8 Operator::attacktable[64][8] = 119 | { 120 | -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, 121 | 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 122 | 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 123 | 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4,-1, 124 | 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, 125 | 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, 126 | 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, 127 | 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, 128 | 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, 129 | 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, 130 | 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, 131 | 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, 132 | 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, 133 | 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, 134 | 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, 135 | 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, 136 | 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, 137 | 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, 138 | 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, 139 | 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, 140 | 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, 141 | 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, 142 | 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, 143 | 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, 144 | 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, 145 | 3, 4, 3, 4, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 3, 4, 146 | 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 147 | 2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 3, 2, 2, 2, 3, 148 | 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 149 | 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 150 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 151 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 152 | }; 153 | 154 | const int Operator::ssgenvtable[8][2][3][2] = 155 | { 156 | 1, 1, 1, 1, 1, 1, // 08 157 | 0, 1, 1, 1, 1, 1, // 08 56~ 158 | 0, 1, 2, 0, 2, 0, // 09 159 | 0, 1, 2, 0, 2, 0, // 09 160 | 1,-1, 0, 1, 1,-1, // 10 161 | 0, 1, 1,-1, 0, 1, // 10 60~ 162 | 1,-1, 0, 0, 0, 0, // 11 163 | 0, 1, 0, 0, 0, 0, // 11 60~ 164 | 2,-1, 2,-1, 2,-1, // 12 165 | 1,-1, 2,-1, 2,-1, // 12 56~ 166 | 1,-1, 0, 0, 0, 0, // 13 167 | 1,-1, 0, 0, 0, 0, // 13 168 | 0, 1, 1,-1, 0, 1, // 14 169 | 1,-1, 0, 1, 1,-1, // 14 60~ 170 | 0, 1, 2, 0, 2, 0, // 15 171 | 1,-1, 2, 0, 2, 0, // 15 60~ 172 | }; 173 | #if defined(__GNUC__) 174 | #pragma GCC diagnostic pop 175 | #endif 176 | 177 | // fixed equasion-based tables 178 | int pmtable[2][8][FM_LFOENTS]; 179 | uint amtable[2][4][FM_LFOENTS]; 180 | 181 | static bool tablemade = false; 182 | } 183 | 184 | namespace FM 185 | { 186 | 187 | // --------------------------------------------------------------------------- 188 | // テーブル作成 189 | // 190 | void MakeLFOTable() 191 | { 192 | if (tablemade) 193 | return; 194 | 195 | tablemade = true; 196 | 197 | int i; 198 | 199 | static const double pms[2][8] = 200 | { 201 | { 0, 1/360., 2/360., 3/360., 4/360., 6/360., 12/360., 24/360., }, // OPNA 202 | // { 0, 1/240., 2/240., 4/240., 10/240., 20/240., 80/240., 140/240., }, // OPM 203 | { 0, 1/480., 2/480., 4/480., 10/480., 20/480., 80/480., 140/480., }, // OPM 204 | // { 0, 1/960., 2/960., 4/960., 10/960., 20/960., 80/960., 140/960., }, // OPM 205 | }; 206 | // 3 6, 12 30 60 240 420 / 720 207 | // 1.000963 208 | // lfofref[level * max * wave]; 209 | // pre = lfofref[level][pms * wave >> 8]; 210 | static const uint8 amt[2][4] = 211 | { 212 | { 31, 6, 4, 3 }, // OPNA 213 | { 31, 2, 1, 0 }, // OPM 214 | }; 215 | 216 | for (int type = 0; type < 2; type++) 217 | { 218 | for (i=0; i<8; i++) 219 | { 220 | double pmb = pms[type][i]; 221 | for (int j=0; j> amt[type][i]) * 2) << 2; 239 | } 240 | } 241 | } 242 | } 243 | 244 | 245 | // --------------------------------------------------------------------------- 246 | // チップ内で共通な部分 247 | // 248 | Chip::Chip() 249 | : ratio_(0), aml_(0), pml_(0), pmv_(0), optype_(typeN) 250 | { 251 | } 252 | 253 | // クロック・サンプリングレート比に依存するテーブルを作成 254 | void Chip::SetRatio(uint ratio) 255 | { 256 | if (ratio_ != ratio) 257 | { 258 | ratio_ = ratio; 259 | MakeTable(); 260 | } 261 | } 262 | 263 | void Chip::MakeTable() 264 | { 265 | int h, l; 266 | 267 | // PG Part 268 | static const float dt2lv[4] = { 1.f, 1.414f, 1.581f, 1.732f }; 269 | for (h=0; h<4; h++) 270 | { 271 | assert(2 + FM_RATIOBITS - FM_PGBITS >= 0); 272 | double rr = dt2lv[h] * double(ratio_) / (1 << (2 + FM_RATIOBITS - FM_PGBITS)); 273 | for (l=0; l<16; l++) 274 | { 275 | int mul = l ? l * 2 : 1; 276 | multable_[h][l] = uint(mul * rr); 277 | } 278 | } 279 | } 280 | 281 | 282 | // --------------------------------------------------------------------------- 283 | // Operator 284 | // 285 | bool FM::Operator::tablehasmade = false; 286 | uint FM::Operator::sinetable[1024]; 287 | int32 FM::Operator::cltable[FM_CLENTS]; 288 | 289 | // 構築 290 | FM::Operator::Operator() 291 | : chip_(0) 292 | { 293 | if (!tablehasmade) 294 | MakeTable(); 295 | 296 | // EG Part 297 | ar_ = dr_ = sr_ = rr_ = key_scale_rate_ = 0; 298 | ams_ = amtable[0][0]; 299 | mute_ = false; 300 | keyon_ = false; 301 | tl_out_ = false; 302 | ssg_type_ = 0; 303 | 304 | // PG Part 305 | multiple_ = 0; 306 | detune_ = 0; 307 | detune2_ = 0; 308 | 309 | // LFO 310 | ms_ = 0; 311 | 312 | // Reset(); 313 | } 314 | 315 | // 初期化 316 | void FM::Operator::Reset() 317 | { 318 | // EG part 319 | tl_ = tl_latch_ = 127; 320 | ShiftPhase(off); 321 | eg_count_ = 0; 322 | eg_curve_count_ = 0; 323 | ssg_phase_ = 0; 324 | 325 | // PG part 326 | pg_count_ = 0; 327 | 328 | // OP part 329 | out_ = out2_ = 0; 330 | 331 | param_changed_ = true; 332 | PARAMCHANGE(0); 333 | } 334 | 335 | void Operator::MakeTable() 336 | { 337 | // 対数テーブルの作成 338 | assert(FM_CLENTS >= 256); 339 | 340 | int* p = cltable; 341 | int i; 342 | for (i=0; i<256; i++) 343 | { 344 | int v = int(floor(pow(2., 13. - i / 256.))); 345 | v = (v + 2) & ~3; 346 | *p++ = v; 347 | *p++ = -v; 348 | } 349 | while (p < cltable + FM_CLENTS) 350 | { 351 | *p = p[-512] / 2; 352 | p++; 353 | } 354 | 355 | // for (i=0; i<13*256; i++) 356 | // printf("%4d, %d, %d\n", i, cltable[i*2], cltable[i*2+1]); 357 | 358 | // サインテーブルの作成 359 | double log2 = log(2.); 360 | for (i=0; iGetMulValue(detune2_, multiple_); 392 | pg_diff_lfo_ = pg_diff_ >> 11; 393 | 394 | // EG Part 395 | key_scale_rate_ = bn_ >> (3-ks_); 396 | tl_out_ = mute_ ? 0x3ff : tl_ * 8; 397 | 398 | switch (eg_phase_) 399 | { 400 | case attack: 401 | SetEGRate(ar_ ? Min(63, ar_ + key_scale_rate_) : 0); 402 | break; 403 | case decay: 404 | SetEGRate(dr_ ? Min(63, dr_ + key_scale_rate_) : 0); 405 | eg_level_on_next_phase_ = sl_ * 8; 406 | break; 407 | case sustain: 408 | SetEGRate(sr_ ? Min(63, sr_ + key_scale_rate_) : 0); 409 | break; 410 | case release: 411 | SetEGRate(Min(63, rr_ + key_scale_rate_)); 412 | break; 413 | default: 414 | break; 415 | } 416 | 417 | // SSG-EG 418 | if (ssg_type_ && (eg_phase_ != release)) 419 | { 420 | int m = (ar_ >= (uint)((ssg_type_ == 8 || ssg_type_ == 12) ? 56 : 60)); 421 | 422 | assert(0 <= ssg_phase_ && ssg_phase_ <= 2); 423 | const int* table = ssgenvtable[ssg_type_ & 7][m][ssg_phase_]; 424 | 425 | ssg_offset_ = table[0] * 0x200; 426 | ssg_vector_ = table[1]; 427 | } 428 | // LFO 429 | ams_ = amtable[type_][amon_ ? (ms_ >> 4) & 3 : 0]; 430 | EGUpdate(); 431 | 432 | dbgopout_ = 0; 433 | } 434 | } 435 | // envelop の eg_phase_ 変更 436 | void Operator::ShiftPhase(EGPhase nextphase) 437 | { 438 | switch (nextphase) 439 | { 440 | case attack: // Attack Phase 441 | tl_ = tl_latch_; 442 | if (ssg_type_) 443 | { 444 | ssg_phase_ = ssg_phase_ + 1; 445 | if (ssg_phase_ > 2) 446 | ssg_phase_ = 1; 447 | 448 | int m = (ar_ >= (uint)((ssg_type_ == 8 || ssg_type_ == 12) ? 56 : 60)); 449 | 450 | assert(0 <= ssg_phase_ && ssg_phase_ <= 2); 451 | const int* table = ssgenvtable[ssg_type_ & 7][m][ssg_phase_]; 452 | 453 | ssg_offset_ = table[0] * 0x200; 454 | ssg_vector_ = table[1]; 455 | } 456 | if ((ar_ + key_scale_rate_) < 62) 457 | { 458 | SetEGRate(ar_ ? Min(63, ar_ + key_scale_rate_) : 0); 459 | eg_phase_ = attack; 460 | break; 461 | } 462 | case decay: // Decay Phase 463 | if (sl_) 464 | { 465 | eg_level_ = 0; 466 | eg_level_on_next_phase_ = ssg_type_ ? Min(sl_ * 8, 0x200) : sl_ * 8; 467 | 468 | SetEGRate(dr_ ? Min(63, dr_ + key_scale_rate_) : 0); 469 | eg_phase_ = decay; 470 | break; 471 | } 472 | case sustain: // Sustain Phase 473 | eg_level_ = sl_ * 8; 474 | eg_level_on_next_phase_ = ssg_type_ ? 0x200 : 0x400; 475 | 476 | SetEGRate(sr_ ? Min(63, sr_ + key_scale_rate_) : 0); 477 | eg_phase_ = sustain; 478 | break; 479 | 480 | case release: // Release Phase 481 | if (ssg_type_) 482 | { 483 | eg_level_ = eg_level_ * ssg_vector_ + ssg_offset_; 484 | ssg_vector_ = 1; 485 | ssg_offset_ = 0; 486 | } 487 | if (eg_phase_ == attack || (eg_level_ < FM_EG_BOTTOM)) //0x400/* && eg_phase_ != off*/)) 488 | { 489 | eg_level_on_next_phase_ = 0x400; 490 | SetEGRate(Min(63, rr_ + key_scale_rate_)); 491 | eg_phase_ = release; 492 | break; 493 | } 494 | case off: // off 495 | default: 496 | eg_level_ = FM_EG_BOTTOM; 497 | eg_level_on_next_phase_ = FM_EG_BOTTOM; 498 | EGUpdate(); 499 | SetEGRate(0); 500 | eg_phase_ = off; 501 | break; 502 | } 503 | } 504 | 505 | // Block/F-Num 506 | void Operator::SetFNum(uint f) 507 | { 508 | dp_ = (f & 2047) << ((f >> 11) & 7); 509 | bn_ = notetable[(f >> 7) & 127]; 510 | param_changed_ = true; 511 | PARAMCHANGE(2); 512 | } 513 | 514 | // 1サンプル合成 515 | 516 | // ISample を envelop count (2π) に変換するシフト量 517 | #define IS2EC_SHIFT ((20 + FM_PGBITS) - 13) 518 | 519 | 520 | // 入力: s = 20+FM_PGBITS = 29 521 | #define Sine(s) sinetable[((s) >> (20+FM_PGBITS-FM_OPSINBITS))&(FM_OPSINENTS-1)] 522 | #define SINE(s) sinetable[(s) & (FM_OPSINENTS-1)] 523 | 524 | inline FM::ISample Operator::LogToLin(uint a) 525 | { 526 | #if 1 // FM_CLENTS < 0xc00 // 400 for TL, 400 for ENV, 400 for LFO. 527 | return (a < FM_CLENTS) ? cltable[a] : 0; 528 | #else 529 | return cltable[a]; 530 | #endif 531 | } 532 | 533 | inline void Operator::EGUpdate() 534 | { 535 | if (!ssg_type_) 536 | { 537 | eg_out_ = Min(tl_out_ + eg_level_, 0x3ff) << (1 + 2); 538 | } 539 | else 540 | { 541 | eg_out_ = Min(tl_out_ + eg_level_ * ssg_vector_ + ssg_offset_, 0x3ff) << (1 + 2); 542 | } 543 | } 544 | 545 | inline void Operator::SetEGRate(uint rate) 546 | { 547 | eg_rate_ = rate; 548 | eg_count_diff_ = decaytable2[rate / 4] * chip_->GetRatio(); 549 | } 550 | 551 | // EG 計算 552 | void FM::Operator::EGCalc() 553 | { 554 | eg_count_ = (2047 * 3) << FM_RATIOBITS; // ##この手抜きは再現性を低下させる 555 | 556 | if (eg_phase_ == attack) 557 | { 558 | int c = attacktable[eg_rate_][eg_curve_count_ & 7]; 559 | if (c >= 0) 560 | { 561 | eg_level_ -= 1 + (eg_level_ >> c); 562 | if (eg_level_ <= 0) 563 | ShiftPhase(decay); 564 | } 565 | EGUpdate(); 566 | } 567 | else 568 | { 569 | if (!ssg_type_) 570 | { 571 | eg_level_ += decaytable1[eg_rate_][eg_curve_count_ & 7]; 572 | if (eg_level_ >= eg_level_on_next_phase_) 573 | ShiftPhase(EGPhase(eg_phase_+1)); 574 | EGUpdate(); 575 | } 576 | else 577 | { 578 | eg_level_ += 4 * decaytable1[eg_rate_][eg_curve_count_ & 7]; 579 | if (eg_level_ >= eg_level_on_next_phase_) 580 | { 581 | EGUpdate(); 582 | switch (eg_phase_) 583 | { 584 | case decay: 585 | ShiftPhase(sustain); 586 | break; 587 | case sustain: 588 | ShiftPhase(attack); 589 | break; 590 | case release: 591 | ShiftPhase(off); 592 | break; 593 | default: 594 | break; 595 | } 596 | } 597 | } 598 | } 599 | eg_curve_count_++; 600 | } 601 | 602 | inline void FM::Operator::EGStep() 603 | { 604 | eg_count_ -= eg_count_diff_; 605 | 606 | // EG の変化は全スロットで同期しているという噂もある 607 | if (eg_count_ <= 0) 608 | EGCalc(); 609 | } 610 | 611 | // PG 計算 612 | // ret:2^(20+PGBITS) / cycle 613 | inline uint32 FM::Operator::PGCalc() 614 | { 615 | uint32 ret = pg_count_; 616 | pg_count_ += pg_diff_; 617 | dbgpgout_ = ret; 618 | return ret; 619 | } 620 | 621 | inline uint32 FM::Operator::PGCalcL() 622 | { 623 | uint32 ret = pg_count_; 624 | pg_count_ += pg_diff_ + ((pg_diff_lfo_ * chip_->GetPMV()) >> 5);// & -(1 << (2+IS2EC_SHIFT))); 625 | dbgpgout_ = ret; 626 | return ret /* + pmv * pg_diff_;*/; 627 | } 628 | 629 | // OP 計算 630 | // in: ISample (最大 8π) 631 | inline FM::ISample FM::Operator::Calc(ISample in) 632 | { 633 | EGStep(); 634 | out2_ = out_; 635 | 636 | int pgin = PGCalc() >> (20+FM_PGBITS-FM_OPSINBITS); 637 | pgin += in >> (20+FM_PGBITS-FM_OPSINBITS-(2+IS2EC_SHIFT)); 638 | out_ = LogToLin(eg_out_ + SINE(pgin)); 639 | 640 | dbgopout_ = out_; 641 | return out_; 642 | } 643 | 644 | inline FM::ISample FM::Operator::CalcL(ISample in) 645 | { 646 | EGStep(); 647 | 648 | int pgin = PGCalcL() >> (20+FM_PGBITS-FM_OPSINBITS); 649 | pgin += in >> (20+FM_PGBITS-FM_OPSINBITS-(2+IS2EC_SHIFT)); 650 | out_ = LogToLin(eg_out_ + SINE(pgin) + ams_[chip_->GetAML()]); 651 | 652 | dbgopout_ = out_; 653 | return out_; 654 | } 655 | 656 | inline FM::ISample FM::Operator::CalcN(uint noise) 657 | { 658 | EGStep(); 659 | 660 | int lv = Max(0, 0x3ff - (tl_out_ + eg_level_)) << 1; 661 | 662 | // noise & 1 ? lv : -lv と等価 663 | noise = (noise & 1) - 1; 664 | out_ = (lv + noise) ^ noise; 665 | 666 | dbgopout_ = out_; 667 | return out_; 668 | } 669 | 670 | // OP (FB) 計算 671 | // Self Feedback の変調最大 = 4π 672 | inline FM::ISample FM::Operator::CalcFB(uint fb) 673 | { 674 | EGStep(); 675 | 676 | ISample in = out_ + out2_; 677 | out2_ = out_; 678 | 679 | int pgin = PGCalc() >> (20+FM_PGBITS-FM_OPSINBITS); 680 | if (fb < 31) 681 | { 682 | pgin += ((in << (1 + IS2EC_SHIFT)) >> fb) >> (20+FM_PGBITS-FM_OPSINBITS); 683 | } 684 | out_ = LogToLin(eg_out_ + SINE(pgin)); 685 | dbgopout_ = out2_; 686 | 687 | return out2_; 688 | } 689 | 690 | inline FM::ISample FM::Operator::CalcFBL(uint fb) 691 | { 692 | EGStep(); 693 | 694 | ISample in = out_ + out2_; 695 | out2_ = out_; 696 | 697 | int pgin = PGCalcL() >> (20+FM_PGBITS-FM_OPSINBITS); 698 | if (fb < 31) 699 | { 700 | pgin += ((in << (1 + IS2EC_SHIFT)) >> fb) >> (20+FM_PGBITS-FM_OPSINBITS); 701 | } 702 | 703 | out_ = LogToLin(eg_out_ + SINE(pgin) + ams_[chip_->GetAML()]); 704 | dbgopout_ = out_; 705 | 706 | return out_; 707 | } 708 | 709 | #undef Sine 710 | 711 | // --------------------------------------------------------------------------- 712 | // 4-op Channel 713 | // 714 | const uint8 Channel4::fbtable[8] = { 31, 7, 6, 5, 4, 3, 2, 1 }; 715 | int Channel4::kftable[64]; 716 | 717 | bool Channel4::tablehasmade = false; 718 | 719 | 720 | Channel4::Channel4() 721 | { 722 | if (!tablehasmade) 723 | MakeTable(); 724 | 725 | SetAlgorithm(0); 726 | pms = pmtable[0][0]; 727 | } 728 | 729 | void Channel4::MakeTable() 730 | { 731 | // 100/64 cent = 2^(i*100/64*1200) 732 | for (int i=0; i<64; i++) 733 | { 734 | kftable[i] = int(0x10000 * pow(2., i / 768.) ); 735 | } 736 | } 737 | 738 | // リセット 739 | void Channel4::Reset() 740 | { 741 | op[0].Reset(); 742 | op[1].Reset(); 743 | op[2].Reset(); 744 | op[3].Reset(); 745 | } 746 | 747 | // Calc の用意 748 | int Channel4::Prepare() 749 | { 750 | op[0].Prepare(); 751 | op[1].Prepare(); 752 | op[2].Prepare(); 753 | op[3].Prepare(); 754 | 755 | pms = pmtable[op[0].type_][op[0].ms_ & 7]; 756 | int key = (op[0].IsOn() | op[1].IsOn() | op[2].IsOn() | op[3].IsOn()) ? 1 : 0; 757 | int lfo = op[0].ms_ & (op[0].amon_ | op[1].amon_ | op[2].amon_ | op[3].amon_ ? 0x37 : 7) ? 2 : 0; 758 | return key | lfo; 759 | } 760 | 761 | // F-Number/BLOCK を設定 762 | void Channel4::SetFNum(uint f) 763 | { 764 | for (int i=0; i<4; i++) 765 | op[i].SetFNum(f); 766 | } 767 | 768 | // KC/KF を設定 769 | void Channel4::SetKCKF(uint kc, uint kf) 770 | { 771 | const static uint kctable[16] = 772 | { 773 | 5197, 5506, 5833, 6180, 6180, 6547, 6937, 7349, 774 | 7349, 7786, 8249, 8740, 8740, 9259, 9810, 10394, 775 | }; 776 | 777 | int oct = 19 - ((kc >> 4) & 7); 778 | 779 | //printf("%p", this); 780 | uint kcv = kctable[kc & 0x0f]; 781 | kcv = (kcv + 2) / 4 * 4; 782 | //printf(" %.4x", kcv); 783 | uint dp = kcv * kftable[kf & 0x3f]; 784 | //printf(" %.4x %.4x %.8x", kcv, kftable[kf & 0x3f], dp >> oct); 785 | dp >>= 16 + 3; 786 | dp <<= 16 + 3; 787 | dp >>= oct; 788 | uint bn = (kc >> 2) & 31; 789 | op[0].SetDPBN(dp, bn); 790 | op[1].SetDPBN(dp, bn); 791 | op[2].SetDPBN(dp, bn); 792 | op[3].SetDPBN(dp, bn); 793 | //printf(" %.8x\n", dp); 794 | } 795 | 796 | // キー制御 797 | void Channel4::KeyControl(uint key) 798 | { 799 | if (key & 0x1) op[0].KeyOn(); else op[0].KeyOff(); 800 | if (key & 0x2) op[1].KeyOn(); else op[1].KeyOff(); 801 | if (key & 0x4) op[2].KeyOn(); else op[2].KeyOff(); 802 | if (key & 0x8) op[3].KeyOn(); else op[3].KeyOff(); 803 | } 804 | 805 | // アルゴリズムを設定 806 | void Channel4::SetAlgorithm(uint algo) 807 | { 808 | static const uint8 table1[8][6] = 809 | { 810 | { 0, 1, 1, 2, 2, 3 }, { 1, 0, 0, 1, 1, 2 }, 811 | { 1, 1, 1, 0, 0, 2 }, { 0, 1, 2, 1, 1, 2 }, 812 | { 0, 1, 2, 2, 2, 1 }, { 0, 1, 0, 1, 0, 1 }, 813 | { 0, 1, 2, 1, 2, 1 }, { 1, 0, 1, 0, 1, 0 }, 814 | }; 815 | 816 | in [0] = &buf[table1[algo][0]]; 817 | out[0] = &buf[table1[algo][1]]; 818 | in [1] = &buf[table1[algo][2]]; 819 | out[1] = &buf[table1[algo][3]]; 820 | in [2] = &buf[table1[algo][4]]; 821 | out[2] = &buf[table1[algo][5]]; 822 | 823 | op[0].ResetFB(); 824 | algo_ = algo; 825 | } 826 | 827 | // 合成 828 | ISample Channel4::Calc() 829 | { 830 | int r = 0; 831 | switch (algo_) 832 | { 833 | case 0: 834 | op[2].Calc(op[1].Out()); 835 | op[1].Calc(op[0].Out()); 836 | r = op[3].Calc(op[2].Out()); 837 | op[0].CalcFB(fb); 838 | break; 839 | case 1: 840 | op[2].Calc(op[0].Out() + op[1].Out()); 841 | op[1].Calc(0); 842 | r = op[3].Calc(op[2].Out()); 843 | op[0].CalcFB(fb); 844 | break; 845 | case 2: 846 | op[2].Calc(op[1].Out()); 847 | op[1].Calc(0); 848 | r = op[3].Calc(op[0].Out() + op[2].Out()); 849 | op[0].CalcFB(fb); 850 | break; 851 | case 3: 852 | op[2].Calc(0); 853 | op[1].Calc(op[0].Out()); 854 | r = op[3].Calc(op[1].Out() + op[2].Out()); 855 | op[0].CalcFB(fb); 856 | break; 857 | case 4: 858 | op[2].Calc(0); 859 | r = op[1].Calc(op[0].Out()); 860 | r += op[3].Calc(op[2].Out()); 861 | op[0].CalcFB(fb); 862 | break; 863 | case 5: 864 | r = op[2].Calc(op[0].Out()); 865 | r += op[1].Calc(op[0].Out()); 866 | r += op[3].Calc(op[0].Out()); 867 | op[0].CalcFB(fb); 868 | break; 869 | case 6: 870 | r = op[2].Calc(0); 871 | r += op[1].Calc(op[0].Out()); 872 | r += op[3].Calc(0); 873 | op[0].CalcFB(fb); 874 | break; 875 | case 7: 876 | r = op[2].Calc(0); 877 | r += op[1].Calc(0); 878 | r += op[3].Calc(0); 879 | r += op[0].CalcFB(fb); 880 | break; 881 | } 882 | return r; 883 | } 884 | 885 | // 合成 886 | ISample Channel4::CalcL() 887 | { 888 | chip_->SetPMV(pms[chip_->GetPML()]); 889 | 890 | int r = 0; 891 | switch (algo_) 892 | { 893 | case 0: 894 | op[2].CalcL(op[1].Out()); 895 | op[1].CalcL(op[0].Out()); 896 | r = op[3].CalcL(op[2].Out()); 897 | op[0].CalcFBL(fb); 898 | break; 899 | case 1: 900 | op[2].CalcL(op[0].Out() + op[1].Out()); 901 | op[1].CalcL(0); 902 | r = op[3].CalcL(op[2].Out()); 903 | op[0].CalcFBL(fb); 904 | break; 905 | case 2: 906 | op[2].CalcL(op[1].Out()); 907 | op[1].CalcL(0); 908 | r = op[3].CalcL(op[0].Out() + op[2].Out()); 909 | op[0].CalcFBL(fb); 910 | break; 911 | case 3: 912 | op[2].CalcL(0); 913 | op[1].CalcL(op[0].Out()); 914 | r = op[3].CalcL(op[1].Out() + op[2].Out()); 915 | op[0].CalcFBL(fb); 916 | break; 917 | case 4: 918 | op[2].CalcL(0); 919 | r = op[1].CalcL(op[0].Out()); 920 | r += op[3].CalcL(op[2].Out()); 921 | op[0].CalcFBL(fb); 922 | break; 923 | case 5: 924 | r = op[2].CalcL(op[0].Out()); 925 | r += op[1].CalcL(op[0].Out()); 926 | r += op[3].CalcL(op[0].Out()); 927 | op[0].CalcFBL(fb); 928 | break; 929 | case 6: 930 | r = op[2].CalcL(0); 931 | r += op[1].CalcL(op[0].Out()); 932 | r += op[3].CalcL(0); 933 | op[0].CalcFBL(fb); 934 | break; 935 | case 7: 936 | r = op[2].CalcL(0); 937 | r += op[1].CalcL(0); 938 | r += op[3].CalcL(0); 939 | r += op[0].CalcFBL(fb); 940 | break; 941 | } 942 | return r; 943 | } 944 | 945 | // 合成 946 | ISample Channel4::CalcN(uint noise) 947 | { 948 | buf[1] = buf[2] = buf[3] = 0; 949 | 950 | buf[0] = op[0].out_; op[0].CalcFB(fb); 951 | *out[0] += op[1].Calc(*in[0]); 952 | *out[1] += op[2].Calc(*in[1]); 953 | int o = op[3].out_; 954 | op[3].CalcN(noise); 955 | return *out[2] + o; 956 | } 957 | 958 | // 合成 959 | ISample Channel4::CalcLN(uint noise) 960 | { 961 | chip_->SetPMV(pms[chip_->GetPML()]); 962 | buf[1] = buf[2] = buf[3] = 0; 963 | 964 | buf[0] = op[0].out_; op[0].CalcFBL(fb); 965 | *out[0] += op[1].CalcL(*in[0]); 966 | *out[1] += op[2].CalcL(*in[1]); 967 | int o = op[3].out_; 968 | op[3].CalcN(noise); 969 | return *out[2] + o; 970 | } 971 | 972 | } // namespace FM 973 | -------------------------------------------------------------------------------- /gamdx/downsample/lowpass_48.dat: -------------------------------------------------------------------------------- 1 | 1, 14, 13, -17, 10, 9, -33, 42, -20, -33, 88, -102, 43, 77, -195, 222, -100, -142, 382, -452, 239, 220, -707, 907, -571, -302, 1378,-2051, 1642, 404,-4677,15367,22496, -125,-2973, 3022,-1770, 243, 844,-1177, 848, -208, -350, 580, -461, 147, 152, -290, 243, -87, -65, 137, -115, 41, 29, -59, 46, -13, -14, 22, -15, 2, 18, 4, 2 | 4, 18, 4, -16, 21, -10, -18, 48, -55, 19, 51, -118, 127, -43, -110, 251, -271, 108, 195, -482, 549, -268, -305, 900,-1129, 684, 456,-1907, 2921,-2487,-1055,21693,16616,-4278, -70, 1927,-2105, 1267, -137, -693, 941, -662, 141, 304, -475, 363, -102, -135, 235, -187, 59, 59, -108, 85, -25, -27, 45, -32, 6, 12, -17, 12, 15, 2, 3 | 8, 19, -7, -8, 24, -28, 10, 29, -67, 69, -17, -76, 155, -156, 42, 152, -318, 328, -113, -263, 605, -667, 300, 419,-1156, 1432, -841, -708, 2859,-4827, 5314,24770, 8986,-5315, 2242, 132,-1416, 1573, -945, 68, 579, -759, 518, -91, -263, 387, -283, 68, 118, -189, 142, -37, -53, 84, -61, 13, 23, -33, 20, -2, -11, 17, 10, 1, 4 | 1, 12, 15, -15, 6, 14, -34, 36, -7, -46, 90, -86, 12, 107, -201, 189, -37, -205, 400, -395, 116, 350, -759, 813, -336, -577, 1518,-1881, 1090, 1191,-5157,13020,23669, 1742,-3780, 3091,-1444, -159, 1105,-1220, 720, -21, -487, 615, -405, 53, 226, -313, 218, -42, -103, 150, -105, 21, 45, -64, 42, -5, -20, 24, -13, -1, 19, 5, 5 | 3, 17, 7, -17, 19, -4, -24, 49, -45, 2, 67, -119, 105, -4, -146, 255, -227, 27, 272, -500, 474, -114, -463, 955,-1001, 379, 807,-2072, 2637,-1579,-2511,20003,18724,-3320, -966, 2384,-2121, 1012, 171, -890, 965, -553, -11, 411, -498, 314, -26, -193, 251, -166, 22, 88, -117, 76, -9, -38, 48, -28, 0, 16, -17, 9, 16, 2, 6 | 6, 19, -4, -11, 24, -23, 1, 38, -66, 56, 6, -95, 155, -126, -9, 195, -321, 271, -13, -355, 621, -568, 107, 611,-1215, 1255, -434,-1176, 3052,-4252, 3110,24242,11412,-5313, 1655, 708,-1719, 1567, -739, -174, 730, -772, 426, 32, -347, 402, -241, 6, 163, -199, 123, -8, -73, 89, -53, 1, 31, -34, 17, 3, -14, 16, 11, 1, 7 | 1, 11, 17, -13, 1, 18, -34, 29, 5, -56, 88, -67, -18, 130, -197, 149, 27, -257, 399, -320, -9, 460, -772, 683, -93, -813, 1578,-1626, 515, 1866,-5344,10603,24463, 3827,-4463, 3005,-1028, -571, 1320,-1202, 551, 172, -604, 619, -326, -46, 291, -322, 182, 8, -136, 156, -89, -2, 61, -67, 35, 4, -25, 24, -10, -5, 19, 7, 8 | 2, 16, 10, -17, 15, 2, -29, 47, -35, -15, 79, -115, 78, 35, -174, 247, -174, -52, 332, -493, 377, 41, -593, 962, -828, 67, 1105,-2127, 2241, -663,-3673,18044,20599,-2058,-1885, 2745,-2029, 695, 482,-1049, 942, -413, -166, 501, -497, 248, 54, -243, 255, -135, -17, 113, -120, 62, 8, -49, 49, -22, -6, 20, -17, 6, 17, 3, 9 | 5, 19, 0, -14, 23, -18, -8, 44, -63, 40, 28, -109, 146, -90, -57, 228, -307, 202, 86, -426, 607, -444, -85, 767,-1212, 1022, -23,-1563, 3085,-3522, 1093,23318,13813,-5031, 940, 1278,-1948, 1480, -489, -416, 849, -746, 309, 157, -416, 397, -185, -58, 201, -200, 98, 22, -92, 90, -42, -11, 38, -34, 13, 7, -16, 14, 13, 1, 10 | 1, 9, 18, -11, -3, 21, -32, 21, 17, -63, 82, -45, -46, 146, -183, 103, 87, -294, 378, -232, -130, 543, -746, 523, 147,-1002, 1558,-1302, -56, 2406,-5258, 8183,24855, 6081,-4977, 2759, -537, -972, 1477,-1123, 348, 363, -694, 593, -229, -146, 344, -314, 136, 58, -165, 154, -68, -25, 73, -66, 26, 13, -29, 23, -6, -8, 18, 8, 11 | 1, 14, 12, -17, 11, 8, -32, 43, -22, -30, 87, -104, 49, 70, -192, 227, -114, -126, 375, -462, 265, 189, -690, 922, -621, -237, 1336,-2077, 1758, 217,-4529,15872,22187, -507,-2781, 2986,-1829, 330, 781,-1160, 870, -247, -318, 569, -470, 167, 134, -283, 246, -97, -56, 133, -117, 45, 25, -57, 47, -15, -13, 22, -16, 3, 18, 4, 12 | 4, 18, 3, -16, 22, -12, -16, 47, -56, 23, 47, -117, 131, -52, -101, 248, -279, 125, 176, -475, 563, -301, -267, 881,-1150, 749, 372,-1856, 2966,-2684, -693,22026,16122,-4449, 123, 1815,-2087, 1314, -204, -645, 929, -681, 173, 278, -466, 371, -118, -121, 230, -190, 66, 53, -106, 86, -28, -24, 44, -32, 7, 12, -17, 12, 14, 1, 13 | 8, 19, -8, -7, 23, -29, 12, 27, -66, 72, -22, -71, 155, -162, 53, 141, -316, 339, -135, -241, 597, -685, 342, 372,-1135, 1463, -929, -595, 2794,-4929, 5824,24832, 8450,-5280, 2353, 6,-1341, 1564, -984, 121, 542, -751, 535, -117, -242, 381, -291, 81, 108, -185, 145, -43, -48, 83, -62, 16, 21, -33, 21, -2, -11, 18, 10, 1, 14 | 1, 13, 15, -16, 7, 13, -34, 38, -10, -43, 90, -90, 19, 101, -200, 197, -51, -192, 398, -409, 143, 323, -751, 838, -390, -518, 1493,-1926, 1216, 1025,-5076,13550,23440, 1307,-3610, 3089,-1525, -68, 1051,-1216, 752, -64, -458, 610, -419, 75, 210, -309, 225, -52, -95, 147, -108, 25, 42, -63, 43, -7, -19, 24, -13, -1, 19, 5, 15 | 3, 17, 6, -17, 19, -5, -23, 49, -48, 6, 64, -120, 110, -12, -139, 255, -238, 45, 256, -498, 492, -149, -430, 947,-1034, 448, 733,-2045, 2710,-1783,-2213,20404,18273,-3559, -764, 2290,-2127, 1075, 102, -849, 964, -580, 24, 389, -495, 327, -43, -181, 249, -171, 30, 82, -115, 78, -13, -36, 47, -29, 1, 16, -17, 10, 16, 2, 16 | 6, 19, -4, -10, 24, -25, 3, 36, -67, 59, 1, -91, 155, -133, 2, 187, -321, 285, -35, -336, 620, -592, 151, 571,-1207, 1299, -526,-1078, 3023,-4395, 3586,24395,10873,-5337, 1797, 579,-1658, 1575, -789, -120, 699, -772, 449, 4, -329, 400, -252, 20, 154, -198, 128, -15, -69, 89, -55, 4, 30, -34, 18, 2, -13, 16, 11, 1, 17 | 1, 11, 16, -14, 2, 17, -34, 31, 3, -54, 89, -71, -11, 125, -198, 158, 13, -246, 401, -338, 18, 437, -772, 715, -147, -765, 1571,-1689, 643, 1727,-5327,11143,24321, 3347,-4324, 3038,-1127, -480, 1277,-1212, 591, 129, -580, 621, -346, -24, 278, -321, 191, -3, -129, 155, -93, 3, 57, -66, 37, 2, -24, 24, -11, -4, 19, 6, 18 | 2, 16, 9, -17, 16, 1, -28, 47, -37, -11, 77, -116, 85, 26, -168, 250, -187, -35, 320, -497, 400, 7, -567, 965, -870, 137, 1044,-2124, 2338, -865,-3441,18500,20205,-2364,-1681, 2674,-2059, 771, 414,-1018, 952, -447, -131, 483, -499, 264, 36, -233, 255, -143, -8, 107, -119, 66, 4, -47, 49, -23, -5, 19, -17, 7, 17, 3, 19 | 5, 19, -1, -13, 24, -19, -6, 42, -64, 44, 23, -106, 149, -99, -47, 222, -311, 218, 64, -412, 613, -473, -43, 736,-1218, 1078, -114,-1485, 3091,-3696, 1523,23557,13285,-5119, 1108, 1153,-1904, 1506, -548, -363, 826, -755, 337, 129, -402, 399, -199, -44, 193, -201, 104, 15, -88, 90, -44, -8, 37, -34, 14, 6, -15, 15, 13, 1, 20 | 1, 10, 18, -11, -2, 21, -33, 22, 15, -61, 84, -50, -40, 143, -187, 113, 74, -287, 384, -253, -104, 527, -755, 561, 95, -965, 1569,-1379, 69, 2298,-5299, 8718,24803, 5568,-4879, 2828, -652, -885, 1448,-1146, 396, 321, -676, 601, -252, -124, 333, -317, 147, 47, -159, 155, -73, -20, 71, -67, 28, 11, -29, 23, -7, -7, 19, 8, 21 | 1, 15, 12, -17, 12, 7, -32, 44, -25, -27, 86, -107, 56, 62, -189, 233, -128, -110, 367, -471, 291, 157, -672, 935, -669, -171, 1291,-2097, 1872, 27,-4365,16370,21861, -875,-2586, 2944,-1882, 414, 716,-1140, 890, -286, -285, 556, -478, 186, 117, -275, 249, -106, -48, 129, -118, 49, 21, -56, 48, -17, -11, 22, -16, 3, 18, 4, 22 | 4, 18, 2, -15, 22, -13, -14, 47, -58, 27, 43, -116, 135, -61, -92, 244, -286, 143, 157, -466, 575, -334, -228, 859,-1169, 812, 287,-1800, 3005,-2877, -318,22343,15620,-4605, 311, 1701,-2065, 1358, -269, -596, 915, -699, 204, 252, -457, 379, -134, -107, 225, -193, 74, 46, -103, 88, -32, -21, 43, -33, 9, 11, -17, 13, 14, 1, 23 | 8, 18, -8, -6, 23, -30, 14, 25, -66, 74, -27, -65, 153, -167, 64, 130, -312, 349, -157, -217, 588, -702, 384, 324,-1110, 1490,-1015, -479, 2722,-5022, 6340,24873, 7917,-5233, 2457, -118,-1263, 1551,-1020, 173, 504, -741, 551, -143, -222, 374, -297, 94, 97, -181, 147, -49, -43, 81, -63, 18, 20, -32, 22, -3, -10, 18, 9, 1, 24 | 1, 13, 14, -16, 8, 12, -34, 39, -13, -40, 90, -93, 26, 94, -199, 205, -65, -178, 395, -423, 171, 295, -741, 860, -443, -458, 1465,-1968, 1340, 853,-4981,14075,23192, 883,-3434, 3079,-1601, 22, 994,-1208, 782, -106, -429, 603, -433, 96, 194, -304, 231, -62, -86, 145, -110, 30, 38, -62, 44, -9, -17, 23, -14, 0, 18, 5, 25 | 3, 17, 6, -17, 20, -7, -21, 48, -50, 10, 61, -120, 115, -21, -131, 255, -248, 63, 239, -495, 510, -183, -396, 937,-1064, 516, 657,-2012, 2778,-1986,-1899,20791,17812,-3784, -563, 2191,-2127, 1134, 33, -807, 960, -606, 58, 365, -491, 338, -61, -168, 246, -176, 39, 75, -114, 80, -16, -33, 47, -29, 3, 15, -17, 10, 15, 2, 26 | 7, 19, -5, -10, 24, -26, 5, 34, -67, 62, -4, -87, 156, -140, 13, 178, -322, 298, -57, -317, 618, -615, 194, 530,-1197, 1341, -617, -977, 2986,-4529, 4070,24527,10333,-5347, 1933, 451,-1593, 1579, -837, -66, 666, -771, 470, -23, -311, 397, -262, 34, 144, -196, 132, -21, -64, 88, -57, 7, 28, -34, 19, 1, -13, 17, 11, 1, 27 | 1, 12, 16, -14, 3, 17, -34, 32, 0, -52, 90, -76, -5, 120, -200, 168, -1, -235, 402, -355, 46, 414, -771, 745, -202, -714, 1561,-1749, 772, 1581,-5296,11682,24159, 2876,-4178, 3063,-1223, -388, 1231,-1218, 630, 86, -555, 621, -364, -1, 264, -320, 200, -14, -122, 154, -97, 9, 54, -66, 38, 0, -23, 24, -11, -3, 19, 6, 28 | 2, 16, 9, -17, 17, -1, -27, 48, -40, -7, 74, -117, 91, 18, -163, 252, -199, -17, 308, -499, 422, -28, -539, 965, -910, 206, 980,-2116, 2429,-1068,-3194,18945,19798,-2655,-1477, 2598,-2083, 843, 345, -984, 959, -479, -97, 464, -500, 279, 18, -222, 255, -150, 1, 102, -119, 69, 0, -44, 48, -25, -3, 18, -17, 7, 17, 3, 29 | 6, 19, -2, -13, 24, -20, -4, 41, -65, 47, 18, -103, 151, -107, -36, 215, -315, 234, 43, -397, 617, -501, 0, 703,-1221, 1132, -205,-1402, 3089,-3863, 1964,23776,12754,-5192, 1272, 1027,-1856, 1528, -605, -310, 801, -762, 364, 102, -387, 401, -212, -29, 185, -201, 110, 9, -84, 90, -47, -6, 35, -34, 15, 5, -15, 15, 12, 1, 30 | 1, 10, 17, -12, -1, 20, -33, 24, 12, -60, 85, -55, -34, 140, -191, 124, 61, -279, 389, -273, -77, 509, -762, 597, 41, -925, 1576,-1453, 195, 2184,-5328, 9255,24732, 5061,-4772, 2888, -763, -797, 1415,-1166, 442, 279, -658, 608, -274, -102, 322, -319, 158, 36, -153, 156, -78, -14, 68, -67, 30, 9, -28, 24, -8, -7, 19, 7, 31 | 2, 15, 11, -17, 13, 5, -31, 45, -28, -23, 84, -110, 62, 55, -185, 238, -142, -94, 359, -479, 316, 124, -652, 946, -717, -104, 1242,-2112, 1982, -167,-4187,16860,21520,-1230,-2388, 2895,-1931, 497, 651,-1117, 908, -324, -251, 542, -485, 204, 99, -266, 252, -115, -39, 125, -119, 53, 17, -54, 48, -18, -10, 21, -16, 4, 18, 4, 32 | 4, 18, 2, -15, 23, -15, -13, 46, -60, 31, 39, -114, 138, -69, -82, 240, -293, 160, 137, -456, 586, -366, -188, 836,-1185, 875, 200,-1739, 3037,-3067, 70,22644,15111,-4745, 496, 1583,-2037, 1397, -334, -546, 898, -715, 235, 225, -447, 385, -149, -93, 218, -196, 81, 39, -100, 89, -35, -18, 42, -33, 10, 10, -16, 13, 14, 1, 33 | 9, 18, -9, -5, 23, -31, 16, 23, -65, 77, -32, -60, 152, -172, 75, 118, -308, 358, -179, -193, 577, -717, 424, 275,-1083, 1514,-1100, -361, 2641,-5103, 6861,24893, 7387,-5174, 2553, -240,-1182, 1534,-1053, 224, 465, -730, 564, -168, -201, 367, -303, 106, 86, -177, 150, -55, -38, 79, -64, 21, 18, -31, 22, -4, -10, 18, 9, 0, 34 | 1, 13, 14, -16, 9, 11, -34, 40, -15, -38, 89, -97, 32, 88, -198, 212, -79, -164, 390, -435, 198, 265, -729, 880, -495, -397, 1433,-2005, 1463, 677,-4871,14596,22927, 470,-3253, 3062,-1672, 111, 935,-1198, 810, -147, -398, 595, -445, 117, 177, -299, 236, -73, -78, 142, -112, 35, 35, -61, 45, -11, -16, 23, -15, 1, 18, 5, 35 | 3, 17, 5, -17, 20, -8, -20, 48, -52, 14, 57, -119, 120, -30, -123, 254, -257, 81, 222, -491, 527, -217, -360, 924,-1092, 584, 578,-1974, 2840,-2188,-1572,21163,17341,-3993, -364, 2089,-2122, 1190, -36, -763, 954, -630, 91, 341, -485, 349, -77, -155, 242, -181, 47, 69, -112, 82, -20, -31, 46, -30, 4, 14, -17, 11, 15, 2, 36 | 7, 19, -6, -9, 24, -27, 7, 32, -67, 65, -9, -83, 156, -146, 25, 168, -321, 310, -80, -296, 614, -637, 237, 486,-1183, 1380, -707, -872, 2941,-4655, 4562,24639, 9794,-5344, 2062, 323,-1525, 1580, -882, -12, 632, -768, 491, -50, -292, 394, -271, 48, 134, -193, 136, -28, -60, 86, -58, 9, 26, -34, 19, 0, -12, 17, 10, 1, 37 | 1, 12, 16, -15, 4, 16, -34, 34, -3, -49, 90, -80, 2, 115, -200, 177, -15, -224, 402, -372, 74, 389, -768, 774, -256, -660, 1547,-1804, 900, 1430,-5251,12219,23977, 2415,-4024, 3080,-1315, -297, 1183,-1221, 668, 43, -529, 620, -381, 21, 249, -318, 207, -25, -114, 153, -100, 13, 51, -65, 40, -2, -22, 24, -12, -3, 19, 6, 38 | 2, 16, 8, -17, 17, -2, -26, 48, -42, -4, 72, -118, 96, 9, -156, 254, -211, 1, 294, -500, 444, -62, -510, 963, -948, 275, 913,-2102, 2516,-1272,-2932,19378,19378,-2932,-1272, 2516,-2102, 913, 275, -948, 963, -510, -62, 444, -500, 294, 1, -211, 254, -156, 9, 96, -118, 72, -4, -42, 48, -26, -2, 17, -17, 8, 16, 2, 39 | 6, 19, -3, -12, 24, -22, -2, 40, -65, 51, 13, -100, 153, -114, -25, 207, -318, 249, 21, -381, 620, -529, 43, 668,-1221, 1183, -297,-1315, 3080,-4024, 2415,23977,12219,-5251, 1430, 900,-1804, 1547, -660, -256, 774, -768, 389, 74, -372, 402, -224, -15, 177, -200, 115, 2, -80, 90, -49, -3, 34, -34, 16, 4, -15, 16, 12, 1, 40 | 1, 10, 17, -12, 0, 19, -34, 26, 9, -58, 86, -60, -28, 136, -193, 134, 48, -271, 394, -292, -50, 491, -768, 632, -12, -882, 1580,-1525, 323, 2062,-5344, 9794,24639, 4562,-4655, 2941, -872, -707, 1380,-1183, 486, 237, -637, 614, -296, -80, 310, -321, 168, 25, -146, 156, -83, -9, 65, -67, 32, 7, -27, 24, -9, -6, 19, 7, 41 | 2, 15, 11, -17, 14, 4, -30, 46, -31, -20, 82, -112, 69, 47, -181, 242, -155, -77, 349, -485, 341, 91, -630, 954, -763, -36, 1190,-2122, 2089, -364,-3993,17341,21163,-1572,-2188, 2840,-1974, 578, 584,-1092, 924, -360, -217, 527, -491, 222, 81, -257, 254, -123, -30, 120, -119, 57, 14, -52, 48, -20, -8, 20, -17, 5, 17, 3, 42 | 5, 18, 1, -15, 23, -16, -11, 45, -61, 35, 35, -112, 142, -78, -73, 236, -299, 177, 117, -445, 595, -398, -147, 810,-1198, 935, 111,-1672, 3062,-3253, 470,22927,14596,-4871, 677, 1463,-2005, 1433, -397, -495, 880, -729, 265, 198, -435, 390, -164, -79, 212, -198, 88, 32, -97, 89, -38, -15, 40, -34, 11, 9, -16, 14, 13, 1, 43 | 9, 18, -10, -4, 22, -31, 18, 21, -64, 79, -38, -55, 150, -177, 86, 106, -303, 367, -201, -168, 564, -730, 465, 224,-1053, 1534,-1182, -240, 2553,-5174, 7387,24893, 6861,-5103, 2641, -361,-1100, 1514,-1083, 275, 424, -717, 577, -193, -179, 358, -308, 118, 75, -172, 152, -60, -32, 77, -65, 23, 16, -31, 23, -5, -9, 18, 9, 0, 44 | 1, 14, 13, -16, 10, 10, -33, 42, -18, -35, 89, -100, 39, 81, -196, 218, -93, -149, 385, -447, 225, 235, -715, 898, -546, -334, 1397,-2037, 1583, 496,-4745,15111,22644, 70,-3067, 3037,-1739, 200, 875,-1185, 836, -188, -366, 586, -456, 137, 160, -293, 240, -82, -69, 138, -114, 39, 31, -60, 46, -13, -15, 23, -15, 2, 18, 4, 45 | 4, 18, 4, -16, 21, -10, -18, 48, -54, 17, 53, -119, 125, -39, -115, 252, -266, 99, 204, -485, 542, -251, -324, 908,-1117, 651, 497,-1931, 2895,-2388,-1230,21520,16860,-4187, -167, 1982,-2112, 1242, -104, -717, 946, -652, 124, 316, -479, 359, -94, -142, 238, -185, 55, 62, -110, 84, -23, -28, 45, -31, 5, 13, -17, 11, 15, 2, 46 | 7, 19, -7, -8, 24, -28, 9, 30, -67, 68, -14, -78, 156, -153, 36, 158, -319, 322, -102, -274, 608, -658, 279, 442,-1166, 1415, -797, -763, 2888,-4772, 5061,24732, 9255,-5328, 2184, 195,-1453, 1576, -925, 41, 597, -762, 509, -77, -273, 389, -279, 61, 124, -191, 140, -34, -55, 85, -60, 12, 24, -33, 20, -1, -12, 17, 10, 1, 47 | 1, 12, 15, -15, 5, 15, -34, 35, -6, -47, 90, -84, 9, 110, -201, 185, -29, -212, 401, -387, 102, 364, -762, 801, -310, -605, 1528,-1856, 1027, 1272,-5192,12754,23776, 1964,-3863, 3089,-1402, -205, 1132,-1221, 703, 0, -501, 617, -397, 43, 234, -315, 215, -36, -107, 151, -103, 18, 47, -65, 41, -4, -20, 24, -13, -2, 19, 6, 48 | 3, 17, 7, -17, 18, -3, -25, 48, -44, 0, 69, -119, 102, 1, -150, 255, -222, 18, 279, -500, 464, -97, -479, 959, -984, 345, 843,-2083, 2598,-1477,-2655,19798,18945,-3194,-1068, 2429,-2116, 980, 206, -910, 965, -539, -28, 422, -499, 308, -17, -199, 252, -163, 18, 91, -117, 74, -7, -40, 48, -27, -1, 17, -17, 9, 16, 2, 49 | 6, 19, -3, -11, 24, -23, 0, 38, -66, 54, 9, -97, 154, -122, -14, 200, -320, 264, -1, -364, 621, -555, 86, 630,-1218, 1231, -388,-1223, 3063,-4178, 2876,24159,11682,-5296, 1581, 772,-1749, 1561, -714, -202, 745, -771, 414, 46, -355, 402, -235, -1, 168, -200, 120, -5, -76, 90, -52, 0, 32, -34, 17, 3, -14, 16, 12, 1, 50 | 1, 11, 17, -13, 1, 19, -34, 28, 7, -57, 88, -64, -21, 132, -196, 144, 34, -262, 397, -311, -23, 470, -771, 666, -66, -837, 1579,-1593, 451, 1933,-5347,10333,24527, 4070,-4529, 2986, -977, -617, 1341,-1197, 530, 194, -615, 618, -317, -57, 298, -322, 178, 13, -140, 156, -87, -4, 62, -67, 34, 5, -26, 24, -10, -5, 19, 7, 51 | 2, 15, 10, -17, 15, 3, -29, 47, -33, -16, 80, -114, 75, 39, -176, 246, -168, -61, 338, -491, 365, 58, -606, 960, -807, 33, 1134,-2127, 2191, -563,-3784,17812,20791,-1899,-1986, 2778,-2012, 657, 516,-1064, 937, -396, -183, 510, -495, 239, 63, -248, 255, -131, -21, 115, -120, 61, 10, -50, 48, -21, -7, 20, -17, 6, 17, 3, 52 | 5, 18, 0, -14, 23, -17, -9, 44, -62, 38, 30, -110, 145, -86, -62, 231, -304, 194, 96, -433, 603, -429, -106, 782,-1208, 994, 22,-1601, 3079,-3434, 883,23192,14075,-4981, 853, 1340,-1968, 1465, -458, -443, 860, -741, 295, 171, -423, 395, -178, -65, 205, -199, 94, 26, -93, 90, -40, -13, 39, -34, 12, 8, -16, 14, 13, 1, 53 | 1, 9, 18, -10, -3, 22, -32, 20, 18, -63, 81, -43, -49, 147, -181, 97, 94, -297, 374, -222, -143, 551, -741, 504, 173,-1020, 1551,-1263, -118, 2457,-5233, 7917,24873, 6340,-5022, 2722, -479,-1015, 1490,-1110, 324, 384, -702, 588, -217, -157, 349, -312, 130, 64, -167, 153, -65, -27, 74, -66, 25, 14, -30, 23, -6, -8, 18, 8, 54 | 1, 14, 13, -17, 11, 9, -33, 43, -21, -32, 88, -103, 46, 74, -193, 225, -107, -134, 379, -457, 252, 204, -699, 915, -596, -269, 1358,-2065, 1701, 311,-4605,15620,22343, -318,-2877, 3005,-1800, 287, 812,-1169, 859, -228, -334, 575, -466, 157, 143, -286, 244, -92, -61, 135, -116, 43, 27, -58, 47, -14, -13, 22, -15, 2, 18, 4, 55 | 4, 18, 3, -16, 22, -11, -17, 48, -56, 21, 49, -118, 129, -48, -106, 249, -275, 117, 186, -478, 556, -285, -286, 890,-1140, 716, 414,-1882, 2944,-2586, -875,21861,16370,-4365, 27, 1872,-2097, 1291, -171, -669, 935, -672, 157, 291, -471, 367, -110, -128, 233, -189, 62, 56, -107, 86, -27, -25, 44, -32, 7, 12, -17, 12, 15, 1, 56 | 8, 19, -7, -7, 23, -29, 11, 28, -67, 71, -20, -73, 155, -159, 47, 147, -317, 333, -124, -252, 601, -676, 321, 396,-1146, 1448, -885, -652, 2828,-4879, 5568,24803, 8718,-5299, 2298, 69,-1379, 1569, -965, 95, 561, -755, 527, -104, -253, 384, -287, 74, 113, -187, 143, -40, -50, 84, -61, 15, 22, -33, 21, -2, -11, 18, 10, 1, 57 | 1, 13, 15, -15, 6, 14, -34, 37, -8, -44, 90, -88, 15, 104, -201, 193, -44, -199, 399, -402, 129, 337, -755, 826, -363, -548, 1506,-1904, 1153, 1108,-5119,13285,23557, 1523,-3696, 3091,-1485, -114, 1078,-1218, 736, -43, -473, 613, -412, 64, 218, -311, 222, -47, -99, 149, -106, 23, 44, -64, 42, -6, -19, 24, -13, -1, 19, 5, 58 | 3, 17, 7, -17, 19, -5, -23, 49, -47, 4, 66, -119, 107, -8, -143, 255, -233, 36, 264, -499, 483, -131, -447, 952,-1018, 414, 771,-2059, 2674,-1681,-2364,20205,18500,-3441, -865, 2338,-2124, 1044, 137, -870, 965, -567, 7, 400, -497, 320, -35, -187, 250, -168, 26, 85, -116, 77, -11, -37, 47, -28, 1, 16, -17, 9, 16, 2, 59 | 6, 19, -4, -11, 24, -24, 2, 37, -66, 57, 3, -93, 155, -129, -3, 191, -321, 278, -24, -346, 621, -580, 129, 591,-1212, 1277, -480,-1127, 3038,-4324, 3347,24321,11143,-5327, 1727, 643,-1689, 1571, -765, -147, 715, -772, 437, 18, -338, 401, -246, 13, 158, -198, 125, -11, -71, 89, -54, 3, 31, -34, 17, 2, -14, 16, 11, 1, 60 | 1, 11, 16, -13, 2, 18, -34, 30, 4, -55, 89, -69, -15, 128, -198, 154, 20, -252, 400, -329, 4, 449, -772, 699, -120, -789, 1575,-1658, 579, 1797,-5337,10873,24395, 3586,-4395, 3023,-1078, -526, 1299,-1207, 571, 151, -592, 620, -336, -35, 285, -321, 187, 2, -133, 155, -91, 1, 59, -67, 36, 3, -25, 24, -10, -4, 19, 6, 61 | 2, 16, 10, -17, 16, 1, -29, 47, -36, -13, 78, -115, 82, 30, -171, 249, -181, -43, 327, -495, 389, 24, -580, 964, -849, 102, 1075,-2127, 2290, -764,-3559,18273,20404,-2213,-1783, 2710,-2045, 733, 448,-1034, 947, -430, -149, 492, -498, 256, 45, -238, 255, -139, -12, 110, -120, 64, 6, -48, 49, -23, -5, 19, -17, 6, 17, 3, 62 | 5, 19, -1, -13, 24, -19, -7, 43, -63, 42, 25, -108, 147, -95, -52, 225, -309, 210, 75, -419, 610, -458, -64, 752,-1216, 1051, -68,-1525, 3089,-3610, 1307,23440,13550,-5076, 1025, 1216,-1926, 1493, -518, -390, 838, -751, 323, 143, -409, 398, -192, -51, 197, -200, 101, 19, -90, 90, -43, -10, 38, -34, 13, 7, -16, 15, 13, 1, 63 | 1, 10, 18, -11, -2, 21, -33, 21, 16, -62, 83, -48, -43, 145, -185, 108, 81, -291, 381, -242, -117, 535, -751, 542, 121, -984, 1564,-1341, 6, 2353,-5280, 8450,24832, 5824,-4929, 2794, -595, -929, 1463,-1135, 372, 342, -685, 597, -241, -135, 339, -316, 141, 53, -162, 155, -71, -22, 72, -66, 27, 12, -29, 23, -7, -8, 19, 8, 64 | 1, 14, 12, -17, 12, 7, -32, 44, -24, -28, 86, -106, 53, 66, -190, 230, -121, -118, 371, -466, 278, 173, -681, 929, -645, -204, 1314,-2087, 1815, 123,-4449,16122,22026, -693,-2684, 2966,-1856, 372, 749,-1150, 881, -267, -301, 563, -475, 176, 125, -279, 248, -101, -52, 131, -117, 47, 23, -56, 47, -16, -12, 22, -16, 3, 18, 4, 65 | 4, 18, 3, -16, 22, -13, -15, 47, -57, 25, 45, -117, 133, -56, -97, 246, -283, 134, 167, -470, 569, -318, -247, 870,-1160, 781, 330,-1829, 2986,-2781, -507,22187,15872,-4529, 217, 1758,-2077, 1336, -237, -621, 922, -690, 189, 265, -462, 375, -126, -114, 227, -192, 70, 49, -104, 87, -30, -22, 43, -32, 8, 11, -17, 12, 14, 1, 66 | 8, 18, -8, -6, 23, -29, 13, 26, -66, 73, -25, -68, 154, -165, 58, 136, -314, 344, -146, -229, 593, -694, 363, 348,-1123, 1477, -972, -537, 2759,-4977, 6081,24855, 8183,-5258, 2406, -56,-1302, 1558,-1002, 147, 523, -746, 543, -130, -232, 378, -294, 87, 103, -183, 146, -46, -45, 82, -63, 17, 21, -32, 21, -3, -11, 18, 9, 1, 67 | 1, 13, 14, -16, 7, 13, -34, 38, -11, -42, 90, -92, 22, 98, -200, 201, -58, -185, 397, -416, 157, 309, -746, 849, -416, -489, 1480,-1948, 1278, 940,-5031,13813,23318, 1093,-3522, 3085,-1563, -23, 1022,-1212, 767, -85, -444, 607, -426, 86, 202, -307, 228, -57, -90, 146, -109, 28, 40, -63, 44, -8, -18, 23, -14, 0, 19, 5, 68 | 3, 17, 6, -17, 20, -6, -22, 49, -49, 8, 62, -120, 113, -17, -135, 255, -243, 54, 248, -497, 501, -166, -413, 942,-1049, 482, 695,-2029, 2745,-1885,-2058,20599,18044,-3673, -663, 2241,-2127, 1105, 67, -828, 962, -593, 41, 377, -493, 332, -52, -174, 247, -174, 35, 78, -115, 79, -15, -35, 47, -29, 2, 15, -17, 10, 16, 2, 69 | 7, 19, -5, -10, 24, -25, 4, 35, -67, 61, -2, -89, 156, -136, 8, 182, -322, 291, -46, -326, 619, -604, 172, 551,-1202, 1320, -571,-1028, 3005,-4463, 3827,24463,10603,-5344, 1866, 515,-1626, 1578, -813, -93, 683, -772, 460, -9, -320, 399, -257, 27, 149, -197, 130, -18, -67, 88, -56, 5, 29, -34, 18, 1, -13, 17, 11, 1, 70 | 1, 11, 16, -14, 3, 17, -34, 31, 1, -53, 89, -73, -8, 123, -199, 163, 6, -241, 402, -347, 32, 426, -772, 730, -174, -739, 1567,-1719, 708, 1655,-5313,11412,24242, 3110,-4252, 3052,-1176, -434, 1255,-1215, 611, 107, -568, 621, -355, -13, 271, -321, 195, -9, -126, 155, -95, 6, 56, -66, 38, 1, -23, 24, -11, -4, 19, 6, 71 | 2, 16, 9, -17, 16, 0, -28, 48, -38, -9, 76, -117, 88, 22, -166, 251, -193, -26, 314, -498, 411, -11, -553, 965, -890, 171, 1012,-2121, 2384, -966,-3320,18724,20003,-2511,-1579, 2637,-2072, 807, 379,-1001, 955, -463, -114, 474, -500, 272, 27, -227, 255, -146, -4, 105, -119, 67, 2, -45, 49, -24, -4, 19, -17, 7, 17, 3, 72 | 5, 19, -1, -13, 24, -20, -5, 42, -64, 45, 21, -105, 150, -103, -42, 218, -313, 226, 53, -405, 615, -487, -21, 720,-1220, 1105, -159,-1444, 3091,-3780, 1742,23669,13020,-5157, 1191, 1090,-1881, 1518, -577, -336, 813, -759, 350, 116, -395, 400, -205, -37, 189, -201, 107, 12, -86, 90, -46, -7, 36, -34, 14, 6, -15, 15, 12, 1, 73 | 1, 10, 17, -11, -2, 20, -33, 23, 13, -61, 84, -53, -37, 142, -189, 118, 68, -283, 387, -263, -91, 518, -759, 579, 68, -945, 1573,-1416, 132, 2242,-5315, 8986,24770, 5314,-4827, 2859, -708, -841, 1432,-1156, 419, 300, -667, 605, -263, -113, 328, -318, 152, 42, -156, 155, -76, -17, 69, -67, 29, 10, -28, 24, -8, -7, 19, 8, 74 | 2, 15, 12, -17, 12, 6, -32, 45, -27, -25, 85, -108, 59, 59, -187, 235, -135, -102, 363, -475, 304, 141, -662, 941, -693, -137, 1267,-2105, 1927, -70,-4278,16616,21693,-1055,-2487, 2921,-1907, 456, 684,-1129, 900, -305, -268, 549, -482, 195, 108, -271, 251, -110, -43, 127, -118, 51, 19, -55, 48, -18, -10, 21, -16, 4, 18, 4, 75 | 4, 18, 2, -15, 22, -14, -13, 46, -59, 29, 41, -115, 137, -65, -87, 243, -290, 152, 147, -461, 580, -350, -208, 848,-1177, 844, 243,-1770, 3022,-2973, -125,22496,15367,-4677, 404, 1642,-2051, 1378, -302, -571, 907, -707, 220, 239, -452, 382, -142, -100, 222, -195, 77, 43, -102, 88, -33, -20, 42, -33, 9, 10, -17, 13, 14, 1, 76 | 8, 18, -9, -6, 23, -30, 15, 24, -65, 76, -30, -63, 153, -170, 70, 124, -310, 354, -168, -205, 583, -709, 404, 299,-1097, 1502,-1058, -420, 2682,-5064, 6600,24886, 7651,-5205, 2506, -179,-1223, 1543,-1037, 199, 484, -736, 558, -156, -211, 371, -300, 100, 92, -179, 149, -52, -40, 80, -64, 20, 19, -32, 22, -4, -10, 18, 9, 1, 77 | 1, 13, 14, -16, 8, 12, -34, 40, -14, -39, 90, -95, 29, 91, -199, 208, -72, -171, 393, -429, 185, 280, -735, 870, -469, -428, 1450,-1987, 1402, 766,-4928,14337,23062, 675,-3344, 3071,-1637, 67, 965,-1204, 796, -126, -413, 599, -439, 107, 185, -302, 233, -68, -82, 143, -111, 32, 36, -62, 45, -10, -17, 23, -14, 0, 18, 5, 78 | 3, 17, 5, -17, 20, -8, -21, 48, -51, 12, 59, -119, 118, -26, -127, 254, -253, 72, 231, -493, 519, -200, -378, 930,-1078, 550, 618,-1994, 2810,-2087,-1737,20979,17578,-3890, -463, 2140,-2125, 1162, -1, -785, 957, -618, 74, 353, -488, 344, -69, -161, 244, -179, 43, 72, -113, 81, -18, -32, 46, -30, 3, 14, -17, 10, 15, 2, 79 | 7, 19, -6, -9, 24, -26, 6, 33, -67, 64, -7, -85, 156, -143, 19, 173, -321, 304, -68, -306, 616, -626, 215, 508,-1190, 1361, -662, -925, 2965,-4593, 4315,24586,10063,-5347, 1998, 387,-1559, 1580, -860, -39, 650, -769, 481, -37, -302, 396, -266, 41, 139, -195, 134, -24, -62, 87, -58, 8, 27, -34, 19, 0, -13, 17, 11, 1, 80 | 1, 12, 16, -14, 4, 16, -34, 33, -1, -51, 90, -78, -1, 118, -200, 172, -8, -230, 402, -364, 60, 402, -769, 759, -229, -687, 1554,-1777, 836, 1506,-5275,11950,24070, 2644,-4102, 3073,-1269, -343, 1207,-1220, 649, 64, -542, 621, -373, 10, 256, -319, 204, -20, -118, 153, -99, 11, 52, -66, 39, -1, -22, 24, -12, -3, 19, 6, 81 | 2, 16, 8, -17, 17, -1, -26, 48, -41, -6, 73, -118, 93, 14, -159, 253, -205, -8, 301, -500, 433, -45, -525, 964, -929, 241, 947,-2110, 2473,-1170,-3065,19163,19589,-2796,-1374, 2558,-2094, 878, 310, -966, 961, -494, -80, 454, -501, 287, 9, -216, 254, -153, 5, 99, -119, 70, -2, -43, 48, -25, -3, 18, -17, 8, 17, 3, 82 | 6, 19, -2, -12, 24, -21, -3, 41, -65, 49, 16, -102, 152, -111, -31, 211, -316, 241, 32, -389, 619, -515, 21, 685,-1221, 1157, -251,-1359, 3086,-3944, 2188,23879,12487,-5224, 1351, 964,-1831, 1538, -633, -283, 787, -765, 377, 88, -380, 402, -218, -22, 181, -201, 112, 5, -82, 90, -48, -4, 35, -34, 15, 5, -15, 15, 12, 1, 83 | 1, 10, 17, -12, -1, 20, -33, 25, 11, -59, 86, -57, -31, 138, -192, 129, 54, -275, 392, -282, -64, 500, -765, 615, 15, -904, 1579,-1489, 259, 2124,-5338, 9524,24688, 4811,-4715, 2916, -818, -752, 1398,-1175, 464, 258, -648, 611, -285, -91, 316, -320, 163, 30, -150, 156, -80, -12, 66, -67, 31, 8, -27, 24, -8, -6, 19, 7, 84 | 2, 15, 11, -17, 13, 5, -31, 46, -29, -22, 83, -111, 66, 51, -183, 240, -148, -86, 354, -482, 329, 108, -641, 950, -740, -70, 1216,-2118, 2036, -265,-4092,17101,21343,-1403,-2288, 2868,-1953, 538, 617,-1105, 916, -342, -234, 534, -488, 213, 90, -262, 253, -119, -35, 122, -119, 55, 15, -53, 48, -19, -9, 21, -16, 4, 18, 3, 85 | 4, 18, 1, -15, 23, -15, -12, 46, -60, 33, 37, -113, 140, -74, -78, 238, -296, 169, 127, -451, 591, -382, -167, 823,-1192, 905, 156,-1706, 3050,-3160, 269,22788,14855,-4810, 587, 1523,-2021, 1416, -365, -520, 890, -722, 251, 212, -441, 388, -157, -86, 215, -197, 84, 36, -98, 89, -36, -17, 41, -33, 10, 9, -16, 13, 14, 1, 86 | 9, 18, -9, -5, 22, -31, 17, 22, -65, 78, -35, -57, 151, -175, 81, 112, -306, 362, -190, -181, 571, -723, 445, 249,-1068, 1525,-1141, -301, 2598,-5140, 7123,24896, 7123,-5140, 2598, -301,-1141, 1525,-1068, 249, 445, -723, 571, -181, -190, 362, -306, 112, 81, -175, 151, -57, -35, 78, -65, 22, 17, -31, 22, -5, -9, 18, 9, 0, 87 | 1, 14, 13, -16, 9, 10, -33, 41, -17, -36, 89, -98, 36, 84, -197, 215, -86, -157, 388, -441, 212, 251, -722, 890, -520, -365, 1416,-2021, 1523, 587,-4810,14855,22788, 269,-3160, 3050,-1706, 156, 905,-1192, 823, -167, -382, 591, -451, 127, 169, -296, 238, -78, -74, 140, -113, 37, 33, -60, 46, -12, -15, 23, -15, 1, 18, 4, 88 | 3, 18, 4, -16, 21, -9, -19, 48, -53, 15, 55, -119, 122, -35, -119, 253, -262, 90, 213, -488, 534, -234, -342, 916,-1105, 617, 538,-1953, 2868,-2288,-1403,21343,17101,-4092, -265, 2036,-2118, 1216, -70, -740, 950, -641, 108, 329, -482, 354, -86, -148, 240, -183, 51, 66, -111, 83, -22, -29, 46, -31, 5, 13, -17, 11, 15, 2, 89 | 7, 19, -6, -8, 24, -27, 8, 31, -67, 66, -12, -80, 156, -150, 30, 163, -320, 316, -91, -285, 611, -648, 258, 464,-1175, 1398, -752, -818, 2916,-4715, 4811,24688, 9524,-5338, 2124, 259,-1489, 1579, -904, 15, 615, -765, 500, -64, -282, 392, -275, 54, 129, -192, 138, -31, -57, 86, -59, 11, 25, -33, 20, -1, -12, 17, 10, 1, 90 | 1, 12, 15, -15, 5, 15, -34, 35, -4, -48, 90, -82, 5, 112, -201, 181, -22, -218, 402, -380, 88, 377, -765, 787, -283, -633, 1538,-1831, 964, 1351,-5224,12487,23879, 2188,-3944, 3086,-1359, -251, 1157,-1221, 685, 21, -515, 619, -389, 32, 241, -316, 211, -31, -111, 152, -102, 16, 49, -65, 41, -3, -21, 24, -12, -2, 19, 6, 91 | 3, 17, 8, -17, 18, -3, -25, 48, -43, -2, 70, -119, 99, 5, -153, 254, -216, 9, 287, -501, 454, -80, -494, 961, -966, 310, 878,-2094, 2558,-1374,-2796,19589,19163,-3065,-1170, 2473,-2110, 947, 241, -929, 964, -525, -45, 433, -500, 301, -8, -205, 253, -159, 14, 93, -118, 73, -6, -41, 48, -26, -1, 17, -17, 8, 16, 2, 92 | 6, 19, -3, -12, 24, -22, -1, 39, -66, 52, 11, -99, 153, -118, -20, 204, -319, 256, 10, -373, 621, -542, 64, 649,-1220, 1207, -343,-1269, 3073,-4102, 2644,24070,11950,-5275, 1506, 836,-1777, 1554, -687, -229, 759, -769, 402, 60, -364, 402, -230, -8, 172, -200, 118, -1, -78, 90, -51, -1, 33, -34, 16, 4, -14, 16, 12, 1, 93 | 1, 11, 17, -13, 0, 19, -34, 27, 8, -58, 87, -62, -24, 134, -195, 139, 41, -266, 396, -302, -37, 481, -769, 650, -39, -860, 1580,-1559, 387, 1998,-5347,10063,24586, 4315,-4593, 2965, -925, -662, 1361,-1190, 508, 215, -626, 616, -306, -68, 304, -321, 173, 19, -143, 156, -85, -7, 64, -67, 33, 6, -26, 24, -9, -6, 19, 7, 94 | 2, 15, 10, -17, 14, 3, -30, 46, -32, -18, 81, -113, 72, 43, -179, 244, -161, -69, 344, -488, 353, 74, -618, 957, -785, -1, 1162,-2125, 2140, -463,-3890,17578,20979,-1737,-2087, 2810,-1994, 618, 550,-1078, 930, -378, -200, 519, -493, 231, 72, -253, 254, -127, -26, 118, -119, 59, 12, -51, 48, -21, -8, 20, -17, 5, 17, 3, 95 | 5, 18, 0, -14, 23, -17, -10, 45, -62, 36, 32, -111, 143, -82, -68, 233, -302, 185, 107, -439, 599, -413, -126, 796,-1204, 965, 67,-1637, 3071,-3344, 675,23062,14337,-4928, 766, 1402,-1987, 1450, -428, -469, 870, -735, 280, 185, -429, 393, -171, -72, 208, -199, 91, 29, -95, 90, -39, -14, 40, -34, 12, 8, -16, 14, 13, 1, 96 | 1, 9, 18, -10, -4, 22, -32, 19, 20, -64, 80, -40, -52, 149, -179, 92, 100, -300, 371, -211, -156, 558, -736, 484, 199,-1037, 1543,-1223, -179, 2506,-5205, 7651,24886, 6600,-5064, 2682, -420,-1058, 1502,-1097, 299, 404, -709, 583, -205, -168, 354, -310, 124, 70, -170, 153, -63, -30, 76, -65, 24, 15, -30, 23, -6, -9, 18, 8, 97 | --------------------------------------------------------------------------------