1 module prova.audio.audiosource;
2 
3 import derelict.openal.al,
4        prova.audio,
5        prova.core,
6        prova.math;
7 
8 /// 
9 class AudioSource
10 {
11   private uint sourceId;
12   private AudioClip audioClip;
13   private Entity _entity;
14   private bool _looping = false;
15   private float _volume = 1;
16   private float _pitch = 1;
17 
18   /// Limited to Ogg files for now
19   this(AudioClip audioClip)
20   {
21     this.audioClip = audioClip;
22 
23     alGenSources(1, &sourceId);
24     alSourcei(sourceId, AL_BUFFER, audioClip.bufferId);
25   }
26 
27   ///
28   @property Entity entity()
29   {
30     return _entity;
31   }
32 
33   ///
34   @property void entity(Entity entity)
35   {
36     _entity = entity;
37   }
38 
39   ///
40   @property uint channels()
41   {
42     return audioClip.channels;
43   }
44 
45   ///
46   @property float volume()
47   {
48     return _volume;
49   }
50 
51   ///
52   @property void volume(float value)
53   {
54     _volume = value;
55     alSourcef(sourceId, AL_GAIN, value);
56   }
57 
58   ///
59   @property float pitch()
60   {
61     return _pitch;
62   }
63 
64   ///
65   @property void pitch(float value)
66   {
67     _pitch = value;
68     alSourcef(sourceId, AL_PITCH, value);
69   }
70 
71   ///
72   @property bool isPlaying()
73   {
74     ALenum status;
75     alGetSourcei(sourceId, AL_SOURCE_STATE, &status);
76 
77     return status == AL_PLAYING;
78   }
79 
80   ///
81   @property bool looping()
82   {
83     return _looping;
84   }
85 
86   ///
87   void play(bool loop = false)
88   {
89     if(isPlaying())
90       stop();
91 
92     _looping = loop;
93     alSourcei(sourceId, AL_LOOPING, loop);
94 
95     alSourceRewind(sourceId);
96     alSourcePlay(sourceId);
97   }
98 
99   ///
100   void stop()
101   {
102     alSourceStop(sourceId);
103   }
104 
105   ///
106   void pause()
107   {
108     alSourcePause(sourceId);
109   }
110 
111   ///
112   void resume()
113   {
114     alSourcePlay(sourceId);
115   }
116 
117   package(prova) void update()
118   {
119     if(!entity)
120       return;
121 
122     Vector3 position = entity.getWorldPosition();
123     Vector3 velocity = entity.getWorldRotation() * entity.velocity;
124 
125     position /= Audio.scale;
126     velocity /= Audio.scale;
127 
128     alSource3f(sourceId, AL_POSITION, position.x, position.y, position.z);
129     alSource3f(sourceId, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
130   }
131 
132   ~this()
133   {
134     if(isPlaying)
135       stop();
136 
137     alDeleteSources(1, &sourceId);
138   }
139 }