2 * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
3 * Copyright (C) 1999 - 2005 Simon Peter <dn.tlp@gmx.net>, et al.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * emuopl.cpp - Emulated OPL, by Simon Peter <dn.tlp@gmx.net>
24 CEmuopl::CEmuopl(int rate, bool bit16, bool usestereo)
25 : use16bit(bit16), stereo(usestereo), mixbufSamples(0)
27 opl[0] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
28 opl[1] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
30 currType = TYPE_DUAL_OPL2;
37 OPLDestroy(opl[0]); OPLDestroy(opl[1]);
45 void CEmuopl::update(short *buf, int samples)
49 //ensure that our mix buffers are adequately sized
50 if(mixbufSamples < samples) {
51 if(mixbufSamples) { delete[] mixbuf0; delete[] mixbuf1; }
52 mixbufSamples = samples;
54 //*2 = make room for stereo, if we need it
55 mixbuf0 = new short[samples*2];
56 mixbuf1 = new short[samples*2];
59 //data should be rendered to outbuf
60 //tempbuf should be used as a temporary buffer
61 //if we are supposed to generate 16bit output,
62 //then outbuf may point directly to the actual waveform output "buf"
63 //if we are supposed to generate 8bit output,
64 //then outbuf cannot point to "buf" (because there will not be enough room)
65 //and so it must point to a mixbuf instead--
66 //it will be reduced to 8bit and put in "buf" later
68 short *tempbuf=mixbuf0;
69 short *tempbuf2=mixbuf1;
70 if(use16bit) outbuf = buf;
71 else outbuf = mixbuf1;
72 //...there is a potentially confusing situation where mixbuf1 can be aliased.
73 //beware. it is a little loony.
75 //all of the following rendering code produces 16bit output
80 //render chip0 to the output buffer
81 YM3812UpdateOne(opl[0],outbuf,samples);
83 //if we are supposed to output stereo,
84 //then we need to dup the mono channel
86 for(i=samples-1;i>=0;i--) {
87 outbuf[i*2] = outbuf[i];
88 outbuf[i*2+1] = outbuf[i];
92 case TYPE_OPL3: // unsupported
97 //render each chip to a different tempbuffer
98 YM3812UpdateOne(opl[0],tempbuf2,samples);
99 YM3812UpdateOne(opl[1],tempbuf,samples);
102 //then we need to interleave the two buffers
104 //first, spread tempbuf's samples across left channel
106 for(i=0;i<samples;i++)
107 outbuf[i*2] = tempbuf2[i];
108 //next, insert the samples from tempbuf2 into right channel
109 for(i=0;i<samples;i++)
110 outbuf[i*2+1] = tempbuf[i];
113 //then we need to mix the two buffers into buf
114 for(i=0;i<samples;i++)
115 outbuf[i] = (tempbuf[i]>>1) + (tempbuf2[i]>>1);
119 //now reduce to 8bit if we need to
121 for(i=0;i<(stereo ? samples*2 : samples);i++)
122 ((char *)buf)[i] = (outbuf[i] >> 8) ^ 0x80;
125 void CEmuopl::write(int reg, int val)
130 OPLWrite(opl[currChip], 0, reg);
131 OPLWrite(opl[currChip], 1, val);
133 case TYPE_OPL3: // unsupported
140 OPLResetChip(opl[0]); OPLResetChip(opl[1]);
144 void CEmuopl::settype(ChipType type)