4 |
* * |
* * |
5 |
* Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck * |
* Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck * |
6 |
* Copyright (C) 2005-2008 Christian Schoenebeck * |
* Copyright (C) 2005-2008 Christian Schoenebeck * |
7 |
* Copyright (C) 2009-2011 Christian Schoenebeck and Grigor Iliev * |
* Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev * |
8 |
* * |
* * |
9 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
10 |
* it under the terms of the GNU General Public License as published by * |
* it under the terms of the GNU General Public License as published by * |
29 |
|
|
30 |
#include "../../common/global_private.h" |
#include "../../common/global_private.h" |
31 |
#include "../AbstractEngineChannel.h" |
#include "../AbstractEngineChannel.h" |
32 |
#include "../common/LFOBase.h" |
#include "LFOBase.h" |
33 |
|
#include "Fade.h" |
34 |
#include "../EngineBase.h" |
#include "../EngineBase.h" |
35 |
#include "EG.h" |
#include "EG.h" |
36 |
#include "../gig/EGADSR.h" |
#include "../gig/EGADSR.h" |
42 |
|
|
43 |
// include the appropriate (unsigned) triangle LFO implementation |
// include the appropriate (unsigned) triangle LFO implementation |
44 |
#if CONFIG_UNSIGNED_TRIANG_ALGO == INT_MATH_SOLUTION |
#if CONFIG_UNSIGNED_TRIANG_ALGO == INT_MATH_SOLUTION |
45 |
# include "../common/LFOTriangleIntMath.h" |
# include "LFOTriangleIntMath.h" |
46 |
#elif CONFIG_UNSIGNED_TRIANG_ALGO == INT_ABS_MATH_SOLUTION |
#elif CONFIG_UNSIGNED_TRIANG_ALGO == INT_ABS_MATH_SOLUTION |
47 |
# include "../common/LFOTriangleIntAbsMath.h" |
# include "LFOTriangleIntAbsMath.h" |
48 |
#elif CONFIG_UNSIGNED_TRIANG_ALGO == DI_HARMONIC_SOLUTION |
#elif CONFIG_UNSIGNED_TRIANG_ALGO == DI_HARMONIC_SOLUTION |
49 |
# include "../common/LFOTriangleDiHarmonic.h" |
# include "LFOTriangleDiHarmonic.h" |
50 |
#else |
#else |
51 |
# error "Unknown or no (unsigned) triangle LFO implementation selected!" |
# error "Unknown or no (unsigned) triangle LFO implementation selected!" |
52 |
#endif |
#endif |
53 |
|
|
54 |
// include the appropriate (signed) triangle LFO implementation |
// include the appropriate (signed) triangle LFO implementation |
55 |
#if CONFIG_SIGNED_TRIANG_ALGO == INT_MATH_SOLUTION |
#if CONFIG_SIGNED_TRIANG_ALGO == INT_MATH_SOLUTION |
56 |
# include "../common/LFOTriangleIntMath.h" |
# include "LFOTriangleIntMath.h" |
57 |
#elif CONFIG_SIGNED_TRIANG_ALGO == INT_ABS_MATH_SOLUTION |
#elif CONFIG_SIGNED_TRIANG_ALGO == INT_ABS_MATH_SOLUTION |
58 |
# include "../common/LFOTriangleIntAbsMath.h" |
# include "LFOTriangleIntAbsMath.h" |
59 |
#elif CONFIG_SIGNED_TRIANG_ALGO == DI_HARMONIC_SOLUTION |
#elif CONFIG_SIGNED_TRIANG_ALGO == DI_HARMONIC_SOLUTION |
60 |
# include "../common/LFOTriangleDiHarmonic.h" |
# include "LFOTriangleDiHarmonic.h" |
61 |
#else |
#else |
62 |
# error "Unknown or no (signed) triangle LFO implementation selected!" |
# error "Unknown or no (signed) triangle LFO implementation selected!" |
63 |
#endif |
#endif |
83 |
class AbstractVoice : public Voice { |
class AbstractVoice : public Voice { |
84 |
public: |
public: |
85 |
type_t Type; ///< Voice Type (bit field, a voice may have several types) |
type_t Type; ///< Voice Type (bit field, a voice may have several types) |
86 |
int MIDIKey; ///< MIDI key number of the key that triggered the voice |
NoteBase* pNote; ///< Note this voice belongs to and was caused by. |
87 |
|
int MIDIPan; ///< the current MIDI pan value plus the value from RegionInfo |
88 |
|
|
89 |
AbstractVoice(); |
SignalUnitRack* const pSignalUnitRack; |
90 |
|
|
91 |
|
AbstractVoice(SignalUnitRack* pRack); |
92 |
virtual ~AbstractVoice(); |
virtual ~AbstractVoice(); |
93 |
|
|
94 |
inline bool IsActive() { return PlaybackState; } |
inline bool IsActive() { return PlaybackState; } |
104 |
int iKeyGroup |
int iKeyGroup |
105 |
); |
); |
106 |
|
|
107 |
|
/** Invoked when the voice is freed - gone from active to inactive. */ |
108 |
|
virtual void VoiceFreed() { } |
109 |
|
|
110 |
virtual void Synthesize(uint Samples, sample_t* pSrc, uint Skip); |
virtual void Synthesize(uint Samples, sample_t* pSrc, uint Skip); |
111 |
|
|
112 |
uint GetSampleRate() { return GetEngine()->SampleRate; } |
uint GetSampleRate() { return GetEngine()->SampleRate; } |
113 |
|
|
114 |
virtual SignalUnitRack* GetSignalUnitRack() { return NULL; } |
uint8_t GetControllerValue(uint8_t Controller) { |
115 |
|
return (Controller > 128) ? 0 : pEngineChannel->ControllerTable[Controller]; |
116 |
|
} |
117 |
|
|
118 |
|
/// Keyboard key on which this voice should listen to transitional events (i.e. note-off events to release the voice). |
119 |
|
inline uint8_t HostKey() const { return pNote->hostKey; } |
120 |
|
/// Keyboard key which the voice should use for calculating any synthesis relevant parameters (i.e. pitch). |
121 |
|
inline uint8_t MIDIKey() const { return pNote->cause.Param.Note.Key; } |
122 |
|
/// MIDI note-on velocity value which the voice should use for calculating any synthesis relevant parameters (i.e. amplitude). |
123 |
|
inline uint8_t MIDIVelocity() const { return pNote->cause.Param.Note.Velocity; } |
124 |
|
|
125 |
void processCCEvents(RTList<Event>::Iterator& itEvent, uint End); |
void processCCEvents(RTList<Event>::Iterator& itEvent, uint End); |
126 |
void processPitchEvent(RTList<Event>::Iterator& itEvent); |
void processPitchEvent(RTList<Event>::Iterator& itEvent); |
129 |
void processGroupEvents(RTList<Event>::Iterator& itEvent, uint End); |
void processGroupEvents(RTList<Event>::Iterator& itEvent, uint End); |
130 |
void UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent); |
void UpdatePortamentoPos(Pool<Event>::Iterator& itNoteOffEvent); |
131 |
void Kill(Pool<Event>::Iterator& itKillEvent); |
void Kill(Pool<Event>::Iterator& itKillEvent); |
132 |
|
void CreateEq(); |
133 |
|
void onScaleTuningChanged(); |
134 |
|
|
135 |
bool Orphan; ///< true if this voice is playing a sample from an instrument that is unloaded. When the voice dies, the sample (and dimension region) will be handed back to the instrument resource manager. |
bool Orphan; ///< true if this voice is playing a sample from an instrument that is unloaded. When the voice dies, the sample (and dimension region) will be handed back to the instrument resource manager. |
136 |
playback_state_t PlaybackState; ///< When a sample will be triggered, it will be first played from RAM cache and after a couple of sample points it will switch to disk streaming and at the end of a disk stream we have to add null samples, so the interpolator can do it's work correctly |
playback_state_t PlaybackState; ///< When a sample will be triggered, it will be first played from RAM cache and after a couple of sample points it will switch to disk streaming and at the end of a disk stream we have to add null samples, so the interpolator can do it's work correctly |
138 |
|
|
139 |
template<class TV, class TRR, class TR, class TD, class TIM, class TI> friend class EngineBase; |
template<class TV, class TRR, class TR, class TD, class TIM, class TI> friend class EngineBase; |
140 |
|
|
141 |
|
#if CONFIG_DEVMODE |
142 |
|
public: |
143 |
|
#else |
144 |
protected: |
protected: |
145 |
|
#endif |
146 |
SampleInfo SmplInfo; |
SampleInfo SmplInfo; |
147 |
RegionInfo RgnInfo; |
RegionInfo RgnInfo; |
148 |
InstrumentInfo InstrInfo; |
InstrumentInfo InstrInfo; |
150 |
|
|
151 |
double Pos; ///< Current playback position in sample |
double Pos; ///< Current playback position in sample |
152 |
PitchInfo Pitch; |
PitchInfo Pitch; |
153 |
|
Fade NotePitch; ///< Updated by calls to built-in instrument script function change_tune() (defaults to 1.0, that is neutral). |
154 |
float CutoffBase; ///< Cutoff frequency before control change, EG and LFO are applied |
float CutoffBase; ///< Cutoff frequency before control change, EG and LFO are applied |
155 |
float VolumeLeft; ///< Left channel volume. This factor is calculated when the voice is triggered and doesn't change after that. |
float VolumeLeft; ///< Left channel volume. This factor is calculated when the voice is triggered and doesn't change after that. |
156 |
float VolumeRight; ///< Right channel volume. This factor is calculated when the voice is triggered and doesn't change after that. |
float VolumeRight; ///< Right channel volume. This factor is calculated when the voice is triggered and doesn't change after that. |
157 |
|
float NotePanLeft; ///< Updated by calls to built-in instrument script function change_pan() (defaults to 1.0, that is neutral). |
158 |
|
float NotePanRight; ///< Updated by calls to built-in instrument script function change_pan() (defaults to 1.0, that is neutral). |
159 |
|
float NoteCutoff; ///< Updated by calls to built-in instrument script function change_cutoff() (defaults to 1.0, that is neutral). |
160 |
|
float NoteResonance; ///< Updated by calls to built-in instrument script function change_reso() (defaults to 1.0, that is neutral). |
161 |
gig::SmoothVolume CrossfadeSmoother; ///< Crossfade volume, updated by crossfade CC events |
gig::SmoothVolume CrossfadeSmoother; ///< Crossfade volume, updated by crossfade CC events |
162 |
gig::SmoothVolume VolumeSmoother; ///< Volume, updated by CC 7 (volume) events |
gig::SmoothVolume VolumeSmoother; ///< Volume, updated by CC 7 (volume) events |
163 |
gig::SmoothVolume PanLeftSmoother; ///< Left channel volume, updated by CC 10 (pan) events |
gig::SmoothVolume PanLeftSmoother; ///< Left channel volume, updated by CC 10 (pan) events and change_pan() real-time instrument script calls. |
164 |
gig::SmoothVolume PanRightSmoother; ///< Right channel volume, updated by CC 10 (pan) events |
gig::SmoothVolume PanRightSmoother; ///< Right channel volume, updated by CC 10 (pan) events and change_pan() real-time instrument script calls. |
165 |
|
Fade NoteVolume; ///< Note's global volume, updated by change_vol() real-time instrument script calls (defaults to 1.0, that is neutral). |
166 |
bool DiskVoice; ///< If the sample is very short it completely fits into the RAM cache and doesn't need to be streamed from disk, in that case this flag is set to false |
bool DiskVoice; ///< If the sample is very short it completely fits into the RAM cache and doesn't need to be streamed from disk, in that case this flag is set to false |
167 |
bool RAMLoop; ///< If this voice has a loop defined which completely fits into the cached RAM part of the sample, in this case we handle the looping within the voice class, else if the loop is located in the disk stream part, we let the disk stream handle the looping |
bool RAMLoop; ///< If this voice has a loop defined which completely fits into the cached RAM part of the sample, in this case we handle the looping within the voice class, else if the loop is located in the disk stream part, we let the disk stream handle the looping |
168 |
unsigned long MaxRAMPos; ///< The upper allowed limit (not actually the end) in the RAM sample cache, after that point it's not safe to chase the interpolator another time over over the current cache position, instead we switch to disk then. |
unsigned long MaxRAMPos; ///< The upper allowed limit (not actually the end) in the RAM sample cache, after that point it's not safe to chase the interpolator another time over over the current cache position, instead we switch to disk then. |
186 |
gig::SynthesisParam finalSynthesisParameters; |
gig::SynthesisParam finalSynthesisParameters; |
187 |
gig::Loop loop; |
gig::Loop loop; |
188 |
RTList<Event>* pGroupEvents; ///< Events directed to an exclusive group |
RTList<Event>* pGroupEvents; ///< Events directed to an exclusive group |
189 |
|
|
190 |
|
EqSupport* pEq; ///< Used for per voice equalization |
191 |
|
bool bEqSupport; |
192 |
|
|
193 |
|
void PrintEqInfo() { |
194 |
|
if (!bEqSupport || pEq == NULL) { |
195 |
|
dmsg(1,("EQ support: no\n")); |
196 |
|
} else { |
197 |
|
pEq->PrintInfo(); |
198 |
|
} |
199 |
|
} |
200 |
|
|
201 |
virtual AbstractEngine* GetEngine() = 0; |
virtual AbstractEngine* GetEngine() = 0; |
202 |
virtual SampleInfo GetSampleInfo() = 0; |
virtual SampleInfo GetSampleInfo() = 0; |
311 |
|
|
312 |
virtual void GetFirstEventOnKey(uint8_t MIDIKey, RTList<Event>::Iterator& itEvent) = 0; |
virtual void GetFirstEventOnKey(uint8_t MIDIKey, RTList<Event>::Iterator& itEvent) = 0; |
313 |
virtual void ProcessCCEvent(RTList<Event>::Iterator& itEvent) = 0; |
virtual void ProcessCCEvent(RTList<Event>::Iterator& itEvent) = 0; |
314 |
|
virtual void ProcessChannelPressureEvent(RTList<Event>::Iterator& itEvent) = 0; |
315 |
|
virtual void ProcessPolyphonicKeyPressureEvent(RTList<Event>::Iterator& itEvent) = 0; |
316 |
virtual void ProcessCutoffEvent(RTList<Event>::Iterator& itEvent) = 0; |
virtual void ProcessCutoffEvent(RTList<Event>::Iterator& itEvent) = 0; |
317 |
virtual double GetVelocityRelease(uint8_t MIDIKeyVelocity) = 0; |
virtual double GetVelocityRelease(uint8_t MIDIKeyVelocity) = 0; |
318 |
|
|
320 |
|
|
321 |
virtual void ProcessGroupEvent(RTList<Event>::Iterator& itEvent) = 0; |
virtual void ProcessGroupEvent(RTList<Event>::Iterator& itEvent) = 0; |
322 |
void EnterReleaseStage(); |
void EnterReleaseStage(); |
323 |
|
|
324 |
|
virtual int CalculatePan(uint8_t pan) = 0; |
325 |
}; |
}; |
326 |
} // namespace LinuxSampler |
} // namespace LinuxSampler |
327 |
|
|