]> 4ch.mooo.com Git - 16.git/blob - 16/adplug/adplug/src/emuopl.cpp
compy4 sync
[16.git] / 16 / adplug / adplug / src / emuopl.cpp
1 /*
2  * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
3  * Copyright (C) 1999 - 2005 Simon Peter <dn.tlp@gmx.net>, et al.
4  * 
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.
9  * 
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.
14  * 
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
18  *
19  * emuopl.cpp - Emulated OPL, by Simon Peter <dn.tlp@gmx.net>
20  */
21
22 #include "emuopl.h"
23
24 CEmuopl::CEmuopl(int rate, bool bit16, bool usestereo)
25   : use16bit(bit16), stereo(usestereo), mixbufSamples(0)
26 {
27   opl[0] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
28   opl[1] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
29
30   currType = TYPE_DUAL_OPL2;
31
32   init();
33 }
34
35 CEmuopl::~CEmuopl()
36 {
37   OPLDestroy(opl[0]); OPLDestroy(opl[1]);
38
39   if(mixbufSamples) {
40     delete [] mixbuf0;
41     delete [] mixbuf1;
42   }
43 }
44
45 void CEmuopl::update(short *buf, int samples)
46 {
47   int i;
48
49   //ensure that our mix buffers are adequately sized
50   if(mixbufSamples < samples) {
51     if(mixbufSamples) { delete[] mixbuf0; delete[] mixbuf1; }
52     mixbufSamples = samples;
53
54     //*2 = make room for stereo, if we need it
55     mixbuf0 = new short[samples*2]; 
56     mixbuf1 = new short[samples*2];
57   }
58
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
67   short *outbuf;
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.
74
75   //all of the following rendering code produces 16bit output
76
77   switch(currType) {
78   case TYPE_OPL2:
79     //for opl2 mode:
80     //render chip0 to the output buffer
81     YM3812UpdateOne(opl[0],outbuf,samples);
82
83     //if we are supposed to output stereo,
84     //then we need to dup the mono channel
85     if(stereo)
86       for(i=samples-1;i>=0;i--) {
87         outbuf[i*2] = outbuf[i];
88         outbuf[i*2+1] = outbuf[i];
89       }
90     break;
91
92   case TYPE_OPL3:       // unsupported
93     break;
94
95   case TYPE_DUAL_OPL2:
96     //for dual opl2 mode:
97     //render each chip to a different tempbuffer
98     YM3812UpdateOne(opl[0],tempbuf2,samples);
99     YM3812UpdateOne(opl[1],tempbuf,samples);
100
101     //output stereo:
102     //then we need to interleave the two buffers
103     if(stereo){
104       //first, spread tempbuf's samples across left channel
105       //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];
111     } else
112       //output mono:
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);
116     break;
117   }
118
119   //now reduce to 8bit if we need to
120   if(!use16bit)
121     for(i=0;i<(stereo ? samples*2 : samples);i++)
122       ((char *)buf)[i] = (outbuf[i] >> 8) ^ 0x80;
123 }
124
125 void CEmuopl::write(int reg, int val)
126 {
127   switch(currType){
128   case TYPE_OPL2:
129   case TYPE_DUAL_OPL2:
130     OPLWrite(opl[currChip], 0, reg);
131     OPLWrite(opl[currChip], 1, val);
132     break;
133   case TYPE_OPL3:       // unsupported
134     break;
135   }
136 }
137
138 void CEmuopl::init()
139 {
140   OPLResetChip(opl[0]); OPLResetChip(opl[1]);
141   currChip = 0;
142 }
143
144 void CEmuopl::settype(ChipType type)
145 {
146   currType = type;
147 }