Ecrire des fichiers WAV.

Ecrire des fichiers WAV.

Voir version :

Pas de dépendances

Télécharger :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define FREQUENCE 44100
#define BITPERSAMPLE 16

typedef int int32;
typedef short int16;
typedef char int8;

struct WavHeader
{
    int8 FileTypeBlocID[4];
    int32 FileSize;
    int8 FileFormatID[4];
};

struct WavFmt
{
    int8 FormatBlocID[4];
    int32 BlocSize;
    int16 AudioFormat;
    int16 NbrCanaux;
    int32 Frequence;
    int32 BytePerSec;
    int16 BytePerBloc;
    int16 BitsPerSample;
};

FILE * wavfile_open( const char *filename )
{
    struct WavHeader head = {{'R','I','F','F'},0,{'W','A','V','E'}};
    struct WavFmt Fmt = {{'f','m','t',' '},16,1,1,FREQUENCE,FREQUENCE*BITPERSAMPLE/8,BITPERSAMPLE/8,BITPERSAMPLE};
    FILE* F;
    F = fopen(filename,"wb");
    if(!F) 
        return 0;
    fwrite(&head,sizeof(head),1,F);
    fwrite(&Fmt,sizeof(Fmt),1,F);
    return F;
}

void wavfile_write(FILE *F, int16* data, int32 length )
{
    char subhead[5] = "data";
    fwrite(subhead,4,1,F);
    fwrite(&length,sizeof(length),1,F);
    fwrite(data,sizeof(short),length,F);
}

void wavfile_close( FILE *file )
{
    int file_length = ftell(file);
    int32 FileSize = file_length - 8;
    fseek(file,4,SEEK_SET);
    fwrite(&FileSize,sizeof(FileSize),1,file);
    fclose(file);
}

int main()
{
    FILE* F;
    int i;
    int nbsecondes = 10;
    int updown = 1;
    int16* datas = malloc(nbsecondes*FREQUENCE*sizeof(int16));
    for(i=0;i<nbsecondes*FREQUENCE;i++)
    {
        int largeurcarre = ((i/FREQUENCE)+1)*100;
        if (i%largeurcarre==0)
            updown= -1*updown;
        datas[i] = updown*16384;
    }
    F = wavfile_open("sound.wav");
    if (!F)
        return -1;
    wavfile_write(F,datas,nbsecondes*FREQUENCE);
    free(datas);
    wavfile_close(F);
    return 0;
}




Commentaires

	Avant de commencer, voila quelques documents :

	Voici tout d'abord la documentation du format WAV :
	https://fr.wikipedia.org/wiki/WAVEform_audio_format

	Ensuite, mon exemple est inspiré de : 
	http://www3.nd.edu/~dthain/courses/cse20211/fall2013/wavfile/

	le son est une vibration de l'air, une variation de pression.
	On peut représenter le son comme une courbe de la pression en fonction du temps.

	C'est cette courbe qu'un va représenter dans un fichier Wav.
	Sur le lien ci dessus, vous voyez des courbes. Pour qu'il y ait un son, il faut que la courbe oscille rapidement, sinon on n'entend rien.

	Pour encoder une courbe, il suffit de l'échantillonnner : c'est à dire prendre des points (beaucoup de points pour être précis).

	Combien de point prendre ? Et bien ma variable FREQUENCE a été mise à 44100. C'est à dire 44100 points par seconde ! C'est l'échantillange des CD.
	Nous allons donc imaginer que nous traçons par dessus notre courbe des lignes verticales, et 44100 par seconde : donc lignes très serrées.

	Ensuite, pour chacun de ces points, qu'est ce que je note ? A quelle précision ?
	Pour cela, on va définir un minimum et un maximum pour la courbe, et diviser cet intervalle par 65536.
	Et donc on va tracer, depuis le minimum vers le maximum, 65536 lignes horizontales.

	Nous avons donc une grille très fine sur notre courbe : pour l'échantilloner, pour toutes les lignes verticales, on note le point de la grille le plus proche de la grille réelle.

	Pourquoi 65536 ? Car c'est le nombre de possibilités qu'on a sur 2 octets, 16 bits.

	Nous dirons donc qu'on a échantilloné la courbe à 44100 Hrz, 16 bits. 

	Le fichier Wav stocke, dans l'ordre, chaque valeur approchée de la courbe pour chaque lignes verticale.

	Donc un grand, grand tableau de short (16 bits). 44100 short par secondes.

	Si vous échantillonnez moins, votre fichier prendra moins de place, mais la courbe sera plus grossière, moins précise, donc le son moins joli.

	Plus on échantillonne finement, plus les points notés sont proches de la courbe réelle, plus le son est fidèle à l'original.

	Après cette introduction rapide, voyons le code :

	Le fichier Wav est simple quand on a compris l'échantillonnage du son.

	Dans le header, on stocke la taille du fichier. Dans le bloc fmt qui suit, on stockes les valeurs d'échantillonnage, et le nombre de canaux
	(on peut avoir plusieurs canaux, pour du son stéréo, ici j'ai choisi un son mono, 1 canal)

	Ensuite, on passe un tableau de short.

	Vu ce que j'ai mis dans le for, j'ai décrit un signal carré périodique, qui, toutes les secondes, allonge sa période.
	Période plus longue = son plus grave.

	A vous d'essayer de faire de jolies sinusoïdes, de superposer des sons pour avoir de belles musiques !