/[svn]/linuxsampler/trunk/src/engines/common/Event.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/engines/common/Event.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3283 - (hide annotations) (download)
Wed Jun 21 20:59:06 2017 UTC (6 years, 10 months ago) by schoenebeck
File size: 9067 byte(s)
* RT Instrument Scripts: Fixed potential memory access bug
  and potential undefined behavior of "init" event handlers.
* Bumped version (2.0.0.svn62).

1 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 2871 * Copyright (C) 2005 - 2016 Christian Schoenebeck *
7 schoenebeck 53 * *
8     * This program is free software; you can redistribute it and/or modify *
9     * it under the terms of the GNU General Public License as published by *
10     * the Free Software Foundation; either version 2 of the License, or *
11     * (at your option) any later version. *
12     * *
13     * This program is distributed in the hope that it will be useful, *
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16     * GNU General Public License for more details. *
17     * *
18     * You should have received a copy of the GNU General Public License *
19     * along with this program; if not, write to the Free Software *
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21     * MA 02111-1307 USA *
22     ***************************************************************************/
23    
24     #include "Event.h"
25    
26     namespace LinuxSampler {
27    
28     /**
29     * Create an EventGenerator.
30     *
31     * @param SampleRate - sample rate of the sampler engine's audio output
32     * signal (in Hz)
33     */
34     EventGenerator::EventGenerator(uint SampleRate) {
35     uiSampleRate = SampleRate;
36     uiSamplesProcessed = 0;
37 schoenebeck 328 FragmentTime.end = RTMath::CreateTimeStamp();
38 schoenebeck 2871 uiTotalSamplesProcessed = 0;
39 schoenebeck 53 }
40    
41 schoenebeck 3283 void EventGenerator::SetSampleRate(uint SampleRate) {
42     uiSampleRate = SampleRate;
43     }
44    
45 schoenebeck 53 /**
46     * Updates the time stamps for the beginning and end of the current audio
47     * fragment. This is needed to be able to calculate the respective sample
48     * point later to which an event belongs to.
49     *
50     * @param SamplesToProcess - number of sample points to process in this
51     * audio fragment cycle
52     */
53     void EventGenerator::UpdateFragmentTime(uint SamplesToProcess) {
54 schoenebeck 2871 // update total amount of sample points being processed since this object was created
55     uiTotalSamplesProcessed += uiSamplesProcessed;
56 schoenebeck 53 // update time stamp for this audio fragment cycle
57     FragmentTime.begin = FragmentTime.end;
58 schoenebeck 328 FragmentTime.end = RTMath::CreateTimeStamp();
59 schoenebeck 53 // recalculate sample ratio for this audio fragment
60     time_stamp_t fragmentDuration = FragmentTime.end - FragmentTime.begin;
61     FragmentTime.sample_ratio = (float) uiSamplesProcessed / (float) fragmentDuration;
62     // store amount of samples to process for the next cycle
63     uiSamplesProcessed = SamplesToProcess;
64     }
65 schoenebeck 2871
66     /**
67     * Get the next scheduled MIDI event (the one with the lowest time value)
68     * for the current audio fragment cycle and remove it from the queue. This
69     * method will not return any event scheduled past the current audio
70     * fragment boundary.
71     *
72     * @param queue - where the MIDI events are scheduled on
73     * @param pool - used to allocate and deallocate ScheduledEvent objects
74     * @param end - you @b MUST always pass EventGenerator::schedTimeAtCurrentFragmentEnd()
75     * here reflecting the current audio fragment's scheduler end time
76     */
77     RTList<ScheduledEvent>::Iterator EventGenerator::popNextScheduledEvent(RTAVLTree<ScheduledEvent>& queue, Pool<ScheduledEvent>& pool, sched_time_t end) {
78     if (queue.isEmpty())
79     return RTList<ScheduledEvent>::Iterator(); // return invalid iterator
80     ScheduledEvent& e = queue.lowest();
81     if (e.scheduleTime >= end)
82     return RTList<ScheduledEvent>::Iterator(); // no event scheduled before 'end'
83     RTList<ScheduledEvent>::Iterator itEvent = pool.fromPtr(&e);
84     queue.erase(e);
85     if (!itEvent || !itEvent->itEvent) {
86     dmsg(1,("EventGenerator::popNextScheduledEvent(): !itEvent\n"));
87     return itEvent; // should never happen at this point, but just to be sure
88     }
89     if (!itEvent->itEvent) {
90     dmsg(1,("EventGenerator::popNextScheduledEvent(): !itEvent->itEvent\n"));
91     return itEvent; // should never happen at this point, but just to be sure
92     }
93 schoenebeck 53
94 schoenebeck 2871 // update position of this event in the current audio fragment
95     // (since calling scheduleAheadMicroSec() will relate to this)
96 schoenebeck 3054 itEvent->itEvent->iFragmentPos = int32_t( uiSamplesProcessed - (end - itEvent->scheduleTime) );
97 schoenebeck 2871 // safety first: fragment boundary sanity checks
98     if (itEvent->itEvent->iFragmentPos < 0)
99     itEvent->itEvent->iFragmentPos = 0;
100     if (itEvent->itEvent->iFragmentPos >= uiSamplesProcessed)
101     itEvent->itEvent->iFragmentPos = uiSamplesProcessed - 1;
102    
103     return itEvent;
104     }
105    
106 schoenebeck 53 /**
107 schoenebeck 2871 * Get the next instrument script event (the one with the lowest time value)
108     * for the current audio fragment cycle and remove it from the queue. This
109     * method will not return any event scheduled past the current audio
110     * fragment boundary.
111     *
112     * @param queue - where the instrument script events are scheduled on
113     * @param pool - used to allocate and deallocate ScriptEvent objects
114     * @param end - you @b MUST always pass EventGenerator::schedTimeAtCurrentFragmentEnd()
115     * here reflecting the current audio fragment's scheduler end time
116     */
117     RTList<ScriptEvent>::Iterator EventGenerator::popNextScheduledScriptEvent(RTAVLTree<ScriptEvent>& queue, Pool<ScriptEvent>& pool, sched_time_t end) {
118     if (queue.isEmpty())
119     return RTList<ScriptEvent>::Iterator(); // return invalid iterator
120     ScriptEvent& e = queue.lowest();
121     if (e.scheduleTime >= end)
122     return RTList<ScriptEvent>::Iterator(); // no event scheduled before 'end'
123     RTList<ScriptEvent>::Iterator itEvent = pool.fromPtr(&e);
124     queue.erase(e);
125     if (!itEvent) { // should never happen at this point, but just to be sure
126     dmsg(1,("EventGenerator::popNextScheduledScriptEvent(): !itEvent\n"));
127     return itEvent;
128     }
129    
130     // update position of this event in the current audio fragment
131     // (since calling scheduleAheadMicroSec() will relate to this)
132 schoenebeck 3054 itEvent->cause.iFragmentPos = int32_t( uiSamplesProcessed - (end - itEvent->scheduleTime) );
133 schoenebeck 2871 // safety first: fragment boundary sanity checks
134     if (itEvent->cause.iFragmentPos < 0)
135     itEvent->cause.iFragmentPos = 0;
136     if (itEvent->cause.iFragmentPos >= uiSamplesProcessed)
137     itEvent->cause.iFragmentPos = uiSamplesProcessed - 1;
138    
139     return itEvent;
140     }
141    
142     /**
143 schoenebeck 53 * Create a new event with the current time as time stamp.
144     */
145     Event EventGenerator::CreateEvent() {
146 schoenebeck 328 return Event(this, RTMath::CreateTimeStamp());
147 schoenebeck 53 }
148    
149     /**
150 schoenebeck 906 * Create a new event for the given sample point position in the current
151     * audio fragment.
152     *
153     * @param FragmentPos - actual sample point position in the current
154     * audio fragment to which the new event belongs to
155     */
156     Event EventGenerator::CreateEvent(int32_t FragmentPos) {
157     return Event(this, FragmentPos);
158     }
159    
160     /**
161 schoenebeck 53 * Will be called by an EventGenerator to create a new Event.
162 schoenebeck 906 * This Constructor expects a time stamp. The actual sample point
163     * position to which this event belongs to will be calculated later
164     * when FragmentPos() was called the first time.
165     *
166     * @param pGenerator - creator of this event
167     * @param Time - time stamp on which this event occured
168 schoenebeck 53 */
169     Event::Event(EventGenerator* pGenerator, time_stamp_t Time) {
170 schoenebeck 2879 Init();
171 schoenebeck 53 pEventGenerator = pGenerator;
172     TimeStamp = Time;
173     iFragmentPos = -1;
174     }
175    
176 schoenebeck 906 /**
177     * Will be called by an EventGenerator to create a new Event.
178     * This constructor expects the final sample point position to which
179     * this event belongs to.
180     *
181     * @param pGenerator - creator of this event
182     * @param FragmentPos - actual sample point position in the current
183     * audio fragment to which this event belongs to
184     */
185     Event::Event(EventGenerator* pGenerator, int32_t FragmentPos) {
186 schoenebeck 2879 Init();
187 schoenebeck 906 pEventGenerator = pGenerator;
188     iFragmentPos = FragmentPos;
189     }
190    
191 schoenebeck 53 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC