1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MT32EMU_PARTIAL_H
#define MT32EMU_PARTIAL_H
namespace MT32Emu {
class Synth;
class Part;
class TVA;
struct ControlROMPCMStruct;
// A partial represents one of up to four waveform generators currently playing within a poly.
class Partial {
private:
Synth *synth;
const int debugPartialNum; // Only used for debugging
// Number of the sample currently being rendered by produceOutput(), or 0 if no run is in progress
// This is only kept available for debugging purposes.
unsigned long sampleNum;
// Actually, this is a 4-bit register but we abuse this to emulate inverted mixing.
// Also we double the value to enable INACCURATE_SMOOTH_PAN, with respect to MoK.
Bit32s leftPanValue, rightPanValue;
int ownerPart; // -1 if unassigned
int mixType;
int structurePosition; // 0 or 1 of a structure pair
// Only used for PCM partials
int pcmNum;
// FIXME: Give this a better name (e.g. pcmWaveInfo)
PCMWaveEntry *pcmWave;
// Final pulse width value, with velfollow applied, matching what is sent to the LA32.
// Range: 0-255
int pulseWidthVal;
Poly *poly;
Partial *pair;
TVA *tva;
TVP *tvp;
TVF *tvf;
LA32Ramp ampRamp;
LA32Ramp cutoffModifierRamp;
// TODO: This should be owned by PartialPair
LA32PartialPair la32Pair;
const PatchCache *patchCache;
PatchCache cachebackup;
Bit32u getAmpValue();
Bit32u getCutoffValue();
public:
bool alreadyOutputed;
Partial(Synth *synth, int debugPartialNum);
~Partial();
int debugGetPartialNum() const;
unsigned long debugGetSampleNum() const;
int getOwnerPart() const;
const Poly *getPoly() const;
bool isActive() const;
void activate(int part);
void deactivate(void);
void startPartial(const Part *part, Poly *usePoly, const PatchCache *useCache, const MemParams::RhythmTemp *rhythmTemp, Partial *pairPartial);
void startAbort();
void startDecayAll();
bool shouldReverb();
bool hasRingModulatingSlave() const;
bool isRingModulatingSlave() const;
bool isPCM() const;
const ControlROMPCMStruct *getControlROMPCMStruct() const;
Synth *getSynth() const;
TVA *getTVA() const;
void backupCache(const PatchCache &cache);
// Returns true only if data written to buffer
// This function (unlike the one below it) returns processed stereo samples
// made from combining this single partial with its pair, if it has one.
bool produceOutput(Sample *leftBuf, Sample *rightBuf, unsigned long length);
};
}
#endif
|