| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  audio_stream.cpp                                                     */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							| 
									
										
										
										
											2017-08-27 14:16:55 +02:00
										 |  |  | /*                      https://godotengine.org                          */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2019-01-01 12:53:14 +01:00
										 |  |  | /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #include "audio_stream.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | #include "core/os/os.h"
 | 
					
						
							| 
									
										
										
										
											2018-12-14 00:35:01 +09:00
										 |  |  | #include "core/project_settings.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 18:50:52 -03:00
										 |  |  | //////////////////////////////
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-21 19:00:25 -03:00
										 |  |  | void AudioStreamPlaybackResampled::_begin_resample() { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-21 19:00:25 -03:00
										 |  |  | 	//clear cubic interpolation history
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	internal_buffer[0] = AudioFrame(0.0, 0.0); | 
					
						
							|  |  |  | 	internal_buffer[1] = AudioFrame(0.0, 0.0); | 
					
						
							|  |  |  | 	internal_buffer[2] = AudioFrame(0.0, 0.0); | 
					
						
							|  |  |  | 	internal_buffer[3] = AudioFrame(0.0, 0.0); | 
					
						
							| 
									
										
										
										
											2017-01-21 19:00:25 -03:00
										 |  |  | 	//mix buffer
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	_mix_internal(internal_buffer + 4, INTERNAL_BUFFER_LEN); | 
					
						
							|  |  |  | 	mix_offset = 0; | 
					
						
							| 
									
										
										
										
											2017-01-21 19:00:25 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-01 22:23:16 +01:00
										 |  |  | 	float target_rate = AudioServer::get_singleton()->get_mix_rate(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-01 22:23:16 +01:00
										 |  |  | 	uint64_t mix_increment = uint64_t(((get_stream_sampling_rate() * p_rate_scale) / double(target_rate)) * double(FP_LEN)); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < p_frames; i++) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-21 19:00:25 -03:00
										 |  |  | 		uint32_t idx = CUBIC_INTERP_HISTORY + uint32_t(mix_offset >> FP_BITS); | 
					
						
							|  |  |  | 		//standard cubic interpolation (great quality/performance ratio)
 | 
					
						
							|  |  |  | 		//this used to be moved to a LUT for greater performance, but nowadays CPU speed is generally faster than memory.
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		float mu = (mix_offset & FP_MASK) / float(FP_LEN); | 
					
						
							|  |  |  | 		AudioFrame y0 = internal_buffer[idx - 3]; | 
					
						
							|  |  |  | 		AudioFrame y1 = internal_buffer[idx - 2]; | 
					
						
							|  |  |  | 		AudioFrame y2 = internal_buffer[idx - 1]; | 
					
						
							|  |  |  | 		AudioFrame y3 = internal_buffer[idx - 0]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		float mu2 = mu * mu; | 
					
						
							| 
									
										
										
										
											2017-01-21 19:00:25 -03:00
										 |  |  | 		AudioFrame a0 = y3 - y2 - y0 + y1; | 
					
						
							|  |  |  | 		AudioFrame a1 = y0 - y1 - a0; | 
					
						
							|  |  |  | 		AudioFrame a2 = y2 - y0; | 
					
						
							|  |  |  | 		AudioFrame a3 = y1; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		p_buffer[i] = (a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		mix_offset += mix_increment; | 
					
						
							| 
									
										
										
										
											2017-01-21 19:00:25 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		while ((mix_offset >> FP_BITS) >= INTERNAL_BUFFER_LEN) { | 
					
						
							| 
									
										
										
										
											2017-01-21 19:00:25 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			internal_buffer[0] = internal_buffer[INTERNAL_BUFFER_LEN + 0]; | 
					
						
							|  |  |  | 			internal_buffer[1] = internal_buffer[INTERNAL_BUFFER_LEN + 1]; | 
					
						
							|  |  |  | 			internal_buffer[2] = internal_buffer[INTERNAL_BUFFER_LEN + 2]; | 
					
						
							|  |  |  | 			internal_buffer[3] = internal_buffer[INTERNAL_BUFFER_LEN + 3]; | 
					
						
							| 
									
										
										
										
											2017-12-20 13:55:30 -03:00
										 |  |  | 			if (is_playing()) { | 
					
						
							|  |  |  | 				_mix_internal(internal_buffer + 4, INTERNAL_BUFFER_LEN); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				//fill with silence, not playing
 | 
					
						
							| 
									
										
										
										
											2019-02-12 21:10:08 +01:00
										 |  |  | 				for (int j = 0; j < INTERNAL_BUFFER_LEN; ++j) { | 
					
						
							|  |  |  | 					internal_buffer[j + 4] = AudioFrame(0, 0); | 
					
						
							| 
									
										
										
										
											2017-12-17 22:31:35 +01:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			mix_offset -= (INTERNAL_BUFFER_LEN << FP_BITS); | 
					
						
							| 
									
										
										
										
											2017-01-21 19:00:25 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-06-07 12:46:14 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-15 01:23:10 -03:00
										 |  |  | ////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-22 20:35:33 +01:00
										 |  |  | void AudioStream::_bind_methods() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_length"), &AudioStream::get_length); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 07:54:56 +00:00
										 |  |  | Ref<AudioStreamPlayback> AudioStreamMicrophone::instance_playback() { | 
					
						
							|  |  |  | 	Ref<AudioStreamPlaybackMicrophone> playback; | 
					
						
							|  |  |  | 	playback.instance(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	playbacks.insert(playback.ptr()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	playback->microphone = Ref<AudioStreamMicrophone>((AudioStreamMicrophone *)this); | 
					
						
							|  |  |  | 	playback->active = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return playback; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String AudioStreamMicrophone::get_stream_name() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//if (audio_stream.is_valid()) {
 | 
					
						
							|  |  |  | 	//return "Random: " + audio_stream->get_name();
 | 
					
						
							|  |  |  | 	//}
 | 
					
						
							|  |  |  | 	return "Microphone"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float AudioStreamMicrophone::get_length() const { | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioStreamMicrophone::_bind_methods() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AudioStreamMicrophone::AudioStreamMicrophone() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_frames) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-03 22:08:43 -03:00
										 |  |  | 	AudioDriver::get_singleton()->lock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 15:09:03 -03:00
										 |  |  | 	Vector<int32_t> buf = AudioDriver::get_singleton()->get_input_buffer(); | 
					
						
							|  |  |  | 	unsigned int input_size = AudioDriver::get_singleton()->get_input_size(); | 
					
						
							| 
									
										
										
										
											2018-10-19 16:32:03 -03:00
										 |  |  | 	int mix_rate = AudioDriver::get_singleton()->get_mix_rate(); | 
					
						
							| 
									
										
										
										
											2019-02-21 20:57:39 +01:00
										 |  |  | 	unsigned int playback_delay = MIN(((50 * mix_rate) / 1000) * 2, buf.size() >> 1); | 
					
						
							| 
									
										
										
										
											2018-10-19 16:32:03 -03:00
										 |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	unsigned int input_position = AudioDriver::get_singleton()->get_input_position(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-02-27 07:54:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-19 16:32:03 -03:00
										 |  |  | 	if (playback_delay > input_size) { | 
					
						
							| 
									
										
										
										
											2018-07-27 03:47:22 +01:00
										 |  |  | 		for (int i = 0; i < p_frames; i++) { | 
					
						
							|  |  |  | 			p_buffer[i] = AudioFrame(0.0f, 0.0f); | 
					
						
							| 
									
										
										
										
											2018-02-27 07:54:56 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-07-27 03:47:22 +01:00
										 |  |  | 		input_ofs = 0; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		for (int i = 0; i < p_frames; i++) { | 
					
						
							| 
									
										
										
										
											2019-03-02 15:01:26 -03:00
										 |  |  | 			if (input_size > input_ofs && (int)input_ofs < buf.size()) { | 
					
						
							| 
									
										
										
										
											2018-07-27 03:47:22 +01:00
										 |  |  | 				float l = (buf[input_ofs++] >> 16) / 32768.f; | 
					
						
							| 
									
										
										
										
											2019-02-21 20:57:39 +01:00
										 |  |  | 				if ((int)input_ofs >= buf.size()) { | 
					
						
							| 
									
										
										
										
											2018-07-27 03:47:22 +01:00
										 |  |  | 					input_ofs = 0; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				float r = (buf[input_ofs++] >> 16) / 32768.f; | 
					
						
							| 
									
										
										
										
											2019-02-21 20:57:39 +01:00
										 |  |  | 				if ((int)input_ofs >= buf.size()) { | 
					
						
							| 
									
										
										
										
											2018-07-27 03:47:22 +01:00
										 |  |  | 					input_ofs = 0; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-07-03 22:08:43 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-27 03:47:22 +01:00
										 |  |  | 				p_buffer[i] = AudioFrame(l, r); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				p_buffer[i] = AudioFrame(0.0f, 0.0f); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-27 07:54:56 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-03 22:08:43 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-19 16:32:03 -03:00
										 |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							| 
									
										
										
										
											2019-02-21 20:57:39 +01:00
										 |  |  | 	if (input_ofs > input_position && (int)(input_ofs - input_position) < (p_frames * 2)) { | 
					
						
							| 
									
										
										
										
											2018-10-19 16:32:03 -03:00
										 |  |  | 		print_verbose(String(get_class_name()) + " buffer underrun: input_position=" + itos(input_position) + " input_ofs=" + itos(input_ofs) + " input_size=" + itos(input_size)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-03 22:08:43 -03:00
										 |  |  | 	AudioDriver::get_singleton()->unlock(); | 
					
						
							| 
									
										
										
										
											2018-02-27 07:54:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioStreamPlaybackMicrophone::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { | 
					
						
							|  |  |  | 	AudioStreamPlaybackResampled::mix(p_buffer, p_rate_scale, p_frames); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float AudioStreamPlaybackMicrophone::get_stream_sampling_rate() { | 
					
						
							| 
									
										
										
										
											2018-07-03 22:08:43 -03:00
										 |  |  | 	return AudioDriver::get_singleton()->get_mix_rate(); | 
					
						
							| 
									
										
										
										
											2018-02-27 07:54:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioStreamPlaybackMicrophone::start(float p_from_pos) { | 
					
						
							| 
									
										
										
										
											2018-12-14 00:35:01 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-01 09:33:15 -03:00
										 |  |  | 	if (active) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-14 00:35:01 +09:00
										 |  |  | 	if (!GLOBAL_GET("audio/enable_audio_input")) { | 
					
						
							|  |  |  | 		WARN_PRINTS("Need to enable Project settings > Audio > Enable Audio Input option to use capturing."); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-03 22:08:43 -03:00
										 |  |  | 	input_ofs = 0; | 
					
						
							| 
									
										
										
										
											2018-02-27 07:54:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-01 09:33:15 -03:00
										 |  |  | 	if (AudioDriver::get_singleton()->capture_start() == OK) { | 
					
						
							|  |  |  | 		active = true; | 
					
						
							|  |  |  | 		_begin_resample(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-27 07:54:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioStreamPlaybackMicrophone::stop() { | 
					
						
							| 
									
										
										
										
											2019-03-01 09:33:15 -03:00
										 |  |  | 	if (active) { | 
					
						
							|  |  |  | 		AudioDriver::get_singleton()->capture_stop(); | 
					
						
							|  |  |  | 		active = false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-27 07:54:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool AudioStreamPlaybackMicrophone::is_playing() const { | 
					
						
							|  |  |  | 	return active; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int AudioStreamPlaybackMicrophone::get_loop_count() const { | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float AudioStreamPlaybackMicrophone::get_playback_position() const { | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioStreamPlaybackMicrophone::seek(float p_time) { | 
					
						
							|  |  |  | 	return; // Can't seek a microphone input
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AudioStreamPlaybackMicrophone::~AudioStreamPlaybackMicrophone() { | 
					
						
							|  |  |  | 	microphone->playbacks.erase(this); | 
					
						
							|  |  |  | 	stop(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AudioStreamPlaybackMicrophone::AudioStreamPlaybackMicrophone() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-15 01:23:10 -03:00
										 |  |  | void AudioStreamRandomPitch::set_audio_stream(const Ref<AudioStream> &p_audio_stream) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	audio_stream = p_audio_stream; | 
					
						
							|  |  |  | 	if (audio_stream.is_valid()) { | 
					
						
							|  |  |  | 		for (Set<AudioStreamPlaybackRandomPitch *>::Element *E = playbacks.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 			E->get()->playback = audio_stream->instance_playback(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Ref<AudioStream> AudioStreamRandomPitch::get_audio_stream() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return audio_stream; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioStreamRandomPitch::set_random_pitch(float p_pitch) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (p_pitch < 1) | 
					
						
							|  |  |  | 		p_pitch = 1; | 
					
						
							|  |  |  | 	random_pitch = p_pitch; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float AudioStreamRandomPitch::get_random_pitch() const { | 
					
						
							|  |  |  | 	return random_pitch; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Ref<AudioStreamPlayback> AudioStreamRandomPitch::instance_playback() { | 
					
						
							|  |  |  | 	Ref<AudioStreamPlaybackRandomPitch> playback; | 
					
						
							|  |  |  | 	playback.instance(); | 
					
						
							|  |  |  | 	if (audio_stream.is_valid()) | 
					
						
							|  |  |  | 		playback->playback = audio_stream->instance_playback(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	playbacks.insert(playback.ptr()); | 
					
						
							|  |  |  | 	playback->random_pitch = Ref<AudioStreamRandomPitch>((AudioStreamRandomPitch *)this); | 
					
						
							|  |  |  | 	return playback; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String AudioStreamRandomPitch::get_stream_name() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (audio_stream.is_valid()) { | 
					
						
							|  |  |  | 		return "Random: " + audio_stream->get_name(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return "RandomPitch"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-22 20:35:33 +01:00
										 |  |  | float AudioStreamRandomPitch::get_length() const { | 
					
						
							|  |  |  | 	if (audio_stream.is_valid()) { | 
					
						
							|  |  |  | 		return audio_stream->get_length(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-15 01:23:10 -03:00
										 |  |  | void AudioStreamRandomPitch::_bind_methods() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_audio_stream", "stream"), &AudioStreamRandomPitch::set_audio_stream); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_audio_stream"), &AudioStreamRandomPitch::get_audio_stream); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_random_pitch", "scale"), &AudioStreamRandomPitch::set_random_pitch); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_random_pitch"), &AudioStreamRandomPitch::get_random_pitch); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "audio_stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_audio_stream", "get_audio_stream"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "random_pitch", PROPERTY_HINT_RANGE, "1,16,0.01"), "set_random_pitch", "get_random_pitch"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AudioStreamRandomPitch::AudioStreamRandomPitch() { | 
					
						
							|  |  |  | 	random_pitch = 1.1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioStreamPlaybackRandomPitch::start(float p_from_pos) { | 
					
						
							|  |  |  | 	playing = playback; | 
					
						
							|  |  |  | 	float range_from = 1.0 / random_pitch->random_pitch; | 
					
						
							|  |  |  | 	float range_to = random_pitch->random_pitch; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pitch_scale = range_from + Math::randf() * (range_to - range_from); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (playing.is_valid()) { | 
					
						
							|  |  |  | 		playing->start(p_from_pos); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioStreamPlaybackRandomPitch::stop() { | 
					
						
							|  |  |  | 	if (playing.is_valid()) { | 
					
						
							|  |  |  | 		playing->stop(); | 
					
						
							|  |  |  | 		; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool AudioStreamPlaybackRandomPitch::is_playing() const { | 
					
						
							|  |  |  | 	if (playing.is_valid()) { | 
					
						
							|  |  |  | 		return playing->is_playing(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int AudioStreamPlaybackRandomPitch::get_loop_count() const { | 
					
						
							|  |  |  | 	if (playing.is_valid()) { | 
					
						
							|  |  |  | 		return playing->get_loop_count(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-21 00:31:36 -03:00
										 |  |  | float AudioStreamPlaybackRandomPitch::get_playback_position() const { | 
					
						
							| 
									
										
										
										
											2017-07-15 01:23:10 -03:00
										 |  |  | 	if (playing.is_valid()) { | 
					
						
							| 
									
										
										
										
											2017-09-21 00:31:36 -03:00
										 |  |  | 		return playing->get_playback_position(); | 
					
						
							| 
									
										
										
										
											2017-07-15 01:23:10 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-09-21 00:31:36 -03:00
										 |  |  | void AudioStreamPlaybackRandomPitch::seek(float p_time) { | 
					
						
							| 
									
										
										
										
											2017-07-15 01:23:10 -03:00
										 |  |  | 	if (playing.is_valid()) { | 
					
						
							| 
									
										
										
										
											2017-09-21 00:31:36 -03:00
										 |  |  | 		playing->seek(p_time); | 
					
						
							| 
									
										
										
										
											2017-07-15 01:23:10 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-28 19:04:25 +07:00
										 |  |  | void AudioStreamPlaybackRandomPitch::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { | 
					
						
							| 
									
										
										
										
											2017-07-15 01:23:10 -03:00
										 |  |  | 	if (playing.is_valid()) { | 
					
						
							| 
									
										
										
										
											2017-10-28 19:04:25 +07:00
										 |  |  | 		playing->mix(p_buffer, p_rate_scale * pitch_scale, p_frames); | 
					
						
							| 
									
										
										
										
											2017-07-15 01:23:10 -03:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		for (int i = 0; i < p_frames; i++) { | 
					
						
							| 
									
										
										
										
											2017-10-28 19:04:25 +07:00
										 |  |  | 			p_buffer[i] = AudioFrame(0, 0); | 
					
						
							| 
									
										
										
										
											2017-07-15 01:23:10 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AudioStreamPlaybackRandomPitch::~AudioStreamPlaybackRandomPitch() { | 
					
						
							|  |  |  | 	random_pitch->playbacks.erase(this); | 
					
						
							|  |  |  | } |