]> git.mxchange.org Git - flightgear.git/blob - Lib/src/slSamplePlayer.cxx
Merge FG_Lib as subdirectory
[flightgear.git] / Lib / src / slSamplePlayer.cxx
1
2 #include "sl.h"
3
4 void slSamplePlayer::addEnvelope ( int i, slEnvelope *_env, slEnvelopeType _type )
5 {
6   if ( i < 0 || i >= SL_MAX_ENVELOPES ) return ;
7
8   if ( env [ i ] != NULL )
9     env [ i ] -> unRef () ;
10
11   env [ i ] = _env ;
12
13   if ( _env != NULL )
14     env [ i ] -> ref () ;
15
16   env_type [ i ] = _type ;
17   env_start_time [ i ] = slScheduler::getCurrent() -> getTimeNow () ;
18 }
19
20 int slSamplePlayer::preempt ( int delay )
21 {
22   slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_PREEMPTED, magic ) ;
23
24   switch ( preempt_mode )
25   {
26     case SL_SAMPLE_CONTINUE: if ( isRunning() )
27                                return SL_FALSE ;
28                              /* FALLTHROUGH! */
29     case SL_SAMPLE_DELAY   :                   break ;
30     case SL_SAMPLE_MUTE    : skip  ( delay ) ; break ;
31     case SL_SAMPLE_ABORT   : stop  ()        ; break ;
32     case SL_SAMPLE_RESTART : reset ()        ; break ;
33   }
34
35   return SL_TRUE ;
36 }
37
38 slSamplePlayer::~slSamplePlayer ()
39 {
40   if ( sample )
41     sample -> unRef () ;
42
43   slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_COMPLETE, magic ) ;
44 }
45
46 void slSamplePlayer::skip ( int nframes )
47 {
48   if ( nframes < lengthRemaining )
49   {
50     lengthRemaining -= nframes ;
51     bufferPos       += nframes ;
52   }
53   else 
54   if ( replay_mode == SL_SAMPLE_LOOP )
55   {
56     slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_LOOPED, magic ) ;
57
58     nframes -= lengthRemaining ;
59
60     while ( nframes >= sample->getLength () )
61       nframes -= sample->getLength () ;
62
63     lengthRemaining = sample->getLength() - nframes ;
64     bufferPos = & ( sample->getBuffer() [ nframes ] ) ;
65   }
66   else
67     stop () ;
68 }
69
70
71 void slSamplePlayer::read ( int nframes, Uchar *dst, int next_env )
72 {
73   /*
74     WARNING:
75
76        CO-RECURSIVE!
77   */
78
79   /* Find the next envelope */
80
81   while ( next_env < SL_MAX_ENVELOPES && env [ next_env ] == NULL )
82     next_env++ ;
83
84   /*
85     If there are no fancy envelopes to process then return
86     the raw data.
87   */
88
89   if ( next_env >= SL_MAX_ENVELOPES ) /* No fancy envelopes left */
90   {
91     low_read ( nframes, dst ) ;
92     return ;
93   }
94
95   /*
96     Envelope processing required...
97
98     Process the next envelope using data read recursively through
99     the remaining envelopes.
100   */
101
102   switch ( env_type [ next_env ] )
103   {
104     /* For Volume envelopes, SRC and DST can be the same buffer */
105
106     case SL_INVERSE_VOLUME_ENVELOPE:
107       read ( nframes, dst, next_env+1 ) ;
108       env[ next_env ]->applyToInvVolume ( dst,dst,nframes,env_start_time[ next_env ] ) ;
109       break ;
110
111     case SL_VOLUME_ENVELOPE :
112       read ( nframes, dst, next_env+1 ) ;
113       env[ next_env ]->applyToVolume ( dst,dst,nframes,env_start_time[ next_env ] ) ;
114       break ;
115
116     case SL_INVERSE_PITCH_ENVELOPE :
117       env[ next_env ]->applyToInvPitch ( dst,this,nframes,env_start_time[ next_env ], next_env+1 ) ;
118       break ;
119
120     case SL_PITCH_ENVELOPE  :
121       env[ next_env ]->applyToPitch ( dst,this,nframes,env_start_time[ next_env ], next_env+1 ) ;
122       break ;
123
124     case SL_INVERSE_FILTER_ENVELOPE:
125     case SL_FILTER_ENVELOPE :
126       read ( nframes, dst, next_env+1 ) ;
127       break ;
128
129     case SL_INVERSE_PAN_ENVELOPE   :
130     case SL_PAN_ENVELOPE    :
131       read ( nframes, dst, next_env+1 ) ;
132       break ;
133
134     case SL_INVERSE_ECHO_ENVELOPE  :
135     case SL_ECHO_ENVELOPE   :
136       read ( nframes, dst, next_env+1 ) ;
137       break ;
138   }
139 }
140
141
142 void slSamplePlayer::low_read ( int nframes, Uchar *dst )
143 {
144   if ( isWaiting() ) start () ;
145
146   if ( bufferPos == NULL )  /* Run out of sample & no repeats */
147   {
148     memset ( dst, 0x80, nframes ) ;
149     return ;
150   }
151
152   while ( SL_TRUE )
153   {
154     /*
155       If we can satisfy this request in one read (with data left in
156       the sample buffer ready for next time around) - then we are done...
157     */
158
159     if ( nframes < lengthRemaining )
160     {
161       memcpy ( dst, bufferPos, nframes ) ;
162       bufferPos       += nframes ;
163       lengthRemaining -= nframes ;
164       return ;
165     }
166
167     memcpy ( dst, bufferPos, lengthRemaining ) ;
168     bufferPos       += lengthRemaining ;
169     dst             += lengthRemaining ;
170     nframes         -= lengthRemaining ;
171     lengthRemaining  = 0 ;
172
173     if ( replay_mode == SL_SAMPLE_ONE_SHOT )
174     {
175       stop () ;
176       memset ( dst, 0x80, nframes ) ;
177       return ;
178     }
179     else
180     {
181       slScheduler::getCurrent() -> addCallBack ( callback, sample, SL_EVENT_LOOPED, magic ) ;
182       start () ;
183     }
184   }
185 }
186
187
188