Jump to content

[Resolvido] Ler e Escrever um arquivo WAV em C


Recommended Posts

Posted (edited)

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
Posted

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!

Posted

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

Posted

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!

Posted (edited)

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
Posted (edited)

@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
Posted

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.

Posted

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?

Posted

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
Posted

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

Posted

@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.

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
×
×
  • Create New...

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.