Mercurial > audlegacy-plugins
comparison src/adplug/core/emuopl.cxx @ 12:3da1b8942b8b trunk
[svn] - remove src/Input src/Output src/Effect src/General src/Visualization src/Container
author | nenolod |
---|---|
date | Mon, 18 Sep 2006 03:14:20 -0700 |
parents | src/Input/adplug/core/emuopl.cxx@13389e613d67 |
children | 4709ce4e209e |
comparison
equal
deleted
inserted
replaced
11:cff1d04026ae | 12:3da1b8942b8b |
---|---|
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 } |