/[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 2106 - (hide annotations) (download)
Sun Jul 4 12:50:51 2010 UTC (13 years, 11 months ago) by persson
File size: 8836 byte(s)
* sfz engine: optimized sample lookup
* sfz engine: fixed bug introduced in previous commit: sample lookup
  returned wrong sample

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     dmsg(4,("Engine::ContinuousController cc=%d v=%d\n", itControlChangeEvent->Param.CC.Controller, itControlChangeEvent->Param.CC.Value));
43    
44 persson 2106 EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel);
45 iliev 2012 // handle the "control triggered" MIDI rule: a control change
46     // event can trigger a new note on or note off event
47     if (pChannel->pInstrument) {
48    
49     // TODO:
50     }
51    
52     // update controller value in the engine channel's controller table
53     pChannel->ControllerTable[itControlChangeEvent->Param.CC.Controller] = itControlChangeEvent->Param.CC.Value;
54    
55     ProcessHardcodedControllers(pEngineChannel, itControlChangeEvent);
56    
57     // handle FX send controllers
58     ProcessFxSendControllers(pChannel, itControlChangeEvent);
59     }
60    
61     DiskThread* Engine::CreateDiskThread() {
62     return new DiskThread (
63     iMaxDiskStreams,
64     ((pAudioOutputDevice->MaxSamplesPerCycle() << CONFIG_MAX_PITCH) << 1) + 6, //FIXME: assuming stereo
65     &instruments
66     );
67     }
68    
69     void Engine::TriggerNewVoices (
70     LinuxSampler::EngineChannel* pEngineChannel,
71     RTList<Event>::Iterator& itNoteOnEvent,
72     bool HandleKeyGroupConflicts
73     ) {
74     EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel);
75 persson 2106 ::sfz::Query q;
76 persson 2101 q.chan = pChannel->MidiChannel();
77     q.key = itNoteOnEvent->Param.Note.Key;
78     q.vel = itNoteOnEvent->Param.Note.Velocity;
79     q.bend = pChannel->Pitch;
80     q.bpm = 0;
81     q.chanaft = pChannel->ControllerTable[128];
82     q.polyaft = 0;
83     q.prog = 0;
84     q.rand = Random();
85     q.cc = pChannel->ControllerTable;
86     q.timer = 0;
87     q.sw = pChannel->PressedKeys;
88     q.last_sw_key = pChannel->LastKeySwitch;
89     q.prev_sw_key = pChannel->LastKey;
90     q.trig = TRIGGER_ATTACK |
91     ((pChannel->LastKey != -1 &&
92     pChannel->PressedKeys[pChannel->LastKey] &&
93     pChannel->LastKey != q.key) ?
94     TRIGGER_LEGATO : TRIGGER_FIRST);
95 iliev 2012
96 persson 2106 q.search(pChannel->pInstrument);
97    
98 persson 2101 int i = 0;
99     while (::sfz::Region* region = q.next()) {
100     if (!RegionSuspended(region)) {
101     itNoteOnEvent->Param.Note.pRegion = region;
102 iliev 2012 LaunchVoice(pChannel, itNoteOnEvent, i, false, true, HandleKeyGroupConflicts);
103     }
104 persson 2101 i++;
105 iliev 2012 }
106     }
107    
108     void Engine::TriggerReleaseVoices (
109     LinuxSampler::EngineChannel* pEngineChannel,
110     RTList<Event>::Iterator& itNoteOffEvent
111     ) {
112     EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel);
113 persson 2106 ::sfz::Query q;
114 persson 2101 q.chan = pChannel->MidiChannel();
115     q.key = itNoteOffEvent->Param.Note.Key;
116 persson 2061
117     // MIDI note-on velocity is used instead of note-off velocity
118 persson 2101 q.vel = pChannel->pMIDIKeyInfo[q.key].Velocity;
119     itNoteOffEvent->Param.Note.Velocity = q.vel;
120 persson 2061
121 persson 2101 q.bend = pChannel->Pitch;
122     q.bpm = 0;
123     q.chanaft = pChannel->ControllerTable[128];
124     q.polyaft = 0;
125     q.prog = 0;
126     q.rand = Random();
127     q.cc = pChannel->ControllerTable;
128     q.timer = 0;
129     q.sw = pChannel->PressedKeys;
130     q.last_sw_key = pChannel->LastKeySwitch;
131     q.prev_sw_key = pChannel->LastKey;
132     q.trig = TRIGGER_RELEASE;
133 iliev 2012
134 persson 2106 q.search(pChannel->pInstrument);
135    
136 iliev 2012 // now launch the required amount of voices
137 persson 2101 int i = 0;
138     while (::sfz::Region* region = q.next()) {
139     itNoteOffEvent->Param.Note.pRegion = region;
140 iliev 2012 LaunchVoice(pChannel, itNoteOffEvent, i, true, false, false); //FIXME: for the moment we don't perform voice stealing for release triggered samples
141 persson 2101 i++;
142 iliev 2012 }
143     }
144    
145     Pool<Voice>::Iterator Engine::LaunchVoice (
146     LinuxSampler::EngineChannel* pEngineChannel,
147     Pool<Event>::Iterator& itNoteOnEvent,
148     int iLayer,
149     bool ReleaseTriggerVoice,
150     bool VoiceStealing,
151     bool HandleKeyGroupConflicts
152     ) {
153     EngineChannel* pChannel = static_cast<EngineChannel*>(pEngineChannel);
154     int key = itNoteOnEvent->Param.Note.Key;
155     EngineChannel::MidiKey* pKey = &pChannel->pMIDIKeyInfo[key];
156 persson 2061 Voice::type_t VoiceType = (ReleaseTriggerVoice) ? Voice::type_release_trigger : (!iLayer) ? Voice::type_release_trigger_required : Voice::type_normal;
157 iliev 2012
158     Pool<Voice>::Iterator itNewVoice;
159 persson 2101 ::sfz::Region* pRgn = static_cast< ::sfz::Region*>(itNoteOnEvent->Param.Note.pRegion);
160 iliev 2012
161     // no need to process if sample is silent
162 iliev 2027 if (!pRgn->GetSample() || !pRgn->GetSample()->GetTotalFrameCount()) return Pool<Voice>::Iterator();
163 iliev 2012
164 iliev 2027 // only mark the first voice of a layered voice (group) to be in a
165     // key group, so the layered voices won't kill each other
166     int iKeyGroup = (iLayer == 0 && !ReleaseTriggerVoice) ? pRgn->group : 0;
167 persson 2063 if (HandleKeyGroupConflicts) pChannel->HandleKeyGroupConflicts(iKeyGroup, itNoteOnEvent, pRgn->off_mode == ::sfz::OFF_NORMAL);
168 iliev 2027
169 iliev 2012 // allocate a new voice for the key
170     itNewVoice = pKey->pActiveVoices->allocAppend();
171 iliev 2027 int res = InitNewVoice (
172     pChannel, pRgn, itNoteOnEvent, VoiceType, iLayer,
173     iKeyGroup, ReleaseTriggerVoice, VoiceStealing, itNewVoice
174     );
175     if (!res) return itNewVoice;
176 iliev 2012
177     // return if this is a release triggered voice and there is no
178     // releasetrigger dimension (could happen if an instrument
179     // change has occured between note on and off)
180     //if (ReleaseTriggerVoice && VoiceType != Voice::type_release_trigger) return Pool<Voice>::Iterator();
181    
182 iliev 2027 return Pool<Voice>::Iterator(); // no free voice or error
183 iliev 2012 }
184    
185     bool Engine::DiskStreamSupported() {
186     return true;
187     }
188    
189     String Engine::Description() {
190     return "SFZ Format Engine";
191     }
192    
193     String Engine::Version() {
194 persson 2106 String s = "$Revision: 1.9 $";
195 iliev 2012 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
196     }
197    
198     }} // namespace LinuxSampler::sfz

  ViewVC Help
Powered by ViewVC