1 module armos.audio.source;
2 
3 import derelict.openal.al;
4 import armos.math;
5 import armos.audio.buffer;
6 import armos.audio.spectrum;
7 
8 /++
9 +/
10 enum SourceState {
11     Initial = AL_INITIAL,
12     Playing = AL_PLAYING,
13     Paused  = AL_PAUSED,
14     Stopped = AL_STOPPED
15 }//enum SourceState
16 
17 /++
18 +/
19 class Source{
20     public{
21         ///
22         this(){
23             alGenSources(1, cast(uint*)&_id); 
24         }
25         
26         ///
27         ~this(){
28             alDeleteSources(1, cast(uint*)&_id);
29         }
30         
31         ///
32         Source buffer(Buffer b){
33             alSourcei(_id, AL_BUFFER, b.id);
34             _buffer = b;
35             return this;
36         }
37         
38         ///
39         SourceState state(){
40             int s;
41             alGetSourcei(_id, AL_SOURCE_STATE, &s);
42             switch (s) {
43                 case AL_INITIAL:
44                          _state = SourceState.Initial;
45                          break;
46                 case AL_PLAYING:
47                          _state = SourceState.Playing;
48                          break;
49                 case AL_PAUSED:
50                          _state = SourceState.Paused;
51                          break;
52                 case AL_STOPPED:
53                          _state = SourceState.Stopped;
54                          break;
55                 default:
56                          assert(0);
57             }
58             return _state;
59         };
60         
61         ///
62         Source play(){
63             alSourcePlay(_id);
64             return this;
65         }
66         
67         ///
68         Source pause(){
69             alSourcePause(_id);
70             return this;
71         }
72         
73         ///
74         Source stop(){
75             alSourceStop(_id);
76             return this;
77         }
78         
79         ///
80         Source Rewind(){
81             alSourceRewind(_id);
82             return this;
83         }
84         
85         ///
86         Source position(V)(in V p)if(isVector!(V) && V.dimention >= 3){
87             alSource3f(_id, AL_POSITION, p[0], p[1], p[2]);
88             _position[3] = 1f;
89             foreach (int i, e; p.elements) {
90                 _position[i] = e;
91             }
92             return this;
93         }
94         
95         ///
96         Source velocity (V)(in V v)if(isVector!(V) && V.dimention >= 3){
97             alSource3f(_id, AL_VELOCITY, v[0], v[1], v[2]);
98             _velocity[3] = 0f;
99             foreach (int i, e; v.elements) {
100                 _velocity[i] = e;
101             }
102             return this;
103         }
104         
105         Source direction (V)(in V v)if(isVector!(V) && V.dimention >= 3){
106             alSource3f(_id, AL_DIRECTION, v[0], v[1], v[2]);
107             _direction[3] = 0f;
108             foreach (int i, e; v.elements) {
109                 _direction[i] = e;
110             }
111             return this;
112         }
113         
114         /// 
115         Vector4f position()const{
116             return _position;
117         }
118         
119         /// 
120         Vector4f velocity()const{
121             return _velocity;
122         }
123         
124         /// 
125         Vector4f direction()const{
126             return _direction;
127         }
128         
129         ///
130         Source gain(in float g){
131             alSourcef(_id, AL_GAIN, g);
132             _gain = g;
133             return this;
134         }
135         
136         ///
137         float gain(){return _gain;}
138         
139         ///
140         Source isLooping(in bool f){
141             alSourcei(_id, AL_LOOPING, f?AL_TRUE:AL_FALSE);
142             _isLooping = f;
143             return this;
144         }
145         
146         ///
147         bool isLooping()const{return _isLooping;}
148         
149         ///
150         float currentPlaybackTime()const{
151             float result;
152             alGetSourcef(_id, AL_SEC_OFFSET, &result);
153             return result;   
154         }
155         
156         ///
157         size_t currentPlaybackIndex()const{
158             import std.conv:to;
159             return (currentPlaybackTime*_buffer.samplingRate.to!float).to!size_t;
160         }
161         
162         ///
163         Spectrum!double currentSpectrum(in size_t channel, in size_t bufferSize)const{
164             return _buffer.spectrumAtIndex(channel, currentPlaybackIndex, bufferSize);
165         }
166     }//public
167 
168     private{
169         int _id;
170         Vector4f _position  = Vector4f(0, 0, 0, 1); 
171         Vector4f _velocity  = Vector4f(0, 0, 0, 0);
172         Vector4f _direction = Vector4f(0, 0, 0, 0);
173         float _gain = 1f;
174         bool _isLooping = false;
175         Buffer _buffer;
176         
177         SourceState _state;
178     }//private
179 }//class Source