| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  event_stream_chibi.cpp                                               */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                    http://www.godotengine.org                         */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2016-01-01 11:50:53 -02:00
										 |  |  | /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							| 
									
										
										
										
											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.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | #include "event_stream_chibi.h"
 | 
					
						
							|  |  |  | #include "cp_loader_it.h"
 | 
					
						
							|  |  |  | #include "cp_loader_xm.h"
 | 
					
						
							|  |  |  | #include "cp_loader_s3m.h"
 | 
					
						
							|  |  |  | #include "cp_loader_mod.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static CPSampleManagerImpl *sample_manager; | 
					
						
							|  |  |  | static ResourceFormatLoaderChibi *resource_loader; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CPSample_ID CPSampleManagerImpl::create(bool p_16bits,bool p_stereo,int32_t p_len) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	AudioServer::SampleFormat sf=p_16bits?AudioServer::SAMPLE_FORMAT_PCM16:AudioServer::SAMPLE_FORMAT_PCM8; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd = memnew( SampleData ); | 
					
						
							|  |  |  | 	sd->rid = AudioServer::get_singleton()->sample_create(sf,p_stereo,p_len); | 
					
						
							|  |  |  | 	sd->stereo=p_stereo; | 
					
						
							|  |  |  | 	sd->len=p_len; | 
					
						
							|  |  |  | 	sd->is16=p_16bits; | 
					
						
							|  |  |  | 	sd->mixfreq=44100; | 
					
						
							|  |  |  | 	sd->loop_begin=0; | 
					
						
							|  |  |  | 	sd->loop_end=0; | 
					
						
							|  |  |  | 	sd->loop_type=CP_LOOP_NONE; | 
					
						
							|  |  |  | 	sd->locks=0; | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	valid.insert(sd); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	CPSample_ID sid; | 
					
						
							|  |  |  | 	sid._private=sd; | 
					
						
							|  |  |  | 	return sid; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPSampleManagerImpl::recreate(CPSample_ID p_id,bool p_16bits,bool p_stereo,int32_t p_len){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	AudioServer::SampleFormat sf=p_16bits?AudioServer::SAMPLE_FORMAT_PCM16:AudioServer::SAMPLE_FORMAT_PCM8; | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!valid.has(sd)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	AudioServer::get_singleton()->free(sd->rid); | 
					
						
							|  |  |  | 	sd->rid = AudioServer::get_singleton()->sample_create(sf,p_stereo,p_len); | 
					
						
							|  |  |  | 	sd->stereo=p_stereo; | 
					
						
							|  |  |  | 	sd->len=p_len; | 
					
						
							|  |  |  | 	sd->is16=p_16bits; | 
					
						
							|  |  |  | 	sd->mixfreq=44100; | 
					
						
							|  |  |  | 	sd->loop_begin=0; | 
					
						
							|  |  |  | 	sd->loop_end=0; | 
					
						
							|  |  |  | 	sd->loop_type=CP_LOOP_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void CPSampleManagerImpl::destroy(CPSample_ID p_id){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!valid.has(sd)); | 
					
						
							|  |  |  | 	valid.erase(sd); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	AudioServer::get_singleton()->free(sd->rid); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memdelete(sd); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool CPSampleManagerImpl::check(CPSample_ID p_id){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	return valid.has(sd); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	return _getsd(p_id)!=NULL; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPSampleManagerImpl::set_c5_freq(CPSample_ID p_id,int32_t p_freq){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!valid.has(sd)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	sd->mixfreq=p_freq; | 
					
						
							|  |  |  | 	AudioServer::get_singleton()->sample_set_mix_rate(sd->rid,p_freq); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void CPSampleManagerImpl::set_loop_begin(CPSample_ID p_id,int32_t p_begin){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!valid.has(sd)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	sd->loop_begin=p_begin; | 
					
						
							|  |  |  | 	AudioServer::get_singleton()->sample_set_loop_begin(sd->rid,p_begin); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void CPSampleManagerImpl::set_loop_end(CPSample_ID p_id,int32_t p_end){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!valid.has(sd)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	sd->loop_end=p_end; | 
					
						
							|  |  |  | 	AudioServer::get_singleton()->sample_set_loop_end(sd->rid,p_end); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void CPSampleManagerImpl::set_loop_type(CPSample_ID p_id,CPSample_Loop_Type p_type){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!valid.has(sd)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sd->loop_type=p_type; | 
					
						
							|  |  |  | 	AudioServer::get_singleton()->sample_set_loop_format(sd->rid,AudioServer::SampleLoopFormat(p_type)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void CPSampleManagerImpl::set_chunk(CPSample_ID p_id,int32_t p_index,void *p_data,int p_data_len){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!valid.has(sd)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int32_t CPSampleManagerImpl::get_loop_begin(CPSample_ID p_id){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!valid.has(sd),0); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sd->loop_begin; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | int32_t CPSampleManagerImpl::get_loop_end(CPSample_ID p_id){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!valid.has(sd),0); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sd->loop_end; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | CPSample_Loop_Type CPSampleManagerImpl::get_loop_type(CPSample_ID p_id){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!valid.has(sd),CP_LOOP_NONE); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sd->loop_type; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | int32_t CPSampleManagerImpl::get_c5_freq(CPSample_ID p_id){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!valid.has(sd),0); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sd->mixfreq; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | int32_t CPSampleManagerImpl::get_size(CPSample_ID p_id){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!valid.has(sd),0); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sd->len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool CPSampleManagerImpl::is_16bits(CPSample_ID p_id){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!valid.has(sd),false); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sd->is16; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool CPSampleManagerImpl::is_stereo(CPSample_ID p_id){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!valid.has(sd),false); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	return sd->stereo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool CPSampleManagerImpl::lock_data(CPSample_ID p_id){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!valid.has(sd),0); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sd->locks++; | 
					
						
							|  |  |  | 	if (sd->locks==1) { | 
					
						
							|  |  |  | 		sd->lock=AudioServer::get_singleton()->sample_get_data(sd->rid); | 
					
						
							|  |  |  | 		sd->w=sd->lock.write(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void *CPSampleManagerImpl::get_data(CPSample_ID p_id){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!valid.has(sd),0); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(sd->locks==0,0); | 
					
						
							|  |  |  | 	return sd->w.ptr(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int16_t CPSampleManagerImpl::get_data(CPSample_ID p_id, int p_sample, int p_channel){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!valid.has(sd),0); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_V(0); | 
					
						
							|  |  |  | 	lock_data(p_id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int sofs = sd->stereo ? 2:1; | 
					
						
							|  |  |  | 	uint16_t v=0; | 
					
						
							|  |  |  | 	if (sd->is16) { | 
					
						
							|  |  |  | 		int16_t *p=(int16_t*)sd->w.ptr(); | 
					
						
							|  |  |  | 		v=p[p_sample*sofs+p_channel]; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		int8_t *p=(int8_t*)sd->w.ptr(); | 
					
						
							|  |  |  | 		v=p[p_sample*sofs+p_channel]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unlock_data(p_id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void CPSampleManagerImpl::set_data(CPSample_ID p_id, int p_sample, int16_t p_data,int p_channel){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!valid.has(sd)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL(); | 
					
						
							|  |  |  | 	lock_data(p_id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int sofs = sd->stereo ? 2:1; | 
					
						
							|  |  |  | 	if (sd->is16) { | 
					
						
							|  |  |  | 		int16_t *p=(int16_t*)sd->w.ptr(); | 
					
						
							|  |  |  | 		p[p_sample*sofs+p_channel]=p_data; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		int8_t *p=(int8_t*)sd->w.ptr(); | 
					
						
							|  |  |  | 		p[p_sample*sofs+p_channel]=p_data; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unlock_data(p_id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void CPSampleManagerImpl::unlock_data(CPSample_ID p_id){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!valid.has(sd)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(sd->locks==0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sd->locks--; | 
					
						
							|  |  |  | 	if (sd->locks==0) { | 
					
						
							|  |  |  | 		sd->w=DVector<uint8_t>::Write(); | 
					
						
							|  |  |  | 		AudioServer::get_singleton()->sample_set_data(sd->rid,sd->lock); | 
					
						
							|  |  |  | 		sd->lock=DVector<uint8_t>(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPSampleManagerImpl::get_chunk(CPSample_ID p_id,int32_t p_index,void *p_data,int p_data_len) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SampleData *sd=_getsd(p_id); | 
					
						
							|  |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(!valid.has(sd)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** MIXER **/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPMixerImpl::set_callback_interval(int p_interval_us) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	callback_interval=p_interval_us; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPMixerImpl::set_callback(void (*p_callback)(void*),void *p_userdata) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	callback=p_callback; | 
					
						
							|  |  |  | 	userdata=p_userdata; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPMixerImpl::setup_voice(int p_voice_index,CPSample_ID p_sample_id,int32_t p_start_index) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Voice &v=voices[p_voice_index]; | 
					
						
							|  |  |  | 	if (v.channel!=AudioMixer::INVALID_CHANNEL) { | 
					
						
							|  |  |  | 		mixer->channel_free(v.channel); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	v.channel=mixer->channel_alloc(sample_manager->get_rid(p_sample_id)); | 
					
						
							|  |  |  | 	v.freq_mult = sample_manager->get_c5_freq(p_sample_id)/261.6255653006; | 
					
						
							|  |  |  | 	v.sample = p_sample_id; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPMixerImpl::stop_voice(int p_voice_index)  { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Voice &v=voices[p_voice_index]; | 
					
						
							|  |  |  | 	if (v.channel==AudioMixer::INVALID_CHANNEL) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mixer->channel_free(v.channel); | 
					
						
							|  |  |  | 	v.channel=AudioMixer::INVALID_CHANNEL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPMixerImpl::set_voice_frequency(int p_voice_index,int32_t p_freq) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Voice &v=voices[p_voice_index]; | 
					
						
							|  |  |  | 	ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); | 
					
						
							|  |  |  | 	float f = p_freq / 256.0; | 
					
						
							|  |  |  | 	f*=pitch_scale; | 
					
						
							|  |  |  | 	mixer->channel_set_mix_rate(v.channel,f * v.freq_mult ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPMixerImpl::set_voice_panning(int p_voice_index,int p_pan) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Voice &v=voices[p_voice_index]; | 
					
						
							|  |  |  | 	ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); | 
					
						
							|  |  |  | 	if (p_pan==CP_PAN_SURROUND) | 
					
						
							|  |  |  | 		p_pan=CP_PAN_CENTER; | 
					
						
							|  |  |  | 	float p = p_pan / 256.0; | 
					
						
							|  |  |  | 	mixer->channel_set_pan(v.channel,p); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPMixerImpl::set_voice_volume(int p_voice_index,int p_vol) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-17 20:03:10 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	Voice &v=voices[p_voice_index]; | 
					
						
							|  |  |  | 	ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); | 
					
						
							|  |  |  | 	float vol = p_vol/512.0; | 
					
						
							|  |  |  | 	vol*=voice_scale; | 
					
						
							|  |  |  | 	mixer->channel_set_volume(v.channel,vol); | 
					
						
							|  |  |  | 	mixer->channel_set_reverb(v.channel,reverb_type,vol*v.reverb); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPMixerImpl::set_voice_filter(int p_voice_index,bool p_enabled,uint8_t p_cutoff, uint8_t p_resonance ){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Voice &v=voices[p_voice_index]; | 
					
						
							|  |  |  | 	ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPMixerImpl::set_voice_reverb_send(int p_voice_index,int p_reverb){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Voice &v=voices[p_voice_index]; | 
					
						
							|  |  |  | 	ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); | 
					
						
							|  |  |  | 	v.reverb=p_reverb/255.0; | 
					
						
							|  |  |  | 	//mixer->channel_set_reverb(v.channel,reverb_type,p_reverb/255.0);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPMixerImpl::set_voice_chorus_send(int p_voice_index,int p_chorus){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Voice &v=voices[p_voice_index]; | 
					
						
							|  |  |  | 	ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL); | 
					
						
							|  |  |  | 	mixer->channel_set_chorus(v.channel,p_chorus/255.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPMixerImpl::set_reverb_mode(ReverbMode p_mode){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //	Voice &v=voices[p_voice_index];
 | 
					
						
							|  |  |  | //	ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL);
 | 
					
						
							|  |  |  | 	switch(p_mode) { | 
					
						
							|  |  |  | 		case CPMixer::REVERB_MODE_STUDIO_SMALL: reverb_type=AudioMixer::REVERB_SMALL; break; | 
					
						
							|  |  |  | 		case CPMixer::REVERB_MODE_STUDIO_MEDIUM: reverb_type=AudioMixer::REVERB_MEDIUM; break; | 
					
						
							|  |  |  | 		case CPMixer::REVERB_MODE_STUDIO_LARGE: reverb_type=AudioMixer::REVERB_LARGE; break; | 
					
						
							|  |  |  | 		case CPMixer::REVERB_MODE_HALL: reverb_type=AudioMixer::REVERB_HALL; break; | 
					
						
							|  |  |  | 		default: reverb_type=AudioMixer::REVERB_SMALL; break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPMixerImpl::set_chorus_params(unsigned int p_delay_ms,unsigned int p_separation_ms,unsigned int p_depth_ms10,unsigned int p_speed_hz10){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //	Voice &v=voices[p_voice_index];
 | 
					
						
							|  |  |  | //	ERR_FAIL_COND(v.channel==AudioMixer::INVALID_CHANNEL);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Info retrieving */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int32_t CPMixerImpl::get_voice_sample_pos_index(int p_voice_index) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Voice &v=voices[p_voice_index]; | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(v.channel==AudioMixer::INVALID_CHANNEL,0); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int CPMixerImpl::get_voice_panning(int p_voice_index) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Voice &v=voices[p_voice_index]; | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!is_voice_active(p_voice_index),0); | 
					
						
							|  |  |  | 	return mixer->channel_get_pan(v.channel)*CP_PAN_RIGHT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int CPMixerImpl::get_voice_volume(int p_voice_index) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Voice &v=voices[p_voice_index]; | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(!is_voice_active(p_voice_index),0); | 
					
						
							|  |  |  | 	return mixer->channel_get_volume(v.channel); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CPSample_ID CPMixerImpl::get_voice_sample_id(int p_voice_index) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Voice &v=voices[p_voice_index]; | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(v.channel==AudioMixer::INVALID_CHANNEL,CPSample_ID()); | 
					
						
							|  |  |  | 	return v.sample; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool CPMixerImpl::is_voice_active(int p_voice_index){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Voice &v=voices[p_voice_index]; | 
					
						
							|  |  |  | 	if (v.channel==AudioMixer::INVALID_CHANNEL) | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	if (!mixer->channel_is_valid(v.channel)) | 
					
						
							|  |  |  | 		v.channel=AudioMixer::INVALID_CHANNEL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return v.channel!=AudioMixer::INVALID_CHANNEL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPMixerImpl::process_usecs(int p_usec,float p_volume,float p_pitch_scale,float p_tempo_scale) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND(callback_interval==0); | 
					
						
							|  |  |  | 	//update this somewhere
 | 
					
						
							|  |  |  | 	pitch_scale=p_pitch_scale; | 
					
						
							|  |  |  | 	tempo_scale=p_tempo_scale; | 
					
						
							|  |  |  | 	voice_scale = AudioServer::get_singleton()->get_event_voice_global_volume_scale()*p_volume; | 
					
						
							|  |  |  | 	while(p_usec) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (p_usec>=callback_timeout) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			p_usec-=callback_timeout; | 
					
						
							|  |  |  | 			callback_timeout=0; | 
					
						
							| 
									
										
										
										
											2014-09-17 20:03:10 -03:00
										 |  |  | 			if (callback) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				callback(userdata); | 
					
						
							| 
									
										
										
										
											2014-09-17 20:03:10 -03:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			callback_timeout=callback_interval*(1.0/p_tempo_scale); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			callback_timeout-=p_usec; | 
					
						
							|  |  |  | 			p_usec=0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CPMixerImpl::CPMixerImpl(AudioMixer *p_mixer) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	callback_interval=1; | 
					
						
							|  |  |  | 	callback_timeout=0; | 
					
						
							|  |  |  | 	userdata=0; | 
					
						
							|  |  |  | 	callback=0; | 
					
						
							|  |  |  | 	tempo_scale=1.0; | 
					
						
							|  |  |  | 	pitch_scale=1.0; | 
					
						
							|  |  |  | 	mixer=p_mixer; | 
					
						
							|  |  |  | 	voice_scale = AudioServer::get_singleton()->get_event_voice_global_volume_scale(); | 
					
						
							|  |  |  | 	reverb_type = AudioMixer::REVERB_SMALL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** FILE ACCESS WRAPPER **/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CPFileAccessWrapperImpl::Error CPFileAccessWrapperImpl::open(const char *p_filename, int p_mode_flags) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V(p_mode_flags&WRITE,ERROR_WRITING_FILE); | 
					
						
							|  |  |  | 	close(); | 
					
						
							|  |  |  | 	f = FileAccess::open(String::utf8(p_filename),p_mode_flags); | 
					
						
							|  |  |  | 	if (!f) | 
					
						
							|  |  |  | 		return ERROR_FILE_NOT_FOUND; | 
					
						
							|  |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPFileAccessWrapperImpl::close(){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (f) | 
					
						
							|  |  |  | 		memdelete(f); | 
					
						
							|  |  |  | 	f=NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPFileAccessWrapperImpl::seek(uint32_t p_position){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f->seek(p_position); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void CPFileAccessWrapperImpl::seek_end(){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f->seek_end(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | uint32_t CPFileAccessWrapperImpl::get_pos(){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return f->get_pos(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool CPFileAccessWrapperImpl::eof_reached(){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return f->eof_reached(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint8_t CPFileAccessWrapperImpl::get_byte(){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return f->get_8(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void CPFileAccessWrapperImpl::get_byte_array(uint8_t *p_dest,int p_elements){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f->get_buffer(p_dest,p_elements); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void CPFileAccessWrapperImpl::get_word_array(uint16_t *p_dest,int p_elements){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(int i=0;i<p_elements;i++) { | 
					
						
							|  |  |  | 		p_dest[i]=f->get_16(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint16_t CPFileAccessWrapperImpl::get_word(){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return f->get_16(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | uint32_t CPFileAccessWrapperImpl::get_dword(){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return f->get_32(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPFileAccessWrapperImpl::set_endian_conversion(bool p_swap){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f->set_endian_swap(p_swap); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool CPFileAccessWrapperImpl::is_open(){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return f!=NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CPFileAccessWrapperImpl::Error CPFileAccessWrapperImpl::get_error(){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return (f->get_error()!=::OK)?ERROR_READING_FILE:OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPFileAccessWrapperImpl::store_byte(uint8_t p_dest){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void CPFileAccessWrapperImpl::store_byte_array(const uint8_t *p_dest,int p_elements){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CPFileAccessWrapperImpl::store_word(uint16_t p_dest){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void CPFileAccessWrapperImpl::store_dword(uint32_t p_dest){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Error EventStreamPlaybackChibi::_play() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	last_order=0; | 
					
						
							|  |  |  | 	loops++; | 
					
						
							|  |  |  | 	player->play_start_song(); | 
					
						
							|  |  |  | 	total_usec=0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return OK; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EventStreamPlaybackChibi::_update(AudioMixer* p_mixer, uint64_t p_usec){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	total_usec+=p_usec; | 
					
						
							|  |  |  | 	mixer.process_usecs(p_usec,volume,pitch_scale,tempo_scale); | 
					
						
							|  |  |  | 	int order=player->get_current_order(); | 
					
						
							|  |  |  | 	if (order<last_order && !loop) { | 
					
						
							|  |  |  | 		stop(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		loops++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	last_order=order; | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void EventStreamPlaybackChibi::_stop(){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	player->play_stop(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EventStreamPlaybackChibi::set_paused(bool p_paused){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool EventStreamPlaybackChibi::is_paused() const{ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void EventStreamPlaybackChibi::set_loop(bool p_loop){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	loop=p_loop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool EventStreamPlaybackChibi::is_loop_enabled() const{ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return loop; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int EventStreamPlaybackChibi::get_loop_count() const{ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//return player->is
 | 
					
						
							|  |  |  | 	return loops; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float EventStreamPlaybackChibi::get_pos() const{ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return double(total_usec)/1000000.0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void EventStreamPlaybackChibi::seek_pos(float p_time){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	WARN_PRINT("seek_pos unimplemented."); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EventStreamPlaybackChibi::set_volume(float p_volume) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	volume=p_volume; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float EventStreamPlaybackChibi::get_volume() const{ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return volume; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EventStreamPlaybackChibi::set_pitch_scale(float p_pitch_scale) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pitch_scale=p_pitch_scale; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float EventStreamPlaybackChibi::get_pitch_scale() const{ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return pitch_scale; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EventStreamPlaybackChibi::set_tempo_scale(float p_tempo_scale) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tempo_scale=p_tempo_scale; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float EventStreamPlaybackChibi::get_tempo_scale() const{ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return tempo_scale; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EventStreamPlaybackChibi::set_channel_volume(int p_channel,float p_volume) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-17 20:03:10 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (p_channel>=64) | 
					
						
							|  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	player->set_channel_global_volume(p_channel,p_volume*256); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float EventStreamPlaybackChibi::get_channel_volume(int p_channel) const{ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return player->get_channel_global_volume(p_channel)/256.0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float EventStreamPlaybackChibi::get_last_note_time(int p_channel) const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	double v = (player->get_channel_last_note_time_usec(p_channel))/1000000.0; | 
					
						
							|  |  |  | 	if (v<0) | 
					
						
							|  |  |  | 		v=-1; | 
					
						
							|  |  |  | 	return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EventStreamPlaybackChibi::EventStreamPlaybackChibi(Ref<EventStreamChibi> p_stream) : mixer(_get_mixer()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	stream=p_stream; | 
					
						
							|  |  |  | 	player = memnew( CPPlayer(&mixer,&p_stream->song) ); | 
					
						
							|  |  |  | 	loop=false; | 
					
						
							|  |  |  | 	last_order=0; | 
					
						
							|  |  |  | 	loops=0; | 
					
						
							|  |  |  | 	volume=1.0; | 
					
						
							|  |  |  | 	pitch_scale=1.0; | 
					
						
							|  |  |  | 	tempo_scale=1.0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | EventStreamPlaybackChibi::~EventStreamPlaybackChibi(){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	player->play_stop(); | 
					
						
							|  |  |  | 	memdelete(player); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Ref<EventStreamPlayback> EventStreamChibi::instance_playback() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return Ref<EventStreamPlayback>( memnew(EventStreamPlaybackChibi(Ref<EventStreamChibi>(this))) ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String EventStreamChibi::get_stream_name() const{ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return song.get_name(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float EventStreamChibi::get_length() const{ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EventStreamChibi::EventStreamChibi() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-23 20:15:56 -03:00
										 |  |  | RES ResourceFormatLoaderChibi::load(const String &p_path, const String& p_original_path, Error *r_error) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-23 20:15:56 -03:00
										 |  |  | 	if (r_error) | 
					
						
							|  |  |  | 		*r_error=ERR_FILE_CANT_OPEN; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	String el = p_path.extension().to_lower(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CPFileAccessWrapperImpl f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (el=="it") { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Ref<EventStreamChibi> esc( memnew( EventStreamChibi ) ); | 
					
						
							|  |  |  | 		CPLoader_IT loader(&f); | 
					
						
							| 
									
										
										
										
											2014-09-17 20:03:10 -03:00
										 |  |  | 		CPLoader::Error err = loader.load_song(p_path.utf8().get_data(),&esc->song,false); | 
					
						
							|  |  |  | 		ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); | 
					
						
							| 
									
										
										
										
											2015-08-23 20:15:56 -03:00
										 |  |  | 		if (r_error) | 
					
						
							|  |  |  | 			*r_error=OK; | 
					
						
							| 
									
										
										
										
											2014-09-17 20:03:10 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return esc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} else if (el=="xm") { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Ref<EventStreamChibi> esc( memnew( EventStreamChibi ) ); | 
					
						
							|  |  |  | 		CPLoader_XM loader(&f); | 
					
						
							| 
									
										
										
										
											2014-09-17 20:03:10 -03:00
										 |  |  | 		CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false); | 
					
						
							|  |  |  | 		ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); | 
					
						
							| 
									
										
										
										
											2015-08-23 20:15:56 -03:00
										 |  |  | 		if (r_error) | 
					
						
							|  |  |  | 			*r_error=OK; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return esc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} else if (el=="s3m") { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Ref<EventStreamChibi> esc( memnew( EventStreamChibi ) ); | 
					
						
							|  |  |  | 		CPLoader_S3M loader(&f); | 
					
						
							| 
									
										
										
										
											2014-09-17 20:03:10 -03:00
										 |  |  | 		CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false); | 
					
						
							|  |  |  | 		ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); | 
					
						
							| 
									
										
										
										
											2015-08-23 20:15:56 -03:00
										 |  |  | 		if (r_error) | 
					
						
							|  |  |  | 			*r_error=OK; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return esc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} else if (el=="mod") { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Ref<EventStreamChibi> esc( memnew( EventStreamChibi ) ); | 
					
						
							|  |  |  | 		CPLoader_MOD loader(&f); | 
					
						
							| 
									
										
										
										
											2014-09-17 20:03:10 -03:00
										 |  |  | 		CPLoader::Error err=loader.load_song(p_path.utf8().get_data(),&esc->song,false); | 
					
						
							|  |  |  | 		ERR_FAIL_COND_V(err!=CPLoader::FILE_OK,RES()); | 
					
						
							| 
									
										
										
										
											2015-08-23 20:15:56 -03:00
										 |  |  | 		if (r_error) | 
					
						
							|  |  |  | 			*r_error=OK; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return esc; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return RES(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ResourceFormatLoaderChibi::get_recognized_extensions(List<String> *p_extensions) const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p_extensions->push_back("it"); | 
					
						
							|  |  |  | 	p_extensions->push_back("xm"); | 
					
						
							|  |  |  | 	p_extensions->push_back("s3m"); | 
					
						
							|  |  |  | 	p_extensions->push_back("mod"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool ResourceFormatLoaderChibi::handles_type(const String& p_type) const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return (p_type=="EventStreamChibi" || p_type=="EventStream"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String ResourceFormatLoaderChibi::get_resource_type(const String &p_path) const { | 
					
						
							|  |  |  | 	String el = p_path.extension().to_lower(); | 
					
						
							|  |  |  | 	if (el=="it" || el=="s3m" || el=="xm" || el=="mod") | 
					
						
							|  |  |  | 		return "EventStreamChibi"; | 
					
						
							|  |  |  | 	return ""; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | void initialize_chibi() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sample_manager = memnew( CPSampleManagerImpl ); | 
					
						
							|  |  |  | 	resource_loader = memnew( ResourceFormatLoaderChibi ); | 
					
						
							|  |  |  | 	ObjectTypeDB::register_type<EventStreamChibi>(); | 
					
						
							|  |  |  | 	ResourceLoader::add_resource_format_loader( resource_loader ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void finalize_chibi() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memdelete( sample_manager ); | 
					
						
							|  |  |  | 	memdelete( resource_loader ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |