/src/diff.c
C | 676 lines | 530 code | 113 blank | 33 comment | 123 complexity | 6b26a883e7dc43d25db33599e7d02abe MD5 | raw file
- #include <stdio.h>
- #include <stdlib.h>
- #include "diff.h"
-
- #define WINDOW_SIZE 8
-
- /*Determina o modulo do numero x*/
- int modulo(int x)
- {
- if(x < 0)
- {
- return -x;
- }
- else return x;
- }
-
- /*Retorna 1 se o bit b do char a for igual a 1, 0 caso contrario*/
- int bit_check(char a, int b)
- {
- if(a & (1 << (7 - b)))
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
-
- /*Torna o bit b do char a igual a 1*/
- void bit_on(char *a, int b)
- {
- *a = *a | (1 << (7 - b));
- }
-
- /*Torna o bit b do char a igual a 0*/
- void bit_off(char *a, int b)
- {
- *a = *a & (~(1 << (7 - b)));
- }
-
- /*Retorna 1 se o bit b do short int a for igual a 1, 0 caso contrario*/
- int bit_check2(short int a, int b)
- {
- if(a & (1 << (15 - b)))
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
-
- /*Retorna o número de bits necessários para representar o numero max em binario*/
- short int determina_tamanho(short int max)
- {
- short int i = 1;
-
- while(max/2 != 0)
- {
- max /= 2;
- i++;
- }
-
- return i;
- }
-
- /*Escreve o inteiro dado de tamanho em bits igual a tamanho no Stream stream_saida,
- acrescentando um sinal.
- O char c é utilizado para auxiliar nas operacoes bit a bit, bem como o int ocupado,
- que indica o offset de c*/
- void escreve(short int dado, int tamanho, char *c, int *ocupado, Stream stream_saida)
- {
- int i;
- short int sinal;
- short int mascara = 0;
-
- if(dado < 0)
- {
- sinal = 0x01;
- dado = -dado;
- }
- else
- {
- sinal = 0x00;
- }
-
- for(i = 0; i < tamanho; i++)
- {
- mascara = mascara << 1;
- mascara |= 0x01;
- }
- dado &= mascara;
-
- sinal = sinal << tamanho;
- dado |= sinal;
-
- for(i = 16 - tamanho -1; i < 16; i++)
- {
- if(bit_check2(dado, i) == 1)
- {
- bit_on(c, *ocupado);
- }
- else
- {
- bit_off(c, *ocupado);
- }
-
- *ocupado += 1;
-
- if(*ocupado == 8)
- {
- ST_put_char(stream_saida, *c);
- *ocupado = 0;
- }
- }
- }
-
- /*Escreve o char dado de tamanho igual a tamanho no Stream stream_saida.
- O char c é utilizado para auxiliar nas operacoes bit a bit, bem como o int ocupado,
- que indica o offset de c*/
- void escreve_amostra(char dado, int tamanho, char *c, int *ocupado, Stream stream_saida)
- {
- int i;
-
- for(i = 0; i < tamanho; i++)
- {
- if(bit_check(dado, i) == 1)
- {
- bit_on(c, *ocupado);
- }
- else
- {
- bit_off(c, *ocupado);
- }
-
- *ocupado += 1;
-
- if(*ocupado == 8)
- {
- ST_put_char(stream_saida, *c);
- *ocupado = 0;
- }
- }
- }
-
- /*Escreve o int dado de tamanho igual a tamanho no Stream stream_saida.
- O char c é utilizado para auxiliar nas operacoes bit a bit, bem como o int ocupado,
- que indica o offset de c*/
- void escreve_amostra2(short int dado, int tamanho, char *c, int *ocupado, Stream stream_saida)
- {
- int i;
-
- for(i = 0; i < tamanho; i++)
- {
- if(bit_check2(dado, i) == 1)
- {
- bit_on(c, *ocupado);
- }
- else
- {
- bit_off(c, *ocupado);
- }
-
- *ocupado += 1;
-
- if(*ocupado == 8)
- {
- ST_put_char(stream_saida, *c);
- *ocupado = 0;
- }
- }
- }
-
- /*Realiza a compactação por ADPCM do Stream stream_entrada, com numero de canais
- igual a num_channels, tamanho igual a size e 8 bits por amostra*/
- int compacta1(int num_channels, int size, Stream stream_entrada, Stream stream_saida)
- {
- char sample;
- char samples[WINDOW_SIZE];
- char samples2[WINDOW_SIZE];
- int i, j;
- int ocupado;
- int samples_read;
- short int max;
- char c;
-
- ocupado = 0;
-
- for(i = 0; i < size;)
- {
- samples_read = 0;
-
- for(j = 0; j < WINDOW_SIZE; j++)
- {
- samples[j] = 0;
- samples2[j] = 0;
- }
-
- for(j = 0; j < WINDOW_SIZE && i < size; j++)
- {
- ST_get_char(stream_entrada, &sample);
- samples[j] = sample;
-
- if(num_channels == 2)
- {
- ST_get_char(stream_entrada, &sample);
- samples2[j] = sample;
- i++;
- samples_read++;
- }
-
- i++;
- samples_read++;
- }
-
- sample = samples[0];
- max = 0;
-
- for(j = 1; j < WINDOW_SIZE && (i - samples_read +j) < size; j++)
- {
- if(modulo(samples[0] - samples[j]) > max)
- {
- max = modulo(samples[0] - samples[j]);
- }
- }
-
- if(samples_read > 0)
- {
- escreve(determina_tamanho(max), 4, &c, &ocupado, stream_saida);
- escreve_amostra(samples[0], 8*sizeof(char), &c, &ocupado, stream_saida);
- for(j = 1; j < WINDOW_SIZE && j < samples_read; j++)
- {
- escreve(samples[0] - samples[j], determina_tamanho(max), &c, &ocupado, stream_saida);
- }
-
- if(num_channels == 2)
- {
- for(j = 1; j < WINDOW_SIZE && i < size; j++)
- {
- if(modulo(samples2[0] - samples2[j]) > max)
- {
- max = modulo(samples2[0] - samples2[j]);
- }
- }
-
- escreve(determina_tamanho(max), 4, &c, &ocupado, stream_saida);
- escreve_amostra(samples2[0], 8*sizeof(char), &c, &ocupado, stream_saida);
- for(j = 1; j < WINDOW_SIZE && j < samples_read; j++)
- {
- escreve(samples2[0] - samples2[j], determina_tamanho(max), &c, &ocupado, stream_saida);
- }
- }
- }
- }
-
- if(ocupado < 8)
- {
- ST_put_char(stream_saida, c);
- }
-
- return 0;
- }
-
- /*Realiza a compactação por ADPCM do Stream stream_entrada, com numero de canais
- igual a num_channels, tamanho igual a size e 16 bits por amostra*/
- int compacta2(int num_channels, int size, Stream stream_entrada, Stream stream_saida)
- {
- short int sample;
- short int samples[WINDOW_SIZE];
- short int samples2[WINDOW_SIZE];
- int i, j;
- int ocupado;
- int samples_read;
- short int max;
- char c;
-
- ocupado = 0;
-
- for(i = 0; i < size/2;)
- {
- samples_read = 0;
-
- for(j = 0; j < WINDOW_SIZE; j++)
- {
- samples[j] = -1;
- samples2[j] = -1;
- }
-
- for(j = 0; j < WINDOW_SIZE && i < size/2; j++)
- {
- ST_get_short(stream_entrada, &sample);
- samples[j] = sample;
-
- if(num_channels == 2)
- {
- ST_get_short(stream_entrada, &sample);
- samples2[j] = sample;
- i++;
- samples_read++;
- }
-
- i++;
- samples_read++;
- }
-
- sample = samples[0];
- max = 0;
-
- for(j = 1; j < WINDOW_SIZE && (i - samples_read + j) < size/2; j++)
- {
- if(modulo(samples[0] - samples[j]) > max)
- {
- max = modulo(samples[0] - samples[j]);
- }
- }
-
- if(samples_read > 0)
- {
- escreve(determina_tamanho(max), 4, &c, &ocupado, stream_saida);
- escreve_amostra2(samples[0], 8*sizeof(short int), &c, &ocupado, stream_saida);
- for(j = 1; j < WINDOW_SIZE && j < samples_read; j++)
- {
- escreve(samples[0] - samples[j], determina_tamanho(max), &c, &ocupado, stream_saida);
- }
- if(num_channels == 2)
- {
- for(j = 1; j < WINDOW_SIZE && i < size/2; j++)
- {
- if(modulo(samples2[0] - samples2[j]) > max)
- {
- max = modulo(samples2[0] - samples2[j]);
- }
- }
-
- escreve(determina_tamanho(max), 4, &c, &ocupado, stream_saida);
- escreve_amostra2(samples2[0], 8*sizeof(short int), &c, &ocupado, stream_saida);
- for(j = 1; j < WINDOW_SIZE && j < samples_read; j++)
- {
- escreve(samples2[0] - samples2[j], determina_tamanho(max), &c, &ocupado, stream_saida);
- }
- }
- }
- }
-
- if(ocupado < 8)
- {
- ST_put_char(stream_saida, c);
- }
-
- return 0;
- }
-
- int DF_compress(Stream si, Stream so, int data_size)
- {
- /*Compactacao*/
- if(data_size == 1)
- {
- compacta1(1, ST_get_size(si), si, so);
- }
- else if(data_size == 2)
- {
- compacta2(1, ST_get_size(si), si, so);
- }
-
- return 0;
- }
-
-
- /*Le um dado de tamanho igual a tamanho do Stream stream_entrada e o retorna.
- O char c e o inteiro lido auxiliam nas operacoes bit a bit*/
- short int le(int tamanho, char *c, int *lido, Stream stream_entrada)
- {
- short int dado;
- short int sinal;
- int i;
-
- dado = 0;
-
- for(i = 0; i < tamanho+1; i++)
- {
- if(i == 0)
- {
- if(bit_check(*c, *lido) == 1)
- {
- sinal = 1;
- }
- else
- {
- sinal = 0;
- }
- *lido += 1;
- }
- else
- {
- if(bit_check(*c, *lido) == 1)
- {
- dado |= 0x01;
- }
- else
- {
- dado |= 0x00;
- }
-
- if(i < tamanho)
- {
- dado = dado << 1;
- }
-
- *lido += 1;
- }
-
- if(*lido == 8)
- {
- *lido = 0;
- ST_get_char(stream_entrada, c);
- }
- }
-
- if(sinal)
- {
- dado = -dado;
- }
-
- return dado;
- }
-
- /*Le um dado de 8 bits do Stream stream_entrada e o retorna.
- O char c e o inteiro lido auxiliam nas operacoes bit a bit*/
- short int le_amostra(char *c, int *lido, Stream stream_entrada)
- {
- short int dado;
- int i;
-
- dado = 0;
-
- for(i = 0; i < 8; i++)
- {
- if(bit_check(*c, *lido) == 1)
- {
- dado |= 0x01;
- }
- else
- {
- dado |= 0x00;
- }
-
- if(i < 7)
- {
- dado = dado << 1;
- }
-
- *lido += 1;
-
- if(*lido == 8)
- {
- *lido = 0;
- ST_get_char(stream_entrada, c);
- }
- }
-
- return dado;
- }
-
- /*Le um dado de 16 bits do Stream stream_entrada e o retorna.
- O char c e o inteiro lido auxiliam nas operacoes bit a bit*/
- short int le_amostra2(char *c, int *lido, Stream stream_entrada)
- {
- short int dado;
- int i;
-
- dado = 0;
-
- for(i = 0; i < 16; i++)
- {
- if(bit_check(*c, *lido) == 1)
- {
- dado |= 0x01;
- }
- else
- {
- dado |= 0x00;
- }
-
- if(i < 15)
- {
- dado = dado << 1;
- }
-
- *lido += 1;
-
- if(*lido == 8)
- {
- *lido = 0;
- ST_get_char(stream_entrada, c);
- }
- }
-
- return dado;
- }
-
- /*Descompata um Stream stream_entrada que foi comprimido por ADPCM e
- que tem tamanho size, um numero de canais igual a num_channels e
- 8 bits por amostra.*/
- int descompacta1(int num_channels, int size, Stream stream_entrada, Stream stream_saida)
- {
- char sample;
- char samples[WINDOW_SIZE], samples2[WINDOW_SIZE];
- short int max;
- int i, j;
- int lido = 0;
- char c;
-
- ST_get_char(stream_entrada, &c);
-
- for(i = 0; i < size;)
- {
- max = le(4, &c, &lido, stream_entrada);
-
- for(j = 0; j < WINDOW_SIZE; j++)
- {
- if(j == 0)
- {
- samples[j] = le_amostra(&c, &lido, stream_entrada);
- }
- else
- {
- samples[j] = le(max, &c, &lido, stream_entrada);
- }
- }
-
- if(num_channels == 2)
- {
- max = le(4, &c, &lido, stream_entrada);
-
- for(j = 0; j < WINDOW_SIZE; j++)
- {
- if(j == 0)
- {
- samples2[j] = le_amostra(&c, &lido, stream_entrada);
- }
- else
- {
- samples2[j] = le(max, &c, &lido, stream_entrada);
- }
- }
- }
-
- ST_put_char(stream_saida, samples[0]);
- i++;
- if(num_channels == 2)
- {
- ST_put_char(stream_saida, samples2[0]);
- i++;
- }
-
- for(j = 1; j < WINDOW_SIZE; j++)
- {
- sample = samples[0] - samples[j];
- ST_put_char(stream_saida, sample);
-
- if(num_channels == 2)
- {
- sample = samples2[0] - samples2[j];
- ST_put_char(stream_saida, sample);
- i++;
- }
- i++;
- }
- }
-
- return 0;
- }
-
- /*Descompata um Stream stream_entrada que foi comprimido por ADPCM e
- que tem tamanho size, um numero de canais igual a num_channels e
- 16 bits por amostra.*/
- int descompacta2(int num_channels, int size, Stream stream_entrada, Stream stream_saida)
- {
- short int sample;
- short int samples[WINDOW_SIZE], samples2[WINDOW_SIZE];
- short int max;
- int i, j;
- int lido = 0;
- char c;
-
-
- ST_get_char(stream_entrada, &c);
-
- for(i = 0; i < size/2;)
- {
- max = le(4, &c, &lido, stream_entrada);
- for(j = 0; j < WINDOW_SIZE; j++)
- {
- if(j == 0)
- {
- samples[j] = le_amostra2(&c, &lido, stream_entrada);
- }
- else
- {
- samples[j] = le(max, &c, &lido, stream_entrada);
- }
- }
-
- if(num_channels == 2)
- {
- max = le(4, &c, &lido, stream_entrada);
-
- for(j = 0; j < WINDOW_SIZE; j++)
- {
- if(j == 0)
- {
- samples2[j] = le_amostra2(&c, &lido, stream_entrada);
- }
- else
- {
- samples2[j] = le(max, &c, &lido, stream_entrada);
- }
- }
- }
-
- ST_put_short(stream_saida, samples[0]);
-
- i++;
- if(num_channels == 2)
- {
- ST_put_short(stream_saida, samples2[0]);
- i++;
- }
- for(j = 1; j < WINDOW_SIZE; j++)
- {
- sample = samples[0] - samples[j];
- ST_put_short(stream_saida, sample);
- if(num_channels == 2)
- {
- sample = samples2[0] - samples2[j];
- ST_put_short(stream_saida, sample);
- i++;
- }
- i++;
- }
- }
-
- return 0;
- }
-
- int DF_decompress(Stream si, Stream so, int data_size, int tamanho)
- {
- if(data_size == 1)
- {
- descompacta1(1, tamanho, si, so);
- }
- else if(data_size == 2)
- {
- descompacta2(1, tamanho, si, so);
- }
- return 0;
- }