PageRenderTime 81ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 1ms

/src/diff.c

https://bitbucket.org/fcoelho/hipermidia
C | 676 lines | 530 code | 113 blank | 33 comment | 123 complexity | 6b26a883e7dc43d25db33599e7d02abe MD5 | raw file
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "diff.h"
  4. #define WINDOW_SIZE 8
  5. /*Determina o modulo do numero x*/
  6. int modulo(int x)
  7. {
  8. if(x < 0)
  9. {
  10. return -x;
  11. }
  12. else return x;
  13. }
  14. /*Retorna 1 se o bit b do char a for igual a 1, 0 caso contrario*/
  15. int bit_check(char a, int b)
  16. {
  17. if(a & (1 << (7 - b)))
  18. {
  19. return 1;
  20. }
  21. else
  22. {
  23. return 0;
  24. }
  25. }
  26. /*Torna o bit b do char a igual a 1*/
  27. void bit_on(char *a, int b)
  28. {
  29. *a = *a | (1 << (7 - b));
  30. }
  31. /*Torna o bit b do char a igual a 0*/
  32. void bit_off(char *a, int b)
  33. {
  34. *a = *a & (~(1 << (7 - b)));
  35. }
  36. /*Retorna 1 se o bit b do short int a for igual a 1, 0 caso contrario*/
  37. int bit_check2(short int a, int b)
  38. {
  39. if(a & (1 << (15 - b)))
  40. {
  41. return 1;
  42. }
  43. else
  44. {
  45. return 0;
  46. }
  47. }
  48. /*Retorna o número de bits necessários para representar o numero max em binario*/
  49. short int determina_tamanho(short int max)
  50. {
  51. short int i = 1;
  52. while(max/2 != 0)
  53. {
  54. max /= 2;
  55. i++;
  56. }
  57. return i;
  58. }
  59. /*Escreve o inteiro dado de tamanho em bits igual a tamanho no Stream stream_saida,
  60. acrescentando um sinal.
  61. O char c é utilizado para auxiliar nas operacoes bit a bit, bem como o int ocupado,
  62. que indica o offset de c*/
  63. void escreve(short int dado, int tamanho, char *c, int *ocupado, Stream stream_saida)
  64. {
  65. int i;
  66. short int sinal;
  67. short int mascara = 0;
  68. if(dado < 0)
  69. {
  70. sinal = 0x01;
  71. dado = -dado;
  72. }
  73. else
  74. {
  75. sinal = 0x00;
  76. }
  77. for(i = 0; i < tamanho; i++)
  78. {
  79. mascara = mascara << 1;
  80. mascara |= 0x01;
  81. }
  82. dado &= mascara;
  83. sinal = sinal << tamanho;
  84. dado |= sinal;
  85. for(i = 16 - tamanho -1; i < 16; i++)
  86. {
  87. if(bit_check2(dado, i) == 1)
  88. {
  89. bit_on(c, *ocupado);
  90. }
  91. else
  92. {
  93. bit_off(c, *ocupado);
  94. }
  95. *ocupado += 1;
  96. if(*ocupado == 8)
  97. {
  98. ST_put_char(stream_saida, *c);
  99. *ocupado = 0;
  100. }
  101. }
  102. }
  103. /*Escreve o char dado de tamanho igual a tamanho no Stream stream_saida.
  104. O char c é utilizado para auxiliar nas operacoes bit a bit, bem como o int ocupado,
  105. que indica o offset de c*/
  106. void escreve_amostra(char dado, int tamanho, char *c, int *ocupado, Stream stream_saida)
  107. {
  108. int i;
  109. for(i = 0; i < tamanho; i++)
  110. {
  111. if(bit_check(dado, i) == 1)
  112. {
  113. bit_on(c, *ocupado);
  114. }
  115. else
  116. {
  117. bit_off(c, *ocupado);
  118. }
  119. *ocupado += 1;
  120. if(*ocupado == 8)
  121. {
  122. ST_put_char(stream_saida, *c);
  123. *ocupado = 0;
  124. }
  125. }
  126. }
  127. /*Escreve o int dado de tamanho igual a tamanho no Stream stream_saida.
  128. O char c é utilizado para auxiliar nas operacoes bit a bit, bem como o int ocupado,
  129. que indica o offset de c*/
  130. void escreve_amostra2(short int dado, int tamanho, char *c, int *ocupado, Stream stream_saida)
  131. {
  132. int i;
  133. for(i = 0; i < tamanho; i++)
  134. {
  135. if(bit_check2(dado, i) == 1)
  136. {
  137. bit_on(c, *ocupado);
  138. }
  139. else
  140. {
  141. bit_off(c, *ocupado);
  142. }
  143. *ocupado += 1;
  144. if(*ocupado == 8)
  145. {
  146. ST_put_char(stream_saida, *c);
  147. *ocupado = 0;
  148. }
  149. }
  150. }
  151. /*Realiza a compactação por ADPCM do Stream stream_entrada, com numero de canais
  152. igual a num_channels, tamanho igual a size e 8 bits por amostra*/
  153. int compacta1(int num_channels, int size, Stream stream_entrada, Stream stream_saida)
  154. {
  155. char sample;
  156. char samples[WINDOW_SIZE];
  157. char samples2[WINDOW_SIZE];
  158. int i, j;
  159. int ocupado;
  160. int samples_read;
  161. short int max;
  162. char c;
  163. ocupado = 0;
  164. for(i = 0; i < size;)
  165. {
  166. samples_read = 0;
  167. for(j = 0; j < WINDOW_SIZE; j++)
  168. {
  169. samples[j] = 0;
  170. samples2[j] = 0;
  171. }
  172. for(j = 0; j < WINDOW_SIZE && i < size; j++)
  173. {
  174. ST_get_char(stream_entrada, &sample);
  175. samples[j] = sample;
  176. if(num_channels == 2)
  177. {
  178. ST_get_char(stream_entrada, &sample);
  179. samples2[j] = sample;
  180. i++;
  181. samples_read++;
  182. }
  183. i++;
  184. samples_read++;
  185. }
  186. sample = samples[0];
  187. max = 0;
  188. for(j = 1; j < WINDOW_SIZE && (i - samples_read +j) < size; j++)
  189. {
  190. if(modulo(samples[0] - samples[j]) > max)
  191. {
  192. max = modulo(samples[0] - samples[j]);
  193. }
  194. }
  195. if(samples_read > 0)
  196. {
  197. escreve(determina_tamanho(max), 4, &c, &ocupado, stream_saida);
  198. escreve_amostra(samples[0], 8*sizeof(char), &c, &ocupado, stream_saida);
  199. for(j = 1; j < WINDOW_SIZE && j < samples_read; j++)
  200. {
  201. escreve(samples[0] - samples[j], determina_tamanho(max), &c, &ocupado, stream_saida);
  202. }
  203. if(num_channels == 2)
  204. {
  205. for(j = 1; j < WINDOW_SIZE && i < size; j++)
  206. {
  207. if(modulo(samples2[0] - samples2[j]) > max)
  208. {
  209. max = modulo(samples2[0] - samples2[j]);
  210. }
  211. }
  212. escreve(determina_tamanho(max), 4, &c, &ocupado, stream_saida);
  213. escreve_amostra(samples2[0], 8*sizeof(char), &c, &ocupado, stream_saida);
  214. for(j = 1; j < WINDOW_SIZE && j < samples_read; j++)
  215. {
  216. escreve(samples2[0] - samples2[j], determina_tamanho(max), &c, &ocupado, stream_saida);
  217. }
  218. }
  219. }
  220. }
  221. if(ocupado < 8)
  222. {
  223. ST_put_char(stream_saida, c);
  224. }
  225. return 0;
  226. }
  227. /*Realiza a compactação por ADPCM do Stream stream_entrada, com numero de canais
  228. igual a num_channels, tamanho igual a size e 16 bits por amostra*/
  229. int compacta2(int num_channels, int size, Stream stream_entrada, Stream stream_saida)
  230. {
  231. short int sample;
  232. short int samples[WINDOW_SIZE];
  233. short int samples2[WINDOW_SIZE];
  234. int i, j;
  235. int ocupado;
  236. int samples_read;
  237. short int max;
  238. char c;
  239. ocupado = 0;
  240. for(i = 0; i < size/2;)
  241. {
  242. samples_read = 0;
  243. for(j = 0; j < WINDOW_SIZE; j++)
  244. {
  245. samples[j] = -1;
  246. samples2[j] = -1;
  247. }
  248. for(j = 0; j < WINDOW_SIZE && i < size/2; j++)
  249. {
  250. ST_get_short(stream_entrada, &sample);
  251. samples[j] = sample;
  252. if(num_channels == 2)
  253. {
  254. ST_get_short(stream_entrada, &sample);
  255. samples2[j] = sample;
  256. i++;
  257. samples_read++;
  258. }
  259. i++;
  260. samples_read++;
  261. }
  262. sample = samples[0];
  263. max = 0;
  264. for(j = 1; j < WINDOW_SIZE && (i - samples_read + j) < size/2; j++)
  265. {
  266. if(modulo(samples[0] - samples[j]) > max)
  267. {
  268. max = modulo(samples[0] - samples[j]);
  269. }
  270. }
  271. if(samples_read > 0)
  272. {
  273. escreve(determina_tamanho(max), 4, &c, &ocupado, stream_saida);
  274. escreve_amostra2(samples[0], 8*sizeof(short int), &c, &ocupado, stream_saida);
  275. for(j = 1; j < WINDOW_SIZE && j < samples_read; j++)
  276. {
  277. escreve(samples[0] - samples[j], determina_tamanho(max), &c, &ocupado, stream_saida);
  278. }
  279. if(num_channels == 2)
  280. {
  281. for(j = 1; j < WINDOW_SIZE && i < size/2; j++)
  282. {
  283. if(modulo(samples2[0] - samples2[j]) > max)
  284. {
  285. max = modulo(samples2[0] - samples2[j]);
  286. }
  287. }
  288. escreve(determina_tamanho(max), 4, &c, &ocupado, stream_saida);
  289. escreve_amostra2(samples2[0], 8*sizeof(short int), &c, &ocupado, stream_saida);
  290. for(j = 1; j < WINDOW_SIZE && j < samples_read; j++)
  291. {
  292. escreve(samples2[0] - samples2[j], determina_tamanho(max), &c, &ocupado, stream_saida);
  293. }
  294. }
  295. }
  296. }
  297. if(ocupado < 8)
  298. {
  299. ST_put_char(stream_saida, c);
  300. }
  301. return 0;
  302. }
  303. int DF_compress(Stream si, Stream so, int data_size)
  304. {
  305. /*Compactacao*/
  306. if(data_size == 1)
  307. {
  308. compacta1(1, ST_get_size(si), si, so);
  309. }
  310. else if(data_size == 2)
  311. {
  312. compacta2(1, ST_get_size(si), si, so);
  313. }
  314. return 0;
  315. }
  316. /*Le um dado de tamanho igual a tamanho do Stream stream_entrada e o retorna.
  317. O char c e o inteiro lido auxiliam nas operacoes bit a bit*/
  318. short int le(int tamanho, char *c, int *lido, Stream stream_entrada)
  319. {
  320. short int dado;
  321. short int sinal;
  322. int i;
  323. dado = 0;
  324. for(i = 0; i < tamanho+1; i++)
  325. {
  326. if(i == 0)
  327. {
  328. if(bit_check(*c, *lido) == 1)
  329. {
  330. sinal = 1;
  331. }
  332. else
  333. {
  334. sinal = 0;
  335. }
  336. *lido += 1;
  337. }
  338. else
  339. {
  340. if(bit_check(*c, *lido) == 1)
  341. {
  342. dado |= 0x01;
  343. }
  344. else
  345. {
  346. dado |= 0x00;
  347. }
  348. if(i < tamanho)
  349. {
  350. dado = dado << 1;
  351. }
  352. *lido += 1;
  353. }
  354. if(*lido == 8)
  355. {
  356. *lido = 0;
  357. ST_get_char(stream_entrada, c);
  358. }
  359. }
  360. if(sinal)
  361. {
  362. dado = -dado;
  363. }
  364. return dado;
  365. }
  366. /*Le um dado de 8 bits do Stream stream_entrada e o retorna.
  367. O char c e o inteiro lido auxiliam nas operacoes bit a bit*/
  368. short int le_amostra(char *c, int *lido, Stream stream_entrada)
  369. {
  370. short int dado;
  371. int i;
  372. dado = 0;
  373. for(i = 0; i < 8; i++)
  374. {
  375. if(bit_check(*c, *lido) == 1)
  376. {
  377. dado |= 0x01;
  378. }
  379. else
  380. {
  381. dado |= 0x00;
  382. }
  383. if(i < 7)
  384. {
  385. dado = dado << 1;
  386. }
  387. *lido += 1;
  388. if(*lido == 8)
  389. {
  390. *lido = 0;
  391. ST_get_char(stream_entrada, c);
  392. }
  393. }
  394. return dado;
  395. }
  396. /*Le um dado de 16 bits do Stream stream_entrada e o retorna.
  397. O char c e o inteiro lido auxiliam nas operacoes bit a bit*/
  398. short int le_amostra2(char *c, int *lido, Stream stream_entrada)
  399. {
  400. short int dado;
  401. int i;
  402. dado = 0;
  403. for(i = 0; i < 16; i++)
  404. {
  405. if(bit_check(*c, *lido) == 1)
  406. {
  407. dado |= 0x01;
  408. }
  409. else
  410. {
  411. dado |= 0x00;
  412. }
  413. if(i < 15)
  414. {
  415. dado = dado << 1;
  416. }
  417. *lido += 1;
  418. if(*lido == 8)
  419. {
  420. *lido = 0;
  421. ST_get_char(stream_entrada, c);
  422. }
  423. }
  424. return dado;
  425. }
  426. /*Descompata um Stream stream_entrada que foi comprimido por ADPCM e
  427. que tem tamanho size, um numero de canais igual a num_channels e
  428. 8 bits por amostra.*/
  429. int descompacta1(int num_channels, int size, Stream stream_entrada, Stream stream_saida)
  430. {
  431. char sample;
  432. char samples[WINDOW_SIZE], samples2[WINDOW_SIZE];
  433. short int max;
  434. int i, j;
  435. int lido = 0;
  436. char c;
  437. ST_get_char(stream_entrada, &c);
  438. for(i = 0; i < size;)
  439. {
  440. max = le(4, &c, &lido, stream_entrada);
  441. for(j = 0; j < WINDOW_SIZE; j++)
  442. {
  443. if(j == 0)
  444. {
  445. samples[j] = le_amostra(&c, &lido, stream_entrada);
  446. }
  447. else
  448. {
  449. samples[j] = le(max, &c, &lido, stream_entrada);
  450. }
  451. }
  452. if(num_channels == 2)
  453. {
  454. max = le(4, &c, &lido, stream_entrada);
  455. for(j = 0; j < WINDOW_SIZE; j++)
  456. {
  457. if(j == 0)
  458. {
  459. samples2[j] = le_amostra(&c, &lido, stream_entrada);
  460. }
  461. else
  462. {
  463. samples2[j] = le(max, &c, &lido, stream_entrada);
  464. }
  465. }
  466. }
  467. ST_put_char(stream_saida, samples[0]);
  468. i++;
  469. if(num_channels == 2)
  470. {
  471. ST_put_char(stream_saida, samples2[0]);
  472. i++;
  473. }
  474. for(j = 1; j < WINDOW_SIZE; j++)
  475. {
  476. sample = samples[0] - samples[j];
  477. ST_put_char(stream_saida, sample);
  478. if(num_channels == 2)
  479. {
  480. sample = samples2[0] - samples2[j];
  481. ST_put_char(stream_saida, sample);
  482. i++;
  483. }
  484. i++;
  485. }
  486. }
  487. return 0;
  488. }
  489. /*Descompata um Stream stream_entrada que foi comprimido por ADPCM e
  490. que tem tamanho size, um numero de canais igual a num_channels e
  491. 16 bits por amostra.*/
  492. int descompacta2(int num_channels, int size, Stream stream_entrada, Stream stream_saida)
  493. {
  494. short int sample;
  495. short int samples[WINDOW_SIZE], samples2[WINDOW_SIZE];
  496. short int max;
  497. int i, j;
  498. int lido = 0;
  499. char c;
  500. ST_get_char(stream_entrada, &c);
  501. for(i = 0; i < size/2;)
  502. {
  503. max = le(4, &c, &lido, stream_entrada);
  504. for(j = 0; j < WINDOW_SIZE; j++)
  505. {
  506. if(j == 0)
  507. {
  508. samples[j] = le_amostra2(&c, &lido, stream_entrada);
  509. }
  510. else
  511. {
  512. samples[j] = le(max, &c, &lido, stream_entrada);
  513. }
  514. }
  515. if(num_channels == 2)
  516. {
  517. max = le(4, &c, &lido, stream_entrada);
  518. for(j = 0; j < WINDOW_SIZE; j++)
  519. {
  520. if(j == 0)
  521. {
  522. samples2[j] = le_amostra2(&c, &lido, stream_entrada);
  523. }
  524. else
  525. {
  526. samples2[j] = le(max, &c, &lido, stream_entrada);
  527. }
  528. }
  529. }
  530. ST_put_short(stream_saida, samples[0]);
  531. i++;
  532. if(num_channels == 2)
  533. {
  534. ST_put_short(stream_saida, samples2[0]);
  535. i++;
  536. }
  537. for(j = 1; j < WINDOW_SIZE; j++)
  538. {
  539. sample = samples[0] - samples[j];
  540. ST_put_short(stream_saida, sample);
  541. if(num_channels == 2)
  542. {
  543. sample = samples2[0] - samples2[j];
  544. ST_put_short(stream_saida, sample);
  545. i++;
  546. }
  547. i++;
  548. }
  549. }
  550. return 0;
  551. }
  552. int DF_decompress(Stream si, Stream so, int data_size, int tamanho)
  553. {
  554. if(data_size == 1)
  555. {
  556. descompacta1(1, tamanho, si, so);
  557. }
  558. else if(data_size == 2)
  559. {
  560. descompacta2(1, tamanho, si, so);
  561. }
  562. return 0;
  563. }