/[svn]/linuxsampler/trunk/src/engines/sfz/Voice.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/engines/sfz/Voice.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2559 - (hide annotations) (download)
Sun May 18 17:38:25 2014 UTC (10 years ago) by schoenebeck
File size: 13542 byte(s)
* Aftertouch: extended API to explicitly handle channel pressure and
  polyphonic key pressure events (so far polyphonic pressure was not
  supported at all, and channel pressure was rerouted as CC128 but not
  used so far).
* Gig Engine: Fixed support for 'aftertouch' attenuation controller.
* Bumped version (1.0.0.svn39).

1 iliev 2012 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 persson 2055 * Copyright (C) 2005 - 2008 Christian Schoenebeck *
7 persson 2403 * Copyright (C) 2009 - 2013 Christian Schoenebeck and Grigor Iliev *
8 iliev 2012 * *
9     * 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 *
11     * the Free Software Foundation; either version 2 of the License, or *
12     * (at your option) any later version. *
13     * *
14     * This program is distributed in the hope that it will be useful, *
15     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17     * GNU General Public License for more details. *
18     * *
19     * You should have received a copy of the GNU General Public License *
20     * along with this program; if not, write to the Free Software *
21     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
22     * MA 02111-1307 USA *
23     ***************************************************************************/
24    
25 iliev 2015 #include "Voice.h"
26    
27 iliev 2012 #include "Engine.h"
28     #include "EngineChannel.h"
29    
30 persson 2072 #define LN_10_DIV_20 0.115129254649702
31    
32 iliev 2012 namespace LinuxSampler { namespace sfz {
33    
34 iliev 2218 typedef LinuxSampler::VoiceBase<EngineChannel, ::sfz::Region, Sample, DiskThread> SfzVoice;
35     Voice::Voice(): SignalRack(this), SfzVoice(&SignalRack) {
36 iliev 2012 pEngine = NULL;
37 iliev 2298 bEqSupport = true;
38 iliev 2012 }
39    
40     Voice::~Voice() {
41 iliev 2015
42 iliev 2012 }
43    
44 iliev 2015 EngineChannel* Voice::GetSfzEngineChannel() {
45     return static_cast<EngineChannel*>(pEngineChannel);
46     }
47    
48 iliev 2012 void Voice::SetEngine(LinuxSampler::Engine* pEngine) {
49     Engine* engine = static_cast<Engine*>(pEngine);
50     this->pEngine = engine;
51     this->pDiskThread = engine->pDiskThread;
52     dmsg(6,("Voice::SetEngine()\n"));
53     }
54    
55 iliev 2015 Voice::SampleInfo Voice::GetSampleInfo() {
56     SampleInfo si;
57     si.SampleRate = pSample->GetSampleRate();
58     si.ChannelCount = pSample->GetChannelCount();
59     si.FrameSize = pSample->GetFrameSize();
60     si.BitDepth = (pSample->GetFrameSize() / pSample->GetChannelCount()) * 8;
61     si.TotalFrameCount = pSample->GetTotalFrameCount();
62 iliev 2012
63 iliev 2021 si.HasLoops = pRegion->HasLoop();
64     si.LoopStart = pRegion->GetLoopStart();
65     si.LoopLength = pRegion->GetLoopEnd() - pRegion->GetLoopStart();
66     si.LoopPlayCount = pRegion->GetLoopCount();
67     si.Unpitched = pRegion->pitch_keytrack == 0;
68 iliev 2015 return si;
69     }
70 iliev 2012
71 iliev 2015 Voice::RegionInfo Voice::GetRegionInfo() {
72     RegionInfo ri;
73 iliev 2018 ri.UnityNote = pRegion->pitch_keycenter;
74 persson 2086 ri.FineTune = pRegion->tune + pRegion->transpose * 100;
75 persson 2045 ri.Pan = int(pRegion->pan * 0.63); // convert from -100..100 to -64..63
76 iliev 2216 ri.SampleStartOffset = pRegion->offset ? *(pRegion->offset) : 0;
77 iliev 2012
78 persson 2175 ri.VCFEnabled = pRegion->cutoff;
79     switch (pRegion->fil_type) {
80     case ::sfz::LPF_1P:
81     ri.VCFType = Filter::vcf_type_1p_lowpass;
82     break;
83     case ::sfz::LPF_2P:
84     ri.VCFType = Filter::vcf_type_2p_lowpass;
85     break;
86     case ::sfz::LPF_4P:
87     ri.VCFType = Filter::vcf_type_4p_lowpass;
88     break;
89     case ::sfz::LPF_6P:
90     ri.VCFType = Filter::vcf_type_6p_lowpass;
91     break;
92     case ::sfz::HPF_1P:
93     ri.VCFType = Filter::vcf_type_1p_highpass;
94     break;
95     case ::sfz::HPF_2P:
96     ri.VCFType = Filter::vcf_type_2p_highpass;
97     break;
98     case ::sfz::HPF_4P:
99     ri.VCFType = Filter::vcf_type_4p_highpass;
100     break;
101     case ::sfz::HPF_6P:
102     ri.VCFType = Filter::vcf_type_6p_highpass;
103     break;
104     case ::sfz::BPF_1P:
105     case ::sfz::BPF_2P:
106     ri.VCFType = Filter::vcf_type_2p_bandpass;
107     break;
108     case ::sfz::BRF_1P:
109     case ::sfz::BRF_2P:
110     ri.VCFType = Filter::vcf_type_2p_bandreject;
111     break;
112     case ::sfz::APF_1P:
113     case ::sfz::PKF_2P:
114     default:
115     ri.VCFEnabled = false;
116     break;
117     }
118 iliev 2012
119 persson 2175 ri.VCFResonance = pRegion->resonance;
120    
121 persson 2061 // rt_decay is in dB. Precalculate a suitable value for exp in
122     // GetReleaseTriggerAttenuation: -ln(10) / 20 * rt_decay
123 persson 2072 ri.ReleaseTriggerDecay = -LN_10_DIV_20 * pRegion->rt_decay;
124 iliev 2012
125 iliev 2015 return ri;
126     }
127 iliev 2012
128 iliev 2015 Voice::InstrumentInfo Voice::GetInstrumentInfo() {
129     InstrumentInfo ii;
130     ii.FineTune = 0; // TODO:
131     ii.PitchbendRange = 2; // TODO:
132    
133     return ii;
134     }
135    
136     double Voice::GetSampleAttenuation() {
137 persson 2403 return exp(LN_10_DIV_20 * pRegion->volume) * pRegion->amplitude / 100;
138 iliev 2015 }
139    
140     double Voice::GetVelocityAttenuation(uint8_t MIDIKeyVelocity) {
141 persson 2315 float offset = -pRegion->amp_veltrack;
142     if (offset <= 0) offset += 100;
143     return (offset + pRegion->amp_veltrack * pRegion->amp_velcurve[MIDIKeyVelocity]) / 100;
144 iliev 2015 }
145    
146     double Voice::GetVelocityRelease(uint8_t MIDIKeyVelocity) {
147 persson 2176 return 127.0 / MIDIKeyVelocity;
148 iliev 2015 }
149    
150     void Voice::ProcessCCEvent(RTList<Event>::Iterator& itEvent) {
151     /*if (itEvent->Type == Event::type_control_change && itEvent->Param.CC.Controller) { // if (valid) MIDI control change event
152     if (pRegion->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
153     itEvent->Param.CC.Controller == pRegion->AttenuationController.controller_number) {
154     CrossfadeSmoother.update(AbstractEngine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);
155     }
156     }*/ // TODO: ^^^
157     }
158    
159 schoenebeck 2559 void Voice::ProcessChannelPressureEvent(RTList<Event>::Iterator& itEvent) {
160     //TODO: ...
161     }
162    
163     void Voice::ProcessPolyphonicKeyPressureEvent(RTList<Event>::Iterator& itEvent) {
164     //TODO: ...
165     }
166    
167 iliev 2015 double Voice::CalculateCrossfadeVolume(uint8_t MIDIKeyVelocity) {
168 iliev 2012 /*float crossfadeVolume;
169     switch (pRegion->AttenuationController.type) {
170     case ::gig::attenuation_ctrl_t::type_channelaftertouch:
171 iliev 2015 crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(GetSfzEngineChannel()->ControllerTable[128])];
172 iliev 2012 break;
173     case ::gig::attenuation_ctrl_t::type_velocity:
174 iliev 2015 crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(MIDIKeyVelocity)];
175 iliev 2012 break;
176     case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
177 iliev 2015 crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(GetSfzEngineChannel()->ControllerTable[pRegion->AttenuationController.controller_number])];
178 iliev 2012 break;
179     case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
180     default:
181     crossfadeVolume = 1.0f;
182     }
183    
184 iliev 2015 return crossfadeVolume;*/ // TODO: ^^^
185     return 1.0f;
186     }
187 iliev 2012
188 iliev 2015 double Voice::GetEG1ControllerValue(uint8_t MIDIKeyVelocity) {
189     /*double eg1controllervalue = 0;
190     switch (pRegion->EG1Controller.type) {
191     case ::gig::eg1_ctrl_t::type_none: // no controller defined
192     eg1controllervalue = 0;
193     break;
194     case ::gig::eg1_ctrl_t::type_channelaftertouch:
195     eg1controllervalue = GetSfzEngineChannel()->ControllerTable[128];
196     break;
197     case ::gig::eg1_ctrl_t::type_velocity:
198     eg1controllervalue = MIDIKeyVelocity;
199     break;
200     case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
201     eg1controllervalue = GetSfzEngineChannel()->ControllerTable[pRegion->EG1Controller.controller_number];
202     break;
203 iliev 2012 }
204 iliev 2015 if (pRegion->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
205 iliev 2012
206 iliev 2015 return eg1controllervalue;*/ // TODO: ^^^
207     return 0;
208     }
209 iliev 2012
210 iliev 2015 Voice::EGInfo Voice::CalculateEG1ControllerInfluence(double eg1ControllerValue) {
211     /*EGInfo eg;
212     // (eg1attack is different from the others)
213     eg.Attack = (pRegion->EG1ControllerAttackInfluence) ?
214     1 + 0.031 * (double) (pRegion->EG1ControllerAttackInfluence == 1 ?
215     1 : 1 << pRegion->EG1ControllerAttackInfluence) * eg1ControllerValue : 1.0;
216     eg.Decay = (pRegion->EG1ControllerDecayInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG1ControllerDecayInfluence) * eg1ControllerValue : 1.0;
217     eg.Release = (pRegion->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG1ControllerReleaseInfluence) * eg1ControllerValue : 1.0;
218 iliev 2012
219 iliev 2015 return eg;*/ // TODO: ^^^
220     EGInfo eg;
221     eg.Attack = 1.0;
222     eg.Decay = 1.0;
223     eg.Release = 1.0;
224     return eg;
225     }
226 iliev 2012
227 persson 2176 double Voice::GetEG2ControllerValue(uint8_t MIDIKeyVelocity) {
228 iliev 2015 /*double eg2controllervalue = 0;
229     switch (pRegion->EG2Controller.type) {
230     case ::gig::eg2_ctrl_t::type_none: // no controller defined
231     eg2controllervalue = 0;
232     break;
233     case ::gig::eg2_ctrl_t::type_channelaftertouch:
234     eg2controllervalue = GetSfzEngineChannel()->ControllerTable[128];
235     break;
236     case ::gig::eg2_ctrl_t::type_velocity:
237     eg2controllervalue = MIDIKeyVelocity;
238     break;
239     case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
240     eg2controllervalue = GetSfzEngineChannel()->ControllerTable[pRegion->EG2Controller.controller_number];
241     break;
242 iliev 2012 }
243 iliev 2015 if (pRegion->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
244 iliev 2012
245 iliev 2015 return eg2controllervalue;*/ // TODO: ^^^
246     return 0;
247     }
248 iliev 2012
249 iliev 2015 Voice::EGInfo Voice::CalculateEG2ControllerInfluence(double eg2ControllerValue) {
250     /*EGInfo eg;
251     eg.Attack = (pRegion->EG2ControllerAttackInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerAttackInfluence) * eg2ControllerValue : 1.0;
252     eg.Decay = (pRegion->EG2ControllerDecayInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerDecayInfluence) * eg2ControllerValue : 1.0;
253     eg.Release = (pRegion->EG2ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerReleaseInfluence) * eg2ControllerValue : 1.0;
254 iliev 2012
255 iliev 2015 return eg;*/ // TODO: ^^^
256     EGInfo eg;
257     eg.Attack = 1.0;
258     eg.Decay = 1.0;
259     eg.Release = 1.0;
260     return eg;
261     }
262 iliev 2012
263 iliev 2015 float Voice::CalculateCutoffBase(uint8_t MIDIKeyVelocity) {
264 persson 2175 float cutoff = *pRegion->cutoff;
265     cutoff *= RTMath::CentsToFreqRatioUnlimited(
266     MIDIKeyVelocity / 127.0f * pRegion->fil_veltrack +
267     (MIDIKey - pRegion->fil_keycenter) * pRegion->fil_keytrack);
268     return cutoff;
269 iliev 2012 }
270    
271 iliev 2015 float Voice::CalculateFinalCutoff(float cutoffBase) {
272 iliev 2252 float cutoff = cutoffBase;
273 persson 2175 if (cutoff > 0.49 * pEngine->SampleRate) cutoff = 0.49 * pEngine->SampleRate;
274     return cutoff;
275 iliev 2012 }
276    
277 persson 2061 float Voice::GetReleaseTriggerAttenuation(float noteLength) {
278     // pow(10, -rt_decay * noteLength / 20):
279     return expf(RgnInfo.ReleaseTriggerDecay * noteLength);
280     }
281    
282 persson 2114 void Voice::ProcessGroupEvent(RTList<Event>::Iterator& itEvent) {
283     dmsg(4,("Voice %x processGroupEvents event type=%d", this, itEvent->Type));
284 persson 2115 if (itEvent->Type == Event::type_control_change ||
285     (Type & Voice::type_controller_triggered) ||
286     itEvent->Param.Note.Key != MIDIKey) {
287 persson 2114 dmsg(4,("Voice %x - kill", this));
288     if (pRegion->off_mode == ::sfz::OFF_NORMAL) {
289     // turn off the voice by entering release envelope stage
290     EnterReleaseStage();
291     } else {
292     // kill the voice fast
293 iliev 2218 SignalRack.EnterFadeOutStage();
294 persson 2114 }
295     }
296     }
297 iliev 2216
298     void Voice::SetSampleStartOffset() {
299     if (DiskVoice && RgnInfo.SampleStartOffset > pSample->MaxOffset) {
300     // The offset is applied to the RAM buffer
301     finalSynthesisParameters.dPos = 0;
302     Pos = 0;
303     } else {
304     finalSynthesisParameters.dPos = RgnInfo.SampleStartOffset; // offset where we should start playback of sample
305     Pos = RgnInfo.SampleStartOffset;
306     }
307     }
308 persson 2114
309 persson 2327 void Voice::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
310     SignalRack.CalculateFadeOutCoeff(FadeOutTime, SampleRate);
311     }
312    
313 persson 2382 int Voice::CalculatePan(uint8_t pan) {
314     // the value isn't limited to [0, 127] here, as this is done
315     // later in SignalUnit.CalculatePan
316     return pan + RgnInfo.Pan;
317     }
318    
319 iliev 2012 }} // namespace LinuxSampler::sfz

  ViewVC Help
Powered by ViewVC