quinta-feira, 27 de dezembro de 2012

Brincando com transformações de BMP em WAV

Todo arquivo é um punhado de bytes. O que faz ele ser imagem, texto, som ou vídeo é a forma como estes bytes estão organizados. Mas nada impede de pegar os bytes de um arquivo e "enganar" o computador dizendo para ele que é outro arquivo. Isto pode ser feito simplesmente alterando o cabeçalho do arquivo.
Bem, fiz 2 programas: um que coloca cabeçalho BMP e outro que coloca cabeçalho WAV.
De forma geral podemos pensar que ele converte qualquer coisa em imagem e outro que converte em som.
Depois eu testei com várias coisas: PDF, doc, MP3, imagens, textos, ...
E o que ficou mais legal de ouvir foram arquivos de log do sistema operacional. Talvez por serem "periódicos".
Escolhi um arquivo de log. Depois de ouvir e achar legal, converti em imagem, abri o gimp e mudei a imagem na mão. A cada alteração eu gerei o som correspondente. Editado no Gimp ele foi se transformando em novos sons.

Depois juntei imagem e som em um vídeo.
















C ANSI arquivos para wave

Já teve vontade de "ouvir" fotos, arquivos PDFs e coisas assim? Ok, não é exatamente útil mas sim, pode ser divertido.

gcc towav.c -o towav e Voilá!




#include <sys/stat.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>


int main(int argc, char ** argv){

   if(argc < 4){
      printf("Usage:\n");
      printf("%s sample_rate bit_depth\n", argv[0]);
      exit(0);
   }

   char * filename = malloc(strlen(argv[1]));
   strcpy(filename, argv[1]);

   struct stat st;
   stat(filename, &st);
   uint32_t size = st.st_size; //limita o tamanho do arquivo!
   printf("filesize: %d\n", size);

   // Read file data
   char * buffer = 0;
   FILE * f = fopen (filename, "rb");
   buffer = malloc(size);
   fread (buffer, 1, size, f);
   fclose (f);

   char * newfilename = malloc(strlen(argv[1] + 4));
   strcpy(newfilename, filename);
   strcat(newfilename, ".wav");
   FILE *fp = fopen(newfilename,"wb+");

   fwrite("RIFF", 1, 4, fp);
   int newsize = size + 32; // file size - 8
   fwrite(&newsize, 1, sizeof(newsize), fp);
   fwrite("WAVE", 1, 4, fp);

   fwrite("fmt ", 1, 4, fp);
   int flag = 16; // chunk size
   fwrite(&flag, 1, 4, fp);
   flag = 1; // compression code
   fwrite(&flag, 1, 2, fp);
   flag = 1; // number of channels
   fwrite(&flag, 1, 2, fp);
   flag = atoi(argv[2]); // sample rate
   fwrite(&flag, 1, 4, fp);
   flag = flag * atoi(argv[3]) / 8; // bytes per second
   fwrite(&flag, 1, 4, fp);
   flag = atoi(argv[3]) / 8; // block align
   fwrite(&flag, 1, 2, fp);
   flag = atoi(argv[3]); // significant bits per sample
   fwrite(&flag, 1, 2, fp);

   fwrite("data", 1, 4, fp);
   fwrite(&size, 1, 4, fp);

   fwrite(buffer, 1, size, fp);
   fclose(fp);

}

Algumas referências:



O dmesg ficou muito bom tocado a 10025 com 8 bits!