mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-29 12:44:31 +00:00 
			
		
		
		
	
		
			
	
	
		
			621 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			621 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | /*************************************************************************/ | ||
|  | /*  cp_loader_it_samples.cpp                                             */ | ||
|  | /*************************************************************************/ | ||
|  | /*                       This file is part of:                           */ | ||
|  | /*                           GODOT ENGINE                                */ | ||
|  | /*                    http://www.godotengine.org                         */ | ||
|  | /*************************************************************************/ | ||
|  | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                 */ | ||
|  | /*                                                                       */ | ||
|  | /* 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 "cp_loader_it.h"
 | ||
|  | #include "cp_sample.h"
 | ||
|  | 
 | ||
|  | struct AuxSampleData { | ||
|  | 
 | ||
|  | 
 | ||
|  | 	uint32_t fileofs; | ||
|  | 	uint32_t c5spd; | ||
|  | 	uint32_t length; | ||
|  | 	uint32_t loop_begin; | ||
|  | 	uint32_t loop_end; | ||
|  | 	bool loop_enabled; | ||
|  | 	bool pingpong_enabled; | ||
|  | 	bool is16bit; | ||
|  | 	bool stereo; | ||
|  | 	bool exists; | ||
|  | 	bool compressed; | ||
|  | 
 | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | enum IT_Sample_Flags { | ||
|  | 
 | ||
|  | 	IT_SAMPLE_EXISTS=1, | ||
|  | 	IT_SAMPLE_16BITS=2, | ||
|  | 	IT_SAMPLE_STEREO=4, | ||
|  | 	IT_SAMPLE_COMPRESSED=8, | ||
|  | 	IT_SAMPLE_LOOPED=16, | ||
|  | 	IT_SAMPLE_SUSTAIN_LOOPED=32, | ||
|  | 	IT_SAMPLE_LOOP_IS_PINGPONG=64, | ||
|  | 	IT_SAMPLE_SUSTAIN_LOOP_IS_PINGPONG=128 | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | CPLoader::Error CPLoader_IT::load_sample(CPSample *p_sample) { | ||
|  | 
 | ||
|  | 
 | ||
|  | 	AuxSampleData aux_sample_data; | ||
|  | 
 | ||
|  | 	char aux_header[4]; | ||
|  | 
 | ||
|  | 	file->get_byte_array((uint8_t*)aux_header,4); | ||
|  | 	 | ||
|  | 	if (	aux_header[0]!='I' || | ||
|  | 		aux_header[1]!='M' || | ||
|  | 		aux_header[2]!='P' || | ||
|  | 		       aux_header[3]!='S') { | ||
|  | 		 | ||
|  | 		//CP_PRINTERR("IT CPLoader CPSample: Failed Identifier");
 | ||
|  | 		return FILE_UNRECOGNIZED; | ||
|  | 	} | ||
|  | 		 | ||
|  | 
 | ||
|  | 	// Ignore deprecated 8.3 filename
 | ||
|  | 	for (int i=0;i<12;i++) file->get_byte(); | ||
|  | 	 | ||
|  | 	file->get_byte(); //ignore zerobyte
 | ||
|  | 	 | ||
|  | 	p_sample->set_global_volume( file->get_byte() ); | ||
|  | 	 | ||
|  | 	/* SAMPLE FLAGS */ | ||
|  |        	uint8_t flags=file->get_byte(); | ||
|  | 	aux_sample_data.loop_enabled=flags&IT_SAMPLE_LOOPED; | ||
|  | 	aux_sample_data.pingpong_enabled=flags&IT_SAMPLE_LOOP_IS_PINGPONG; | ||
|  | 	aux_sample_data.is16bit=flags&IT_SAMPLE_16BITS; | ||
|  | 	aux_sample_data.exists=flags&IT_SAMPLE_EXISTS; | ||
|  | 	aux_sample_data.stereo=flags&IT_SAMPLE_STEREO; | ||
|  | 	aux_sample_data.compressed=flags&IT_SAMPLE_COMPRESSED; | ||
|  | 	 | ||
|  | 	p_sample->set_default_volume(file->get_byte()); | ||
|  | 	/* SAMPLE NAME */ | ||
|  | 	char aux_name[26]; | ||
|  | 	file->get_byte_array((uint8_t*)aux_name,26); | ||
|  | 	p_sample->set_name(aux_name); | ||
|  | 	 | ||
|  | 	// ??
 | ||
|  | 	uint8_t convert_flag=file->get_byte(); | ||
|  | 	// PAN
 | ||
|  | 	uint8_t pan=file->get_byte(); | ||
|  | 	p_sample->set_pan( pan&0x7F );  | ||
|  | 	p_sample->set_pan_enabled( pan & 0x80 ); | ||
|  | 
 | ||
|  | 	aux_sample_data.length=file->get_dword(); | ||
|  | 
 | ||
|  | 	 | ||
|  | 	aux_sample_data.loop_begin= file->get_dword(); | ||
|  | 	aux_sample_data.loop_end= file->get_dword(); | ||
|  | 	aux_sample_data.c5spd=file->get_dword(); | ||
|  | 	/*p_sample->data.set_sustain_loop_begin=*/file->get_dword(); | ||
|  | 	/*p_sample->data.sustain_loop_end=*/file->get_dword(); | ||
|  | 	aux_sample_data.fileofs=file->get_dword(); | ||
|  | 	p_sample->set_vibrato_speed( file->get_byte() ); | ||
|  | 	p_sample->set_vibrato_depth( file->get_byte() ); | ||
|  | 	p_sample->set_vibrato_rate( file->get_byte() ); | ||
|  | 	switch( file->get_byte() ) { | ||
|  | 		/* Vibrato Wave: 0=sine, 1=rampdown, 2=square, 3=random */ | ||
|  | 		case 0: p_sample->set_vibrato_type( CPSample::VIBRATO_SINE ); break; | ||
|  | 		case 1: p_sample->set_vibrato_type( CPSample::VIBRATO_SAW ); break; | ||
|  | 		case 2: p_sample->set_vibrato_type( CPSample::VIBRATO_SQUARE ); break; | ||
|  | 		case 3: p_sample->set_vibrato_type( CPSample::VIBRATO_RANDOM ); break; | ||
|  | 		default: p_sample->set_vibrato_type( CPSample::VIBRATO_SINE ); break; | ||
|  | 	} | ||
|  | 	 | ||
|  | 	//printf("Name %s - Flags: fileofs :%i - c5spd %i - len %i 16b %i - data?: %i\n",p_sample->get_name(),aux_sample_data.fileofs,aux_sample_data.c5spd, aux_sample_data.length, aux_sample_data.is16bit,aux_sample_data.exists);
 | ||
|  | 	CPSample_ID samp_id; | ||
|  | 	 | ||
|  | 	if (aux_sample_data.exists) { | ||
|  | 		samp_id=load_sample_data(aux_sample_data); | ||
|  | 		CPSampleManager::get_singleton()->set_c5_freq(samp_id,aux_sample_data.c5spd); | ||
|  | 		CPSampleManager::get_singleton()->set_loop_begin( samp_id,aux_sample_data.loop_begin ); | ||
|  | 		CPSampleManager::get_singleton()->set_loop_end( samp_id,aux_sample_data.loop_end ); | ||
|  | 		CPSample_Loop_Type loop_type=aux_sample_data.loop_enabled?( aux_sample_data.pingpong_enabled? CP_LOOP_BIDI: CP_LOOP_FORWARD):CP_LOOP_NONE; | ||
|  | 		CPSampleManager::get_singleton()->set_loop_end( samp_id,aux_sample_data.loop_end ); | ||
|  | 		CPSampleManager::get_singleton()->set_loop_type( samp_id, loop_type); | ||
|  | 		 | ||
|  | 	} | ||
|  | 	 | ||
|  | 	//printf("Loaded id is null?: %i\n",samp_id.is_null());
 | ||
|  | 	p_sample->set_sample_data(samp_id); | ||
|  | 	if (!samp_id.is_null()) { | ||
|  | 		 | ||
|  | 	//	printf("Loaded ID: stereo: %i len %i 16bit %i\n",CPSampleManager::get_singleton()->is_stereo(samp_id), CPSampleManager::get_singleton()->get_size( samp_id), CPSampleManager::get_singleton()->is_16bits( samp_id) );
 | ||
|  | 	} | ||
|  | 	 | ||
|  | 	CP_ERR_COND_V( file->eof_reached(),FILE_CORRUPTED ); | ||
|  | 	CP_ERR_COND_V( file->get_error(),FILE_CORRUPTED ); | ||
|  | 	 | ||
|  | 	return FILE_OK; | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | CPSample_ID CPLoader_IT::load_sample_data(AuxSampleData& p_sample_data) { | ||
|  | 
 | ||
|  | 
 | ||
|  | 	int aux_sample_properties = (p_sample_data.is16bit?IT_SAMPLE_16BITS:0)|(p_sample_data.compressed?IT_SAMPLE_COMPRESSED:0)|(p_sample_data.stereo?IT_SAMPLE_STEREO:0); | ||
|  | 
 | ||
|  | 	file->seek(p_sample_data.fileofs); | ||
|  | 	 | ||
|  | 	CPSampleManager *sm=CPSampleManager::get_singleton(); | ||
|  | 
 | ||
|  | 	CPSample_ID id; | ||
|  | 	 | ||
|  | 	switch (aux_sample_properties) { | ||
|  | 
 | ||
|  | 		case (0):  // 8 bits, mono
 | ||
|  | 		case (IT_SAMPLE_16BITS):  // 16 bits mono
 | ||
|  | 		case (IT_SAMPLE_STEREO):  // 8 bits stereo
 | ||
|  | 		case (IT_SAMPLE_16BITS|IT_SAMPLE_STEREO): { // 16 bits mono
 | ||
|  | 
 | ||
|  | 			id=sm->create(p_sample_data.is16bit,p_sample_data.stereo,p_sample_data.length);  | ||
|  | 			if (id.is_null()) | ||
|  | 				break; | ||
|  | 
 | ||
|  | 			sm->lock_data(id); | ||
|  | 
 | ||
|  | 			int16_t *ptr16 = (int16_t*)sm->get_data(id); | ||
|  | 			int8_t *ptr8=(int8_t*)ptr16; | ||
|  | 
 | ||
|  | 			int chans=p_sample_data.stereo?2:1; | ||
|  | 
 | ||
|  | 			if (p_sample_data.is16bit) { | ||
|  | 
 | ||
|  | 				for (int c=0;c<chans;c++) { | ||
|  | 
 | ||
|  | 					for (int i=0;i<p_sample_data.length;i++) { | ||
|  | 
 | ||
|  | 						ptr16[i*chans+c]=file->get_word(); | ||
|  | 					} | ||
|  | 				} | ||
|  | 			} else { | ||
|  | 
 | ||
|  | 				for (int c=0;c<chans;c++) { | ||
|  | 
 | ||
|  | 					for (int i=0;i<p_sample_data.length;i++) { | ||
|  | 
 | ||
|  | 						ptr8[i*chans+c]=file->get_byte(); | ||
|  | 					} | ||
|  | 				} | ||
|  | 
 | ||
|  | 			} | ||
|  | 
 | ||
|  | 			sm->unlock_data(id); | ||
|  | 
 | ||
|  | 		} break; | ||
|  | 		case (IT_SAMPLE_COMPRESSED): { // 8 bits compressed
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 			id=sm->create(false,false,p_sample_data.length);  | ||
|  | 			if (id.is_null()) | ||
|  | 				break; | ||
|  | 			sm->lock_data(id); | ||
|  | 			 | ||
|  | 			if ( load_sample_8bits_IT_compressed((void*)sm->get_data( id),p_sample_data.length) ) { | ||
|  | 
 | ||
|  | 				sm->unlock_data(id); | ||
|  | 				sm->destroy(id); | ||
|  | 				 | ||
|  | 				break; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			sm->unlock_data(id); | ||
|  | 
 | ||
|  | 
 | ||
|  | 		} break; | ||
|  | 		case (IT_SAMPLE_16BITS|IT_SAMPLE_COMPRESSED): { // 16 bits compressed
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 			id=sm->create(true,false,p_sample_data.length);  | ||
|  | 			if (id.is_null()) | ||
|  | 				break; | ||
|  | 			sm->lock_data(id); | ||
|  | 			 | ||
|  | 			if ( load_sample_16bits_IT_compressed((void*)sm->get_data(id),p_sample_data.length) ) { | ||
|  | 
 | ||
|  | 				sm->unlock_data(id); | ||
|  | 				sm->destroy(id); | ||
|  | 				break; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			sm->unlock_data(id); | ||
|  | 
 | ||
|  | 		} break; | ||
|  | 		default: { | ||
|  | 			 | ||
|  | 			// I dont know how to handle stereo compressed, does that exist?
 | ||
|  | 		} break; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 
 | ||
|  | 	return id; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | CPLoader::Error CPLoader_IT::load_samples() { | ||
|  | 
 | ||
|  | 	for (int i=0;i<header.smpnum;i++) { | ||
|  | 
 | ||
|  | 		//seek to sample 
 | ||
|  | 		file->seek(0xC0+header.ordnum+header.insnum*4+i*4); | ||
|  | 		 | ||
|  | 		uint32_t final_location=file->get_dword(); | ||
|  | 		file->seek( final_location ); | ||
|  | 		 | ||
|  | 
 | ||
|  | 		Error err=load_sample(song->get_sample(i)); | ||
|  | 		CP_ERR_COND_V(err,err); | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if (file->eof_reached() || file->get_error()) | ||
|  | 		return FILE_CORRUPTED; | ||
|  | 
 | ||
|  | 	return FILE_OK; | ||
|  | } | ||
|  | /* * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE
 | ||
|  | 
 | ||
|  |  -The following sample decompression code is based on xmp's code.(http://xmp.helllabs.org) which is based in openCP code.
 | ||
|  | 
 | ||
|  | * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE */ | ||
|  | 
 | ||
|  | uint32_t CPLoader_IT::read_n_bits_from_IT_compressed_block (uint8_t p_bits_to_read) { | ||
|  | 
 | ||
|  |     uint32_t aux_return_value; | ||
|  |     uint32_t val; | ||
|  | 
 | ||
|  |     uint8_t *buffer=(uint8_t*)source_position; | ||
|  |     if ( p_bits_to_read <= source_remaining_bits ) { | ||
|  | 
 | ||
|  |     	val=buffer[3]; | ||
|  | 	val<<=8; | ||
|  |     	val|=buffer[2]; | ||
|  | 	val<<=8; | ||
|  |     	val|=buffer[1]; | ||
|  | 	val<<=8; | ||
|  |     	val|=buffer[0]; | ||
|  | 
 | ||
|  | 	aux_return_value = val & ((1 << p_bits_to_read) - 1); | ||
|  | 	val >>= p_bits_to_read; | ||
|  | 	source_remaining_bits -= p_bits_to_read; | ||
|  | 
 | ||
|  | 	buffer[3]=val>>24; | ||
|  |     	buffer[2]=(val>>16)&0xFF; | ||
|  |     	buffer[1]=(val>>8)&0xFF; | ||
|  |     	buffer[0]=(val)&0xFF; | ||
|  | 
 | ||
|  |     } else { | ||
|  |     	aux_return_value=buffer[3]; | ||
|  | 	aux_return_value<<=8; | ||
|  |     	aux_return_value|=buffer[2]; | ||
|  | 	aux_return_value<<=8; | ||
|  |     	aux_return_value|=buffer[1]; | ||
|  | 	aux_return_value<<=8; | ||
|  |     	aux_return_value|=buffer[0]; | ||
|  | 
 | ||
|  | 	uint32_t nbits = p_bits_to_read - source_remaining_bits; | ||
|  | 	source_position++; | ||
|  | 
 | ||
|  |         buffer+=4; | ||
|  |     	val=buffer[3]; | ||
|  | 	val<<=8; | ||
|  |     	val|=buffer[2]; | ||
|  | 	val<<=8; | ||
|  |     	val|=buffer[1]; | ||
|  | 	val<<=8; | ||
|  |     	val|=buffer[0]; | ||
|  | 	aux_return_value |= ((val & ((1 << nbits) - 1)) << source_remaining_bits); | ||
|  | 	val >>= nbits; | ||
|  | 	source_remaining_bits = 32 - nbits; | ||
|  | 	buffer[3]=val>>24; | ||
|  |     	buffer[2]=(val>>16)&0xFF; | ||
|  |     	buffer[1]=(val>>8)&0xFF; | ||
|  |     	buffer[0]=(val)&0xFF; | ||
|  | 
 | ||
|  |     } | ||
|  | 
 | ||
|  |     return aux_return_value; | ||
|  | } | ||
|  | 
 | ||
|  | bool CPLoader_IT::read_IT_compressed_block (bool p_16bits) { | ||
|  | 
 | ||
|  | 	uint16_t size; | ||
|  | 
 | ||
|  | 	size=file->get_word(); | ||
|  | 
 | ||
|  | 	if (file->eof_reached() || file->get_error()) return true; | ||
|  | 
 | ||
|  | 	pat_data = (uint8_t*)CP_ALLOC( 4* ((size >> 2) + 2) ); | ||
|  | 	if (!pat_data) | ||
|  | 		return true; | ||
|  | 	 | ||
|  | 
 | ||
|  | 	source_buffer=(uint32_t*)pat_data; | ||
|  | 	file->get_byte_array((uint8_t*)source_buffer,size); | ||
|  | 	 | ||
|  | 	if (file->eof_reached() || file->get_error()) { | ||
|  | 		 | ||
|  | 		free_IT_compressed_block(); | ||
|  | 		return true; | ||
|  | 	} | ||
|  | 	 | ||
|  | 	source_position = source_buffer; | ||
|  | 	source_remaining_bits = 32; | ||
|  | 
 | ||
|  | 	return false; | ||
|  | } | ||
|  | 
 | ||
|  | void CPLoader_IT::free_IT_compressed_block () { | ||
|  | 
 | ||
|  | 
 | ||
|  | 	if (pat_data) { | ||
|  | 		CP_FREE(pat_data); | ||
|  | 		pat_data=NULL; | ||
|  | 	} | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | bool CPLoader_IT::load_sample_8bits_IT_compressed(void *p_dest_buffer,int p_buffsize) { | ||
|  | 
 | ||
|  | 	int8_t *dest_buffer;		/* destination buffer which will be returned */ | ||
|  |    	uint16_t block_length;		/* length of compressed data block in samples */ | ||
|  | 	uint16_t block_position;		/* position in block */ | ||
|  | 	uint8_t bit_width;			/* actual "bit width" */ | ||
|  | 	uint16_t aux_value;			/* value read from file to be processed */ | ||
|  | 	int8_t d1, d2;		/* integrator buffers (d2 for it2.15) */ | ||
|  | 	int8_t *dest_position;		/* position in output buffer */ | ||
|  | 	int8_t v;			/* sample value */ | ||
|  | 	bool it215; // is this an it215 module?
 | ||
|  | 
 | ||
|  | 	dest_buffer = (int8_t *) p_dest_buffer; | ||
|  | 
 | ||
|  | 	if (dest_buffer==NULL)  | ||
|  | 		return true; | ||
|  | 
 | ||
|  | 	for (int i=0;i<p_buffsize;i++) | ||
|  | 		dest_buffer[i]=0; | ||
|  | 
 | ||
|  | 
 | ||
|  | 	dest_position = dest_buffer; | ||
|  | 
 | ||
|  | 	it215=(header.cmwt==0x215); | ||
|  | 
 | ||
|  | 	/* now unpack data till the dest buffer is full */ | ||
|  | 
 | ||
|  | 	while (p_buffsize) { | ||
|  | 	/* read a new block of compressed data and reset variables */ | ||
|  | 		if ( read_IT_compressed_block(false) ) { | ||
|  | 			CP_PRINTERR("Out of memory decompressing IT CPSample"); | ||
|  | 			return true; | ||
|  | 		} | ||
|  | 
 | ||
|  | 
 | ||
|  | 		block_length = (p_buffsize < 0x8000) ? p_buffsize : 0x8000; | ||
|  | 
 | ||
|  | 		block_position = 0; | ||
|  | 
 | ||
|  | 		bit_width = 9;		/* start with width of 9 bits */ | ||
|  | 
 | ||
|  | 		d1 = d2 = 0;		/* reset integrator buffers */ | ||
|  | 
 | ||
|  | 	/* now uncompress the data block */ | ||
|  | 		while ( block_position < block_length ) { | ||
|  | 
 | ||
|  | 			aux_value = read_n_bits_from_IT_compressed_block(bit_width);			/* read bits */ | ||
|  | 
 | ||
|  | 			if ( bit_width < 7 ) { /* method 1 (1-6 bits) */ | ||
|  | 
 | ||
|  | 				if ( aux_value == (1 << (bit_width - 1)) ) { /* check for "100..." */ | ||
|  | 
 | ||
|  | 					aux_value = read_n_bits_from_IT_compressed_block(3) + 1; /* yes -> read new width; */ | ||
|  | 		    			bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1; | ||
|  | 							/* and expand it */ | ||
|  | 		    			continue; /* ... next value */ | ||
|  | 				} | ||
|  | 
 | ||
|  | 			} else if ( bit_width < 9 ) { /* method 2 (7-8 bits) */ | ||
|  | 
 | ||
|  | 				uint8_t border = (0xFF >> (9 - bit_width)) - 4; | ||
|  | 							/* lower border for width chg */ | ||
|  | 
 | ||
|  | 				if ( aux_value > border && aux_value <= (border + 8) ) { | ||
|  | 
 | ||
|  | 					aux_value -= border; /* convert width to 1-8 */ | ||
|  | 					bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1; | ||
|  | 							/* and expand it */ | ||
|  | 		    			continue; /* ... next value */ | ||
|  | 				} | ||
|  | 
 | ||
|  | 
 | ||
|  | 			} else if ( bit_width == 9 ) { /* method 3 (9 bits) */ | ||
|  | 
 | ||
|  | 				if ( aux_value & 0x100 ) {			/* bit 8 set? */ | ||
|  | 
 | ||
|  | 					bit_width = (aux_value + 1) & 0xff;		/* new width... */ | ||
|  | 		    			continue;				/* ... and next value */ | ||
|  | 				} | ||
|  | 
 | ||
|  | 			} else { /* illegal width, abort */ | ||
|  | 
 | ||
|  | 				 | ||
|  | 				free_IT_compressed_block(); | ||
|  | 				CP_PRINTERR("CPSample has illegal BitWidth "); | ||
|  | 				return true; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			/* now expand value to signed byte */ | ||
|  | 			if ( bit_width < 8 ) { | ||
|  | 
 | ||
|  | 				uint8_t tmp_shift = 8 - bit_width; | ||
|  | 
 | ||
|  | 				v=(aux_value << tmp_shift); | ||
|  | 				v>>=tmp_shift; | ||
|  | 
 | ||
|  | 			} else v = (int8_t) aux_value; | ||
|  | 
 | ||
|  | 			/* integrate upon the sample values */ | ||
|  | 			d1 += v; | ||
|  | 	    		d2 += d1; | ||
|  | 
 | ||
|  | 			/* ... and store it into the buffer */ | ||
|  | 			*(dest_position++) = it215 ? d2 : d1; | ||
|  | 			block_position++; | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/* now subtract block lenght from total length and go on */ | ||
|  | 		free_IT_compressed_block(); | ||
|  | 		p_buffsize -= block_length; | ||
|  | 	} | ||
|  | 
 | ||
|  | 
 | ||
|  | 	return false; | ||
|  | } | ||
|  | 
 | ||
|  | bool CPLoader_IT::load_sample_16bits_IT_compressed(void *p_dest_buffer,int p_buffsize) { | ||
|  | 
 | ||
|  | 	int16_t *dest_buffer;		/* destination buffer which will be returned */ | ||
|  |    	uint16_t block_length;		/* length of compressed data block in samples */ | ||
|  | 	uint16_t block_position;		/* position in block */ | ||
|  | 	uint8_t bit_width;			/* actual "bit width" */ | ||
|  | 	uint32_t aux_value;			/* value read from file to be processed */ | ||
|  | 	int16_t d1, d2;		/* integrator buffers (d2 for it2.15) */ | ||
|  | 	int16_t *dest_position;		/* position in output buffer */ | ||
|  | 	int16_t v;			/* sample value */ | ||
|  | 
 | ||
|  | 	bool it215; // is this an it215 module?
 | ||
|  | 
 | ||
|  | 	dest_buffer = (int16_t *) p_dest_buffer; | ||
|  | 
 | ||
|  | 	if (dest_buffer==NULL)  | ||
|  | 		return true; | ||
|  | 
 | ||
|  | 	for (int i=0;i<p_buffsize;i++) | ||
|  | 		dest_buffer[i]=0; | ||
|  | 
 | ||
|  | 	dest_position = dest_buffer; | ||
|  | 
 | ||
|  | 	it215=(header.cmwt==0x215); | ||
|  | 
 | ||
|  | 
 | ||
|  | 	while (p_buffsize) { | ||
|  | 	/* read a new block of compressed data and reset variables */ | ||
|  | 		if ( read_IT_compressed_block(true) ) { | ||
|  | 
 | ||
|  | 			return true; | ||
|  | 		} | ||
|  | 
 | ||
|  | 
 | ||
|  | 		block_length = (p_buffsize < 0x4000) ? p_buffsize : 0x4000; | ||
|  | 
 | ||
|  | 		block_position = 0; | ||
|  | 
 | ||
|  | 		bit_width = 17;		/* start with width of 9 bits */ | ||
|  | 
 | ||
|  | 		d1 = d2 = 0;		/* reset integrator buffers */ | ||
|  | 
 | ||
|  | 		while ( block_position < block_length ) { | ||
|  | 
 | ||
|  | 			aux_value = read_n_bits_from_IT_compressed_block(bit_width);			/* read bits */ | ||
|  | 
 | ||
|  | 			if ( bit_width < 7 ) { /* method 1 (1-6 bits) */ | ||
|  | 
 | ||
|  | 				if ( (signed)aux_value == (1 << (bit_width - 1)) ) { /* check for "100..." */ | ||
|  | 
 | ||
|  | 					aux_value = read_n_bits_from_IT_compressed_block(4) + 1; /* yes -> read new width; */ | ||
|  | 		    			bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1; | ||
|  | 							/* and expand it */ | ||
|  | 		    			continue; /* ... next value */ | ||
|  | 				} | ||
|  | 
 | ||
|  | 			} else if ( bit_width < 17 ) { | ||
|  | 
 | ||
|  | 				uint16_t border = (0xFFFF >> (17 - bit_width)) - 8; | ||
|  | 
 | ||
|  | 				if ( (int)aux_value > (int)border && (int)aux_value <= ((int)border + 16) ) { | ||
|  | 
 | ||
|  | 					aux_value -= border; /* convert width to 1-8 */ | ||
|  | 					bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1; | ||
|  | 							/* and expand it */ | ||
|  | 		    			continue; /* ... next value */ | ||
|  | 				} | ||
|  | 
 | ||
|  | 
 | ||
|  | 			} else if ( bit_width == 17 ) { | ||
|  | 
 | ||
|  | 				if ( aux_value & 0x10000 ) {			/* bit 8 set? */ | ||
|  | 
 | ||
|  | 					bit_width = (aux_value + 1) & 0xff;		/* new width... */ | ||
|  | 		    			continue;				/* ... and next value */ | ||
|  | 				} | ||
|  | 
 | ||
|  | 			} else { /* illegal width, abort */ | ||
|  | 
 | ||
|  | 				CP_PRINTERR("CPSample has illegal BitWidth "); | ||
|  | 
 | ||
|  | 				free_IT_compressed_block(); | ||
|  | 			 | ||
|  | 				return true; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			/* now expand value to signed byte */ | ||
|  | 			if ( bit_width < 16 ) { | ||
|  | 
 | ||
|  | 				uint8_t tmp_shift = 16 - bit_width; | ||
|  | 
 | ||
|  | 				v=(aux_value << tmp_shift); | ||
|  | 				v>>=tmp_shift; | ||
|  | 
 | ||
|  | 			} else v = (int16_t) aux_value; | ||
|  | 
 | ||
|  | 			/* integrate upon the sample values */ | ||
|  | 			d1 += v; | ||
|  | 	    		d2 += d1; | ||
|  | 
 | ||
|  | 			/* ... and store it into the buffer */ | ||
|  | 			*(dest_position++) = it215 ? d2 : d1; | ||
|  | 			block_position++; | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/* now subtract block lenght from total length and go on */ | ||
|  | 		free_IT_compressed_block(); | ||
|  | 		p_buffsize -= block_length; | ||
|  | 	} | ||
|  | 
 | ||
|  | 
 | ||
|  | 	return false; | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 |