1 /*************************************************************************/
2 /*  audio_stream_mpc.cpp                                                 */
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 #include "audio_stream_mpc.h"
31 
_open_file()32 Error AudioStreamPlaybackMPC::_open_file() {
33 
34 	if (f) {
35 		memdelete(f);
36 		f = NULL;
37 	}
38 	Error err;
39 	//printf("mpc open file %ls\n", file.c_str());
40 	f = FileAccess::open(file, FileAccess::READ, &err);
41 
42 	if (err) {
43 		f = NULL;
44 		ERR_FAIL_V(err);
45 		return err;
46 	}
47 
48 	//printf("file size is %i\n", f->get_len());
49 	//f->seek_end(0);
50 	streamlen = f->get_len();
51 	//f->seek(0);
52 	if (streamlen <= 0) {
53 		memdelete(f);
54 		f = NULL;
55 		ERR_FAIL_V(ERR_INVALID_DATA);
56 	}
57 
58 	data_ofs = 0;
59 	if (preload) {
60 
61 		data.resize(streamlen);
62 		DVector<uint8_t>::Write w = data.write();
63 		f->get_buffer(&w[0], streamlen);
64 		memdelete(f);
65 		f = NULL;
66 	}
67 
68 	return OK;
69 }
70 
_close_file()71 void AudioStreamPlaybackMPC::_close_file() {
72 
73 	if (f) {
74 		memdelete(f);
75 		f = NULL;
76 	}
77 	data.resize(0);
78 	streamlen = 0;
79 	data_ofs = 0;
80 }
81 
_read_file(void * p_dst,int p_bytes)82 int AudioStreamPlaybackMPC::_read_file(void *p_dst, int p_bytes) {
83 
84 	if (f)
85 		return f->get_buffer((uint8_t *)p_dst, p_bytes);
86 
87 	DVector<uint8_t>::Read r = data.read();
88 	if (p_bytes + data_ofs > streamlen) {
89 		p_bytes = streamlen - data_ofs;
90 	}
91 
92 	copymem(p_dst, &r[data_ofs], p_bytes);
93 	//print_line("read file: "+itos(p_bytes));
94 	data_ofs += p_bytes;
95 	return p_bytes;
96 }
97 
_seek_file(int p_pos)98 bool AudioStreamPlaybackMPC::_seek_file(int p_pos) {
99 
100 	if (p_pos < 0 || p_pos > streamlen)
101 		return false;
102 
103 	if (f) {
104 		f->seek(p_pos);
105 		return true;
106 	}
107 
108 	//print_line("read file to: "+itos(p_pos));
109 	data_ofs = p_pos;
110 	return true;
111 }
_tell_file() const112 int AudioStreamPlaybackMPC::_tell_file() const {
113 
114 	if (f)
115 		return f->get_pos();
116 
117 	//print_line("tell file, get: "+itos(data_ofs));
118 	return data_ofs;
119 }
120 
_sizeof_file() const121 int AudioStreamPlaybackMPC::_sizeof_file() const {
122 
123 	//print_line("sizeof file, get: "+itos(streamlen));
124 	return streamlen;
125 }
126 
_canseek_file() const127 bool AudioStreamPlaybackMPC::_canseek_file() const {
128 
129 	//print_line("canseek file, get true");
130 	return true;
131 }
132 
133 /////////////////////
134 
_mpc_read(mpc_reader * p_reader,void * p_dst,mpc_int32_t p_bytes)135 mpc_int32_t AudioStreamPlaybackMPC::_mpc_read(mpc_reader *p_reader, void *p_dst, mpc_int32_t p_bytes) {
136 
137 	AudioStreamPlaybackMPC *smpc = (AudioStreamPlaybackMPC *)p_reader->data;
138 	return smpc->_read_file(p_dst, p_bytes);
139 }
140 
_mpc_seek(mpc_reader * p_reader,mpc_int32_t p_offset)141 mpc_bool_t AudioStreamPlaybackMPC::_mpc_seek(mpc_reader *p_reader, mpc_int32_t p_offset) {
142 
143 	AudioStreamPlaybackMPC *smpc = (AudioStreamPlaybackMPC *)p_reader->data;
144 	return smpc->_seek_file(p_offset);
145 }
_mpc_tell(mpc_reader * p_reader)146 mpc_int32_t AudioStreamPlaybackMPC::_mpc_tell(mpc_reader *p_reader) {
147 
148 	AudioStreamPlaybackMPC *smpc = (AudioStreamPlaybackMPC *)p_reader->data;
149 	return smpc->_tell_file();
150 }
_mpc_get_size(mpc_reader * p_reader)151 mpc_int32_t AudioStreamPlaybackMPC::_mpc_get_size(mpc_reader *p_reader) {
152 
153 	AudioStreamPlaybackMPC *smpc = (AudioStreamPlaybackMPC *)p_reader->data;
154 	return smpc->_sizeof_file();
155 }
_mpc_canseek(mpc_reader * p_reader)156 mpc_bool_t AudioStreamPlaybackMPC::_mpc_canseek(mpc_reader *p_reader) {
157 
158 	AudioStreamPlaybackMPC *smpc = (AudioStreamPlaybackMPC *)p_reader->data;
159 	return smpc->_canseek_file();
160 }
161 
mix(int16_t * p_bufer,int p_frames)162 int AudioStreamPlaybackMPC::mix(int16_t *p_bufer, int p_frames) {
163 
164 	if (!active || paused)
165 		return 0;
166 
167 	int todo = p_frames;
168 
169 	while (todo > MPC_DECODER_BUFFER_LENGTH / si.channels) {
170 
171 		mpc_frame_info frame;
172 
173 		frame.buffer = sample_buffer;
174 
175 		mpc_status err = mpc_demux_decode(demux, &frame);
176 		if (frame.bits != -1) {
177 
178 			int16_t *dst_buff = p_bufer;
179 
180 #ifdef MPC_FIXED_POINT
181 
182 			for (int i = 0; i < frame.samples * si.channels; i++) {
183 				int tmp = sample_buffer[i] >> MPC_FIXED_POINT_FRACTPART;
184 				if (tmp > ((1 << 15) - 1)) tmp = ((1 << 15) - 1);
185 				if (tmp < -(1 << 15)) tmp = -(1 << 15);
186 				dst_buff[i] = tmp;
187 			}
188 #else
189 			for (int i = 0; i < frame.samples * si.channels; i++) {
190 
191 				int tmp = Math::fast_ftoi(sample_buffer[i] * 32767.0);
192 				if (tmp > ((1 << 15) - 1)) tmp = ((1 << 15) - 1);
193 				if (tmp < -(1 << 15)) tmp = -(1 << 15);
194 				dst_buff[i] = tmp;
195 			}
196 
197 #endif
198 
199 			int frames = frame.samples;
200 			p_bufer += si.channels * frames;
201 			todo -= frames;
202 		} else {
203 
204 			if (err != MPC_STATUS_OK) {
205 
206 				stop();
207 				ERR_PRINT("Error decoding MPC");
208 				break;
209 			} else {
210 
211 				//finished
212 				if (!loop) {
213 					stop();
214 					break;
215 				} else {
216 
217 					loops++;
218 					mpc_demux_exit(demux);
219 					_seek_file(0);
220 					demux = mpc_demux_init(&reader);
221 					//do loop somehow
222 				}
223 			}
224 		}
225 	}
226 
227 	return p_frames - todo;
228 }
229 
_reload()230 Error AudioStreamPlaybackMPC::_reload() {
231 
232 	ERR_FAIL_COND_V(demux != NULL, ERR_FILE_ALREADY_IN_USE);
233 
234 	Error err = _open_file();
235 	ERR_FAIL_COND_V(err != OK, ERR_CANT_OPEN);
236 
237 	demux = mpc_demux_init(&reader);
238 	ERR_FAIL_COND_V(!demux, ERR_CANT_CREATE);
239 	mpc_demux_get_info(demux, &si);
240 
241 	return OK;
242 }
243 
set_file(const String & p_file)244 void AudioStreamPlaybackMPC::set_file(const String &p_file) {
245 
246 	file = p_file;
247 
248 	Error err = _open_file();
249 	ERR_FAIL_COND(err != OK);
250 	demux = mpc_demux_init(&reader);
251 	ERR_FAIL_COND(!demux);
252 	mpc_demux_get_info(demux, &si);
253 	stream_min_size = MPC_DECODER_BUFFER_LENGTH * 2 / si.channels;
254 	stream_rate = si.sample_freq;
255 	stream_channels = si.channels;
256 
257 	mpc_demux_exit(demux);
258 	demux = NULL;
259 	_close_file();
260 }
261 
get_file() const262 String AudioStreamPlaybackMPC::get_file() const {
263 
264 	return file;
265 }
266 
play(float p_offset)267 void AudioStreamPlaybackMPC::play(float p_offset) {
268 
269 	if (active)
270 		stop();
271 	active = false;
272 
273 	Error err = _open_file();
274 	ERR_FAIL_COND(err != OK);
275 	if (_reload() != OK)
276 		return;
277 	active = true;
278 	loops = 0;
279 }
280 
stop()281 void AudioStreamPlaybackMPC::stop() {
282 
283 	if (!active)
284 		return;
285 	if (demux) {
286 		mpc_demux_exit(demux);
287 		demux = NULL;
288 	}
289 	_close_file();
290 	active = false;
291 }
is_playing() const292 bool AudioStreamPlaybackMPC::is_playing() const {
293 
294 	return active;
295 }
296 
set_loop(bool p_enable)297 void AudioStreamPlaybackMPC::set_loop(bool p_enable) {
298 
299 	loop = p_enable;
300 }
has_loop() const301 bool AudioStreamPlaybackMPC::has_loop() const {
302 
303 	return loop;
304 }
305 
get_length() const306 float AudioStreamPlaybackMPC::get_length() const {
307 
308 	return 0;
309 }
310 
get_stream_name() const311 String AudioStreamPlaybackMPC::get_stream_name() const {
312 
313 	return "";
314 }
315 
get_loop_count() const316 int AudioStreamPlaybackMPC::get_loop_count() const {
317 
318 	return 0;
319 }
320 
get_pos() const321 float AudioStreamPlaybackMPC::get_pos() const {
322 
323 	return 0;
324 }
seek_pos(float p_time)325 void AudioStreamPlaybackMPC::seek_pos(float p_time) {
326 }
327 
_bind_methods()328 void AudioStreamPlaybackMPC::_bind_methods() {
329 
330 	ObjectTypeDB::bind_method(_MD("set_file", "name"), &AudioStreamPlaybackMPC::set_file);
331 	ObjectTypeDB::bind_method(_MD("get_file"), &AudioStreamPlaybackMPC::get_file);
332 
333 	ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "file", PROPERTY_HINT_FILE, "mpc"), _SCS("set_file"), _SCS("get_file"));
334 }
335 
AudioStreamPlaybackMPC()336 AudioStreamPlaybackMPC::AudioStreamPlaybackMPC() {
337 
338 	preload = false;
339 	f = NULL;
340 	streamlen = 0;
341 	data_ofs = 0;
342 	active = false;
343 	paused = false;
344 	loop = false;
345 	demux = NULL;
346 	reader.data = this;
347 	reader.read = _mpc_read;
348 	reader.seek = _mpc_seek;
349 	reader.tell = _mpc_tell;
350 	reader.get_size = _mpc_get_size;
351 	reader.canseek = _mpc_canseek;
352 	loops = 0;
353 }
354 
~AudioStreamPlaybackMPC()355 AudioStreamPlaybackMPC::~AudioStreamPlaybackMPC() {
356 
357 	stop();
358 
359 	if (f)
360 		memdelete(f);
361 }
362 
load(const String & p_path,const String & p_original_path,Error * r_error)363 RES ResourceFormatLoaderAudioStreamMPC::load(const String &p_path, const String &p_original_path, Error *r_error) {
364 	if (r_error)
365 		*r_error = OK; //streamed so it will always work..
366 	AudioStreamMPC *mpc_stream = memnew(AudioStreamMPC);
367 	mpc_stream->set_file(p_path);
368 	return Ref<AudioStreamMPC>(mpc_stream);
369 }
370 
get_recognized_extensions(List<String> * p_extensions) const371 void ResourceFormatLoaderAudioStreamMPC::get_recognized_extensions(List<String> *p_extensions) const {
372 
373 	p_extensions->push_back("mpc");
374 }
handles_type(const String & p_type) const375 bool ResourceFormatLoaderAudioStreamMPC::handles_type(const String &p_type) const {
376 
377 	return (p_type == "AudioStream") || (p_type == "AudioStreamMPC");
378 }
379 
get_resource_type(const String & p_path) const380 String ResourceFormatLoaderAudioStreamMPC::get_resource_type(const String &p_path) const {
381 
382 	if (p_path.extension().to_lower() == "mpc")
383 		return "AudioStreamMPC";
384 	return "";
385 }
386