Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lDEVinux
GitHub Repository: lDEVinux/eaglercraft
Path: blob/main/src/lwjgl/java/paulscode/sound/libraries/SourceLWJGLOpenAL.java
8650 views
1
package paulscode.sound.libraries;
2
3
import java.nio.IntBuffer;
4
import java.nio.FloatBuffer;
5
import java.util.LinkedList;
6
import javax.sound.sampled.AudioFormat;
7
8
// From the lwjgl library, http://www.lwjgl.org
9
import org.lwjgl.BufferUtils;
10
import org.lwjgl.openal.AL10;
11
12
import paulscode.sound.Channel;
13
import paulscode.sound.FilenameURL;
14
import paulscode.sound.Source;
15
import paulscode.sound.SoundBuffer;
16
import paulscode.sound.SoundSystemConfig;
17
18
/**
19
* The SourceLWJGLOpenAL class provides an interface to the lwjgl binding of OpenAL.
20
*<b><br><br>
21
* This software is based on or using the LWJGL Lightweight Java Gaming
22
* Library available from
23
* http://www.lwjgl.org/.
24
*</b><br><br>
25
* LWJGL License:
26
*<br><i>
27
* Copyright (c) 2002-2008 Lightweight Java Game Library Project
28
* All rights reserved.
29
*<br>
30
* Redistribution and use in source and binary forms, with or without
31
* modification, are permitted provided that the following conditions are
32
* met:
33
* <br>
34
* * Redistributions of source code must retain the above copyright
35
* notice, this list of conditions and the following disclaimer.
36
*<br>
37
* * Redistributions in binary form must reproduce the above copyright
38
* notice, this list of conditions and the following disclaimer in the
39
* documentation and/or other materials provided with the distribution.
40
*<br>
41
* * Neither the name of 'Light Weight Java Game Library' nor the names of
42
* its contributors may be used to endorse or promote products derived
43
* from this software without specific prior written permission.
44
* <br>
45
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
46
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
47
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
48
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
49
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
50
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
52
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
53
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
54
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
55
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56
* <br><br><br></i>
57
*<b><i> SoundSystem LibraryLWJGLOpenAL License:</b></i><br><b><br>
58
*<b>
59
* You are free to use this library for any purpose, commercial or otherwise.
60
* You may modify this library or source code, and distribute it any way you
61
* like, provided the following conditions are met:
62
*<br>
63
* 1) You must abide by the conditions of the aforementioned LWJGL License.
64
*<br>
65
* 2) You may not falsely claim to be the author of this library or any
66
* unmodified portion of it.
67
*<br>
68
* 3) You may not copyright this library or a modified version of it and then
69
* sue me for copyright infringement.
70
*<br>
71
* 4) If you modify the source code, you must clearly document the changes
72
* made before redistributing the modified source code, so other users know
73
* it is not the original code.
74
*<br>
75
* 5) You are not required to give me credit for this library in any derived
76
* work, but if you do, you must also mention my website:
77
* http://www.paulscode.com
78
*<br>
79
* 6) I the author will not be responsible for any damages (physical,
80
* financial, or otherwise) caused by the use if this library or any part
81
* of it.
82
*<br>
83
* 7) I the author do not guarantee, warrant, or make any representations,
84
* either expressed or implied, regarding the use of this library or any
85
* part of it.
86
* <br><br>
87
* Author: Paul Lamb
88
* <br>
89
* http://www.paulscode.com
90
* </b>
91
*/
92
public class SourceLWJGLOpenAL extends Source
93
{
94
/**
95
* The source's basic Channel type-cast to a ChannelLWJGLOpenAL.
96
*/
97
private ChannelLWJGLOpenAL channelOpenAL = (ChannelLWJGLOpenAL) channel;
98
99
/**
100
* OpenAL IntBuffer sound-buffer identifier for this source if it is a normal
101
* source.
102
*/
103
private IntBuffer myBuffer;
104
105
/**
106
* FloatBuffer containing the listener's 3D coordinates.
107
*/
108
private FloatBuffer listenerPosition;
109
110
/**
111
* FloatBuffer containing the source's 3D coordinates.
112
*/
113
private FloatBuffer sourcePosition;
114
115
/**
116
* FloatBuffer containing the source's velocity vector.
117
*/
118
private FloatBuffer sourceVelocity;
119
120
/**
121
* Constructor: Creates a new source using the specified parameters.
122
* @param listenerPosition FloatBuffer containing the listener's 3D coordinates.
123
* @param myBuffer OpenAL IntBuffer sound-buffer identifier to use for a new normal source.
124
* @param priority Setting this to true will prevent other sounds from overriding this one.
125
* @param toStream Setting this to true will create a streaming source.
126
* @param toLoop Should this source loop, or play only once.
127
* @param sourcename A unique identifier for this source. Two sources may not use the same sourcename.
128
* @param filenameURL Filename/URL of the sound file to play at this source.
129
* @param soundBuffer Buffer containing audio data, or null if not loaded yet.
130
* @param x X position for this source.
131
* @param y Y position for this source.
132
* @param z Z position for this source.
133
* @param attModel Attenuation model to use.
134
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of 'att'.
135
* @param temporary Whether or not to remove this source after it finishes playing.
136
*/
137
public SourceLWJGLOpenAL( FloatBuffer listenerPosition, IntBuffer myBuffer,
138
boolean priority, boolean toStream,
139
boolean toLoop, String sourcename,
140
FilenameURL filenameURL, SoundBuffer soundBuffer,
141
float x, float y, float z, int attModel,
142
float distOrRoll, boolean temporary )
143
{
144
super( priority, toStream, toLoop, sourcename, filenameURL, soundBuffer,
145
x, y, z, attModel, distOrRoll, temporary );
146
if( codec != null )
147
codec.reverseByteOrder( true );
148
this.listenerPosition = listenerPosition;
149
this.myBuffer = myBuffer;
150
libraryType = LibraryLWJGLOpenAL.class;
151
pitch = 1.0f;
152
resetALInformation();
153
}
154
155
/**
156
* Constructor: Creates a new source matching the specified source.
157
* @param listenerPosition FloatBuffer containing the listener's 3D coordinates.
158
* @param myBuffer OpenAL IntBuffer sound-buffer identifier to use for a new normal source.
159
* @param old Source to copy information from.
160
* @param soundBuffer Buffer containing audio data, or null if not loaded yet.
161
*/
162
public SourceLWJGLOpenAL( FloatBuffer listenerPosition, IntBuffer myBuffer,
163
Source old, SoundBuffer soundBuffer )
164
{
165
super( old, soundBuffer );
166
if( codec != null )
167
codec.reverseByteOrder( true );
168
this.listenerPosition = listenerPosition;
169
this.myBuffer = myBuffer;
170
libraryType = LibraryLWJGLOpenAL.class;
171
pitch = 1.0f;
172
resetALInformation();
173
}
174
175
/**
176
* Constructor: Creates a new streaming source that will be directly fed with
177
* raw audio data.
178
* @param listenerPosition FloatBuffer containing the listener's 3D coordinates.
179
* @param audioFormat Format that the data will be in.
180
* @param priority Setting this to true will prevent other sounds from overriding this one.
181
* @param sourcename A unique identifier for this source. Two sources may not use the same sourcename.
182
* @param x X position for this source.
183
* @param y Y position for this source.
184
* @param z Z position for this source.
185
* @param attModel Attenuation model to use.
186
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of 'att'.
187
*/
188
public SourceLWJGLOpenAL( FloatBuffer listenerPosition,
189
AudioFormat audioFormat, boolean priority,
190
String sourcename, float x, float y, float z,
191
int attModel, float distOrRoll )
192
{
193
super( audioFormat, priority, sourcename, x, y, z, attModel,
194
distOrRoll );
195
this.listenerPosition = listenerPosition;
196
libraryType = LibraryLWJGLOpenAL.class;
197
pitch = 1.0f;
198
resetALInformation();
199
}
200
201
/**
202
* Shuts the source down and removes references to all instantiated objects.
203
*/
204
@Override
205
public void cleanup()
206
{
207
208
super.cleanup();
209
}
210
211
/**
212
* Changes the peripheral information about the source using the specified
213
* parameters.
214
* @param listenerPosition FloatBuffer containing the listener's 3D coordinates.
215
* @param myBuffer OpenAL IntBuffer sound-buffer identifier to use for a new normal source.
216
* @param priority Setting this to true will prevent other sounds from overriding this one.
217
* @param toStream Setting this to true will create a streaming source.
218
* @param toLoop Should this source loop, or play only once.
219
* @param sourcename A unique identifier for this source. Two sources may not use the same sourcename.
220
* @param filenameURL Filename/URL of the sound file to play at this source.
221
* @param soundBuffer Buffer containing audio data, or null if not loaded yet.
222
* @param x X position for this source.
223
* @param y Y position for this source.
224
* @param z Z position for this source.
225
* @param attModel Attenuation model to use.
226
* @param distOrRoll Either the fading distance or rolloff factor, depending on the value of 'att'.
227
* @param temporary Whether or not to remove this source after it finishes playing.
228
*/
229
public void changeSource( FloatBuffer listenerPosition, IntBuffer myBuffer,
230
boolean priority, boolean toStream,
231
boolean toLoop, String sourcename,
232
FilenameURL filenameURL, SoundBuffer soundBuffer,
233
float x, float y, float z, int attModel,
234
float distOrRoll, boolean temporary )
235
{
236
super.changeSource( priority, toStream, toLoop, sourcename,
237
filenameURL, soundBuffer, x, y, z, attModel,
238
distOrRoll, temporary );
239
this.listenerPosition = listenerPosition;
240
this.myBuffer = myBuffer;
241
pitch = 1.0f;
242
resetALInformation();
243
}
244
245
/**
246
* Removes the next filename from the sound sequence queue and assigns it to
247
* this source. This method has no effect on non-streaming sources. This
248
* method is used internally by SoundSystem, and it is unlikely that the user
249
* will ever need to use it.
250
* @return True if there was something in the queue.
251
*/
252
@Override
253
public boolean incrementSoundSequence()
254
{
255
if( !toStream )
256
{
257
errorMessage( "Method 'incrementSoundSequence' may only be used " +
258
"for streaming sources." );
259
return false;
260
}
261
synchronized( soundSequenceLock )
262
{
263
if( soundSequenceQueue != null && soundSequenceQueue.size() > 0 )
264
{
265
filenameURL = soundSequenceQueue.remove( 0 );
266
if( codec != null )
267
codec.cleanup();
268
codec = SoundSystemConfig.getCodec( filenameURL.getFilename() );
269
if( codec != null )
270
{
271
codec.reverseByteOrder( true );
272
if( codec.getAudioFormat() == null )
273
codec.initialize( filenameURL.getURL() );
274
275
AudioFormat audioFormat = codec.getAudioFormat();
276
277
if( audioFormat == null )
278
{
279
errorMessage( "Audio Format null in method " +
280
"'incrementSoundSequence'" );
281
return false;
282
}
283
284
int soundFormat = 0;
285
if( audioFormat.getChannels() == 1 )
286
{
287
if( audioFormat.getSampleSizeInBits() == 8 )
288
{
289
soundFormat = AL10.AL_FORMAT_MONO8;
290
}
291
else if( audioFormat.getSampleSizeInBits() == 16 )
292
{
293
soundFormat = AL10.AL_FORMAT_MONO16;
294
}
295
else
296
{
297
errorMessage( "Illegal sample size in method " +
298
"'incrementSoundSequence'" );
299
return false;
300
}
301
}
302
else if( audioFormat.getChannels() == 2 )
303
{
304
if( audioFormat.getSampleSizeInBits() == 8 )
305
{
306
soundFormat = AL10.AL_FORMAT_STEREO8;
307
}
308
else if( audioFormat.getSampleSizeInBits() == 16 )
309
{
310
soundFormat = AL10.AL_FORMAT_STEREO16;
311
}
312
else
313
{
314
errorMessage( "Illegal sample size in method " +
315
"'incrementSoundSequence'" );
316
return false;
317
}
318
}
319
else
320
{
321
errorMessage( "Audio data neither mono nor stereo in " +
322
"method 'incrementSoundSequence'" );
323
return false;
324
}
325
326
// Let the channel know what format and sample rate to use:
327
channelOpenAL.setFormat( soundFormat,
328
(int) audioFormat.getSampleRate() );
329
preLoad = true;
330
}
331
return true;
332
}
333
}
334
return false;
335
}
336
337
/**
338
* Called every time the listener's position or orientation changes.
339
*/
340
@Override
341
public void listenerMoved()
342
{
343
positionChanged();
344
}
345
346
/**
347
* Moves the source to the specified position.
348
* @param x X coordinate to move to.
349
* @param y Y coordinate to move to.
350
* @param z Z coordinate to move to.
351
*/
352
@Override
353
public void setPosition( float x, float y, float z )
354
{
355
super.setPosition( x, y, z );
356
357
// Make sure OpenAL information has been created
358
if( sourcePosition == null )
359
resetALInformation();
360
else
361
positionChanged();
362
363
// put the new position information into the buffer:
364
sourcePosition.put( 0, x );
365
sourcePosition.put( 1, y );
366
sourcePosition.put( 2, z );
367
368
// make sure we are assigned to a channel:
369
if( channel != null && channel.attachedSource == this &&
370
channelOpenAL != null && channelOpenAL.ALSource != null )
371
{
372
// move the source:
373
AL10.alSource( channelOpenAL.ALSource.get( 0 ), AL10.AL_POSITION,
374
sourcePosition );
375
checkALError();
376
}
377
}
378
379
/**
380
* Recalculates the distance from the listner and the gain.
381
*/
382
@Override
383
public void positionChanged()
384
{
385
calculateDistance();
386
calculateGain();
387
388
if( channel != null && channel.attachedSource == this &&
389
channelOpenAL != null && channelOpenAL.ALSource != null )
390
{
391
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
392
AL10.AL_GAIN, (gain * sourceVolume
393
* (float) Math.abs( fadeOutGain )
394
* fadeInGain) );
395
checkALError();
396
}
397
checkPitch();
398
}
399
400
/**
401
* Checks the source's pitch.
402
*/
403
private void checkPitch()
404
{
405
if( channel != null && channel.attachedSource == this &&
406
LibraryLWJGLOpenAL.alPitchSupported() && channelOpenAL != null &&
407
channelOpenAL.ALSource != null )
408
{
409
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
410
AL10.AL_PITCH, pitch );
411
checkALError();
412
}
413
}
414
415
/**
416
* Sets whether this source should loop or only play once.
417
* @param lp True or false.
418
*/
419
@Override
420
public void setLooping( boolean lp )
421
{
422
super.setLooping( lp );
423
424
// make sure we are assigned to a channel:
425
if( channel != null && channel.attachedSource == this &&
426
channelOpenAL != null && channelOpenAL.ALSource != null )
427
{
428
if( lp )
429
AL10.alSourcei( channelOpenAL.ALSource.get( 0 ),
430
AL10.AL_LOOPING, AL10.AL_TRUE );
431
else
432
AL10.alSourcei( channelOpenAL.ALSource.get( 0 ),
433
AL10.AL_LOOPING, AL10.AL_FALSE );
434
checkALError();
435
}
436
}
437
438
/**
439
* Sets this source's attenuation model.
440
* @param model Attenuation model to use.
441
*/
442
@Override
443
public void setAttenuation( int model )
444
{
445
super.setAttenuation( model );
446
// make sure we are assigned to a channel:
447
if( channel != null && channel.attachedSource == this &&
448
channelOpenAL != null && channelOpenAL.ALSource != null )
449
{
450
// attenuation changed, so update the rolloff factor accordingly
451
if( model == SoundSystemConfig.ATTENUATION_ROLLOFF )
452
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
453
AL10.AL_ROLLOFF_FACTOR, distOrRoll );
454
else
455
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
456
AL10.AL_ROLLOFF_FACTOR, 0.0f );
457
checkALError();
458
}
459
}
460
461
/**
462
* Sets this source's fade distance or rolloff factor, depending on the
463
* attenuation model.
464
* @param dr New value for fade distance or rolloff factor.
465
*/
466
@Override
467
public void setDistOrRoll( float dr)
468
{
469
super.setDistOrRoll( dr );
470
// make sure we are assigned to a channel:
471
if( channel != null && channel.attachedSource == this &&
472
channelOpenAL != null && channelOpenAL.ALSource != null )
473
{
474
// if we are using rolloff attenuation, then dr is a rolloff factor:
475
if( attModel == SoundSystemConfig.ATTENUATION_ROLLOFF )
476
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
477
AL10.AL_ROLLOFF_FACTOR, dr );
478
else
479
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
480
AL10.AL_ROLLOFF_FACTOR, 0.0f );
481
checkALError();
482
}
483
}
484
485
/**
486
* Sets this source's velocity, for use in Doppler effect.
487
* @param x Velocity along world x-axis.
488
* @param y Velocity along world y-axis.
489
* @param z Velocity along world z-axis.
490
*/
491
@Override
492
public void setVelocity( float x, float y, float z )
493
{
494
super.setVelocity( x, y, z );
495
496
sourceVelocity = BufferUtils.createFloatBuffer( 3 ).put( new float[]
497
{ x, y, z } );
498
sourceVelocity.flip();
499
// make sure we are assigned to a channel:
500
if( channel != null && channel.attachedSource == this &&
501
channelOpenAL != null && channelOpenAL.ALSource != null )
502
{
503
AL10.alSource( channelOpenAL.ALSource.get( 0 ),
504
AL10.AL_VELOCITY, sourceVelocity );
505
checkALError();
506
}
507
}
508
509
/**
510
* Manually sets this source's pitch.
511
* @param value A float value ( 0.5f - 2.0f ).
512
*/
513
@Override
514
public void setPitch( float value )
515
{
516
super.setPitch( value );
517
checkPitch();
518
}
519
520
/**
521
* Plays the source on the specified channel.
522
* @param c Channel to play on.
523
*/
524
@Override
525
public void play( Channel c )
526
{
527
if( !active() )
528
{
529
if( toLoop )
530
toPlay = true;
531
return;
532
}
533
534
if( c == null )
535
{
536
errorMessage( "Unable to play source, because channel was null" );
537
return;
538
}
539
540
boolean newChannel = (channel != c);
541
if( channel != null && channel.attachedSource != this )
542
newChannel = true;
543
544
boolean wasPaused = paused();
545
546
super.play( c );
547
548
channelOpenAL = (ChannelLWJGLOpenAL) channel;
549
550
// Make sure the channel exists:
551
// check if we are already on this channel:
552
if( newChannel )
553
{
554
setPosition( position.x, position.y, position.z );
555
checkPitch();
556
557
// Send the source's attributes to the channel:
558
if( channelOpenAL != null && channelOpenAL.ALSource != null )
559
{
560
if( LibraryLWJGLOpenAL.alPitchSupported() )
561
{
562
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
563
AL10.AL_PITCH, pitch );
564
checkALError();
565
}
566
AL10.alSource( channelOpenAL.ALSource.get( 0 ),
567
AL10.AL_POSITION, sourcePosition );
568
checkALError();
569
570
AL10.alSource( channelOpenAL.ALSource.get( 0 ),
571
AL10.AL_VELOCITY, sourceVelocity );
572
573
checkALError();
574
575
if( attModel == SoundSystemConfig.ATTENUATION_ROLLOFF )
576
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
577
AL10.AL_ROLLOFF_FACTOR, distOrRoll );
578
else
579
AL10.alSourcef( channelOpenAL.ALSource.get( 0 ),
580
AL10.AL_ROLLOFF_FACTOR, 0.0f );
581
checkALError();
582
583
if( toLoop && (!toStream) )
584
AL10.alSourcei( channelOpenAL.ALSource.get( 0 ),
585
AL10.AL_LOOPING, AL10.AL_TRUE );
586
else
587
AL10.alSourcei( channelOpenAL.ALSource.get( 0 ),
588
AL10.AL_LOOPING, AL10.AL_FALSE );
589
checkALError();
590
}
591
if( !toStream )
592
{
593
// This is not a streaming source, so make sure there is
594
// a sound buffer loaded to play:
595
if( myBuffer == null )
596
{
597
errorMessage( "No sound buffer to play" );
598
return;
599
}
600
601
channelOpenAL.attachBuffer( myBuffer );
602
}
603
}
604
605
// See if we are already playing:
606
if( !playing() )
607
{
608
if( toStream && !wasPaused )
609
{
610
if( codec == null )
611
{
612
errorMessage( "Decoder null in method 'play'" );
613
return;
614
}
615
if( codec.getAudioFormat() == null )
616
codec.initialize( filenameURL.getURL() );
617
618
AudioFormat audioFormat = codec.getAudioFormat();
619
620
if( audioFormat == null )
621
{
622
errorMessage( "Audio Format null in method 'play'" );
623
return;
624
}
625
626
int soundFormat = 0;
627
if( audioFormat.getChannels() == 1 )
628
{
629
if( audioFormat.getSampleSizeInBits() == 8 )
630
{
631
soundFormat = AL10.AL_FORMAT_MONO8;
632
}
633
else if( audioFormat.getSampleSizeInBits() == 16 )
634
{
635
soundFormat = AL10.AL_FORMAT_MONO16;
636
}
637
else
638
{
639
errorMessage( "Illegal sample size in method 'play'" );
640
return;
641
}
642
}
643
else if( audioFormat.getChannels() == 2 )
644
{
645
if( audioFormat.getSampleSizeInBits() == 8 )
646
{
647
soundFormat = AL10.AL_FORMAT_STEREO8;
648
}
649
else if( audioFormat.getSampleSizeInBits() == 16 )
650
{
651
soundFormat = AL10.AL_FORMAT_STEREO16;
652
}
653
else
654
{
655
errorMessage( "Illegal sample size in method 'play'" );
656
return;
657
}
658
}
659
else
660
{
661
errorMessage( "Audio data neither mono nor stereo in " +
662
"method 'play'" );
663
return;
664
}
665
666
// Let the channel know what format and sample rate to use:
667
channelOpenAL.setFormat( soundFormat,
668
(int) audioFormat.getSampleRate() );
669
preLoad = true;
670
}
671
channel.play();
672
if( pitch != 1.0f )
673
checkPitch();
674
}
675
}
676
677
/**
678
* Queues up the initial stream-buffers for the stream.
679
* @return False if the end of the stream was reached.
680
*/
681
@Override
682
public boolean preLoad()
683
{
684
if( codec == null )
685
return false;
686
687
codec.initialize( filenameURL.getURL() );
688
LinkedList<byte[]> preLoadBuffers = new LinkedList<byte[]>();
689
for( int i = 0; i < SoundSystemConfig.getNumberStreamingBuffers(); i++ )
690
{
691
soundBuffer = codec.read();
692
693
if( soundBuffer == null || soundBuffer.audioData == null )
694
break;
695
696
preLoadBuffers.add( soundBuffer.audioData );
697
}
698
positionChanged();
699
700
channel.preLoadBuffers( preLoadBuffers );
701
702
preLoad = false;
703
return true;
704
}
705
706
/**
707
* Resets all the information OpenAL uses to play this source.
708
*/
709
private void resetALInformation()
710
{
711
// Create buffers for the source's position and velocity
712
sourcePosition = BufferUtils.createFloatBuffer( 3 ).put(
713
new float[] { position.x, position.y, position.z } );
714
sourceVelocity = BufferUtils.createFloatBuffer( 3 ).put(
715
new float[] { velocity.x, velocity.y, velocity.z } );
716
717
// flip the buffers, so they can be used:
718
sourcePosition.flip();
719
sourceVelocity.flip();
720
721
positionChanged();
722
}
723
724
/**
725
* Calculates this source's distance from the listener.
726
*/
727
private void calculateDistance()
728
{
729
if( listenerPosition != null )
730
{
731
// Calculate the source's distance from the listener:
732
double dX = position.x - listenerPosition.get( 0 );
733
double dY = position.y - listenerPosition.get( 1 );
734
double dZ = position.z - listenerPosition.get( 2 );
735
distanceFromListener = (float) Math.sqrt( dX*dX + dY*dY + dZ*dZ );
736
}
737
}
738
739
/**
740
* If using linear attenuation, calculates the gain for this source based on
741
* its distance from the listener.
742
*/
743
private void calculateGain()
744
{
745
// If using linear attenuation, calculate the source's gain:
746
if( attModel == SoundSystemConfig.ATTENUATION_LINEAR )
747
{
748
if( distanceFromListener <= 0 )
749
{
750
gain = 1.0f;
751
}
752
else if( distanceFromListener >= distOrRoll )
753
{
754
gain = 0.0f;
755
}
756
else
757
{
758
gain = 1.0f - (distanceFromListener / distOrRoll);
759
}
760
if( gain > 1.0f )
761
gain = 1.0f;
762
if( gain < 0.0f )
763
gain = 0.0f;
764
}
765
else
766
{
767
gain = 1.0f;
768
}
769
}
770
771
/**
772
* Checks for OpenAL errors, and prints a message if there is an error.
773
* @return True if there was an error, False if not.
774
*/
775
private boolean checkALError()
776
{
777
switch( AL10.alGetError() )
778
{
779
case AL10.AL_NO_ERROR:
780
return false;
781
case AL10.AL_INVALID_NAME:
782
errorMessage( "Invalid name parameter." );
783
return true;
784
case AL10.AL_INVALID_ENUM:
785
errorMessage( "Invalid parameter." );
786
return true;
787
case AL10.AL_INVALID_VALUE:
788
errorMessage( "Invalid enumerated parameter value." );
789
return true;
790
case AL10.AL_INVALID_OPERATION:
791
errorMessage( "Illegal call." );
792
return true;
793
case AL10.AL_OUT_OF_MEMORY:
794
errorMessage( "Unable to allocate memory." );
795
return true;
796
default:
797
errorMessage( "An unrecognized error occurred." );
798
return true;
799
}
800
}
801
}
802
803