1 /*************************************************************************/
2 /*  spatial_sound_server_sw.h                                            */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 #ifndef SPATIAL_SOUND_SERVER_SW_H
31 #define SPATIAL_SOUND_SERVER_SW_H
32 
33 #include "octree.h"
34 #include "os/thread_safe.h"
35 #include "servers/spatial_sound_server.h"
36 
37 class SpatialSoundServerSW : public SpatialSoundServer {
38 
39 	OBJ_TYPE(SpatialSoundServerSW, SpatialSoundServer);
40 
41 	_THREAD_SAFE_CLASS_
42 
43 	enum {
44 		MAX_CULL_ROOMS = 128,
45 		INTERNAL_BUFFER_SIZE = 4096,
46 		INTERNAL_BUFFER_MAX_CHANNELS = 4,
47 		VOICE_IS_STREAM = -1
48 
49 	};
50 
51 	struct InternalAudioStream : public AudioServer::AudioStream {
52 
53 		::SpatialSoundServerSW *owner;
54 		virtual int get_channel_count() const;
55 		virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate
56 		virtual bool mix(int32_t *p_buffer, int p_frames);
57 		virtual void update();
58 	};
59 
60 	InternalAudioStream *internal_audio_stream;
61 	RID internal_audio_stream_rid;
62 	int32_t *internal_buffer;
63 	int internal_buffer_channels;
64 
65 	bool internal_buffer_mix(int32_t *p_buffer, int p_frames);
66 
67 	struct Room;
68 
69 	struct Space {
70 
71 		RID default_room;
72 		Set<RID> rooms;
73 		Set<RID> sources;
74 		Set<RID> listeners;
75 
76 		Octree<Room> octree;
77 	};
78 
79 	mutable RID_Owner<Space> space_owner;
80 
81 	struct Room {
82 		RID space;
83 		Transform transform;
84 		Transform inverse_transform;
85 		BSP_Tree bounds;
86 		RoomReverb reverb;
87 		float params[ROOM_PARAM_MAX];
88 		bool override_other_sources;
89 		OctreeElementID octree_id;
90 		int level;
91 
92 		Room();
93 	};
94 
95 	mutable RID_Owner<Room> room_owner;
96 
97 	struct Source {
98 
99 		struct Voice {
100 
101 			RID voice_rid;
102 			RID sample_rid;
103 			bool active;
104 			bool restart;
105 			int priority;
106 			float pitch_scale;
107 			float volume_scale;
108 			int sample_mix_rate;
109 
110 			float last_volume;
111 			float last_filter_gain;
112 			float last_filter_cutoff;
113 			Vector3 last_panning;
114 			int last_mix_rate;
115 			RoomReverb last_reverb_room;
116 			float last_reverb_send;
117 
118 			Voice();
119 			~Voice();
120 		};
121 
122 		struct StreamData {
123 
124 			Vector3 panning;
125 			RoomReverb reverb;
126 			float reverb_send;
127 			float volume;
128 			float filter_gain;
129 			float filter_cutoff;
130 
131 			struct FilterState {
132 
133 				float ha[2];
134 				float hb[2];
135 			} filter_state[4];
136 
StreamDataSource::StreamData137 			StreamData() {
138 
139 				reverb_send = 0;
140 				reverb = ROOM_REVERB_HALL;
141 				volume = 1.0;
142 				filter_gain = 1;
143 				filter_cutoff = 5000;
144 			}
145 		} stream_data;
146 
147 		RID space;
148 		Transform transform;
149 		float params[SOURCE_PARAM_MAX];
150 		AudioServer::AudioStream *stream;
151 		Vector<Voice> voices;
152 		int last_voice;
153 
154 		Source();
155 	};
156 
157 	mutable RID_Owner<Source> source_owner;
158 
159 	struct Listener {
160 
161 		RID space;
162 		Transform transform;
163 		float params[LISTENER_PARAM_MAX];
164 
165 		Listener();
166 	};
167 
168 	mutable RID_Owner<Listener> listener_owner;
169 
170 	struct ActiveVoice {
171 
172 		Source *source;
173 		int voice;
174 		bool operator<(const ActiveVoice &p_voice) const { return (voice == p_voice.voice) ? (source < p_voice.source) : (voice < p_voice.voice); }
175 		ActiveVoice(Source *p_source = NULL, int p_voice = 0) {
176 			source = p_source;
177 			voice = p_voice;
178 		}
179 	};
180 
181 	Room *cull_rooms[MAX_CULL_ROOMS];
182 
183 	Set<Source *> streaming_sources;
184 	Set<ActiveVoice> active_voices;
185 
186 	void _clean_up_owner(RID_OwnerBase *p_owner, const char *p_area);
187 	void _update_sources();
188 
189 public:
190 	/* SPACE */
191 	virtual RID space_create();
192 
193 	/* ROOM */
194 
195 	virtual RID room_create();
196 	virtual void room_set_space(RID p_room, RID p_space);
197 	virtual RID room_get_space(RID p_room) const;
198 
199 	virtual void room_set_bounds(RID p_room, const BSP_Tree &p_bounds);
200 	virtual BSP_Tree room_get_bounds(RID p_room) const;
201 	virtual void room_set_transform(RID p_room, const Transform &p_transform);
202 	virtual Transform room_get_transform(RID p_room) const;
203 
204 	virtual void room_set_param(RID p_room, RoomParam p_param, float p_value);
205 	virtual float room_get_param(RID p_room, RoomParam p_param) const;
206 
207 	virtual void room_set_level(RID p_room, int p_level);
208 	virtual int room_get_level(RID p_room) const;
209 
210 	virtual void room_set_reverb(RID p_room, RoomReverb p_reverb);
211 	virtual RoomReverb room_get_reverb(RID p_room) const;
212 
213 	//useful for underwater or rooms with very strange conditions
214 	virtual void room_set_force_params_to_all_sources(RID p_room, bool p_force);
215 	virtual bool room_is_forcing_params_to_all_sources(RID p_room) const;
216 
217 	/* SOURCE */
218 
219 	virtual RID source_create(RID p_space);
220 
221 	virtual void source_set_polyphony(RID p_source, int p_voice_count);
222 	virtual int source_get_polyphony(RID p_source) const;
223 
224 	virtual void source_set_transform(RID p_source, const Transform &p_transform);
225 	virtual Transform source_get_transform(RID p_source) const;
226 
227 	virtual void source_set_param(RID p_source, SourceParam p_param, float p_value);
228 	virtual float source_get_param(RID p_source, SourceParam p_param) const;
229 
230 	virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream); //null to unset
231 	virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice = SOURCE_NEXT_VOICE, int p_priority = 0);
232 	/* VOICES */
233 	virtual void source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale);
234 	virtual void source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_volume);
235 
236 	virtual bool source_is_voice_active(RID p_source, SourceVoiceID p_voice) const;
237 	virtual void source_stop_voice(RID p_source, SourceVoiceID p_voice);
238 
239 	/* LISTENER */
240 
241 	virtual RID listener_create();
242 	virtual void listener_set_space(RID p_listener, RID p_space);
243 
244 	virtual void listener_set_transform(RID p_listener, const Transform &p_transform);
245 	virtual Transform listener_get_transform(RID p_listener) const;
246 
247 	virtual void listener_set_param(RID p_listener, ListenerParam p_param, float p_value);
248 	virtual float listener_get_param(RID p_listener, ListenerParam p_param) const;
249 
250 	/* MISC */
251 
252 	virtual void free(RID p_id);
253 
254 	virtual void init();
255 	virtual void update(float p_delta);
256 	virtual void finish();
257 
258 	SpatialSoundServerSW();
259 };
260 
261 #endif // SPATIAL_SOUND_SERVER_SW_H
262