1 /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
2 * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation, either version 2.1 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <cstddef>
19
20 #include "internals.h"
21
22 #include "Partial.h"
23 #include "Part.h"
24 #include "Poly.h"
25 #include "Synth.h"
26 #include "Tables.h"
27 #include "TVA.h"
28 #include "TVF.h"
29 #include "TVP.h"
30
31 namespace MT32Emu {
32
33 static const Bit8u PAN_NUMERATOR_MASTER[] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7};
34 static const Bit8u PAN_NUMERATOR_SLAVE[] = {0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7};
35
36 static const Bit32s PAN_FACTORS[] = {0, 18, 37, 55, 73, 91, 110, 128, 146, 165, 183, 201, 219, 238, 256};
37
Partial(Synth * useSynth,int useDebugPartialNum)38 Partial::Partial(Synth *useSynth, int useDebugPartialNum) :
39 synth(useSynth), debugPartialNum(useDebugPartialNum), sampleNum(0) {
40 // Initialisation of tva, tvp and tvf uses 'this' pointer
41 // and thus should not be in the initializer list to avoid a compiler warning
42 tva = new TVA(this, &Ramp);
43 tvp = new TVP(this);
44 tvf = new TVF(this, &cutoffModifierRamp);
45 ownerPart = -1;
46 poly = NULL;
47 pair = NULL;
48 }
49
~Partial()50 Partial::~Partial() {
51 delete tva;
52 delete tvp;
53 delete tvf;
54 }
55
56 // Only used for debugging purposes
debugGetPartialNum() const57 int Partial::debugGetPartialNum() const {
58 return debugPartialNum;
59 }
60
61 // Only used for debugging purposes
debugGetSampleNum() const62 Bit32u Partial::debugGetSampleNum() const {
63 return sampleNum;
64 }
65
getOwnerPart() const66 int Partial::getOwnerPart() const {
67 return ownerPart;
68 }
69
isActive() const70 bool Partial::isActive() const {
71 return ownerPart > -1;
72 }
73
getPoly() const74 const Poly *Partial::getPoly() const {
75 return poly;
76 }
77
activate(int part)78 void Partial::activate(int part) {
79 // This just marks the partial as being assigned to a part
80 ownerPart = part;
81 }
82
deactivate()83 void Partial::deactivate() {
84 if (!isActive()) {
85 return;
86 }
87 ownerPart = -1;
88 if (poly != NULL) {
89 poly->partialDeactivated(this);
90 }
91 #if MT32EMU_MONITOR_PARTIALS > 2
92 synth->printDebug("[+%lu] [Partial %d] Deactivated", sampleNum, debugPartialNum);
93 synth->printPartialUsage(sampleNum);
94 #endif
95 if (isRingModulatingSlave()) {
96 pair->la32Pair.deactivate(LA32PartialPair::SLAVE);
97 } else {
98 la32Pair.deactivate(LA32PartialPair::MASTER);
99 if (hasRingModulatingSlave()) {
100 pair->deactivate();
101 pair = NULL;
102 }
103 }
104 if (pair != NULL) {
105 pair->pair = NULL;
106 }
107 }
108
startPartial(const Part * part,Poly * usePoly,const PatchCache * usePatchCache,const MemParams::RhythmTemp * rhythmTemp,Partial * pairPartial)109 void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *usePatchCache, const MemParams::RhythmTemp *rhythmTemp, Partial *pairPartial) {
110 if (usePoly == NULL || usePatchCache == NULL) {
111 synth->printDebug("[Partial %d] *** Error: Starting partial for owner %d, usePoly=%s, usePatchCache=%s", debugPartialNum, ownerPart, usePoly == NULL ? "*** NULL ***" : "OK", usePatchCache == NULL ? "*** NULL ***" : "OK");
112 return;
113 }
114 patchCache = usePatchCache;
115 poly = usePoly;
116 mixType = patchCache->structureMix;
117 structurePosition = patchCache->structurePosition;
118
119 Bit8u panSetting = rhythmTemp != NULL ? rhythmTemp->panpot : part->getPatchTemp()->panpot;
120 if (mixType == 3) {
121 if (structurePosition == 0) {
122 panSetting = PAN_NUMERATOR_MASTER[panSetting] << 1;
123 } else {
124 panSetting = PAN_NUMERATOR_SLAVE[panSetting] << 1;
125 }
126 // Do a normal mix independent of any pair partial.
127 mixType = 0;
128 pairPartial = NULL;
129 } else {
130 // Mok wanted an option for smoother panning, and we love Mok.
131 #ifndef INACCURATE_SMOOTH_PAN
132 // CONFIRMED by Mok: exactly bytes like this (right shifted?) are sent to the LA32.
133 panSetting &= 0x0E;
134 #endif
135 }
136
137 leftPanValue = synth->reversedStereoEnabled ? 14 - panSetting : panSetting;
138 rightPanValue = 14 - leftPanValue;
139
140 #if !MT32EMU_USE_FLOAT_SAMPLES
141 leftPanValue = PAN_FACTORS[leftPanValue];
142 rightPanValue = PAN_FACTORS[rightPanValue];
143 #endif
144
145 // SEMI-CONFIRMED: From sample analysis:
146 // Found that timbres with 3 or 4 partials (i.e. one using two partial pairs) are mixed in two different ways.
147 // Either partial pairs are added or subtracted, it depends on how the partial pairs are allocated.
148 // It seems that partials are grouped into quarters and if the partial pairs are allocated in different quarters the subtraction happens.
149 // Though, this matters little for the majority of timbres, it becomes crucial for timbres which contain several partials that sound very close.
150 // In this case that timbre can sound totally different depending of the way it is mixed up.
151 // Most easily this effect can be displayed with the help of a special timbre consisting of several identical square wave partials (3 or 4).
152 // Say, it is 3-partial timbre. Just play any two notes simultaneously and the polys very probably are mixed differently.
153 // Moreover, the partial allocator retains the last partial assignment it did and all the subsequent notes will sound the same as the last released one.
154 // The situation is better with 4-partial timbres since then a whole quarter is assigned for each poly. However, if a 3-partial timbre broke the normal
155 // whole-quarter assignment or after some partials got aborted, even 4-partial timbres can be found sounding differently.
156 // This behaviour is also confirmed with two more special timbres: one with identical sawtooth partials, and one with PCM wave 02.
157 // For my personal taste, this behaviour rather enriches the sounding and should be emulated.
158 // Also, the current partial allocator model probably needs to be refined.
159 if (debugPartialNum & 8) {
160 leftPanValue = -leftPanValue;
161 rightPanValue = -rightPanValue;
162 }
163
164 if (patchCache->PCMPartial) {
165 pcmNum = patchCache->pcm;
166 if (synth->controlROMMap->pcmCount > 128) {
167 // CM-32L, etc. support two "banks" of PCMs, selectable by waveform type parameter.
168 if (patchCache->waveform > 1) {
169 pcmNum += 128;
170 }
171 }
172 pcmWave = &synth->pcmWaves[pcmNum];
173 } else {
174 pcmWave = NULL;
175 }
176
177 // CONFIRMED: pulseWidthVal calculation is based on information from Mok
178 pulseWidthVal = (poly->getVelocity() - 64) * (patchCache->srcPartial.wg.pulseWidthVeloSensitivity - 7) + Tables::getInstance().pulseWidth100To255[patchCache->srcPartial.wg.pulseWidth];
179 if (pulseWidthVal < 0) {
180 pulseWidthVal = 0;
181 } else if (pulseWidthVal > 255) {
182 pulseWidthVal = 255;
183 }
184
185 pair = pairPartial;
186 alreadyOutputed = false;
187 tva->reset(part, patchCache->partialParam, rhythmTemp);
188 tvp->reset(part, patchCache->partialParam);
189 tvf->reset(patchCache->partialParam, tvp->getBasePitch());
190
191 LA32PartialPair::PairType pairType;
192 LA32PartialPair *useLA32Pair;
193 if (isRingModulatingSlave()) {
194 pairType = LA32PartialPair::SLAVE;
195 useLA32Pair = &pair->la32Pair;
196 } else {
197 pairType = LA32PartialPair::MASTER;
198 la32Pair.init(hasRingModulatingSlave(), mixType == 1);
199 useLA32Pair = &la32Pair;
200 }
201 if (isPCM()) {
202 useLA32Pair->initPCM(pairType, &synth->pcmROMData[pcmWave->addr], pcmWave->len, pcmWave->loop);
203 } else {
204 useLA32Pair->initSynth(pairType, (patchCache->waveform & 1) != 0, pulseWidthVal, patchCache->srcPartial.tvf.resonance + 1);
205 }
206 if (!hasRingModulatingSlave()) {
207 la32Pair.deactivate(LA32PartialPair::SLAVE);
208 }
209 }
210
getAmpValue()211 Bit32u Partial::getAmpValue() {
212 // SEMI-CONFIRMED: From sample analysis:
213 // (1) Tested with a single partial playing PCM wave 77 with pitchCoarse 36 and no keyfollow, velocity follow, etc.
214 // This gives results within +/- 2 at the output (before any DAC bitshifting)
215 // when sustaining at levels 156 - 255 with no modifiers.
216 // (2) Tested with a special square wave partial (internal capture ID tva5) at TVA envelope levels 155-255.
217 // This gives deltas between -1 and 0 compared to the real output. Note that this special partial only produces
218 // positive amps, so negative still needs to be explored, as well as lower levels.
219 //
220 // Also still partially unconfirmed is the behaviour when ramping between levels, as well as the timing.
221 // TODO: The tests above were performed using the float model, to be refined
222 Bit32u ampRampVal = 67117056 - ampRamp.nextValue();
223 if (ampRamp.checkInterrupt()) {
224 tva->handleInterrupt();
225 }
226 return ampRampVal;
227 }
228
getCutoffValue()229 Bit32u Partial::getCutoffValue() {
230 if (isPCM()) {
231 return 0;
232 }
233 Bit32u cutoffModifierRampVal = cutoffModifierRamp.nextValue();
234 if (cutoffModifierRamp.checkInterrupt()) {
235 tvf->handleInterrupt();
236 }
237 return (tvf->getBaseCutoff() << 18) + cutoffModifierRampVal;
238 }
239
hasRingModulatingSlave() const240 bool Partial::hasRingModulatingSlave() const {
241 return pair != NULL && structurePosition == 0 && (mixType == 1 || mixType == 2);
242 }
243
isRingModulatingSlave() const244 bool Partial::isRingModulatingSlave() const {
245 return pair != NULL && structurePosition == 1 && (mixType == 1 || mixType == 2);
246 }
247
isPCM() const248 bool Partial::isPCM() const {
249 return pcmWave != NULL;
250 }
251
getControlROMPCMStruct() const252 const ControlROMPCMStruct *Partial::getControlROMPCMStruct() const {
253 if (pcmWave != NULL) {
254 return pcmWave->controlROMPCMStruct;
255 }
256 return NULL;
257 }
258
getSynth() const259 Synth *Partial::getSynth() const {
260 return synth;
261 }
262
getTVA() const263 TVA *Partial::getTVA() const {
264 return tva;
265 }
266
backupCache(const PatchCache & cache)267 void Partial::backupCache(const PatchCache &cache) {
268 if (patchCache == &cache) {
269 cachebackup = cache;
270 patchCache = &cachebackup;
271 }
272 }
273
produceOutput(Sample * leftBuf,Sample * rightBuf,Bit32u length)274 bool Partial::produceOutput(Sample *leftBuf, Sample *rightBuf, Bit32u length) {
275 if (!isActive() || alreadyOutputed || isRingModulatingSlave()) {
276 return false;
277 }
278 if (poly == NULL) {
279 synth->printDebug("[Partial %d] *** ERROR: poly is NULL at Partial::produceOutput()!", debugPartialNum);
280 return false;
281 }
282 alreadyOutputed = true;
283
284 for (sampleNum = 0; sampleNum < length; sampleNum++) {
285 if (!tva->isPlaying() || !la32Pair.isActive(LA32PartialPair::MASTER)) {
286 deactivate();
287 break;
288 }
289 la32Pair.generateNextSample(LA32PartialPair::MASTER, getAmpValue(), tvp->nextPitch(), getCutoffValue());
290 if (hasRingModulatingSlave()) {
291 la32Pair.generateNextSample(LA32PartialPair::SLAVE, pair->getAmpValue(), pair->tvp->nextPitch(), pair->getCutoffValue());
292 if (!pair->tva->isPlaying() || !la32Pair.isActive(LA32PartialPair::SLAVE)) {
293 pair->deactivate();
294 if (mixType == 2) {
295 deactivate();
296 break;
297 }
298 }
299 }
300
301 // Although, LA32 applies panning itself, we assume here it is applied in the mixer, not within a pair.
302 // Applying the pan value in the log-space looks like a waste of unlog resources. Though, it needs clarification.
303 Sample sample = la32Pair.nextOutSample();
304
305 // FIXME: Sample analysis suggests that the use of panVal is linear, but there are some quirks that still need to be resolved.
306 #if MT32EMU_USE_FLOAT_SAMPLES
307 Sample leftOut = (sample * (float)leftPanValue) / 14.0f;
308 Sample rightOut = (sample * (float)rightPanValue) / 14.0f;
309 *(leftBuf++) += leftOut;
310 *(rightBuf++) += rightOut;
311 #else
312 // FIXME: Dividing by 7 (or by 14 in a Mok-friendly way) looks of course pointless. Need clarification.
313 // FIXME2: LA32 may produce distorted sound in case if the absolute value of maximal amplitude of the input exceeds 8191
314 // when the panning value is non-zero. Most probably the distortion occurs in the same way it does with ring modulation,
315 // and it seems to be caused by limited precision of the common multiplication circuit.
316 // From analysis of this overflow, it is obvious that the right channel output is actually found
317 // by subtraction of the left channel output from the input.
318 // Though, it is unknown whether this overflow is exploited somewhere.
319 Sample leftOut = Sample((sample * leftPanValue) >> 8);
320 Sample rightOut = Sample((sample * rightPanValue) >> 8);
321 *leftBuf = Synth::clipSampleEx((SampleEx)*leftBuf + (SampleEx)leftOut);
322 *rightBuf = Synth::clipSampleEx((SampleEx)*rightBuf + (SampleEx)rightOut);
323 leftBuf++;
324 rightBuf++;
325 #endif
326 }
327 sampleNum = 0;
328 return true;
329 }
330
shouldReverb()331 bool Partial::shouldReverb() {
332 if (!isActive()) {
333 return false;
334 }
335 return patchCache->reverb;
336 }
337
startAbort()338 void Partial::startAbort() {
339 // This is called when the partial manager needs to terminate partials for re-use by a new Poly.
340 tva->startAbort();
341 }
342
startDecayAll()343 void Partial::startDecayAll() {
344 tva->startDecay();
345 tvp->startDecay();
346 tvf->startDecay();
347 }
348
349 } // namespace MT32Emu
350