1 /*
2  *******************************************************************************************
3  * Dgame (a D game framework) - Copyright (c) Randy Schütt
4  * 
5  * This software is provided 'as-is', without any express or implied warranty.
6  * In no event will the authors be held liable for any damages arising from
7  * the use of this software.
8  * 
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  * 
13  * 1. The origin of this software must not be misrepresented; you must not claim
14  *    that you wrote the original software. If you use this software in a product,
15  *    an acknowledgment in the product documentation would be appreciated but is
16  *    not required.
17  * 
18  * 2. Altered source versions must be plainly marked as such, and must not be
19  *    misrepresented as being the original software.
20  * 
21  * 3. This notice may not be removed or altered from any source distribution.
22  *******************************************************************************************
23  */
24 module Dgame.Audio.Listener;
25 
26 private {
27 	import derelict.openal.al;
28 
29 	import Dgame.Math.Vector3;
30 }
31 
32 @safe
33 pure nothrow
34 private T[n + m] merge(T, uint n, uint m)(auto ref const T[n] lhs, auto ref const T[m] rhs)
35 {
36 	T[n + m] result = void;
37 
38 	size_t i = 0;
39 
40 	foreach (ref const T val; lhs) {
41 		result[i++] = val;
42 	}
43 
44 	foreach (ref const T val; rhs) {
45 		result[i++] = val;
46 	}
47 
48 	return result;
49 }
50 
51 static this() {
52 	Listener.setPosition(0, 0, 0);
53 	Listener.setVelocity(0, 0, 0);
54 	Listener.setOrientation(0, 0, -1, 0, 1, 0);
55 }
56 
57 /**
58  * Listener sets the position, velocity and orientation of the sound set.
59  * Default is <code>vec3f(0, 0, 0)</code> for position and velocity 
60  * and <code>vec6f(0, 0, -1, 0, 1, 0)</code> for orientation.
61  *
62  * Author: rschuett
63  */
64 final abstract class Listener {
65 	/**
66 	 * Set the position.
67 	 * Default is (0, 0, 0)
68 	 */
69 	static void setPosition(float[3] pos) {
70 		alListenerfv(AL_POSITION, &pos[0]);
71 	}
72 
73 	/**
74 	 * Set the position.
75 	 * Default is (0, 0, 0)
76 	 */
77 	static void setPosition(ref const Vector3f pos) {
78 		Listener.setPosition(pos.asArray());
79 	}
80 	
81 	/**
82 	 * Set the position with x, y and z coordinates.
83 	 * Default is (0, 0, 0)
84 	 */
85 	static void setPosition(float x, float y, float z = 0) {
86 		const float[3] pos = [x, y, z];
87 
88 		Listener.setPosition(pos);
89 	}
90 	
91 	/**
92 	 * Returns the current position.
93 	 * Default is (0, 0, 0)
94 	 */
95 	static Vector3f getPosition() {
96 		float[3] pos = void;
97 		alGetListenerfv(AL_POSITION, &pos[0]);
98 		
99 		return Vector3f(pos);
100 	}
101 	
102 	/**
103 	 * Set the velocity.
104 	 * Default is (0, 0, 0)
105 	 */
106 	static void setVelocity(float[3] vel) {
107 		alListenerfv(AL_VELOCITY, &vel[0]);
108 	}
109 
110 	/**
111 	 * Set the velocity.
112 	 * Default is (0, 0, 0)
113 	 */
114 	static void setVelocity(ref const Vector3f vel) {
115 		Listener.setVelocity(vel.asArray());
116 	}
117 
118 	/**
119 	 * Set the velocity with x, y and z coordinates.
120 	 * Default is (0, 0, 0)
121 	 */
122 	static void setVelocity(float x, float y, float z = 0) {
123 		const float[3] vel = [x, y, z];
124 
125 		Listener.setVelocity(vel);
126 	}
127 	
128 	/**
129 	 * Returns the current velocity.
130 	 * Default is (0, 0, 0)
131 	 */
132 	static Vector3f getVelocity() {
133 		float[3] vel = void;
134 		alGetListenerfv(AL_VELOCITY, &vel[0]);
135 		
136 		return Vector3f(vel);
137 	}
138 	
139 	/**
140 	 * Set the orientation.
141 	 * Default is (0, 0, -1, 0, 1, 0)
142 	 */
143 	static void setOrientation(float[6] ori) {
144 		alListenerfv(AL_ORIENTATION, &ori[0]);
145 	}
146 
147 	/**
148 	 * Set the orientation.
149 	 * Default is (0, 0, -1) and (0, 1, 0)
150 	 */
151 	static void setOrientation(ref const Vector3f at, ref const Vector3f up) {
152 		const float[6] ori = merge(at.asArray(), up.asArray());
153 
154 		Listener.setOrientation(ori);
155 	}
156 
157 	/**
158 	 * Set the orientation.
159 	 * Default is (0, 0, -1, 0, 1, 0)
160 	 */
161 	static void setOrientation(float u, float v, float w, float x, float y, float z) {
162 		const float[6] ori = [u, v, w, x, y, z];
163 
164 		Listener.setOrientation(ori);
165 	}
166 	
167 	/**
168 	 * Returns the current orientation.
169 	 * Default s (0, 0, -1, 0, 1, 0)
170 	 */
171 	static Vector3f[2] getOrientation() {
172 		float[6] ori = void;
173 		alGetListenerfv(AL_ORIENTATION, &ori[0]);
174 		
175 		return [Vector3f(ori[0 .. 3]), Vector3f(ori[3 .. 6])];
176 	}
177 }