Ir para o conteúdo
  • 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

Mensagens Recomendadas

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");
}

Editado por pmg
Falta LP no GeSHi

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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

Editado por HappyHippyHippo

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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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");
}


Editado por pmg
Falta LP no GeSHi
  • Voto 1

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pmg

Sugestao: usa um metodo de indentacao mais comum :)

  • Voto 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!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros 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.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.