Our server costs ~$56 per month to run. Please consider donating or becoming a Patron to help keep the site running. Help us gain new members by following us on Twitter and liking our page on Facebook!
Current time: April 27, 2024, 12:48 am

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Generating WAV files
#1
Generating WAV files
Hey, guys!
So, recently, I've made a simple program that converts notes stored in a text file into waveforms. However, now it can't produce WAV files, only raw data, and you need to use ffmpeg or some similar tool to convert them to WAV files. I've tried to write a program in C that produces actual WAV files, however, the players complain its header is corrupt. Can you guess what's actually going on?
Code:
#include <stdint.h>
#include <stdio.h>
#include <math.h>

int main() {
    FILE *wav=fopen("example.wav","wb");
    fprintf(wav,"RIFF");
    const int sampleRate=8192;
    int32_t ChunkSize=36+8*sampleRate*2;
    fwrite(&ChunkSize,4,1,wav);
    fprintf(wav,"WAVEfmt");
    int32_t Subchunk1Size=16; //PCM header is always 16 bytes
    fwrite(&Subchunk1Size,4,1,wav);
    int16_t AudioFormat=1; //PCM
    fwrite(&AudioFormat,2,1,wav);
    int16_t NumChannels=1; //MONO audio.
    fwrite(&NumChannels,2,1,wav);
    int32_t SampleRate=sampleRate;
    fwrite(&SampleRate,4,1,wav);
    int32_t ByteRate=2*sampleRate;
    fwrite(&ByteRate,4,1,wav);
    int16_t BlockAlign=2;
    fwrite(&BlockAlign,2,1,wav);
    int16_t BitsPerSample=16;
    fwrite(&BitsPerSample,2,1,wav);
    fprintf(wav,"data");
    int32_t Subchunk2Size=ChunkSize-36;
    for (int i=0; i<8*sampleRate; i++) {
        float currentFrequency;
        if (i<=sampleRate)
            currentFrequency=262; //The C tone is 262Hz.
        else if (i>sampleRate && i<=2*sampleRate)
            currentFrequency=294; //The D tone is 294Hz.
        else if (i>2*sampleRate && i<=3*sampleRate)
            currentFrequency=330; //The E tone is 330Hz.
        else if (i>3*sampleRate && i<=4*sampleRate)
            currentFrequency=349; //The F tone.
        else if (i>4*sampleRate && i<=5*sampleRate)
            currentFrequency=391; //The G tone.
        else if (i>5*sampleRate && i<=6*sampleRate)
            currentFrequency=440; //The A tone.
        else if (i>6*sampleRate && i<=7*sampleRate)
            currentFrequency=494;  //The H sound.
        else
            currentFrequency=523; //The Tenor C.
        float baseFrequency=sin(2*M_PI*currentFrequency*i/sampleRate)*16384;
        float secondHarmony=sin(2*M_PI*2*currentFrequency*i/sampleRate)*4096;
        float thirdHarmony=sin(2*M_PI*3*currentFrequency*i/sampleRate)*41024;
        float currentAmplitude=baseFrequency+secondHarmony+thirdHarmony*exp(-(float)(i%sampleRate+2000)/2000);
        int16_t numberToBeWritten=currentAmplitude;
        fwrite(&numberToBeWritten,2,1,wav);
    }
    fclose(wav);
}
I've also posted this question on the Audacity forum, however I haven't got a response.
Reply
#2
RE: Generating WAV files
Wavs back.
Reply
#3
RE: Generating WAV files
If it only generates very, very small WAV files, you could call it a microWAV.

But it probably won’t reheat your coffee.

Boru
‘But it does me no injury for my neighbour to say there are twenty gods or no gods. It neither picks my pocket nor breaks my leg.’ - Thomas Jefferson
Reply
#4
RE: Generating WAV files
(May 3, 2020 at 12:25 pm)BrianSoddingBoru4 Wrote: If it only generates very, very small WAV files, you could call it a microWAV.

But it probably won’t reheat your coffee.

Boru

Stop it!
The meek shall inherit the Earth, the rest of us will fly to the stars.

Never underestimate the power of very stupid people in large groups

Arguing with an engineer is like wrestling with a pig in mud ..... after a while you realise that the pig likes it!

Reply
#5
RE: Generating WAV files
(May 3, 2020 at 12:25 pm)BrianSoddingBoru4 Wrote: If it only generates very, very small WAV files, you could call it a microWAV.

But it probably won’t reheat your coffee.

Boru

It generates invalid WAV files, with a corrupt header. But the body of the WAV files is correct, I know that because, if I ask FFMPEG to prepend a valid WAV header to them, I can play them (you can see that here, the "output.raw" is the file that's outputted by my program, and the "output.wav" is that file corrected by FFMPEG).
Reply
#6
RE: Generating WAV files
(May 3, 2020 at 11:52 am)FlatAssembler Wrote: Hey, guys!
So, recently, I've made a simple program that converts notes stored in a text file into waveforms. However, now it can't produce WAV files, only raw data, and you need to use ffmpeg or some similar tool to convert them to WAV files. I've tried to write a program in C that produces actual WAV files, however, the players complain its header is corrupt. Can you guess what's actually going on?
Code:
#include <stdint.h>
#include <stdio.h>
#include <math.h>

int main() {
FILE *wav=fopen("example.wav","wb");
fprintf(wav,"RIFF");
const int sampleRate=8192;
int32_t ChunkSize=36+8*sampleRate*2;
fwrite(&ChunkSize,4,1,wav);
fprintf(wav,"WAVEfmt");
int32_t Subchunk1Size=16; //PCM header is always 16 bytes
fwrite(&Subchunk1Size,4,1,wav);
int16_t AudioFormat=1; //PCM
fwrite(&AudioFormat,2,1,wav);
int16_t NumChannels=1; //MONO audio.
fwrite(&NumChannels,2,1,wav);
int32_t SampleRate=sampleRate;
fwrite(&SampleRate,4,1,wav);
int32_t ByteRate=2*sampleRate;
fwrite(&ByteRate,4,1,wav);
int16_t BlockAlign=2;
fwrite(&BlockAlign,2,1,wav);
int16_t BitsPerSample=16;
fwrite(&BitsPerSample,2,1,wav);
fprintf(wav,"data");
int32_t Subchunk2Size=ChunkSize-36;
for (int i=0; i<8*sampleRate; i++) {
float currentFrequency;
if (i<=sampleRate)
currentFrequency=262; //The C tone is 262Hz.
else if (i>sampleRate && i<=2*sampleRate)
currentFrequency=294; //The D tone is 294Hz.
else if (i>2*sampleRate && i<=3*sampleRate)
currentFrequency=330; //The E tone is 330Hz.
else if (i>3*sampleRate && i<=4*sampleRate)
currentFrequency=349; //The F tone.
else if (i>4*sampleRate && i<=5*sampleRate)
currentFrequency=391; //The G tone.
else if (i>5*sampleRate && i<=6*sampleRate)
currentFrequency=440; //The A tone.
else if (i>6*sampleRate && i<=7*sampleRate)
currentFrequency=494;  //The H sound.
else
currentFrequency=523; //The Tenor C.
float baseFrequency=sin(2*M_PI*currentFrequency*i/sampleRate)*16384;
float secondHarmony=sin(2*M_PI*2*currentFrequency*i/sampleRate)*4096;
float thirdHarmony=sin(2*M_PI*3*currentFrequency*i/sampleRate)*41024;
float currentAmplitude=baseFrequency+secondHarmony+thirdHarmony*exp(-(float)(i%sampleRate+2000)/2000);
int16_t numberToBeWritten=currentAmplitude;
fwrite(&numberToBeWritten,2,1,wav);
}
fclose(wav);
}
I've also posted this question on the Audacity forum, however I haven't got a response.

I was going to suggest Audacity but you are ahead of me!
The meek shall inherit the Earth, the rest of us will fly to the stars.

Never underestimate the power of very stupid people in large groups

Arguing with an engineer is like wrestling with a pig in mud ..... after a while you realise that the pig likes it!

Reply
#7
RE: Generating WAV files
Solved it myself. Here is the correct program:
Code:
#include <stdint.h>
#include <stdio.h>
#include <math.h>

int main() {
    FILE *wav=fopen("example.wav","wb");
    fprintf(wav,"RIFF");
    const int sampleRate=8192;
    int32_t ChunkSize=36+8*sampleRate*2;
    fwrite(&ChunkSize,4,1,wav);
    fprintf(wav,"WAVEfmt "); //This line has been changed!
    int32_t Subchunk1Size=16; //PCM header is always 16 bytes
    fwrite(&Subchunk1Size,4,1,wav);
    int16_t AudioFormat=1; //PCM
    fwrite(&AudioFormat,2,1,wav);
    int16_t NumChannels=1; //MONO audio.
    fwrite(&NumChannels,2,1,wav);
    int32_t SampleRate=sampleRate;
    fwrite(&SampleRate,4,1,wav);
    int32_t ByteRate=2*sampleRate;
    fwrite(&ByteRate,4,1,wav);
    int16_t BlockAlign=2;
    fwrite(&BlockAlign,2,1,wav);
    int16_t BitsPerSample=16;
    fwrite(&BitsPerSample,2,1,wav);
    fprintf(wav,"data");
    int32_t Subchunk2Size=ChunkSize-36;
    for (int i=0; i<8*sampleRate; i++) {
        float currentFrequency;
        if (i<=sampleRate)
            currentFrequency=262; //The C tone is 262Hz.
        else if (i>sampleRate && i<=2*sampleRate)
            currentFrequency=294; //The D tone is 294Hz.
        else if (i>2*sampleRate && i<=3*sampleRate)
            currentFrequency=330; //The E tone is 330Hz.
        else if (i>3*sampleRate && i<=4*sampleRate)
            currentFrequency=349; //The F tone.
        else if (i>4*sampleRate && i<=5*sampleRate)
            currentFrequency=391; //The G tone.
        else if (i>5*sampleRate && i<=6*sampleRate)
            currentFrequency=440; //The A tone.
        else if (i>6*sampleRate && i<=7*sampleRate)
            currentFrequency=494;  //The H sound.
        else
            currentFrequency=523; //The Tenor C.
        float baseFrequency=sin(2*M_PI*currentFrequency*i/sampleRate)*16384;
        float secondHarmony=sin(2*M_PI*2*currentFrequency*i/sampleRate)*4096;
        float thirdHarmony=sin(2*M_PI*3*currentFrequency*i/sampleRate)*41024;
        float currentAmplitude=baseFrequency+secondHarmony+thirdHarmony*exp(-(float)(i%sampleRate+2000)/2000);
        int16_t numberToBeWritten=currentAmplitude;
        fwrite(&numberToBeWritten,2,1,wav);
    }
    fclose(wav);
}
Basically, I forgot to put the space character somewhere, and the program still compiled, but it didn't do what it was supposed to do.
Reply
#8
RE: Generating WAV files
Write code that opens and prints to screen or file the header of a valid WAV.  Compare with what your code produces to find the error.
Reply
#9
RE: Generating WAV files
(May 4, 2020 at 9:13 am)Ranjr Wrote: Write code that opens and prints to screen or file the header of a valid WAV.  Compare with what your code produces to find the error.

Well, that's pretty much how I found the error. Except I didn't write that program that will print the headers myself, but instead I used VIM in the "uhex" mode.
Reply



Possibly Related Threads...
Thread Author Replies Views Last Post
  Help unzipping old zip files popeyespappy 29 2523 December 19, 2018 at 8:10 pm
Last Post: ignoramus
  Can't unzip a bunch of files: Oldandeasilyconfused 4 2072 May 23, 2012 at 11:13 pm
Last Post: Oldandeasilyconfused
  Multi Language Subtitle Files Darwinian 2 1171 April 6, 2012 at 4:49 pm
Last Post: Darwinian



Users browsing this thread: 1 Guest(s)