cp_loader_it_samples.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. /*************************************************************************/
  2. /* cp_loader_it_samples.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #include "cp_loader_it.h"
  30. #include "cp_sample.h"
  31. struct AuxSampleData {
  32. uint32_t fileofs;
  33. uint32_t c5spd;
  34. uint32_t length;
  35. uint32_t loop_begin;
  36. uint32_t loop_end;
  37. bool loop_enabled;
  38. bool pingpong_enabled;
  39. bool is16bit;
  40. bool stereo;
  41. bool exists;
  42. bool compressed;
  43. };
  44. enum IT_Sample_Flags {
  45. IT_SAMPLE_EXISTS=1,
  46. IT_SAMPLE_16BITS=2,
  47. IT_SAMPLE_STEREO=4,
  48. IT_SAMPLE_COMPRESSED=8,
  49. IT_SAMPLE_LOOPED=16,
  50. IT_SAMPLE_SUSTAIN_LOOPED=32,
  51. IT_SAMPLE_LOOP_IS_PINGPONG=64,
  52. IT_SAMPLE_SUSTAIN_LOOP_IS_PINGPONG=128
  53. };
  54. CPLoader::Error CPLoader_IT::load_sample(CPSample *p_sample) {
  55. AuxSampleData aux_sample_data;
  56. char aux_header[4];
  57. file->get_byte_array((uint8_t*)aux_header,4);
  58. if ( aux_header[0]!='I' ||
  59. aux_header[1]!='M' ||
  60. aux_header[2]!='P' ||
  61. aux_header[3]!='S') {
  62. //CP_PRINTERR("IT CPLoader CPSample: Failed Identifier");
  63. return FILE_UNRECOGNIZED;
  64. }
  65. // Ignore deprecated 8.3 filename
  66. for (int i=0;i<12;i++) file->get_byte();
  67. file->get_byte(); //ignore zerobyte
  68. p_sample->set_global_volume( file->get_byte() );
  69. /* SAMPLE FLAGS */
  70. uint8_t flags=file->get_byte();
  71. aux_sample_data.loop_enabled=flags&IT_SAMPLE_LOOPED;
  72. aux_sample_data.pingpong_enabled=flags&IT_SAMPLE_LOOP_IS_PINGPONG;
  73. aux_sample_data.is16bit=flags&IT_SAMPLE_16BITS;
  74. aux_sample_data.exists=flags&IT_SAMPLE_EXISTS;
  75. aux_sample_data.stereo=flags&IT_SAMPLE_STEREO;
  76. aux_sample_data.compressed=flags&IT_SAMPLE_COMPRESSED;
  77. p_sample->set_default_volume(file->get_byte());
  78. /* SAMPLE NAME */
  79. char aux_name[26];
  80. file->get_byte_array((uint8_t*)aux_name,26);
  81. p_sample->set_name(aux_name);
  82. // ??
  83. uint8_t convert_flag=file->get_byte();
  84. // PAN
  85. uint8_t pan=file->get_byte();
  86. p_sample->set_pan( pan&0x7F );
  87. p_sample->set_pan_enabled( pan & 0x80 );
  88. aux_sample_data.length=file->get_dword();
  89. aux_sample_data.loop_begin= file->get_dword();
  90. aux_sample_data.loop_end= file->get_dword();
  91. aux_sample_data.c5spd=file->get_dword();
  92. /*p_sample->data.set_sustain_loop_begin=*/file->get_dword();
  93. /*p_sample->data.sustain_loop_end=*/file->get_dword();
  94. aux_sample_data.fileofs=file->get_dword();
  95. p_sample->set_vibrato_speed( file->get_byte() );
  96. p_sample->set_vibrato_depth( file->get_byte() );
  97. p_sample->set_vibrato_rate( file->get_byte() );
  98. switch( file->get_byte() ) {
  99. /* Vibrato Wave: 0=sine, 1=rampdown, 2=square, 3=random */
  100. case 0: p_sample->set_vibrato_type( CPSample::VIBRATO_SINE ); break;
  101. case 1: p_sample->set_vibrato_type( CPSample::VIBRATO_SAW ); break;
  102. case 2: p_sample->set_vibrato_type( CPSample::VIBRATO_SQUARE ); break;
  103. case 3: p_sample->set_vibrato_type( CPSample::VIBRATO_RANDOM ); break;
  104. default: p_sample->set_vibrato_type( CPSample::VIBRATO_SINE ); break;
  105. }
  106. //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);
  107. CPSample_ID samp_id;
  108. if (aux_sample_data.exists) {
  109. samp_id=load_sample_data(aux_sample_data);
  110. CPSampleManager::get_singleton()->set_c5_freq(samp_id,aux_sample_data.c5spd);
  111. CPSampleManager::get_singleton()->set_loop_begin( samp_id,aux_sample_data.loop_begin );
  112. CPSampleManager::get_singleton()->set_loop_end( samp_id,aux_sample_data.loop_end );
  113. CPSample_Loop_Type loop_type=aux_sample_data.loop_enabled?( aux_sample_data.pingpong_enabled? CP_LOOP_BIDI: CP_LOOP_FORWARD):CP_LOOP_NONE;
  114. CPSampleManager::get_singleton()->set_loop_end( samp_id,aux_sample_data.loop_end );
  115. CPSampleManager::get_singleton()->set_loop_type( samp_id, loop_type);
  116. }
  117. //printf("Loaded id is null?: %i\n",samp_id.is_null());
  118. p_sample->set_sample_data(samp_id);
  119. if (!samp_id.is_null()) {
  120. //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) );
  121. }
  122. CP_ERR_COND_V( file->eof_reached(),FILE_CORRUPTED );
  123. CP_ERR_COND_V( file->get_error(),FILE_CORRUPTED );
  124. return FILE_OK;
  125. }
  126. CPSample_ID CPLoader_IT::load_sample_data(AuxSampleData& p_sample_data) {
  127. 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);
  128. file->seek(p_sample_data.fileofs);
  129. CPSampleManager *sm=CPSampleManager::get_singleton();
  130. CPSample_ID id;
  131. switch (aux_sample_properties) {
  132. case (0): // 8 bits, mono
  133. case (IT_SAMPLE_16BITS): // 16 bits mono
  134. case (IT_SAMPLE_STEREO): // 8 bits stereo
  135. case (IT_SAMPLE_16BITS|IT_SAMPLE_STEREO): { // 16 bits mono
  136. id=sm->create(p_sample_data.is16bit,p_sample_data.stereo,p_sample_data.length);
  137. if (id.is_null())
  138. break;
  139. sm->lock_data(id);
  140. int16_t *ptr16 = (int16_t*)sm->get_data(id);
  141. int8_t *ptr8=(int8_t*)ptr16;
  142. int chans=p_sample_data.stereo?2:1;
  143. if (p_sample_data.is16bit) {
  144. for (int c=0;c<chans;c++) {
  145. for (int i=0;i<p_sample_data.length;i++) {
  146. ptr16[i*chans+c]=file->get_word();
  147. }
  148. }
  149. } else {
  150. for (int c=0;c<chans;c++) {
  151. for (int i=0;i<p_sample_data.length;i++) {
  152. ptr8[i*chans+c]=file->get_byte();
  153. }
  154. }
  155. }
  156. sm->unlock_data(id);
  157. } break;
  158. case (IT_SAMPLE_COMPRESSED): { // 8 bits compressed
  159. id=sm->create(false,false,p_sample_data.length);
  160. if (id.is_null())
  161. break;
  162. sm->lock_data(id);
  163. if ( load_sample_8bits_IT_compressed((void*)sm->get_data( id),p_sample_data.length) ) {
  164. sm->unlock_data(id);
  165. sm->destroy(id);
  166. break;
  167. }
  168. sm->unlock_data(id);
  169. } break;
  170. case (IT_SAMPLE_16BITS|IT_SAMPLE_COMPRESSED): { // 16 bits compressed
  171. id=sm->create(true,false,p_sample_data.length);
  172. if (id.is_null())
  173. break;
  174. sm->lock_data(id);
  175. if ( load_sample_16bits_IT_compressed((void*)sm->get_data(id),p_sample_data.length) ) {
  176. sm->unlock_data(id);
  177. sm->destroy(id);
  178. break;
  179. }
  180. sm->unlock_data(id);
  181. } break;
  182. default: {
  183. // I dont know how to handle stereo compressed, does that exist?
  184. } break;
  185. }
  186. return id;
  187. }
  188. CPLoader::Error CPLoader_IT::load_samples() {
  189. for (int i=0;i<header.smpnum;i++) {
  190. //seek to sample
  191. file->seek(0xC0+header.ordnum+header.insnum*4+i*4);
  192. uint32_t final_location=file->get_dword();
  193. file->seek( final_location );
  194. Error err=load_sample(song->get_sample(i));
  195. CP_ERR_COND_V(err,err);
  196. }
  197. if (file->eof_reached() || file->get_error())
  198. return FILE_CORRUPTED;
  199. return FILE_OK;
  200. }
  201. /* * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE
  202. -The following sample decompression code is based on xmp's code.(http://xmp.helllabs.org) which is based in openCP code.
  203. * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE * NOTICE */
  204. uint32_t CPLoader_IT::read_n_bits_from_IT_compressed_block (uint8_t p_bits_to_read) {
  205. uint32_t aux_return_value;
  206. uint32_t val;
  207. uint8_t *buffer=(uint8_t*)source_position;
  208. if ( p_bits_to_read <= source_remaining_bits ) {
  209. val=buffer[3];
  210. val<<=8;
  211. val|=buffer[2];
  212. val<<=8;
  213. val|=buffer[1];
  214. val<<=8;
  215. val|=buffer[0];
  216. aux_return_value = val & ((1 << p_bits_to_read) - 1);
  217. val >>= p_bits_to_read;
  218. source_remaining_bits -= p_bits_to_read;
  219. buffer[3]=val>>24;
  220. buffer[2]=(val>>16)&0xFF;
  221. buffer[1]=(val>>8)&0xFF;
  222. buffer[0]=(val)&0xFF;
  223. } else {
  224. aux_return_value=buffer[3];
  225. aux_return_value<<=8;
  226. aux_return_value|=buffer[2];
  227. aux_return_value<<=8;
  228. aux_return_value|=buffer[1];
  229. aux_return_value<<=8;
  230. aux_return_value|=buffer[0];
  231. uint32_t nbits = p_bits_to_read - source_remaining_bits;
  232. source_position++;
  233. buffer+=4;
  234. val=buffer[3];
  235. val<<=8;
  236. val|=buffer[2];
  237. val<<=8;
  238. val|=buffer[1];
  239. val<<=8;
  240. val|=buffer[0];
  241. aux_return_value |= ((val & ((1 << nbits) - 1)) << source_remaining_bits);
  242. val >>= nbits;
  243. source_remaining_bits = 32 - nbits;
  244. buffer[3]=val>>24;
  245. buffer[2]=(val>>16)&0xFF;
  246. buffer[1]=(val>>8)&0xFF;
  247. buffer[0]=(val)&0xFF;
  248. }
  249. return aux_return_value;
  250. }
  251. bool CPLoader_IT::read_IT_compressed_block (bool p_16bits) {
  252. uint16_t size;
  253. size=file->get_word();
  254. if (file->eof_reached() || file->get_error()) return true;
  255. pat_data = (uint8_t*)CP_ALLOC( 4* ((size >> 2) + 2) );
  256. if (!pat_data)
  257. return true;
  258. source_buffer=(uint32_t*)pat_data;
  259. file->get_byte_array((uint8_t*)source_buffer,size);
  260. if (file->eof_reached() || file->get_error()) {
  261. free_IT_compressed_block();
  262. return true;
  263. }
  264. source_position = source_buffer;
  265. source_remaining_bits = 32;
  266. return false;
  267. }
  268. void CPLoader_IT::free_IT_compressed_block () {
  269. if (pat_data) {
  270. CP_FREE(pat_data);
  271. pat_data=NULL;
  272. }
  273. }
  274. bool CPLoader_IT::load_sample_8bits_IT_compressed(void *p_dest_buffer,int p_buffsize) {
  275. int8_t *dest_buffer; /* destination buffer which will be returned */
  276. uint16_t block_length; /* length of compressed data block in samples */
  277. uint16_t block_position; /* position in block */
  278. uint8_t bit_width; /* actual "bit width" */
  279. uint16_t aux_value; /* value read from file to be processed */
  280. int8_t d1, d2; /* integrator buffers (d2 for it2.15) */
  281. int8_t *dest_position; /* position in output buffer */
  282. int8_t v; /* sample value */
  283. bool it215; // is this an it215 module?
  284. dest_buffer = (int8_t *) p_dest_buffer;
  285. if (dest_buffer==NULL)
  286. return true;
  287. for (int i=0;i<p_buffsize;i++)
  288. dest_buffer[i]=0;
  289. dest_position = dest_buffer;
  290. it215=(header.cmwt==0x215);
  291. /* now unpack data till the dest buffer is full */
  292. while (p_buffsize) {
  293. /* read a new block of compressed data and reset variables */
  294. if ( read_IT_compressed_block(false) ) {
  295. CP_PRINTERR("Out of memory decompressing IT CPSample");
  296. return true;
  297. }
  298. block_length = (p_buffsize < 0x8000) ? p_buffsize : 0x8000;
  299. block_position = 0;
  300. bit_width = 9; /* start with width of 9 bits */
  301. d1 = d2 = 0; /* reset integrator buffers */
  302. /* now uncompress the data block */
  303. while ( block_position < block_length ) {
  304. aux_value = read_n_bits_from_IT_compressed_block(bit_width); /* read bits */
  305. if ( bit_width < 7 ) { /* method 1 (1-6 bits) */
  306. if ( aux_value == (1 << (bit_width - 1)) ) { /* check for "100..." */
  307. aux_value = read_n_bits_from_IT_compressed_block(3) + 1; /* yes -> read new width; */
  308. bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1;
  309. /* and expand it */
  310. continue; /* ... next value */
  311. }
  312. } else if ( bit_width < 9 ) { /* method 2 (7-8 bits) */
  313. uint8_t border = (0xFF >> (9 - bit_width)) - 4;
  314. /* lower border for width chg */
  315. if ( aux_value > border && aux_value <= (border + 8) ) {
  316. aux_value -= border; /* convert width to 1-8 */
  317. bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1;
  318. /* and expand it */
  319. continue; /* ... next value */
  320. }
  321. } else if ( bit_width == 9 ) { /* method 3 (9 bits) */
  322. if ( aux_value & 0x100 ) { /* bit 8 set? */
  323. bit_width = (aux_value + 1) & 0xff; /* new width... */
  324. continue; /* ... and next value */
  325. }
  326. } else { /* illegal width, abort */
  327. free_IT_compressed_block();
  328. CP_PRINTERR("CPSample has illegal BitWidth ");
  329. return true;
  330. }
  331. /* now expand value to signed byte */
  332. if ( bit_width < 8 ) {
  333. uint8_t tmp_shift = 8 - bit_width;
  334. v=(aux_value << tmp_shift);
  335. v>>=tmp_shift;
  336. } else v = (int8_t) aux_value;
  337. /* integrate upon the sample values */
  338. d1 += v;
  339. d2 += d1;
  340. /* ... and store it into the buffer */
  341. *(dest_position++) = it215 ? d2 : d1;
  342. block_position++;
  343. }
  344. /* now subtract block lenght from total length and go on */
  345. free_IT_compressed_block();
  346. p_buffsize -= block_length;
  347. }
  348. return false;
  349. }
  350. bool CPLoader_IT::load_sample_16bits_IT_compressed(void *p_dest_buffer,int p_buffsize) {
  351. int16_t *dest_buffer; /* destination buffer which will be returned */
  352. uint16_t block_length; /* length of compressed data block in samples */
  353. uint16_t block_position; /* position in block */
  354. uint8_t bit_width; /* actual "bit width" */
  355. uint32_t aux_value; /* value read from file to be processed */
  356. int16_t d1, d2; /* integrator buffers (d2 for it2.15) */
  357. int16_t *dest_position; /* position in output buffer */
  358. int16_t v; /* sample value */
  359. bool it215; // is this an it215 module?
  360. dest_buffer = (int16_t *) p_dest_buffer;
  361. if (dest_buffer==NULL)
  362. return true;
  363. for (int i=0;i<p_buffsize;i++)
  364. dest_buffer[i]=0;
  365. dest_position = dest_buffer;
  366. it215=(header.cmwt==0x215);
  367. while (p_buffsize) {
  368. /* read a new block of compressed data and reset variables */
  369. if ( read_IT_compressed_block(true) ) {
  370. return true;
  371. }
  372. block_length = (p_buffsize < 0x4000) ? p_buffsize : 0x4000;
  373. block_position = 0;
  374. bit_width = 17; /* start with width of 9 bits */
  375. d1 = d2 = 0; /* reset integrator buffers */
  376. while ( block_position < block_length ) {
  377. aux_value = read_n_bits_from_IT_compressed_block(bit_width); /* read bits */
  378. if ( bit_width < 7 ) { /* method 1 (1-6 bits) */
  379. if ( (signed)aux_value == (1 << (bit_width - 1)) ) { /* check for "100..." */
  380. aux_value = read_n_bits_from_IT_compressed_block(4) + 1; /* yes -> read new width; */
  381. bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1;
  382. /* and expand it */
  383. continue; /* ... next value */
  384. }
  385. } else if ( bit_width < 17 ) {
  386. uint16_t border = (0xFFFF >> (17 - bit_width)) - 8;
  387. if ( (int)aux_value > (int)border && (int)aux_value <= ((int)border + 16) ) {
  388. aux_value -= border; /* convert width to 1-8 */
  389. bit_width = (aux_value < bit_width) ? aux_value : aux_value + 1;
  390. /* and expand it */
  391. continue; /* ... next value */
  392. }
  393. } else if ( bit_width == 17 ) {
  394. if ( aux_value & 0x10000 ) { /* bit 8 set? */
  395. bit_width = (aux_value + 1) & 0xff; /* new width... */
  396. continue; /* ... and next value */
  397. }
  398. } else { /* illegal width, abort */
  399. CP_PRINTERR("CPSample has illegal BitWidth ");
  400. free_IT_compressed_block();
  401. return true;
  402. }
  403. /* now expand value to signed byte */
  404. if ( bit_width < 16 ) {
  405. uint8_t tmp_shift = 16 - bit_width;
  406. v=(aux_value << tmp_shift);
  407. v>>=tmp_shift;
  408. } else v = (int16_t) aux_value;
  409. /* integrate upon the sample values */
  410. d1 += v;
  411. d2 += d1;
  412. /* ... and store it into the buffer */
  413. *(dest_position++) = it215 ? d2 : d1;
  414. block_position++;
  415. }
  416. /* now subtract block lenght from total length and go on */
  417. free_IT_compressed_block();
  418. p_buffsize -= block_length;
  419. }
  420. return false;
  421. }