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

Contents of /linuxsampler/trunk/src/engines/sf2/Voice.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2559 - (show annotations) (download)
Sun May 18 17:38:25 2014 UTC (9 years, 11 months ago) by schoenebeck
File size: 14535 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 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2008 Christian Schoenebeck *
7 * Copyright (C) 2009 - 2012 Christian Schoenebeck and Grigor Iliev *
8 * *
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 #include "Voice.h"
26
27 #include "Engine.h"
28 #include "EngineChannel.h"
29
30 namespace LinuxSampler { namespace sf2 {
31
32 typedef LinuxSampler::VoiceBase<EngineChannel, ::sf2::Region, ::sf2::Sample, DiskThread> SF2Voice;
33 Voice::Voice(): SignalRack(this), SF2Voice(&SignalRack) {
34 pEngine = NULL;
35 pEG1 = NULL;
36 pEG2 = NULL;
37 }
38
39 Voice::~Voice() {
40
41 }
42
43 void Voice::AboutToTrigger() {
44
45 }
46
47 EngineChannel* Voice::GetSf2EngineChannel() {
48 return static_cast<EngineChannel*>(pEngineChannel);
49 }
50
51 void Voice::SetEngine(LinuxSampler::Engine* pEngine) {
52 Engine* engine = static_cast<Engine*>(pEngine);
53 this->pEngine = engine;
54 this->pDiskThread = engine->pDiskThread;
55 dmsg(6,("Voice::SetEngine()\n"));
56 }
57
58 Voice::SampleInfo Voice::GetSampleInfo() {
59 SampleInfo si;
60 si.SampleRate = pSample->SampleRate;
61 si.ChannelCount = pSample->GetChannelCount();
62 si.FrameSize = pSample->GetFrameSize();
63 si.BitDepth = (pSample->GetFrameSize() / pSample->GetChannelCount()) * 8;
64 si.TotalFrameCount = pSample->GetTotalFrameCount();
65
66 si.HasLoops = pRegion->HasLoop;
67 si.LoopStart = (si.HasLoops) ? pRegion->LoopStart : 0;
68 si.LoopLength = (si.HasLoops) ? ((pRegion->LoopEnd) - pRegion->LoopStart): 0;
69 si.LoopPlayCount = 0; // TODO:
70 si.Unpitched = pSample->IsUnpitched();
71
72 return si;
73 }
74
75 Voice::RegionInfo Voice::GetRegionInfo() {
76 ::sf2::Region* reg = NULL;
77 ::sf2::Preset* preset = GetSf2EngineChannel()->pInstrument;
78 for (int i = 0; i < preset->GetRegionCount(); i++) { // TODO: some optimization?
79 if (preset->GetRegion(i)->pInstrument == pRegion->GetParentInstrument()) {
80 reg = preset->GetRegion(i); // TODO: Can the instrument belong to more than one preset region?
81 break;
82 }
83 }
84 pPresetRegion = reg;
85
86 RegionInfo ri;
87 ri.UnityNote = pRegion->GetUnityNote();
88 ri.FineTune = pRegion->GetFineTune(reg) + (pRegion->GetCoarseTune(reg) * 100);
89 ri.Pan = pRegion->GetPan(reg);
90 ri.SampleStartOffset = pRegion->startAddrsOffset + pRegion->startAddrsCoarseOffset;
91
92 // sample pitch
93 ri.VCFEnabled = true; // TODO:
94 ri.VCFType = Filter::vcf_type_2p_lowpass; // TODO:
95 ri.VCFResonance = 0; // TODO:
96
97 ri.ReleaseTriggerDecay = 0; // TODO:
98
99 return ri;
100 }
101
102 Voice::InstrumentInfo Voice::GetInstrumentInfo() {
103 InstrumentInfo ii;
104 ii.FineTune = 0; // TODO:
105 ii.PitchbendRange = 2; // TODO:
106
107 return ii;
108 }
109
110 double Voice::GetSampleAttenuation() {
111 return 1.0; // TODO:
112 }
113
114 double Voice::GetVelocityAttenuation(uint8_t MIDIKeyVelocity) {
115 return double(MIDIKeyVelocity) / 127.0f; // TODO:
116 }
117
118 double Voice::GetVelocityRelease(uint8_t MIDIKeyVelocity) {
119 return 0.9; // TODO:
120 }
121
122 void Voice::ProcessCCEvent(RTList<Event>::Iterator& itEvent) {
123 /*if (itEvent->Type == Event::type_control_change && itEvent->Param.CC.Controller) { // if (valid) MIDI control change event
124 if (pRegion->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
125 itEvent->Param.CC.Controller == pRegion->AttenuationController.controller_number) {
126 CrossfadeSmoother.update(AbstractEngine::CrossfadeCurve[CrossfadeAttenuation(itEvent->Param.CC.Value)]);
127 }
128 }*/ // TODO: ^^^
129 }
130
131 void Voice::ProcessChannelPressureEvent(RTList<Event>::Iterator& itEvent) {
132 //TODO: ...
133 }
134
135 void Voice::ProcessPolyphonicKeyPressureEvent(RTList<Event>::Iterator& itEvent) {
136 //TODO: ...
137 }
138
139 void Voice::ProcessCutoffEvent(RTList<Event>::Iterator& itEvent) {
140 /*int ccvalue = itEvent->Param.CC.Value;
141 if (VCFCutoffCtrl.value == ccvalue) return;
142 VCFCutoffCtrl.value == ccvalue;
143 if (pRegion->VCFCutoffControllerInvert) ccvalue = 127 - ccvalue;
144 if (ccvalue < pRegion->VCFVelocityScale) ccvalue = pRegion->VCFVelocityScale;
145 float cutoff = CutoffBase * float(ccvalue);
146 if (cutoff > 127.0f) cutoff = 127.0f;
147
148 VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time
149 fFinalCutoff = cutoff;*/ // TODO: ^^^
150 }
151
152 double Voice::CalculateCrossfadeVolume(uint8_t MIDIKeyVelocity) {
153 /*float crossfadeVolume;
154 switch (pRegion->AttenuationController.type) {
155 case ::gig::attenuation_ctrl_t::type_channelaftertouch:
156 crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(GetSf2EngineChannel()->ControllerTable[128])];
157 break;
158 case ::gig::attenuation_ctrl_t::type_velocity:
159 crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(MIDIKeyVelocity)];
160 break;
161 case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
162 crossfadeVolume = Engine::CrossfadeCurve[CrossfadeAttenuation(GetSf2EngineChannel()->ControllerTable[pRegion->AttenuationController.controller_number])];
163 break;
164 case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
165 default:
166 crossfadeVolume = 1.0f;
167 }
168
169 return crossfadeVolume;*/ // TODO: ^^^
170 return 1.0f;
171 }
172
173 double Voice::GetEG1ControllerValue(uint8_t MIDIKeyVelocity) {
174 /*double eg1controllervalue = 0;
175 switch (pRegion->EG1Controller.type) {
176 case ::gig::eg1_ctrl_t::type_none: // no controller defined
177 eg1controllervalue = 0;
178 break;
179 case ::gig::eg1_ctrl_t::type_channelaftertouch:
180 eg1controllervalue = GetSf2EngineChannel()->ControllerTable[128];
181 break;
182 case ::gig::eg1_ctrl_t::type_velocity:
183 eg1controllervalue = MIDIKeyVelocity;
184 break;
185 case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
186 eg1controllervalue = GetSf2EngineChannel()->ControllerTable[pRegion->EG1Controller.controller_number];
187 break;
188 }
189 if (pRegion->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
190
191 return eg1controllervalue;*/ // TODO: ^^^
192 return 0;
193 }
194
195 Voice::EGInfo Voice::CalculateEG1ControllerInfluence(double eg1ControllerValue) {
196 /*EGInfo eg;
197 // (eg1attack is different from the others)
198 eg.Attack = (pRegion->EG1ControllerAttackInfluence) ?
199 1 + 0.031 * (double) (pRegion->EG1ControllerAttackInfluence == 1 ?
200 1 : 1 << pRegion->EG1ControllerAttackInfluence) * eg1ControllerValue : 1.0;
201 eg.Decay = (pRegion->EG1ControllerDecayInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG1ControllerDecayInfluence) * eg1ControllerValue : 1.0;
202 eg.Release = (pRegion->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG1ControllerReleaseInfluence) * eg1ControllerValue : 1.0;
203
204 return eg;*/ // TODO: ^^^
205 EGInfo eg;
206 eg.Attack = 1.0;
207 eg.Decay = 1.0;
208 eg.Release = 1.0;
209 return eg;
210 }
211
212 double Voice::GetEG2ControllerValue(uint8_t MIDIKeyVelocity) {
213 /*double eg2controllervalue = 0;
214 switch (pRegion->EG2Controller.type) {
215 case ::gig::eg2_ctrl_t::type_none: // no controller defined
216 eg2controllervalue = 0;
217 break;
218 case ::gig::eg2_ctrl_t::type_channelaftertouch:
219 eg2controllervalue = GetSf2EngineChannel()->ControllerTable[128];
220 break;
221 case ::gig::eg2_ctrl_t::type_velocity:
222 eg2controllervalue = MIDIKeyVelocity;
223 break;
224 case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
225 eg2controllervalue = GetSf2EngineChannel()->ControllerTable[pRegion->EG2Controller.controller_number];
226 break;
227 }
228 if (pRegion->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
229
230 return eg2controllervalue;*/ // TODO: ^^^
231 return 0;
232 }
233
234 Voice::EGInfo Voice::CalculateEG2ControllerInfluence(double eg2ControllerValue) {
235 /*EGInfo eg;
236 eg.Attack = (pRegion->EG2ControllerAttackInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerAttackInfluence) * eg2ControllerValue : 1.0;
237 eg.Decay = (pRegion->EG2ControllerDecayInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerDecayInfluence) * eg2ControllerValue : 1.0;
238 eg.Release = (pRegion->EG2ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pRegion->EG2ControllerReleaseInfluence) * eg2ControllerValue : 1.0;
239
240 return eg;*/ // TODO: ^^^
241 EGInfo eg;
242 eg.Attack = 1.0;
243 eg.Decay = 1.0;
244 eg.Release = 1.0;
245 return eg;
246 }
247
248 float Voice::CalculateCutoffBase(uint8_t MIDIKeyVelocity) {
249 float cutoff = pRegion->GetInitialFilterFc(pPresetRegion);
250 if (MIDIKeyVelocity == 0) return cutoff;
251
252 cutoff *= RTMath::CentsToFreqRatioUnlimited (
253 ((127 - MIDIKeyVelocity) / 127.0) * -2400 // 8.4.2 MIDI Note-On Velocity to Filter Cutoff
254 );
255
256 return cutoff;
257 }
258
259 float Voice::CalculateFinalCutoff(float cutoffBase) {
260 /*int cvalue;
261 if (VCFCutoffCtrl.controller) {
262 cvalue = GetSf2EngineChannel()->ControllerTable[VCFCutoffCtrl.controller];
263 if (pRegion->VCFCutoffControllerInvert) cvalue = 127 - cvalue;
264 // VCFVelocityScale in this case means Minimum cutoff
265 if (cvalue < pRegion->VCFVelocityScale) cvalue = pRegion->VCFVelocityScale;
266 }
267 else {
268 cvalue = pRegion->VCFCutoff;
269 }
270 float fco = cutoffBase * float(cvalue);
271 if (fco > 127.0f) fco = 127.0f;
272
273 return fco;*/ // TODO: ^^^
274 return cutoffBase;
275 }
276
277 uint8_t Voice::GetVCFCutoffCtrl() {
278 /*uint8_t ctrl;
279 switch (pRegion->VCFCutoffController) {
280 case ::gig::vcf_cutoff_ctrl_modwheel:
281 ctrl = 1;
282 break;
283 case ::gig::vcf_cutoff_ctrl_effect1:
284 ctrl = 12;
285 break;
286 case ::gig::vcf_cutoff_ctrl_effect2:
287 ctrl = 13;
288 break;
289 case ::gig::vcf_cutoff_ctrl_breath:
290 ctrl = 2;
291 break;
292 case ::gig::vcf_cutoff_ctrl_foot:
293 ctrl = 4;
294 break;
295 case ::gig::vcf_cutoff_ctrl_sustainpedal:
296 ctrl = 64;
297 break;
298 case ::gig::vcf_cutoff_ctrl_softpedal:
299 ctrl = 67;
300 break;
301 case ::gig::vcf_cutoff_ctrl_genpurpose7:
302 ctrl = 82;
303 break;
304 case ::gig::vcf_cutoff_ctrl_genpurpose8:
305 ctrl = 83;
306 break;
307 case ::gig::vcf_cutoff_ctrl_aftertouch:
308 ctrl = 128;
309 break;
310 case ::gig::vcf_cutoff_ctrl_none:
311 default:
312 ctrl = 0;
313 break;
314 }
315
316 return ctrl;*/ // TODO: ^^^
317 return 0;
318 }
319
320 uint8_t Voice::GetVCFResonanceCtrl() {
321 /*uint8_t ctrl;
322 switch (pRegion->VCFResonanceController) {
323 case ::gig::vcf_res_ctrl_genpurpose3:
324 ctrl = 18;
325 break;
326 case ::gig::vcf_res_ctrl_genpurpose4:
327 ctrl = 19;
328 break;
329 case ::gig::vcf_res_ctrl_genpurpose5:
330 ctrl = 80;
331 break;
332 case ::gig::vcf_res_ctrl_genpurpose6:
333 ctrl = 81;
334 break;
335 case ::gig::vcf_res_ctrl_none:
336 default:
337 ctrl = 0;
338 }
339
340 return ctrl;*/ // TODO: ^^^
341 return 0;
342 }
343
344 void Voice::ProcessGroupEvent(RTList<Event>::Iterator& itEvent) {
345 if (itEvent->Param.Note.Key != MIDIKey) {
346 // kill the voice fast
347 SignalRack.EnterFadeOutStage();
348 }
349 }
350
351 void Voice::CalculateFadeOutCoeff(float FadeOutTime, float SampleRate) {
352 SignalRack.CalculateFadeOutCoeff(FadeOutTime, SampleRate);
353 }
354
355 int Voice::CalculatePan(uint8_t pan) {
356 int p = pan + RgnInfo.Pan;
357
358 if (p < 0) return 0;
359 if (p > 127) return 127;
360 return p;
361 }
362
363 }} // namespace LinuxSampler::sf2

  ViewVC Help
Powered by ViewVC