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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2115 - (hide annotations) (download)
Thu Aug 12 15:36:15 2010 UTC (13 years, 8 months ago) by persson
File size: 9950 byte(s)
* sfz engine: added support for controller triggered regions
  (on_locc/on_hicc)
* sfz engine: added support for loop_mode=one_shot

1 iliev 2012 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck *
6     * Copyright (C) 2005-2009 Christian Schoenebeck *
7 persson 2072 * Copyright (C) 2009-2010 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     #include "Engine.h"
26     #include "EngineChannel.h"
27    
28     namespace LinuxSampler { namespace sfz {
29     Engine::Format Engine::GetEngineFormat() { return SFZ; }
30    
31     /**
32     * Reacts on supported control change commands (e.g. pitch bend wheel,
33     * modulation wheel, aftertouch).
34     *
35     * @param pEngineChannel - engine channel on which this event occured on
36     * @param itControlChangeEvent - controller, value and time stamp of the event
37     */
38     void Engine::ProcessControlChange (
39     LinuxSampler::EngineChannel* pEngineChannel,
40     Pool<Event>::Iterator& itControlChangeEvent
41     ) {
42 persson 2115 uint8_t cc = itControlChangeEvent->Param.CC.Controller;
43     dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", cc, itControlChangeEvent->Param.CC.Value));
44 iliev 2012
45 persson 2106 EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel);
46 iliev 2012
47     // update controller value in the engine channel's controller table
48 persson 2115 pChannel->ControllerTable[cc] = itControlChangeEvent->Param.CC.Value;
49 iliev 2012
50     ProcessHardcodedControllers(pEngineChannel, itControlChangeEvent);
51    
52     // handle FX send controllers
53     ProcessFxSendControllers(pChannel, itControlChangeEvent);
54 persson 2115
55     // handle control triggered regions: a control change event
56     // can trigger a new voice
57     if (pChannel->pInstrument && cc < 128) {
58    
59     ::sfz::Query q;
60     q.chan = pChannel->MidiChannel();
61     q.key = 60;
62     q.vel = 127;
63     q.bend = pChannel->Pitch;
64     q.bpm = 0;
65     q.chanaft = pChannel->ControllerTable[128];
66     q.polyaft = 0;
67     q.prog = 0;
68     q.rand = Random();
69     q.cc = pChannel->ControllerTable;
70     q.timer = 0;
71     q.sw = pChannel->PressedKeys;
72     q.last_sw_key = pChannel->LastKeySwitch;
73     q.prev_sw_key = pChannel->LastKey;
74     q.trig = TRIGGER_ATTACK | TRIGGER_FIRST;
75    
76     q.search(pChannel->pInstrument, cc);
77    
78     int i = 0;
79     while (::sfz::Region* region = q.next()) {
80     if (!RegionSuspended(region)) {
81     itControlChangeEvent->Param.Note.Key = 60;
82     itControlChangeEvent->Param.Note.Velocity = 127;
83     itControlChangeEvent->Param.Note.pRegion = region;
84     LaunchVoice(pChannel, itControlChangeEvent, i, false, false, true);
85     }
86     i++;
87     }
88     }
89 iliev 2012 }
90    
91     DiskThread* Engine::CreateDiskThread() {
92     return new DiskThread (
93     iMaxDiskStreams,
94     ((pAudioOutputDevice->MaxSamplesPerCycle() << CONFIG_MAX_PITCH) << 1) + 6, //FIXME: assuming stereo
95     &instruments
96     );
97     }
98    
99     void Engine::TriggerNewVoices (
100     LinuxSampler::EngineChannel* pEngineChannel,
101     RTList<Event>::Iterator& itNoteOnEvent,
102     bool HandleKeyGroupConflicts
103     ) {
104     EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel);
105 persson 2106 ::sfz::Query q;
106 persson 2101 q.chan = pChannel->MidiChannel();
107     q.key = itNoteOnEvent->Param.Note.Key;
108     q.vel = itNoteOnEvent->Param.Note.Velocity;
109     q.bend = pChannel->Pitch;
110     q.bpm = 0;
111     q.chanaft = pChannel->ControllerTable[128];
112     q.polyaft = 0;
113     q.prog = 0;
114     q.rand = Random();
115     q.cc = pChannel->ControllerTable;
116     q.timer = 0;
117     q.sw = pChannel->PressedKeys;
118     q.last_sw_key = pChannel->LastKeySwitch;
119     q.prev_sw_key = pChannel->LastKey;
120     q.trig = TRIGGER_ATTACK |
121     ((pChannel->LastKey != -1 &&
122     pChannel->PressedKeys[pChannel->LastKey] &&
123     pChannel->LastKey != q.key) ?
124     TRIGGER_LEGATO : TRIGGER_FIRST);
125 iliev 2012
126 persson 2106 q.search(pChannel->pInstrument);
127    
128 persson 2101 int i = 0;
129     while (::sfz::Region* region = q.next()) {
130     if (!RegionSuspended(region)) {
131     itNoteOnEvent->Param.Note.pRegion = region;
132 iliev 2012 LaunchVoice(pChannel, itNoteOnEvent, i, false, true, HandleKeyGroupConflicts);
133     }
134 persson 2101 i++;
135 iliev 2012 }
136     }
137    
138     void Engine::TriggerReleaseVoices (
139     LinuxSampler::EngineChannel* pEngineChannel,
140     RTList<Event>::Iterator& itNoteOffEvent
141     ) {
142     EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel);
143 persson 2106 ::sfz::Query q;
144 persson 2101 q.chan = pChannel->MidiChannel();
145     q.key = itNoteOffEvent->Param.Note.Key;
146 persson 2061
147     // MIDI note-on velocity is used instead of note-off velocity
148 persson 2101 q.vel = pChannel->pMIDIKeyInfo[q.key].Velocity;
149     itNoteOffEvent->Param.Note.Velocity = q.vel;
150 persson 2061
151 persson 2101 q.bend = pChannel->Pitch;
152     q.bpm = 0;
153     q.chanaft = pChannel->ControllerTable[128];
154     q.polyaft = 0;
155     q.prog = 0;
156     q.rand = Random();
157     q.cc = pChannel->ControllerTable;
158     q.timer = 0;
159     q.sw = pChannel->PressedKeys;
160     q.last_sw_key = pChannel->LastKeySwitch;
161     q.prev_sw_key = pChannel->LastKey;
162     q.trig = TRIGGER_RELEASE;
163 iliev 2012
164 persson 2106 q.search(pChannel->pInstrument);
165    
166 iliev 2012 // now launch the required amount of voices
167 persson 2101 int i = 0;
168     while (::sfz::Region* region = q.next()) {
169     itNoteOffEvent->Param.Note.pRegion = region;
170 persson 2114 LaunchVoice(pChannel, itNoteOffEvent, i, true, false, true); //FIXME: for the moment we don't perform voice stealing for release triggered samples
171 persson 2101 i++;
172 iliev 2012 }
173     }
174    
175     Pool<Voice>::Iterator Engine::LaunchVoice (
176     LinuxSampler::EngineChannel* pEngineChannel,
177     Pool<Event>::Iterator& itNoteOnEvent,
178     int iLayer,
179     bool ReleaseTriggerVoice,
180     bool VoiceStealing,
181     bool HandleKeyGroupConflicts
182     ) {
183     EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel);
184     int key = itNoteOnEvent->Param.Note.Key;
185     EngineChannel::MidiKey* pKey = &pChannel->pMIDIKeyInfo[key];
186 persson 2115 ::sfz::Region* pRgn = static_cast< ::sfz::Region*>(itNoteOnEvent->Param.Note.pRegion);
187 iliev 2012
188 persson 2115 Voice::type_t VoiceType =
189     itNoteOnEvent->Type == Event::type_control_change ? Voice::type_controller_triggered :
190     ReleaseTriggerVoice ? Voice::type_release_trigger :
191     iLayer == 0 ? Voice::type_release_trigger_required :
192     Voice::type_normal;
193     if (pRgn->loop_mode == ::sfz::ONE_SHOT) VoiceType |= Voice::type_one_shot;
194    
195 iliev 2012 Pool<Voice>::Iterator itNewVoice;
196    
197     // no need to process if sample is silent
198 iliev 2027 if (!pRgn->GetSample() || !pRgn->GetSample()->GetTotalFrameCount()) return Pool<Voice>::Iterator();
199 iliev 2012
200 persson 2114 if (HandleKeyGroupConflicts) pChannel->HandleKeyGroupConflicts(pRgn->group, itNoteOnEvent);
201 iliev 2027
202 iliev 2012 // allocate a new voice for the key
203     itNewVoice = pKey->pActiveVoices->allocAppend();
204 iliev 2027 int res = InitNewVoice (
205     pChannel, pRgn, itNoteOnEvent, VoiceType, iLayer,
206 persson 2114 pRgn->off_by, ReleaseTriggerVoice, VoiceStealing, itNewVoice
207 iliev 2027 );
208     if (!res) return itNewVoice;
209 iliev 2012
210     // return if this is a release triggered voice and there is no
211     // releasetrigger dimension (could happen if an instrument
212     // change has occured between note on and off)
213     //if (ReleaseTriggerVoice && VoiceType != Voice::type_release_trigger) return Pool<Voice>::Iterator();
214    
215 iliev 2027 return Pool<Voice>::Iterator(); // no free voice or error
216 iliev 2012 }
217    
218     bool Engine::DiskStreamSupported() {
219     return true;
220     }
221    
222     String Engine::Description() {
223     return "SFZ Format Engine";
224     }
225    
226     String Engine::Version() {
227 persson 2115 String s = "$Revision: 1.11 $";
228 iliev 2012 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
229     }
230    
231     }} // namespace LinuxSampler::sfz

  ViewVC Help
Powered by ViewVC