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