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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 292 by schoenebeck, Mon Oct 25 14:59:18 2004 UTC revision 3054 by schoenebeck, Thu Dec 15 12:47:45 2016 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6     *   Copyright (C) 2005 - 2016 Christian Schoenebeck                       *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   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  *   *   it under the terms of the GNU General Public License as published by  *
# Line 33  namespace LinuxSampler { Line 34  namespace LinuxSampler {
34      EventGenerator::EventGenerator(uint SampleRate) {      EventGenerator::EventGenerator(uint SampleRate) {
35          uiSampleRate       = SampleRate;          uiSampleRate       = SampleRate;
36          uiSamplesProcessed = 0;          uiSamplesProcessed = 0;
37          FragmentTime.end   = CreateTimeStamp();          FragmentTime.end   = RTMath::CreateTimeStamp();
38            uiTotalSamplesProcessed = 0;
39      }      }
40    
41      /**      /**
# Line 45  namespace LinuxSampler { Line 47  namespace LinuxSampler {
47       *                           audio fragment cycle       *                           audio fragment cycle
48       */       */
49      void EventGenerator::UpdateFragmentTime(uint SamplesToProcess) {      void EventGenerator::UpdateFragmentTime(uint SamplesToProcess) {
50            // update total amount of sample points being processed since this object was created
51            uiTotalSamplesProcessed += uiSamplesProcessed;
52          // update time stamp for this audio fragment cycle          // update time stamp for this audio fragment cycle
53          FragmentTime.begin = FragmentTime.end;          FragmentTime.begin = FragmentTime.end;
54          FragmentTime.end   = CreateTimeStamp();          FragmentTime.end   = RTMath::CreateTimeStamp();
55          // recalculate sample ratio for this audio fragment          // recalculate sample ratio for this audio fragment
56          time_stamp_t fragmentDuration = FragmentTime.end - FragmentTime.begin;          time_stamp_t fragmentDuration = FragmentTime.end - FragmentTime.begin;
57          FragmentTime.sample_ratio = (float) uiSamplesProcessed / (float) fragmentDuration;          FragmentTime.sample_ratio = (float) uiSamplesProcessed / (float) fragmentDuration;
58          // store amount of samples to process for the next cycle          // store amount of samples to process for the next cycle
59          uiSamplesProcessed = SamplesToProcess;          uiSamplesProcessed = SamplesToProcess;
60      }      }
61        
62        /**
63         * Get the next scheduled MIDI event (the one with the lowest time value)
64         * for the current audio fragment cycle and remove it from the queue. This
65         * method will not return any event scheduled past the current audio
66         * fragment boundary.
67         *
68         * @param queue - where the MIDI events are scheduled on
69         * @param pool - used to allocate and deallocate ScheduledEvent objects
70         * @param end - you @b MUST always pass EventGenerator::schedTimeAtCurrentFragmentEnd()
71         *              here reflecting the current audio fragment's scheduler end time
72         */
73        RTList<ScheduledEvent>::Iterator EventGenerator::popNextScheduledEvent(RTAVLTree<ScheduledEvent>& queue, Pool<ScheduledEvent>& pool, sched_time_t end) {
74            if (queue.isEmpty())
75                return RTList<ScheduledEvent>::Iterator(); // return invalid iterator
76            ScheduledEvent& e = queue.lowest();
77            if (e.scheduleTime >= end)
78                return RTList<ScheduledEvent>::Iterator(); // no event scheduled before 'end'
79            RTList<ScheduledEvent>::Iterator itEvent = pool.fromPtr(&e);
80            queue.erase(e);
81            if (!itEvent || !itEvent->itEvent) {
82                dmsg(1,("EventGenerator::popNextScheduledEvent(): !itEvent\n"));
83                return itEvent; // should never happen at this point, but just to be sure
84            }
85            if (!itEvent->itEvent) {
86                dmsg(1,("EventGenerator::popNextScheduledEvent(): !itEvent->itEvent\n"));
87                return itEvent; // should never happen at this point, but just to be sure
88            }
89    
90            // update position of this event in the current audio fragment
91            // (since calling scheduleAheadMicroSec() will relate to this)
92            itEvent->itEvent->iFragmentPos = int32_t( uiSamplesProcessed - (end - itEvent->scheduleTime) );
93            // safety first: fragment boundary sanity checks
94            if (itEvent->itEvent->iFragmentPos < 0)
95                itEvent->itEvent->iFragmentPos = 0;
96            if (itEvent->itEvent->iFragmentPos >= uiSamplesProcessed)
97                itEvent->itEvent->iFragmentPos = uiSamplesProcessed - 1;
98    
99            return itEvent;
100        }
101    
102        /**
103         * Get the next instrument script event (the one with the lowest time value)
104         * for the current audio fragment cycle and remove it from the queue. This
105         * method will not return any event scheduled past the current audio
106         * fragment boundary.
107         *
108         * @param queue - where the instrument script events are scheduled on
109         * @param pool - used to allocate and deallocate ScriptEvent objects
110         * @param end - you @b MUST always pass EventGenerator::schedTimeAtCurrentFragmentEnd()
111         *              here reflecting the current audio fragment's scheduler end time
112         */
113        RTList<ScriptEvent>::Iterator EventGenerator::popNextScheduledScriptEvent(RTAVLTree<ScriptEvent>& queue, Pool<ScriptEvent>& pool, sched_time_t end) {
114            if (queue.isEmpty())
115                return RTList<ScriptEvent>::Iterator(); // return invalid iterator
116            ScriptEvent& e = queue.lowest();
117            if (e.scheduleTime >= end)
118                return RTList<ScriptEvent>::Iterator(); // no event scheduled before 'end'
119            RTList<ScriptEvent>::Iterator itEvent = pool.fromPtr(&e);
120            queue.erase(e);
121            if (!itEvent) { // should never happen at this point, but just to be sure
122                dmsg(1,("EventGenerator::popNextScheduledScriptEvent(): !itEvent\n"));
123                return itEvent;
124            }
125    
126            // update position of this event in the current audio fragment
127            // (since calling scheduleAheadMicroSec() will relate to this)
128            itEvent->cause.iFragmentPos = int32_t( uiSamplesProcessed - (end - itEvent->scheduleTime) );
129            // safety first: fragment boundary sanity checks
130            if (itEvent->cause.iFragmentPos < 0)
131                itEvent->cause.iFragmentPos = 0;
132            if (itEvent->cause.iFragmentPos >= uiSamplesProcessed)
133                itEvent->cause.iFragmentPos = uiSamplesProcessed - 1;
134    
135            return itEvent;
136        }
137    
138      /**      /**
139       * Create a new event with the current time as time stamp.       * Create a new event with the current time as time stamp.
140       */       */
141      Event EventGenerator::CreateEvent() {      Event EventGenerator::CreateEvent() {
142          return Event(this, CreateTimeStamp());          return Event(this, RTMath::CreateTimeStamp());
143      }      }
144    
145      /**      /**
146       * Creates a real time stamp for the current moment. Out of efficiency this       * Create a new event for the given sample point position in the current
147       * is implemented in inline assembly for each CPU independently; we currently       * audio fragment.
148       * don't use a generic solution for CPUs that are not yet covered by the       *
149       * assembly code, instead an error message is prompted on compile time, forcing       * @param FragmentPos - actual sample point position in the current
150       * the user to contact us.       *                      audio fragment to which the new event belongs to
151       */       */
152      EventGenerator::time_stamp_t EventGenerator::CreateTimeStamp() {      Event EventGenerator::CreateEvent(int32_t FragmentPos) {
153          #if defined(__i386__) || defined(__x86_64__)          return Event(this, FragmentPos);
             uint64_t t;  
             __asm__ __volatile__ ("rdtsc" : "=A" (t));  
             return t >> 8;  
         #elif defined(__ia64__)  
             time_stamp_t t;  
             __asm__ __volatile__ ("mov %0=ar.itc" : "=r"(t));  
             return t;  
         #elif defined(__powerpc__)  
             time_stamp_t t;  
             __asm__ __volatile__ (  
                 "98:    mftb %0\n"  
                 "99:\n"  
                 ".section __ftr_fixup,\"a\"\n"  
                 "       .long %1\n"  
                 "       .long 0\n"  
                 "       .long 98b\n"  
                 "       .long 99b\n"  
                 ".previous"  
                 : "=r" (t) : "i" (0x00000100)  
             );  
             return t;  
         #elif defined(__alpha__)  
             time_stamp_t t;  
             __asm__ __volatile__ ("rpcc %0" : "=r"(t));  
             return t;  
         #else // we don't want to use a slow generic solution  
         #  error "Sorry, LinuxSampler lacks time stamp code for your system."  
         #  error "Please report this error and the CPU you are using to the LinuxSampler developers mailing list!"  
         #endif  
154      }      }
155    
156      /**      /**
157       * Will be called by an EventGenerator to create a new Event.       * Will be called by an EventGenerator to create a new Event.
158         * This Constructor expects a time stamp. The actual sample point
159         * position to which this event belongs to will be calculated later
160         * when FragmentPos() was called the first time.
161         *
162         * @param pGenerator - creator of this event
163         * @param Time       - time stamp on which this event occured
164       */       */
165      Event::Event(EventGenerator* pGenerator, time_stamp_t Time) {      Event::Event(EventGenerator* pGenerator, time_stamp_t Time) {
166            Init();
167          pEventGenerator = pGenerator;          pEventGenerator = pGenerator;
168          TimeStamp       = Time;          TimeStamp       = Time;
169          iFragmentPos    = -1;          iFragmentPos    = -1;
170      }      }
171    
172        /**
173         * Will be called by an EventGenerator to create a new Event.
174         * This constructor expects the final sample point position to which
175         * this event belongs to.
176         *
177         * @param pGenerator  - creator of this event
178         * @param FragmentPos - actual sample point position in the current
179         *                      audio fragment to which this event belongs to
180         */
181        Event::Event(EventGenerator* pGenerator, int32_t FragmentPos) {
182            Init();
183            pEventGenerator = pGenerator;
184            iFragmentPos    = FragmentPos;
185        }
186    
187  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.292  
changed lines
  Added in v.3054

  ViewVC Help
Powered by ViewVC