Jump to content
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

neocampos

[Resolvido] Ler e Escrever um arquivo WAV em C

Recommended Posts

neocampos

Olá a todos,

estou a escrever um programa que lê os dados de um arquivo wav e que gera outro arquivo wav com o mesmo conteúdo original. Contudo, o arquivo de saída não reproduz o mesmo som. Abaixo está meu código e peço a ajuda de vocês pra entender o que está errado.

#include <stdio.h>
#include <stdlib.h>
typedef struct{
//Buffers e chunks...
char ChunkID[4], Format[4], Subchunk1ID[4], Subchunk2ID[4];
int ChunkSize, Subchunk1Size, SampleRate, ByteRate, Subchunk2Size;
short AudioFormat, NumChannels, BlockAlign, BitsPerSample;
short *Data;
}headerWAV;
short* createData(FILE *input, headerWAV header){
 short *Data = (short*) malloc(sizeof(short)*(header.Subchunk2Size)*(header.BitsPerSample/8));
 return Data;
}
headerWAV readWAV(FILE *input, headerWAV header){
//Leitura do arquivo WAV
fread(header.ChunkID, 1, 4, input);
fread(&header.ChunkSize, 4, 1, input);
fread(header.Format, 1, 4, input);
fread(header.Subchunk1ID, 1, 4, input);
fread(&header.Subchunk1Size, 4, 1, input);
fread(&header.AudioFormat, 2, 1, input);
fread(&header.NumChannels, 2, 1, input);
fread(&header.SampleRate, 4, 1, input);
fread(&header.ByteRate, 4, 1, input);
fread(&header.BlockAlign, 2, 1, input);
fread(&header.BitsPerSample, 2, 1, input);
fread(header.Subchunk2ID, 1, 4, input);
fread(&header.Subchunk2Size, 4, 1, input);

short *Buffer = createData(input, header);
header.Data = Buffer;
fread(header.Data, header.BitsPerSample/8, header.Subchunk2Size/(header.BitsPerSample/8), input);
fclose(input);

return header;
}
headerWAV writeWAV(FILE *output, headerWAV header){
//Escrita do arquivo WAV
fwrite(header.ChunkID, 1, 4, output);
fwrite(&header.ChunkSize, 4, 1, output);
fwrite(header.Format, 1, 4, output);
fwrite(header.Subchunk1ID, 1, 4, output);
fwrite(&header.Subchunk1Size, 4, 1, output);
fwrite(&header.AudioFormat, 2, 1, output);
fwrite(&header.NumChannels, 2, 1, output);
fwrite(&header.SampleRate, 4, 1, output);
fwrite(&header.ByteRate, 4, 1, output);
fwrite(&header.BlockAlign, 2, 1, output);
fwrite(&header.BitsPerSample, 2, 1, output);
fwrite(header.Subchunk2ID, 1, 4, output);
fwrite(&header.Subchunk2Size, 4, 1, output);

short *Buffer = createData(output, header);
header.Data = Buffer;
fwrite(header.Data, header.BitsPerSample/8, header.Subchunk2Size/(header.BitsPerSample/8), output);
fclose(output);

return header;
}		

int main(){
int i;
headerWAV header, headerOut;

FILE *input = fopen("goat.wav", "r"), *output = fopen("myFile.wav", "w");

if(input == NULL)
 printf("Arquivo nao pode ser aberto!!!\n");

header = readWAV(input, header);

if(output == NULL)
 printf("Arquivo nao pode ser aberto!!!\n");

headerOut = writeWAV(output, header);

for(i = 0; i < 100; i++)
 printf("%d ", header.Data[i]);
printf("\n");
for(i = 0; i < 100; i++)
 printf("%d ", headerOut.Data[i]);
printf("\n");
for(i = 0; i < 4; i++)
 printf("%c ", headerOut.ChunkID[i]);
printf("\n");
system("PAUSE");
}

Edited by pmg
Falta LP no GeSHi

Share this post


Link to post
Share on other sites
pmg

Experimenta abrir os ficheiros em modo binário:

// ...
FILE *input = fopen("goat.wav", "rb"), *output = fopen("myFile.wav", "wb");
// ...


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
HappyHippyHippo

eu não vejo (sequer) a criação do segundo ficheiro de saida ...


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
neocampos

O ficheiro de saída está criado na linha:

FILE *input = fopen("goat.wav", "r"), output = fopen("myFile.wav", "w");

Inclusive, no ficheiro de saída o cabeçalho fica gravado em myFile.wav, mas a partir do 45º byte (aqui começa os bytes do áudio), os bytes não estão correspondendo aos valores originais do ficheiro goat.wav

Share this post


Link to post
Share on other sites
pmg

Na funcao writeWAV(), estas a escrever lixo no ficheiro de output.

Esse lixo vem da memoria recentemente alocada e nao inicializada.

headerWAV writeWAV(FILE *output, headerWAV header) {
   /* ... */
   short *Buffer = createData(output, header); /* Buffer aponta para lixo */
   header.Data = Buffer;                       /* header.Data aponta para lixo */
   fwrite(header.Data, /*...*/);               /* escreve lixo */
   /* ... */
}


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
HappyHippyHippo

O ficheiro de saída está criado na linha:

FILE *input = fopen("goat.wav", "r"), output = fopen("myFile.wav", "w");

erro meu

Inclusive, no ficheiro de saída o cabeçalho fica gravado em myFile.wav, mas a partir do 45º byte (aqui começa os bytes do áudio), os bytes não estão correspondendo aos valores originais do ficheiro goat.wav

já fizeste um diff dos dois ficheiros ?

edit : já respondido pelo @pmg

Edited by HappyHippyHippo

IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
neocampos

@pmg, você tinha razão. O código está agora funcionando e vou postá-lo aqui:

#include 
#include 

typedef struct{
//Buffers e chunks...
char ChunkID[4], Format[4], Subchunk1ID[4], Subchunk2ID[4];
int ChunkSize, Subchunk1Size, SampleRate, ByteRate, Subchunk2Size;
short AudioFormat, NumChannels, BlockAlign, BitsPerSample;
short *Data;
}headerWAV;

short* createData(FILE *input, headerWAV header){
short *Data = (short*) malloc(sizeof(short)*(header.Subchunk2Size)*(header.BitsPerSample/8));
return Data;
}

headerWAV readWAV(FILE *input, headerWAV header){
//Leitura do arquivo WAV
fread(header.ChunkID, 1, 4, input);
fread(&header.ChunkSize, 4, 1, input);
fread(header.Format, 1, 4, input);
fread(header.Subchunk1ID, 1, 4, input);
fread(&header.Subchunk1Size, 4, 1, input);
fread(&header.AudioFormat, 2, 1, input);
fread(&header.NumChannels, 2, 1, input);
fread(&header.SampleRate, 4, 1, input);
fread(&header.ByteRate, 4, 1, input);
fread(&header.BlockAlign, 2, 1, input);
fread(&header.BitsPerSample, 2, 1, input);
fread(header.Subchunk2ID, 1, 4, input);
fread(&header.Subchunk2Size, 4, 1, input);

short *Buffer = createData(input, header);
header.Data = Buffer;
fread(header.Data, header.BitsPerSample/8, header.Subchunk2Size/(header.BitsPerSample/8), input);
fclose(input);

return header;
}

headerWAV writeWAV(FILE *output, headerWAV header){
//Escrita do arquivo WAV
fwrite(header.ChunkID, 1, 4, output);
fwrite(&header.ChunkSize, 4, 1, output);
fwrite(header.Format, 1, 4, output);
fwrite(header.Subchunk1ID, 1, 4, output);
fwrite(&header.Subchunk1Size, 4, 1, output);
fwrite(&header.AudioFormat, 2, 1, output);
fwrite(&header.NumChannels, 2, 1, output);
fwrite(&header.SampleRate, 4, 1, output);
fwrite(&header.ByteRate, 4, 1, output);
fwrite(&header.BlockAlign, 2, 1, output);
fwrite(&header.BitsPerSample, 2, 1, output);
fwrite(header.Subchunk2ID, 1, 4, output);
fwrite(&header.Subchunk2Size, 4, 1, output);

fwrite(header.Data, header.BitsPerSample/8, header.Subchunk2Size/(header.BitsPerSample/8), output);
fclose(output);

return header;
}

int main(){
int i;
headerWAV header, headerOut;

FILE *input = fopen("goat.wav", "rb"), *output = fopen("myFile.wav", "wb");

if(input == NULL)
printf("Arquivo nao pode ser aberto!!!\n");

header = readWAV(input, header);

if(output == NULL)
printf("Arquivo nao pode ser aberto!!!\n");

headerOut = writeWAV(output, header);

printf("\n");
system("PAUSE");
}


Edited by pmg
Falta LP no GeSHi
  • Vote 1

Share this post


Link to post
Share on other sites
HappyHippyHippo

já reparaste que estás a fazer uma cópia directa do ficheiro ?

sabes que o que estás a fazer é realizado em 10% do código que apresentaste, certo ?


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
neocampos

Sim, mas na verdade o objetivo do programa é acessar os bytes do ficheiro e gerar outro ficheiro. Aqui eu simplesmente copiei os bytes, mas eu poderia também aplicar um filtro ou outra manipulação.

Share this post


Link to post
Share on other sites
pmg

Sugestao: usa um metodo de indentacao mais comum :)

  • Vote 1

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
ppturbo

Me ajudou muito, agora eu tenho uma dúvida, em um trabalho tenho que retirar ruídos de som no formato wav, posso comparar 3 'datas' e reorganizar eles ? exemplo:

'data->prv' - 'data' - 'data->next'

mudar de acordo com o 'tamanho' para por ex

'data->next' - 'data->prv' - 'data'

onde 'data->next' é menor que 'data->prv' que é menor que 'data'

substituindo assim o 'data' por 'data->prev', e o proximo da lista seria

'data->prev' - 'data2atual' - 'data2atual->next'

esse procedimento funciona para tirar ruídos de imagens em um formato específico (acredito que pgm), será que funcionaria com som wav?

Share this post


Link to post
Share on other sites
HappyHippyHippo

o processo convencional para remover ruido é aplicar a transformada de Fourier, depois é uma combinação de oeprações:

- remover frequências com pouca intensidade (serão sempre pouco perceptiveis)

- filtros de passa-banda (baixas frequências e altas frequências são indicativos de ruído)

- etc ...

existem vários processos para isso


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
ppturbo

o processo convencional para remover ruido é aplicar a transformada de Fourier, depois é uma combinação de oeprações:

- remover frequências com pouca intensidade (serão sempre pouco perceptiveis)

- filtros de passa-banda (baixas frequências e altas frequências são indicativos de ruído)

- etc ...

existem vários processos para isso

Entendo... mas para uma turma de primeiro ano de programação não é um pouco complicado ? procurei no google e apareceu um monte de conta que nunca vi hehehe

Share this post


Link to post
Share on other sites
neocampos

@ppturbo,

vale lembrar que um formato de imagem é diferente de um formato de som. Então o procedimento que você citou não vai eliminar ruídos. Como o HappyHippyHippo citou, você precisará de uma fft, que também está postada nesse fórum pra fazer uma análise na frequência do seu sinal e utilizar um filtro para eliminar o ruído indesejado. Qualquer progresso que você fizer, gostaria que postasse aqui pra que outros membros pudessem tirar proveito.

Boa noite a todos.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.