DOSBox-X
|
00001 #include "np2glue.h" 00002 //#include "compiler.h" 00003 //#include "pccore.h" 00004 //#include "iocore.h" 00005 #include "sound.h" 00006 #include "fmboard.h" 00007 00008 00009 #if defined(OPNGENX86) 00010 #error use opngen.x86 00011 #endif 00012 00013 00014 extern OPNCFG opncfg; 00015 00016 00017 #define CALCENV(e, c, s) \ 00018 (c)->slot[(s)].freq_cnt += (c)->slot[(s)].freq_inc; \ 00019 (c)->slot[(s)].env_cnt += (c)->slot[(s)].env_inc; \ 00020 if ((c)->slot[(s)].env_cnt >= (c)->slot[(s)].env_end) { \ 00021 switch((c)->slot[(s)].env_mode) { \ 00022 case EM_ATTACK: \ 00023 (c)->slot[(s)].env_mode = EM_DECAY1; \ 00024 (c)->slot[(s)].env_cnt = EC_DECAY; \ 00025 (c)->slot[(s)].env_end = (c)->slot[(s)].decaylevel; \ 00026 (c)->slot[(s)].env_inc = (c)->slot[(s)].env_inc_decay1; \ 00027 break; \ 00028 case EM_DECAY1: \ 00029 (c)->slot[(s)].env_mode = EM_DECAY2; \ 00030 (c)->slot[(s)].env_cnt = (c)->slot[(s)].decaylevel; \ 00031 (c)->slot[(s)].env_end = EC_OFF; \ 00032 (c)->slot[(s)].env_inc = (c)->slot[(s)].env_inc_decay2; \ 00033 break; \ 00034 case EM_RELEASE: \ 00035 (c)->slot[(s)].env_mode = EM_OFF; \ 00036 case EM_DECAY2: \ 00037 (c)->slot[(s)].env_cnt = EC_OFF; \ 00038 (c)->slot[(s)].env_end = EC_OFF + 1; \ 00039 (c)->slot[(s)].env_inc = 0; \ 00040 (c)->playing &= ~(1 << (s)); \ 00041 break; \ 00042 } \ 00043 } \ 00044 (e) = (c)->slot[(s)].totallevel - \ 00045 opncfg.envcurve[(c)->slot[(s)].env_cnt >> ENV_BITS]; 00046 00047 #define SLOTOUT(s, e, c) \ 00048 ((opncfg.sintable[(((s).freq_cnt + (c)) >> \ 00049 (FREQ_BITS - SIN_BITS)) & (SIN_ENT - 1)] * \ 00050 opncfg.envtable[(e)]) >> (ENVTBL_BIT+SINTBL_BIT-TL_BITS)) 00051 00052 00053 static void calcratechannel(OPNCH *ch) { 00054 00055 SINT32 envout; 00056 00057 opngen.feedback2 = 0; 00058 opngen.feedback3 = 0; 00059 opngen.feedback4 = 0; 00060 00061 /* SLOT 1 */ 00062 CALCENV(envout, ch, 0); 00063 if (envout > 0) { 00064 SINT32 opout; 00065 if (ch->feedback) { 00066 /* with self feed back */ 00067 opout = ch->op1fb; 00068 ch->op1fb = SLOTOUT(ch->slot[0], envout, 00069 (ch->op1fb >> ch->feedback)); 00070 opout = (opout + ch->op1fb) / 2; 00071 } 00072 else { 00073 /* without self feed back */ 00074 opout = SLOTOUT(ch->slot[0], envout, 0); 00075 } 00076 /* output slot1 */ 00077 if (!ch->connect1) { 00078 opngen.feedback2 = opngen.feedback3 = opngen.feedback4 = opout; 00079 } 00080 else { 00081 *ch->connect1 += opout; 00082 } 00083 } 00084 /* SLOT 2 */ 00085 CALCENV(envout, ch, 1); 00086 if (envout > 0) { 00087 *ch->connect2 += SLOTOUT(ch->slot[1], envout, opngen.feedback2); 00088 } 00089 /* SLOT 3 */ 00090 CALCENV(envout, ch, 2); 00091 if (envout > 0) { 00092 *ch->connect3 += SLOTOUT(ch->slot[2], envout, opngen.feedback3); 00093 } 00094 /* SLOT 4 */ 00095 CALCENV(envout, ch, 3); 00096 if (envout > 0) { 00097 *ch->connect4 += SLOTOUT(ch->slot[3], envout, opngen.feedback4); 00098 } 00099 } 00100 00101 void SOUNDCALL opngen_getpcm(void *hdl, SINT32 *pcm, UINT count) { 00102 00103 OPNCH *fm; 00104 UINT i; 00105 UINT playing; 00106 00107 if ((!opngen.playing) || (!count)) { 00108 return; 00109 } 00110 fm = opnch; 00111 do { 00112 SINT32 samp_l = opngen.outdl * (opngen.calcremain * -1); 00113 SINT32 samp_r = opngen.outdr * (opngen.calcremain * -1); 00114 opngen.calcremain += FMDIV_ENT; 00115 while(1) { 00116 opngen.outdc = 0; 00117 opngen.outdl = 0; 00118 opngen.outdr = 0; 00119 playing = 0; 00120 for (i=0; i<opngen.playchannels; i++) { 00121 if (fm[i].playing & fm[i].outslot) { 00122 calcratechannel(fm + i); 00123 playing++; 00124 } 00125 } 00126 opngen.outdl += opngen.outdc; 00127 opngen.outdr += opngen.outdc; 00128 opngen.outdl >>= FMVOL_SFTBIT; 00129 opngen.outdr >>= FMVOL_SFTBIT; 00130 if (opngen.calcremain > opncfg.calc1024) { 00131 samp_l += opngen.outdl * opncfg.calc1024; 00132 samp_r += opngen.outdr * opncfg.calc1024; 00133 opngen.calcremain -= opncfg.calc1024; 00134 } 00135 else { 00136 break; 00137 } 00138 } 00139 samp_l += opngen.outdl * opngen.calcremain; 00140 samp_l >>= 8; 00141 samp_l *= opncfg.fmvol; 00142 samp_l >>= (OPM_OUTSB + FMDIV_BITS + 1 + 6 - FMVOL_SFTBIT - 8); 00143 pcm[0] += samp_l; 00144 samp_r += opngen.outdr * opngen.calcremain; 00145 samp_r >>= 8; 00146 samp_r *= opncfg.fmvol; 00147 samp_r >>= (OPM_OUTSB + FMDIV_BITS + 1 + 6 - FMVOL_SFTBIT - 8); 00148 pcm[1] += samp_r; 00149 opngen.calcremain -= opncfg.calc1024; 00150 pcm += 2; 00151 } while(--count); 00152 opngen.playing = playing; 00153 (void)hdl; 00154 } 00155 00156 void SOUNDCALL opngen_getpcmvr(void *hdl, SINT32 *pcm, UINT count) { 00157 00158 OPNCH *fm; 00159 UINT i; 00160 00161 fm = opnch; 00162 while(count--) { 00163 SINT32 samp_l = opngen.outdl * (opngen.calcremain * -1); 00164 SINT32 samp_r = opngen.outdr * (opngen.calcremain * -1); 00165 opngen.calcremain += FMDIV_ENT; 00166 while(1) { 00167 opngen.outdc = 0; 00168 opngen.outdl = 0; 00169 opngen.outdr = 0; 00170 for (i=0; i<opngen.playchannels; i++) { 00171 calcratechannel(fm + i); 00172 } 00173 if (opncfg.vr_en) { 00174 SINT32 tmpl; 00175 SINT32 tmpr; 00176 tmpl = (opngen.outdl >> 5) * opncfg.vr_l; 00177 tmpr = (opngen.outdr >> 5) * opncfg.vr_r; 00178 opngen.outdl += tmpr; 00179 opngen.outdr += tmpl; 00180 } 00181 opngen.outdl += opngen.outdc; 00182 opngen.outdr += opngen.outdc; 00183 opngen.outdl >>= FMVOL_SFTBIT; 00184 opngen.outdr >>= FMVOL_SFTBIT; 00185 if (opngen.calcremain > opncfg.calc1024) { 00186 samp_l += opngen.outdl * opncfg.calc1024; 00187 samp_r += opngen.outdr * opncfg.calc1024; 00188 opngen.calcremain -= opncfg.calc1024; 00189 } 00190 else { 00191 break; 00192 } 00193 } 00194 samp_l += opngen.outdl * opngen.calcremain; 00195 samp_l >>= 8; 00196 samp_l *= opncfg.fmvol; 00197 samp_l >>= (OPM_OUTSB + FMDIV_BITS + 1 + 6 - FMVOL_SFTBIT - 8); 00198 pcm[0] += samp_l; 00199 samp_r += opngen.outdr * opngen.calcremain; 00200 samp_r >>= 8; 00201 samp_r *= opncfg.fmvol; 00202 samp_r >>= (OPM_OUTSB + FMDIV_BITS + 1 + 6 - FMVOL_SFTBIT - 8); 00203 pcm[1] += samp_r; 00204 opngen.calcremain -= opncfg.calc1024; 00205 pcm += 2; 00206 } 00207 (void)hdl; 00208 } 00209