3 <chapter id="rendering">
4 <title>Listener and Sources</title>
6 <sect1 id="object-state">
7 <title>Basic Listener and Source Attributes</title>
9 This section introduces basic attributes that can be set both for
10 the Listener object and for Source objects.
14 <note id="rfc-bk000619-02"><title>RFC: attribute grouping</title><para>
15 JM: "These attributes are of
16 two types: non-positional and positional.
17 Non-positional properties include gain control and Environment Name."
19 I said: (low pass) Filters are applied to the sound during processing
20 at various stages. The exact sequence in which Filters are applied is
21 determined based on the location of the Objects they are
22 set for - spatial arrangement of Objects determines the
23 sequence unless invariance is guaranteed, or invariance
24 violation is permitted by the specification and current &AL;
27 Is there a required order of application, i.e. a pipeline?
29 Filter Parameters vs. Non-positional properties.
30 Spatialization vs. Positional properties.
32 Let's postpone grouping of attributes.
38 The &AL; Listener and Sources have attributes to describe
39 their position, velocity and orientation in three dimensional space.
40 &AL; like &OGL;, uses a right-handed Cartesian coordinate system (RHS),
41 where in a frontal default view X (thumb) points right,
42 Y (index finger) points up, and Z (middle finger) points towards
43 the viewer/camera. To switch from a left handed coordinate system (LHS)
44 to a right handed coordinate systems, flip the sign on the Z coordinate.
49 <title>Listener/Source Position</title>
50 <tgroup cols="4" align="left" colsep=1 rowsep=1>
63 <entry> any except NaN </>
64 <entry> { 0.0f, 0.0f, 0.0f } </>
70 POSITION specifies the current location of the Object in the
71 world coordinate system. Any 3-tuple of valid float/double values
72 is allowed. Implementation behavior on encountering &NaN; and &Infty;
73 is not defined. The Object position is always defined in the
74 world coordinate system.
78 <note><title>Annotation (No Transformation)</title><para>
79 &AL; does not support transformation operations on Objects.
80 Support for transformation matrices is not planned.
87 <title>Listener/Source Velocity</title>
88 <tgroup cols="4" align="left" colsep=1 rowsep=1>
101 <entry> any except NaN </>
102 <entry> { 0.0f, 0.0f, 0.0f } </>
108 VELOCITY specifies the current velocity (speed and direction) of
109 the Object, in the world coordinate system. Any 3-tuple of valid
110 float/double values is allowed. The Object VELOCITY does not affect
112 &AL; does not calculate the velocity from subsequent position
113 updates, nor does it adjust the position over time based on
114 the specified velocity. Any such calculation is left to the
115 application. For the purposes of sound processing, position and
116 velocity are independent parameters affecting different aspects
119 VELOCITY is taken into account by the driver to synthesize the
120 Doppler effect perceived by the Listener for each source, based
121 on the velocity of both Source and Listener, and the Doppler
130 <title>Listener/Source Gain (logarithmic)</title>
131 <tgroup cols="4" align="left" colsep=1 rowsep=1>
144 <entry>0.0f, (0.0f, any</>
151 GAIN defines a scalar amplitude multiplier. As a Source attribute, it applies
152 to that particular source only. As a Listener attribute, it effectively
153 applies to all Sources in the current Context. The default 1.0 means
154 that the sound is un-attenuated. A GAIN value of 0.5 is equivalent to
155 an attenuation of 6 dB. The value zero equals silence (no output). Driver
156 implementations are free to optimize this case and skip mixing and
157 processing stages where applicable. The implementation is in charge of
158 ensuring artifact-free (click-free) changes of gain values and is free
159 to defer actual modification of the sound samples, within the limits of
160 acceptable latencies.
163 GAIN larger than 1 (amplification) is permitted for Source and
164 Listener. However, the implementation is free to clamp the
165 total gain (effective gain per source times listener gain)
166 to 1 to prevent overflow.
171 <note><title>Annotation/ Effective Minimal Distance</title><para>
172 Presuming that the sample uses the entire dynamic range of
173 the encoding format, an effective gain of 1 represents the
174 maximum volume at which a source can reasonably be played.
175 During processing, the implementation combines the Source
176 GAIN (or MIN_GAIN, if set and larger) with distance based
177 attenuation. The distance at which the effective gain is 1
178 is equivalent to the DirectSound3D MIN_DISTANCE parameter.
179 Once the effective gain has reached the maximum possible
180 value, it will not increase with decreasing distance anymore.
186 <note><title>Annotation (Muting a Context)</title><para>
187 To mute the current context, simply set Listener GAIN to zero.
188 The implementation is expected to optimize for this case,
189 calculating necessary (offset) updates but bypassing the
190 mixing and releasing hardware resources.
191 The specification does not guarantee that the implementation
192 will release hardware resources used by a muted context.
197 <note><title>Annotation (Muting a Source)</title><para>
198 To mute a Source, set Source GAIN to zero. The &AL; implementation
199 is encouraged to optimize for this case.
205 <note id="rf-bk000503-01"><title>RFC: GAIN > 1?</title><para>
206 GAIN could exceed 1 (to compensate attenuation elsewhere, or to account
207 for grater dynamic range of the hardware? No guarantees are made with
208 respect to range overflows? Precision loss? Culling by effective gain?
209 Does &AL; clip values during processing, and when/at what stages?
212 <note id="rfc-bk000619-01"><title>RFC: Doppler</title><para>
213 JM wrote: "VELOCITY is used by the driver
214 to synthesize the Doppler effect perceived by the listener for each
215 source, based on the relative velocity of this source with respect
217 Doppler is calculated using Source and Listener velocities measured
218 with respect to the medium. Do we have to account for the medium
219 to move (offsetting listener/source) in later revisions (air/water currents)?
222 <note id="rfc-bk000619-03"><title>RFC: </title><para>
223 JM removed: "For the purposes of sound processing, position and
224 velocity are independent parameters affecting different paths
225 in the sound synthesis." I think the "different aspects of sounds"
226 is ambiguous. Is there a problem with describing &AL; as a
227 multichannel processing machine?
235 <sect1 id="object-listener">
236 <title>Listener Object</title>
239 The Listener Object defines various properties that affect processing of
240 the sound for the actual output. The Listener is unique for an &AL; Context,
241 and has no Name. By controlling the listener, the application controls
242 the way the user experiences the virtual world, as the listener defines
243 the sampling/pickup point and orientation, and other parameters that
244 affect the output stream.
247 It is entirely up to the driver and hardware configuration, i.e.
248 the installation of &AL; as part of the operating system and
249 hardware setup, whether the output stream is generated for
250 headphones or 2 speakers, 4.1 speakers, or other arrangements,
251 whether (and which) HRTF's are applied, etc..
255 <note><title>Annotation (Listener Anatomy)</title><para>
256 The API is ignorant with respect to the real world
257 listener, it does not need to make assumptions on the
258 listening capabilities of the user, its species or its
259 number of ears. It only describes a scene and the position
260 of the listener in this scene. It is the &AL; implementation
261 that is designed for humans with ears on either side of the
268 <note><title>Annotation (Listener State Evaluation)</title><para>
269 Some Listener state (GAIN) affects only the very last
270 stage of sound synthesis, and is thus applied to the sound stream
271 as sampled at the Listener position. Other Listener state is
272 applied earlier. One example is Listener velocity as used to
273 compute the amount of Doppler pitch-shifting applied to each source:
274 In a typical implementation, pitch-shifting (sample-rate conversion)
275 might be the first stage of the audio processing for each source.
281 <title>Listener Attributes</title>
284 Several Source attributes also apply to Listener: e.g. POSITION, VELOCITY,
285 GAIN. In addition, some attributes are listener specific.
287 <title>Listener Orientation</title>
288 <tgroup cols="4" align="left" colsep=1 rowsep=1>
299 <entry>ORIENTATION</>
301 <entry> any except NaN </>
302 <entry> { { 0.0f, 0.0f, -1.0f }, { 0.0f, 1.0f, 0.0f } } </>
308 ORIENTATION is a pair of 3-tuples representing the 'at' direction vector
309 and 'up' direction of the Object in Cartesian space. &AL; expects two
310 vectors that are orthogonal to each other. These
311 vectors are not expected to be normalized. If one or more vectors
312 have zero length, implementation behavior is undefined. If the two
313 vectors are linearly dependent, behavior is undefined.
316 <note id="rfc-bk000503-01"><title>RFC: Orientation Paranoia</title><para>
317 Watch LHS vs. RHS (sign on 'at').
318 Confirm sequence is (up, at) not vice versa.
319 Do we want to allow for different representations down the road?
325 <title>Changing Listener Attributes</title>
327 Listener attributes are changed using the Listener group of commands.
328 <funcsynopsis><funcprototype>
329 <funcdef> void <function> Listener{n}{sifd}{v} </function></funcdef>
330 <paramdef> &enum; <parameter> paramName </parameter></paramdef>
331 <paramdef> &type; <parameter> values </parameter></paramdef>
332 </funcprototype></funcsynopsis>
337 <title>Querying Listener Attributes</title>
339 Listener state is maintained inside the &AL; implementation and can be
340 queried in full. See Querying Object Attributes. The valid values for
341 paramName are identical to the ones for the Listener* command.
342 <funcsynopsis><funcprototype>
343 <funcdef> void <function> GetListener{sifd}v </function></funcdef>
344 <paramdef> &enum; <parameter> paramName </parameter></paramdef>
345 <paramdef> &type;* <parameter> values </parameter></paramdef>
346 </funcprototype></funcsynopsis>
353 <sect1 id="object-sources">
354 <title>Source Objects</title>
356 Sources specify attributes like position, velocity, and a buffer with
357 sample data. By controlling a Source's attributes the
358 application can modify and parameterize the static sample data provided
359 by the Buffer referenced by the Source.
360 Sources define a localized sound, and encapsulate
361 a set of attributes applied to a sound at its origin, i.e. in the
362 very first stage of the processing on the way to the listener.
363 Source related effects have to be applied
364 before Listener related effects unless the output is invariant
365 to any collapse or reversal of order.
368 &AL; also provides additional functions to manipulate and query the
369 execution state of Sources: the current playing status of a
370 source (started, stopped, paused), including access to the current
371 sampling position within the associated Buffer.
375 <note id="rfc-briareos000629-01"><title>RFC: Mike on Source Types</title><para>
376 AL_SOURCE_ABSOLUTE and AL_SOURCE_AMBIENT have been
377 deprecated. AL_SOURCE_ABSOLUTE was simply the converse of the
378 AL_SOURCE_RELATIVE pname, and as such was unnecessary. The
379 effect of AL_SOURCE_AMBIENT is trivially emulated by either
380 querying the Listener position and setting the Source position
381 accordingly, or setting the Source position to (0,0,0) and the
382 type to AL_SOURCE_RELATIVE, and is therefore also unnecessary.
388 <note id="rfc-bk000721-02"><title>RFC: Bernd on Source Types</title><para>
389 Mike seems to miss a few problems here. W/o a converse we can't
390 reset source attributes to ABSOLUTE. Ambient sounds are not
391 necessarily trivial. A3D manual suggested some magic number
392 to fake the effect of ambient (i.e. sound that ideally
393 can't be localized by listener). If we can get away with such magic
394 numbers in a tutorial in a driver-independent way, fine. If there is any
395 risk that the impression of ambient sound requires driver specific
396 hacks, then we need AMBIENT. As soon as we have a third localization
397 type, ABSOLUTE and RELATIVE are needed as there is no unambiguous
400 From the A3D 2.0 Optimize.doc:
401 "Adding some ambient background noise is a great way to fill in the gaps
402 when the audio content is reduced. A great way to make an ambient sound
403 seem like it is coming from everywhere is to load up two buffers with the
404 same sound, and position them about 2 meters behind the listener at
405 about 4 and 8 o\rquote clock. The waves have to be looping (make sure
406 there is no beating when you play them back). Starting the sounds 180
407 degrees out of phase can help, as will playing them with slightly different
413 <note id="rfc-bk000721-03"><title>RFC: Bernd on Source Types (2)</title><para>
414 There is a point to be made in using POSITION_RELATIVE and
415 VELOCITY_RELATIVE iff we do not have AMBIENT to consider.
416 This makes it a call-by-call choice when setting Source3f{v}
417 vectors, as it is applied when dereferencing.
422 <note id="rfc-bk000721-04"><title>RFC: Bernd on Source Types (3)</title><para>
423 Semantically, AMBIENT has nothing to do with coordinate systems,
424 it is a qualifier just like multichannel direct passthru.
429 <note id="rfc-bk000721-05"><title>RFC: Source Attenuation Clamping</title><para>
430 Using AL_SOURCE_ATTENUATION_MIN and AL_SOURCE_ATTENUATION_MAX
431 to specify the clamping values for the normalized attenuation
432 factor (which is a function of distance) is in contradiction
433 to the distance based model that Creative is pushing for
434 (DirectSound). As driver-interall culling of source and other
435 processing might be based on the effective (overall, ultimate)
436 gain composed of amplifications and attenuations accumulated
437 over the entire processing, I raise the question whether a sound
438 designer might not want to control the effective GAIN ranges
439 instead of the distance attenuation itself. Samples commonly
440 use the entire dynamic range provided by the format, which is
441 mapped to the entire dynamic range of the output device. An
442 effective gain exceeding 1 does not make sense, an amplification
443 during processing might.
452 <title>Managing Source Names</title>
454 &AL; provides calls to request and release Source Names handles.
455 Calls to control Source Execution State are also provided.
459 <title>Requesting a Source Name</title>
461 The application requests a number of Sources using GenSources.
462 <funcsynopsis><funcprototype>
463 <funcdef> &void; <function> GenSources </function></funcdef>
464 <paramdef> &sizei; <parameter> n </parameter></paramdef>
465 <paramdef> &uint;* <parameter> sources </parameter></paramdef>
466 </funcprototype></funcsynopsis>
472 <title>Releasing Source Names</title>
474 The application requests deletion of a number of Sources
476 <funcsynopsis><funcprototype>
477 <funcdef> &void; <function> DeleteSources </function></funcdef>
478 <paramdef> &sizei; <parameter> n </parameter></paramdef>
479 <paramdef> &uint;* <parameter> sources </parameter></paramdef>
480 </funcprototype></funcsynopsis>
485 <title>Validating a Source Name</title>
487 The application can verify whether a source name is valid
488 using the IsSource query.
489 <funcsynopsis><funcprototype>
490 <funcdef> &bool; <function> IsSource </function></funcdef>
491 <paramdef> &uint; <parameter> sourceName </parameter></paramdef>
492 </funcprototype></funcsynopsis>
499 <title>Source Attributes</title>
501 This section lists the attributes that are set per Source,
502 affecting the processing of the current buffer. Some of
503 these attributes can also be set for buffer queue entries.
506 <note><title>Annotation (No Priorities)</title><para>
507 There are no per Source priorities, and no explicit priority
508 handling, defined at this point. A mechanism that lets the
509 application express preferences in case that the implementation
510 provides culling and prioritization mechanisms might be added
511 at some later time. This topic is under discussion for GL as
512 well, which already has one exlicit priority API along with
513 internally used MRU heuristics (for resident texture memory).
521 <title>Source Positioning</title>
524 <title>SOURCE_RELATIVE Attribute</title>
525 <tgroup cols="4" align="left" colsep=1 rowsep=1>
536 <entry> SOURCE_RELATIVE </>
538 <entry> FALSE, TRUE</>
544 SOURCE_RELATIVE set to TRUE indicates that the values
545 specified by POSITION are to be interpreted relative
546 to the listener position.
551 <note><title>Annotation (Position only)</title><para>
552 SOURCE_RELATIVE does not affect velocity or orientation
560 <title>Buffer Looping</title>
563 <title>Source LOOPING Attribute</title>
564 <tgroup cols="4" align="left" colsep=1 rowsep=1>
569 <spanspec spanname=hspan namest=c1 nameend=c4 align=left>
582 <entry> TURE, FALSE</>
589 LOOPING is a flag that indicates that the Source will not
590 be in STOPPED state once it reaches the end of last buffer
591 in the buffer queue. Instead, the Source will immediately
592 promote to INITIAL and PLAYING. The default value is FALSE.
593 LOOPING can be changed on a Source in any execution state.
594 In particular, it can be changed on a PLAYING Source.
598 <note><title>Annotation (Finite Repetition)</title><para>
599 Finite reptition is implemented by buffer queueing.
604 <note><title>Annotation (Loop Control)</title><para>
605 To implement a 3 stage "loop point" solution, the
606 application has to queue the FadeIn buffer first,
607 then queue the buffer it wants to loop, and set
608 LOOPING to TRUE once the FadeIn buffer has been
609 processed and unqueued. To fade from looping, the
610 application can queue a FadeOut buffer, then
611 set LOOPING to false on the PLAYING source. Alternatively,
612 the application can decide to not use the LOOPING
613 attribute at all, and just continue to queue the buffer
619 <note><title>Annotation (Rejected alternatives)</title><para>
620 A finite loop counter was rejected because it is
621 ambiguous with respect to persistent (initial counter)
622 vs. transient (current counter). For similar reasons,
623 a Play-equivalent command with a (transient) loop counter
630 <title>Current Buffer</title>
633 <title>Source BUFFER Attribute</title>
634 <tgroup cols="4" align="left" colsep=1 rowsep=1>
647 <entry> any valid bufferName </>
654 Specifies the current Buffer object, making it the
655 head entry in the Source's queue. Using BUFFER on a
656 STOPPED or INITIAL Source empties the entire queue,
657 then appends the one Buffer specified.
660 For a PLAYING or PAUSED Source, using the Source command
661 with BUFFER is an INVALID_OPERATION.
662 It can be applied to INITIAL and STOPPED Sources only.
663 Specifying an invalid bufferName will
664 result in an INVALID_VALUE error while specifying an
665 invalid sourceName results in an INVALID_NAME error.
668 NONE, i.e. 0, is a valid buffer Name.
669 Source( sName, BUFFER, 0 ) is a legal way to release the
670 current buffer queue on an INITIAL or STOPPED Source,
671 whether it has just one entry (current buffer) or more.
672 The Source( sName, BUFFER, NONE) call still causes an
673 INVALID_OPERATION for any source PLAYING or PAUSED,
674 consequently it cannot be abused to mute or stop a source.
678 <note><title>Annotation (repeated Source+BUFFER does not queue) </title><para>
679 Using repeated Source(BUFFER) calls to queue a buffer on
680 an active source would imply that there is no way to
681 release the current buffer e.g. by setting it to 0.
682 On the other hand read-only queues do not allow for
683 releasing a buffer without releasing the entire queue.
685 We can not require BUFFER state to be transient and lost
686 as soon as a Source is implicitely or explicitely stopped.
687 This contradicts queue state being part of the Source's
688 configuration state that is preserved through Stop()
689 operations and available for Play().
698 <title>Queue State Queries</title>
701 <title>BUFFERS_QUEUED Attribute</title>
702 <tgroup cols="4" align="left" colsep=1 rowsep=1>
713 <entry> BUFFERS_QUEUED </>
721 Query only. Query the number of buffers in the queue
722 of a given Source. This includes those not yet played,
723 the one currently playing, and the ones that have been
724 played already. This will return 0 if the current and
725 only bufferName is 0.
731 <title>BUFFERS_PROCESSED Attribute</title>
732 <tgroup cols="4" align="left" colsep=1 rowsep=1>
743 <entry> BUFFERS_PROCESSED </>
751 Query only. Query the number of buffers that have
752 been played by a given Source.
753 Indirectly, this gives the index of the buffer
754 currently playing. Used to determine how much
755 slots are needed for unqueueing them.
756 On an STOPPED Source, all buffers are processed.
757 On an INITIAL Source, no buffers are processed,
758 all buffers are pending.
759 This will return 0 if the current and
760 only bufferName is 0.
764 <note><title>Annotation (per-Source vs. Buffer State)</title><para>
765 BUFFERS_PROCESSED is only defined within the scope of a given
766 Source's queue. It indicates that the given number of buffer names
767 can be unqueued for this Source. It does not guarantee that the
768 buffers can safely be deleted or refilled, as they might still be
769 queued with other Sources. One way to keep track of this is to
770 store, per buffer, the Source for which a given buffer was most
771 recently scheduled (this will not work if Sources sharing buffers
772 might be paused by the application). If necessary an explicit
773 query for a given buffer name can be added in later revisions.
778 <note><title>Annotation (No Looping Queues)</title><para>
779 Unqueueing requires nonzero BUFFERS_PROCESSED,
780 which necessitates no looping on entire queues,
781 unless we accept that no unqueueing is possible
782 from Source looping over the entire queue.
783 Currently not supported, as queueing is
784 primarily meant for streaming, which implies
785 unqueue-refill-requeue operations.
793 <title>Bounds on Gain</title>
796 <title>Source Minimal Gain</title>
797 <tgroup cols="4" align="left" colsep=1 rowsep=1>
810 <entry>0.0f, (0.0f, 1.0f]</>
817 MIN_GAIN is a scalar amplitude threshold. It indicates the minimal GAIN
818 that is always guaranteed for this Source. At the end of the processing
819 of various attenuation factors such as distance based attenuation and
820 Source GAIN, the effective gain calculated is compared to this value.
821 If the effective gain is lower than MIN_GAIN, MIN_GAIN is applied.
822 This happens before the Listener GAIN is applied. If a zero MIN_GAIN
823 is set, then the effective gain will not be corrected.
828 <note><title>Annotation (Effective Maximal Distance)</title><para>
829 By setting MIN_GAIN, the application implicitely defines a
830 maximum distance for a given distance attenuation model and
831 Source GAIN. The distance at which the effective gain is MIN_GAIN
832 can be used as a replacement to the DirectSound3D MAX_DISTANCE parameter.
833 Once the effective gain has reached the MIN_GAIN value, it will
834 no longer decrease with increasing distance.
841 <title>Source Maximal Gain (logarithmic)</title>
842 <tgroup cols="4" align="left" colsep=1 rowsep=1>
855 <entry>0.0f, (0.0f, 1.0f]</>
862 MAX_GAIN defines a scalar amplitude threshold. It indicates the maximal
863 GAIN permitted for this Source. At the end of the processing
864 of various attenuation factors such as distance based attenuation and
865 Source GAIN, the effective gain calculated is compared to this value.
866 If the effective gain is higher than MAX_GAIN, MAX_GAIN is applied.
867 This happens before the Listener GAIN is applied. If the Listener gain
868 times MAX_GAIN still exceeds the maximum gain the implementation can
869 handle, the implementation is free to clamp. If a zero MAX_GAIN
870 is set, then the Source is effectively muted. The implementation is free
871 to optimize for this situation, but no optimization is required or
872 recommended as setting GAIN to zero is the proper way to mute a Source.
876 <note><title>Annotation (Un-attenuated Source)</title><para>
877 Setting MIN_GAIN and MAX_GAIN to the GAIN value will effectively
878 make the Source amplitude independent of distance. The
879 implementation is free to optimize for this situation. However, the
880 recommended way to accomplish this effect is using a ROLLOFF_FACTOR
888 <note><title>Annotation (Internal GAIN threshold)</title><para>
889 The &AL; implementation is free to use an internally chosen
890 threshold level below which a Source is ignored for mixing.
891 Reasonable choices would set this threshold low enough so
892 that the user will not perceive a difference. Setting MIN_GAIN
893 for a source will override any implementation defined test.
901 <title>Distance Model Attributes</title>
904 <title> REFERENCE_DISTANCE Attribute</title>
905 <tgroup cols="4" align="left" colsep=1 rowsep=1>
916 <entry> REFERENCE_DISTANCE </>
924 This is used for distance attenuation calculations
925 based on inverse distance with rolloff. Depending
926 on the distance model it will also act as a distance
927 threshold below which gain is clamped. See the
928 section on distance models for details.
934 <title> ROLLOFF_FACTOR Attribute</title>
935 <tgroup cols="4" align="left" colsep=1 rowsep=1>
946 <entry> ROLLOFF_FACTOR </>
954 This is used for distance attenuation calculations
955 based on inverse distance with rolloff. For
956 distances smaller than MAX_DISTANCE (and, depending
957 on the distance model, larger than REFERENCE_DISTANCE),
958 this will scale the distance attenuation over the
959 applicable range. See section on distance models for
960 details how the attenuation is computed as a function
964 In particular, ROLLOFF_FACTOR can be set to zero for
965 those Sources that are supposed to be exempt from
966 distance attenuation. The implementation is encouraged
967 to optimize this case, bypassing distance attenuation
968 calculation entirely on a per-Source basis.
973 <title> MAX_DISTANCE Attribute</title>
974 <tgroup cols="4" align="left" colsep=1 rowsep=1>
985 <entry> MAX_DISTANCE </>
988 <entry> MAX_FLOAT </>
993 This is used for distance attenuation calculations
994 based on inverse distance with rolloff, if the
995 Inverse Clamped Distance Model is used. In this case,
996 distances greater than MAX_DISTANCE will
997 be clamped to MAX_DISTANCE.
998 MAX_DISTANCE based clamping is applied before MIN_GAIN clamping,
999 so if the effective gain at MAX_DISTANCE is larger than MIN_GAIN,
1000 MIN_GAIN will have no effect. No culling is supported.
1004 <note><title>Annotation (No Culling)</title><para>
1005 This is a per-Source attribute supported for DS3D compatibility
1006 only. Other API features might suffer from side effects due to
1007 the clamping of distance (instead of e.g. clamping to an effective
1008 gain at MAX_DISTANCE).
1018 <title>Frequency Shift by Pitch</title>
1021 <title>Source PITCH Attribute</title>
1022 <tgroup cols="4" align="left" colsep=1 rowsep=1>
1035 <entry> (0.0f, 2.0f]</>
1042 Desired pitch shift, where 1.0 equals identity. Each reduction by 50 percent
1043 equals a pitch shift of -12 semitones (one octave reduction). Zero is not
1050 <title>Direction and Cone</title>
1052 Each Source can be directional, depending on the settings for
1053 CONE_INNER_ANGLE and CONE_OUTER_ANGLE. There are three zones
1054 defined: the inner cone, the outside zone, and the transitional
1056 The angle-dependent gain for a directional source is constant
1057 inside the inner cone, and changes over the transitional zone
1058 to the value specified outside the outer cone.
1059 Source GAIN is applied for the inner cone,
1060 with an application selectable CONE_OUTER_GAIN factor to
1061 define the gain in the outer zone. In the transitional
1062 zone implementation-dependent interpolation between
1063 GAIN and GAIN times CONE_OUTER_GAIN is applied.
1068 <note><title>Annotation (Interpolation Restrictions)</title><para>
1069 The specification does not specify the exact interpolation
1070 applied in the transitional zone, to calculate gain as a
1071 function of angle. The implementation is free to use
1072 linear or other interpolation, as long as the values
1073 are monotonically decreasing from GAIN to GAIN times CONE_OUTER_GAIN.
1080 <title>Source DIRECTION Attribute</title>
1081 <tgroup cols="4" align="left" colsep=1 rowsep=1>
1094 <entry> any except NaN </>
1095 <entry> { 0.0f, 0.0f, 0.0f } </>
1101 If DIRECTION does not equal the zero vector, the Source is directional.
1102 The sound emission is presumed to be symmetric
1103 around the direction vector (cylinder symmetry). Sources are not
1104 oriented in full 3 degrees of freedom, only two angles are effectively
1107 The zero vector is default, indicating that a Source is not directional.
1108 Specifying a non-zero vector will make the Source directional.
1109 Specifying a zero vector for a directional Source will effectively
1110 mark it as nondirectional.
1114 <note id="rfc-bk000821-01"><title>RFC: Oriented Sources </title><para>
1115 Do we want an alternative AZIMUTH/ALTITUDE parametrization?
1116 Do we need ORIENTATION later? Is this superimposable? Can we mix both?
1121 <note><title>Annotation (All Sources Directional)</title><para>
1122 From the point of view of the &AL; implementation, all
1123 Sources are directional. Certain choices for cone angles
1124 as well as a direction vector with zero length are treated
1125 equivalent to an omnidirectional source. The &AL;
1126 implementation is free to flag and optimize these cases.
1131 <note id="rfc-bk000803-05"><title>RFC: Separate GenDirectionSource?</title><para>
1132 Is there any risk that directional sources require different
1133 resources that have to be allocated from the beginning, and
1134 that we can not change an omnidirectional source to a
1135 bidirectional source at runtime?
1142 <title>Source CONE_INNER_ANGLE Attribute</title>
1143 <tgroup cols="4" align="left" colsep=1 rowsep=1>
1154 <entry>CONE_INNER_ANGLE</>
1156 <entry>any except NaN</>
1163 Inside angle of the sound cone, in degrees. The default of 360 means that the
1164 inner angle covers the entire world, which is equivalent to an omnidirectional
1168 <note id="rfc-bk000926-01"><title>RFC: inconsistent cone angles? </title><para>
1169 Is (inner <= outer) required? Do we generate an error?
1170 Shouldn't this be a CONE_ANGLES 2f call specifying both angles at once?
1179 <title>Source CONE_OUTER_ANGLE Attribute</title>
1180 <tgroup cols="4" align="left" colsep=1 rowsep=1>
1191 <entry>CONE_OUTER_ANGLE</>
1193 <entry>any except NaN</>
1199 Description: Outer angle of the sound cone, in degrees. The default of 360 means that the
1200 outer angle covers the entire world. If the inner angle is also 360, then
1201 the zone for angle-dependent attenuation is zero.
1205 <note id="rfc-bk000926-02"><title>RFC: addition? </title><para>
1206 More generally, we could specify:
1207 "If the sum of inner and outer angles is larger than 360,
1208 CONE_OUTER_ANGLE is clamped to (360-CONE_INNER_ANGLE) and
1209 there is no transition zone."
1215 <title>Source CONE_OUTER_GAIN Attribute</title>
1216 <tgroup cols="4" align="left" colsep=1 rowsep=1>
1227 <entry>CONE_OUTER_GAIN</>
1229 <entry>[0.0f, 1.0f]</>
1235 Description: the factor with which GAIN is multiplied to
1236 determine the effective gain outside the cone defined by
1237 the outer angle. The effective gain applied outside the
1238 outer cone is GAIN times CONE_OUTER_GAIN. Changing
1239 GAIN affects all directions, i.e. the source is attenuated
1240 in all directions, for any position of the listener.
1241 The application has to change CONE_OUTER_GAIN as well if
1242 a different behavior is desired.
1247 <note><title>Annotation (GAIN calculation)</title><para>
1248 The angle-dependend gain DGAIN is multiplied with the
1249 gain determined by the source's GAIN and any distance
1250 attenuation as applicable. Let theta be the angle
1251 between the source's direction vector, and the vector
1252 connection the source and the listener. This multiplier
1253 DGAIN is calculated as:
1255 OUTER = CONE_OUTER_ANGLE/2;
1256 INNER = CONE_INNER_ANGLE/2;
1257 if ( theta less/equal INNER )
1259 else if ( theta greater/equal OUTER )
1260 DGAIN = CONE_OUTER_GAIN
1262 DGAIN = 1 - (1-CONE_OUTER_GAIN)*((theta-INNER)/(OUTER-INNER))
1265 in the case of linear interpolation. The implementation
1266 is free to use a different interplation across the (INNER,OUTER)
1267 range as long as it is monotone.
1272 <note><title>Annotation (CONE_OUTER_GAIN always less than GAIN)</title><para>
1273 CONE_OUTER_GAIN is not an absolute value, but (like all GAIN
1274 parameters) a scaling factor. This avoids a possible error
1275 case (implementations can count on effective gain outside the
1276 outer cone being smaller than GAIN), and ensures the common
1277 case in which changing GAIN should affect inner, transitional,
1278 and outer zone simultaneously.
1280 In case that the application desires to have an outer zone
1281 volume exceeding that of the inner cone, the mapping to
1282 &AL; will require to rotate the Source direction to the
1283 opposite direction (negate vector), and swapping
1284 inner and outer angle.
1292 <title>Changing Source Attributes</title>
1294 The Source specifies the position and other properties as
1295 taken into account during sound processing.
1296 <funcsynopsis><funcprototype>
1297 <funcdef> void <function> Source{n}{sifd} </function></funcdef>
1298 <paramdef> &uint; <parameter> sourceName </parameter></paramdef>
1299 <paramdef> &enum; <parameter> paramName </parameter></paramdef>
1300 <paramdef> &type; <parameter> value </parameter></paramdef>
1301 </funcprototype></funcsynopsis>
1302 <funcsynopsis><funcprototype>
1303 <funcdef> void <function> Source{n}{sifd}v </function></funcdef>
1304 <paramdef> &uint; <parameter> sourceName </parameter></paramdef>
1305 <paramdef> &enum; <parameter> paramName </parameter></paramdef>
1306 <paramdef> &type;* <parameter> values </parameter></paramdef>
1307 </funcprototype></funcsynopsis>
1312 <title>Querying Source Attributes</title>
1314 Source state is maintained inside the &AL; implementation, and the
1315 current attributes can be queried. The performance of such queries is
1316 implementation dependent, no performance guarantees are made. The
1317 valid values for the paramName parameter are identical to the ones
1319 <funcsynopsis><funcprototype>
1320 <funcdef> void <function> GetSource{n}{sifd}{v} </function></funcdef>
1321 <paramdef> &uint; <parameter> sourceName </parameter></paramdef>
1322 <paramdef> &enum; <parameter> paramName </parameter></paramdef>
1323 <paramdef> &type;* <parameter> values </parameter></paramdef>
1324 </funcprototype></funcsynopsis>
1329 Old signature: T GetSource{sifd}{v}( uint id, enum param );
1337 <sect2 id="queueing">
1338 <title>Queueing Buffers with a Source</title>
1340 &AL; does not specify a built-in streaming mechanism. There
1341 is no mechanism to stream data e.g. into a Buffer object.
1342 Instead, the API introduces a more flexible and versatile
1343 mechanism to queue Buffers for Sources.
1346 There are many ways to use this feature, with
1347 streaming being only one of them.
1351 Streaming is replaced by queuing static
1352 buffers. This effectively moves any multi-buffer
1353 caching into the application and allows the
1354 application to select how many buffers it wants
1355 to use, whether these are re-used in cycle,
1356 pooled, or thrown away.
1361 Looping (over a finite number of repititions) can be
1362 implemented by explicitely repeating buffers
1363 in the queue. Infinite loops can (theoretically)
1364 be accomplished by sufficiently large repetition counters.
1365 If only a single buffer is supposed to be repeated
1366 infinitely, using the respective Source attribute is
1372 Loop Points for restricted looping inside a buffer
1373 can in many cases be replaced by splitting the
1374 sample into several buffers, queueing the sample
1375 fragments (including repetitions) accordingly.
1379 Buffers can be queued, unqueued after they have been
1380 used, and either be deleted, or refilled and queued again.
1381 Splitting large samples over several buffers maintained
1382 in a queue has a distinct advantages over approaches that
1383 require explicit management of samples and sample indices.
1387 <note id="bk000626-01"><title>RFC: Unified Handling</title><para>
1388 Jonathan Blow has proposed removing the distinction between
1389 streaming and non-streaming buffers. An existing example is
1390 the unified for directional and omnidirectional sources, where
1391 all sources are treated as directional.
1397 <title>Queueing command</title>
1399 The application can queue up one or multiple buffer names
1400 using SourceQueueBuffers. The buffers will be queued in the sequence
1401 in which they appear in the array.
1402 <funcsynopsis><funcprototype>
1403 <funcdef> &void; <function> alSourceQueueBuffers </function></funcdef>
1404 <paramdef> &uint; <parameter> sourceName </parameter></paramdef>
1405 <paramdef> &sizei; <parameter> numBuffers </parameter></paramdef>
1406 <paramdef> &uint; * <parameter> bufferNames </parameter></paramdef>
1407 </funcprototype></funcsynopsis>
1408 This command is legal on a Source in any state (to allow for
1409 streaming, queueing has to be possible on a PLAYING Source).
1410 Queues are read-only with exception of the unqueue operation.
1411 The Buffer Name NONE (i.e. 0) can be queued.
1415 <note><title>Annotation (BUFFER vs. SourceQueueBuffers)</title><para>
1416 A Sourcei( sname, BUFFER, bname ) command is an immediate
1417 command, and executed immediately. It effectively unqueues
1418 all buffers, and then adds the specified buffer to the
1419 then empty queue as its single entry. Consequently, this
1420 call is only legal if SourceUnqueueBuffers is legal.
1421 In particular, the Source has to be STOPPED or INITIAL.
1422 The application is still obliged to delete all
1423 buffers as were contained in the queue.
1424 Sourcei( sname, BUFFER, NONE ) is a legal command,
1425 effectively wiping the queue without specifying an
1426 actually playable buffer.
1432 <note><title>Annotation (Buffer Repetition)</title><para>
1433 To accomplish a finite number of repetitions of a buffer name multiple times,
1434 the buffer has to be queued multiple times. If the need occurs, the
1435 API could be extended by SourceQueueBuffer( sname, bname, repetitions )
1441 <note id="rfc-bk000806-04"><title>RFC: Duration of bName==0? </title><para>
1442 The buffer is considered empty, it should have zero length,
1443 thus zero duration for consistency. If an application wants to
1444 schedule a pause, specifying duration for a gain==0 queue entry
1445 might be a cleaner solution.
1451 <note><title>Annotation (Backwards Compatiblity)</title><para>
1452 Sourcei( sname, BUFFER, bname ) has been rejected as
1453 a queueing command, as it would make semantics dependent on
1454 source state (queueing if PLAYING, immediate else).
1455 The command is not legal on a PLAYING or PAUSED Source.
1460 <note><title>Annotation (No BUFFER_QUEUE)</title><para>
1461 Duplication of one entry point is preferable to
1462 duplicating token enums, and tokens do not express
1463 commands, but specify the attribute/state affected.
1464 From the same reason, there is no BUFFER_UNQUEUE
1472 <title>Unqueueing command</title>
1474 Once a queue entry for a buffer has been appended to a queue
1475 and is pending processing, it should not be changed.
1476 Removal of a given queue entry is not possible unless
1477 either the Source is STOPPED (in which case then entire queue
1478 is considered processed), or if the queue entry has already
1479 been processed (PLAYING or PAUSED Source).
1482 The Unqueue command removes a number of buffers entries that
1483 have finished processing, in the order of appearance, from
1484 the queue. The operation will fail if more buffers are
1485 requested than available, leaving the destination arguments
1486 unchanged. An INVALID_VALUE error will be thrown.
1487 If no error, the destination argument will have been updated
1489 <funcsynopsis><funcprototype>
1490 <funcdef> void <function> SourceUnqueueBuffers </function></funcdef>
1491 <paramdef> &uint; <parameter> sourceName </parameter></paramdef>
1492 <paramdef> &sizei; <parameter> numEntries </parameter></paramdef>
1493 <paramdef> &uint;* <parameter> bufferNames </parameter></paramdef>
1494 </funcprototype></funcsynopsis>
1498 <note><title>Annotation (Unqueueing shared buffers)</title><para>
1499 If a buffer is queued with more than one source, it might have
1500 been processed for some not all of them. With the current
1501 interface, the application is forced to maintain its own list
1502 of consumers (Sources) for a buffer it wishes to unqueue.
1503 For groups of Sources that are never individually PAUSED
1504 nor STOPPED, the application can save the MRU Source for
1505 which the buffer was scheduled last.
1510 <note><title>Annotation (Looping a Queue vs. Unqueue):</title><para>
1511 If a Source is playing repeatedly, it will traverse
1512 the entire Queue repeatedly. Consequently, no buffer
1513 in the queue can be considered processed until
1514 there is no further repetition scheduled.
1519 <note><title>Annotation (No Name based access)</title><para>
1520 No interface is provided to access a queue entry by name,
1521 due to ambiguity (same buffer name scheduled several times
1527 <note><title>Annotation (No Index based access)</title><para>
1528 No interface is provided for random access to a queue entry
1538 <title>More Annotation on Queueing</title>
1541 <note><title>Annotation (No Queue Copying)</title><para>
1542 The current queue of a source could be copied to another source,
1543 as repetition and traversal parameters are stored unless the
1544 queue entry is unqueued, or the queue is replaced using
1545 AL_BUFFER. Copying a queue is a special case of
1546 copying Source state in one sense, and a special case of
1547 a synching problem in another. Due to these unresolved issues
1548 no such command is included in the current specification.
1549 To share queues, the application can keep buffer names
1550 and the selected attributes that define the queue entries
1551 in an array or other lookup table.
1556 <note><title>Annotation (No Explicit QueueClear)</title><para>
1557 Sourcei( sname, BUFFER, NONE ) serves the
1558 same purpose. The operation is also redundant
1559 with respect to Unqueue for a STOPPED Source.
1564 <note><title>Annotation (Queueing vs. AppendData):</title><para>
1565 Buffer queueing does not solve the synchronization and timing
1566 issues raised by possible underflow, as these are inherent
1567 to application-driven (pushed) streaming. However, it turns
1568 an internal AL error condition (offset exceeds valid data)
1569 into an audible artifact (Source stops).
1570 Its main advantage is that it allows the application coder
1571 to operate at a scale of her own choice, selecting the
1572 number and size of buffers used for caching the stream,
1573 and to schedule buffer refill and queueing according to
1574 preferences and constraints. Queueing effectively moves
1575 all problems related to replacing or appending Buffer data
1576 to the scale of entire arrays istead of single samples and
1582 <note><title>Annotation (Multiple Sources on a stream)</title><para>
1583 Queueing allows for the application to determine how much of
1584 a backlog of the data stream is preserved. The application can
1585 keep buffers, and queue them with other Sources after they have
1586 been used already by the original Source. Unlike the mechanism
1587 for appending data to a buffer, the backlog is visible to the
1588 application and under its control, and no synchronization of
1589 Sources using the stream is required.
1596 <note><title>Annotation (Loop Points and Compressed Data)</title><para>
1597 For compressed data, uncompression by the application might be
1598 impossible or undesireable. In consequence, splitting the sample
1599 into several buffers is not possible without explicit support
1600 by the API. Buffer-Buffer operations will be added as needed,
1601 for the time being applications should not try to use compressed
1602 samples if more than full looping is required.
1609 <note><title>Annotation (No Explicit Queue Objects)</title><para>
1610 Explicit Queue objects have been considered and rejected,
1611 as they introduce another producer-consumer dependency with
1612 another level of indirection. Further, e.g. QUEUE would
1613 also require deprecating BUFFER (breaking backwards
1614 compatibility) as an alSource argument, or would introduce
1615 a confusing set of precedence and overide rules if both
1616 are used in sequence. However, in the absence of explicit
1617 queue objects the application will be forced to keep track
1618 where buffers have been queued in case it intends to
1619 unqueue them for refill or deletion. If several sources
1620 use the same buffers (e.g. for synchronous or
1621 asynchronous streaming) the buffer will have to be
1622 unqueued from each single one.
1628 <note><title>Annotation (Queue no Display List)</title><para>
1629 An interface resembling &OGL; display-lists has been
1630 considered and rejected. The problem with this approach
1631 is that not only commands would have to be prohibited
1632 (similarly, not all GL calls are legal within a display
1633 list), but also parameters (enumerations).
1635 In particular, only a small set of operations is meant
1636 to be legal for a queue at this point, and appending
1637 to a queue has to be possible at any time.
1638 Within a hypothetical AL display list, only relative
1639 timing/conditionals are allowed as arguments. This
1640 might necessitate to have multiple forms for deferred
1641 commands, or to not allow for absolute timing.
1645 // lock this queue for overwriting/appending
1646 alBeginQueue( qname, APPEND | REPLACE );
1648 // queue a buffer in sequence, with parameters
1649 // boolean: never skip? never bail?
1650 alQueue( AL_BUFFER, bid, loopdir, repetitions );
1654 // Existing queue content will be replaced
1655 // or appended at this point.
1664 <title>Queue Then Delete </title>
1672 request deletion of buffer1,2,3
1680 <title> Queue and Refill with Dual Buffering</title>
1689 check for unused buffers
1701 <title> Queue for Loop Points</title>
1706 split sample data into pre/main/post
1708 queue main with repetitions
1711 set repetitions to 0 on main when needed
1712 wait till post has been played
1723 <title>Attributes Specific to Queueing</title>
1726 <title>Buffer Traversal</title>
1728 The Buffer traversal attribute specifies the direction
1729 in which the sample in the buffer is supposed to be
1730 processed. To account for the 3 basic modes of traversal that
1731 can be implemented in software and hardware, the following
1734 LOOP_DIRECTION /* traversal direction */
1736 FORWARD /* linear forward (increment) */
1737 BACKWARD /* linear backward (decrement) */
1738 FORWARD_AND_BACK /* RESERVED: ping-pong-looping */
1741 The first and the next two tokens are legal with a buffer queue command.
1742 They are not legal for a Source command, in any possible
1743 Source state. The last token is reserved, but not yet legal to use.
1748 <note><title>Annotation (Ping-Pong postponed)</title><para>
1749 Definition and implementation of ping-pong looping
1750 has been postponed. Applications can fake it at doubling
1751 memory expense by reverse copying the buffer (2nd buffer queued
1752 or in a double size single buffer). If there is hardware support
1753 for this feature, AL will have to support it eventually. A boolean
1754 flag is not acceptable because of this possibility.
1758 ]]> <!-- SCRATCH -->
1769 <title>Managing Source Execution</title>
1771 The execution state of a source can be queried. &AL; provides
1772 a set of functions that initiate state transitions causing
1773 Sources to start and stop execution.
1776 TBA: State Transition Diagram.
1780 <note><title>Annotation/ Source Config/Exec State</title><para>
1781 Sources have configuration state and execution state.
1782 Configuration state is directly set by the application using
1783 AL commands, starting with the INITIAL configuration. Execution
1784 state (e.g. the offset to the current sample) is not under direct
1785 application control and not exposed.
1790 <title>Source State Query</title>
1792 The application can query the current state of any Source
1793 using GetSource with the parameter Name SOURCE_STATE.
1794 Each Source can be in one of four possible execution states:
1795 INITIAL, PLAYING, PAUSED, STOPPED. Sources that are either
1796 PLAYING or PAUSED are considered active. Sources that are
1797 STOPPED or INITIAL are considered inactive. Only PLAYING
1798 Sources are included in the processing. The implementation
1799 is free to skip those processing stages for Sources that
1800 have no effect on the output (e.g. mixing for a Source
1801 muted by zero GAIN, but not sample offset increments).
1802 Depending on the current state of a Source certain (e.g. repeated)
1803 state transition commands are legal NOPs: they will be ignored,
1804 no error is generated.
1809 <title>State Transition Commands</title>
1811 The default state of any Source is INITIAL. From this state
1812 it can be propagated to any other state by appropriate use
1813 of the commands below. There are no irreversible state
1815 <funcsynopsis><funcprototype>
1816 <funcdef> void <function> SourcePlay </function></funcdef>
1817 <paramdef> &uint; <parameter> sName </parameter></paramdef>
1818 </funcprototype></funcsynopsis>
1819 <funcsynopsis><funcprototype>
1820 <funcdef> void <function> SourcePause </function></funcdef>
1821 <paramdef> &uint; <parameter> sName </parameter></paramdef>
1822 </funcprototype></funcsynopsis>
1823 <funcsynopsis><funcprototype>
1824 <funcdef> void <function> SourceStop </function></funcdef>
1825 <paramdef> &uint; <parameter> sName </parameter></paramdef>
1826 </funcprototype></funcsynopsis>
1827 <funcsynopsis><funcprototype>
1828 <funcdef> void <function> SourceRewind </function></funcdef>
1829 <paramdef> &uint; <parameter> sName </parameter></paramdef>
1830 </funcprototype></funcsynopsis>
1835 The functions are also available as a vector variant,
1836 which guarantees synchronized operation on a set of
1838 <funcsynopsis><funcprototype>
1839 <funcdef> void <function> SourcePlayv </function></funcdef>
1840 <paramdef> &sizei; <parameter> n </parameter></paramdef>
1841 <paramdef> &uint;* <parameter> sNames </parameter></paramdef>
1842 </funcprototype></funcsynopsis>
1843 <funcsynopsis><funcprototype>
1844 <funcdef> void <function> SourcePausev </function></funcdef>
1845 <paramdef> &sizei; <parameter> n </parameter></paramdef>
1846 <paramdef> &uint;* <parameter> sNames </parameter></paramdef>
1847 </funcprototype></funcsynopsis>
1848 <funcsynopsis><funcprototype>
1849 <funcdef> void <function> SourceStopv </function></funcdef>
1850 <paramdef> &sizei; <parameter> n </parameter></paramdef>
1851 <paramdef> &uint;* <parameter> sNames </parameter></paramdef>
1852 </funcprototype></funcsynopsis>
1854 <funcsynopsis><funcprototype>
1855 <funcdef> void <function> SourceRewindv </function></funcdef>
1856 <paramdef> &sizei; <parameter> n </parameter></paramdef>
1857 <paramdef> &uint;* <parameter> sNames </parameter></paramdef>
1858 </funcprototype></funcsynopsis>
1862 The following state/command/state transitions are defined:
1866 Play() applied to an INITIAL Source will promote the Source
1867 to PLAYING, thus the data found in the Buffer will be fed
1868 into the processing, starting at the beginning.
1869 Play() applied to a PLAYING Source will restart the Source
1870 from the beginning. It will not affect the configuration,
1871 and will leave the Source in PLAYING state, but reset the
1872 sampling offset to the beginning.
1873 Play() applied to a PAUSED Source will
1874 resume processing using the Source state
1875 as preserved at the Pause() operation.
1876 Play() applied to a STOPPED Source will propagate it
1877 to INITIAL then to PLAYING immediately.
1882 Pause() applied to an INITIAL Source is a legal NOP.
1883 Pause() applied to a PLAYING Source will change its state to
1884 PAUSED. The Source is exempt from processing, its current
1886 Pause() applied to a PAUSED Source is a legal NOP.
1887 Pause() applied to a STOPPED Source is a legal NOP.
1892 Stop() applied to an INITIAL Source is a legal NOP.
1893 Stop() applied to a PLAYING Source will change its state to
1894 STOPPED. The Source is exempt from processing, its current
1896 Stop() applied to a PAUSED Source will change its state
1897 to STOPPED, with the same consequences as on a PLAYING
1899 Stop() applied to a STOPPED Source is a legal NOP.
1904 Rewind() applied to an INITIAL Source is a legal NOP.
1905 Rewind() applied to a PLAYING Source will change its state to
1906 STOPPED then INITIAL. The Source is exempt from processing:
1907 its current state is preserved, with the exception of the
1908 sampling offset, which is reset to the beginning.
1909 Rewind() applied to a PAUSED Source will change its state
1910 to INITIAL, with the same consequences as on a PLAYING
1912 Rewind() applied to a STOPPED Source promotes the Source
1913 to INITIAL, resetting the sampling offset to the beginning.
1920 <note><title>Annotation (SourceNext)</title><para>
1921 The specification does not provide any means to
1922 immediately skip from the current Buffer to the
1923 next in the queue. A conditional stop (following
1924 the next complete traversal) is available.
1925 If necessary an additonal entry point could be
1926 provided in future revisions.
1931 <note><title>Annotation (Rewind() optional)</title><para>
1932 The INITIAL state is not identical to the STOPPED state.
1933 Applications that want to verify whether a Source
1934 has indeed been PLAYING before becoming STOPPED can
1935 use Rewind() to reset the Source state to INITIAL.
1936 This is an optional operation that can safely be
1937 omitted by application without this constraint.
1938 Applications that want to guard against Play() on
1939 a Source that is INITIAL can query the Source state
1945 <note><title>Annotation (Play() on a PLAYING Source)</title><para>
1946 Repeated Play() commands applied a PLAYING Source are
1947 interpreted as an (atomic) sequence to stop and restart a
1948 Source. This can be used by applications that want to restart
1949 a sound but do not care whether the Source has finished or not,
1950 and do not want an audible pause. One example is the DOOM
1951 chaingun repeatedly abbreviating the pistol sound. To guard
1952 against redundant Play() commands, an application can query
1953 the current state before executing Play(). If the application
1954 coder wants to be sure that the Source will play the buffer
1955 again, she can either increment PLAY_COUNT, or queue the buffer.
1960 <note><title>Annotation (redundant commands)</title><para>
1961 The simple variant (e.g. SourcePlay) is redundant to
1962 the vector variant (e.g. SourcePlayv). However, these
1963 calls will be used frequently, and the simple variant
1964 is provided for convenience. However, &AL; does not
1965 enable applications to use literals as source names.
1972 <title>Resetting Configuration</title>
1974 The INITIAL state is not necessarily identical to the
1975 default state in which Source is created. INITIAL merely
1976 indicates that the Source can be executed using the
1977 SourcePlay command. A STOPPED or INITIAL Source can
1978 be reset into the default configuration by using a
1979 sequence Source commands as necessary. As the application
1980 has to specify all relevant state anyway to create a
1981 useful Source configuration, no reset command is provided.
1986 <note id="rfc-bk000802-01"><title>RFC: remove INITIAL</title><para>
1987 INITIAL is identical to STOPPED. The only additional information
1988 conveyed is that INITIAL indicates a source has never been played.
1989 Once a Source is STOPPED, it is not possible by state query alone
1990 to decide whether it has played again. If Sources are used only
1991 once, an application can use INITIAL to verify a Source has been
1993 The problem that I have with this is that if we acknowledge that
1994 the application might need to verify a Source has played once,
1995 why force the application to throw away Sources to accomplish
1996 this? An explicit state PLAYABLE replacing INITIAL and its
1997 inauspicious connotations (default state) and a state transition
1998 function Rewind() that makes a STOPPED Source PLAYABLE again would
1999 be one possibility to address this need. The obvious drawback is
2000 that it breaks backwards compatibility.
2006 <note id="rfc-bk000731-01"><title>RFC: state issues </title><para>
2007 A Source is active if it is PAUSED or PLAYING.
2009 A Source that is STOPPED preserves configuration state,
2010 including buffer/queue information.
2012 Only a Source that is Reset() to INITIAL looses all
2013 buffer and queue information. In this case, the INITIAL
2015 Sources will be stopped implicitely when reaching the
2016 end of a non-repeating (non-looping) buffer traversal.
2017 Sources can be stopped explicitely by the application
2018 with either Stop() or Reset().
2021 the source to STOPPED preserving its configuration state,
2022 setting its execution state to the same as if it reached
2023 the end of execution.
2030 <note><title>Annotation (illegal NOPs)</title><para>
2031 In the current specification there are no illegal NOPs.
2032 In other words, no sequence of commands affecting the
2033 execution state will generate an INVALID_OPERATION error.
2039 <note><title>RFC/bk000504:</title><para>
2040 No UNDEFINED state. Always valid state. I.e. we have a default Buffer
2041 that is used for sources where the application doesn't specify,
2042 and what's in it? Default gain is zero? We need to specify
2046 <note><title>RFC/bk000504:</title><para>
2047 Potential ambiguity: how to we distinguish STOPPED as
2048 requested by the application from INACTIVE for
2049 non-looping sounds once the buffer has been iterated?
2050 Related: handling of Sources using an underflowing
2051 streaming buffer? IMO not recommended, make this
2056 <note><title>RFC/bk000504:</title><para>
2057 Possible redundancy: the only reason for STOP seems to
2058 be resetting the play positions. Redundant if we
2059 ever manipulate offsets directly (rewind/set).
2062 <note><title>RFC/bk000504:</title><para>
2063 Possible redundancy:
2064 If we ever want to support explicit setting of the start
2065 position/offset into Buffer, START is equivalent to Set(0).
2066 Also see LOOP (implies has to be STOPPED). Fade-Out and
2067 Fade-In control - always manually?