2010-10-14 13:30:15 +00:00
<?xml version="1.0" encoding="utf-8"?>
< !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
< html xmlns = "http://www.w3.org/1999/xhtml" lang = "fr" xml:lang = "fr" >
< head >
< meta http-equiv = "Content-Type" content = "text/html; charset=UTF-8" / >
< link rel = "shortcut icon" type = "image/x-icon" href = "/Scratch/img/favicon.ico" / >
< link rel = "stylesheet" type = "text/css" href = "/Scratch/assets/css/main.css" / >
< link rel = "stylesheet" type = "text/css" href = "/Scratch/css/twilight.css" / >
< link rel = "stylesheet" type = "text/css" href = "/Scratch/css/idc.css" / >
< link rel = "alternate" type = "application/rss+xml" title = "RSS" href = "http://feeds.feedburner.com/yannespositocomfr" / >
< link rel = "alternate" lang = "fr" xml:lang = "fr" title = "S'amuser avec un .wav" type = "text/html" hreflang = "fr" href = "/Scratch/fr/blog/2010-10-14-Fun-with-wav/" / >
< link rel = "alternate" lang = "en" xml:lang = "en" title = "Fun with wav" type = "text/html" hreflang = "en" href = "/Scratch/en/blog/2010-10-14-Fun-with-wav/" / >
< script type = "text/javascript" src = "/Scratch/js/jquery-1.3.1.min.js" > < / script >
< script type = "text/javascript" src = "/Scratch/js/jquery.cookie.js" > < / script >
< script type = "text/javascript" src = "/Scratch/js/index.js" > < / script >
2010-11-17 10:10:55 +00:00
<!-- < % if containMaths %>
< script type = "text/javascript" src = "/Scratch/js/MathJax/MathJax.js" > < / script >
< % end %>
-->
2010-10-14 13:30:15 +00:00
< title > S'amuser avec un .wav< / title >
< / head >
< body lang = "fr" >
< script type = "text/javascript" > / / < ! [ C D A T A [
document.write('< div id = "blackpage" > < img src = "/Scratch/img/loading.gif" alt = "Chargement en cours..." / > < / div > ');
// ]]>
< / script >
< div id = "content" >
< div id = "choix" >
< div class = "return" > < a href = "#entete" > ↓ Menu ↓ < / a > < / div >
< div id = "choixlang" >
< a href = "/Scratch/en/blog/2010-10-14-Fun-with-wav/" onclick = "setLanguage('en')" > in English< / a >
< / div >
< / div >
< img src = "/Scratch/img/presentation.png" alt = "Presentation drawing" / >
< div id = "titre" >
< h1 >
S'amuser avec un .wav
< / h1 >
< / div >
< div class = "flush" > < / div >
< div class = "flush" > < / div >
< div id = "afterheader" >
< div class = "corps" >
< div class = "intro" >
2010-10-15 13:11:51 +00:00
< p > < span class = "sc" > < abbr title = "Trop long à lire" > tlàl< / abbr > : < / span > Je me suis amusé à lire un fichier < code > wav< / code > . Le < code > C< / code > fut le langage le mieux adapté à ce traitement. Bien meilleur que Ruby par exemple.< / p >
< p > edit: Je voulais que ce programme fonctionne sur une machine spécifique. En aucun cas je ne pensais publier ce code pour une utilisation autre que celle-ci.< / p >
2010-10-14 13:30:15 +00:00
< / div >
< p > J’ ai eu besoin de calculer la somme des valeurs absolue des données d’ un fichier < code > wav< / code > .
Pour des raison d’ efficacité (et aussi de fun), j’ ai fait le programme en < code > C< / code > .< / p >
< p > Celà faisait longtemps que je n’ avais pas programmé en < code > C< / code > .
De mémoire il était peu aisé de manipuler des fichiers.
Mais je dois concéder que j’ ai été étonné de la clarté du code que j’ ai obtenu.< / p >
< p > Tout d’ abord, un fichier < code > wav< / code > se compose d’ un entête qui contient pas mal de meta données.
Cet entête a été optimisé pour prendre peu de place.
Donc on discute de l’ entête avec des nombres d’ octets :< / p >
< ul >
< li > Les 4 premiers octets doivent contenir < code > RIFF< / code > en ASCII ;< / li >
< li > les 4 octects suivant correspondent à un entier codé sur 32 bits qui donne la taille du fichier moins 8 octets. etc..< / li >
< / ul >
< p > Etonnamment je pense que lire ce type de fichier avec un langage de haut niveau aurait été plus pénible qu’ en C.
La preuve, il m’ a suffit de chercher sur le net le format complet de l’ entête et de l’ écrire dans un struct.< / p >
< pre class = "twilight" >
< span class = "Storage" > struct< / span > wavfile
{
2010-10-14 22:33:07 +00:00
< span class = "Storage" > char< / span > id[< span class = "Constant" > 4< / span > ]; < span class = "Comment" > < span class = "Comment" > //< / span > should always contain " RIFF" < / span >
2010-10-15 13:11:51 +00:00
< span class = "Storage" > int< / span > totallength; < span class = "Comment" > < span class = "Comment" > //< / span > total file length minus 8< / span >
2010-10-14 22:33:07 +00:00
< span class = "Storage" > char< / span > wavefmt[< span class = "Constant" > 8< / span > ]; < span class = "Comment" > < span class = "Comment" > //< / span > should be " WAVEfmt " < / span >
2010-10-15 13:11:51 +00:00
< span class = "Storage" > int< / span > format; < span class = "Comment" > < span class = "Comment" > //< / span > 16 for PCM format< / span >
< span class = "Storage" > short< / span > pcm; < span class = "Comment" > < span class = "Comment" > //< / span > 1 for PCM format< / span >
< span class = "Storage" > short< / span > channels; < span class = "Comment" > < span class = "Comment" > //< / span > channels< / span >
< span class = "Storage" > int< / span > frequency; < span class = "Comment" > < span class = "Comment" > //< / span > sampling frequency< / span >
< span class = "Storage" > int< / span > bytes_per_second;
< span class = "Storage" > short< / span > bytes_by_capture;
< span class = "Storage" > short< / span > bits_per_sample;
2010-10-14 22:33:07 +00:00
< span class = "Storage" > char< / span > data[< span class = "Constant" > 4< / span > ]; < span class = "Comment" > < span class = "Comment" > //< / span > should always contain " data" < / span >
2010-10-15 13:11:51 +00:00
< span class = "Storage" > int< / span > bytes_in_data;
2010-10-14 13:30:15 +00:00
};
< / pre >
< p > Si j’ avais eu à faire ça en Ruby, je pense qu’ il m’ aurait fallu pour chaque bloc de l’ entête écrire un bout de code de lecture du bon nombre d’ octets.
Alors qu’ en < code > C< / code > il m’ a suffit d’ écrire: < / p >
< pre class = "twilight" >
2010-10-15 13:11:51 +00:00
< span class = "SupportFunction" > fread< / span > (& header,< span class = "Keyword" > sizeof< / span > (header),< span class = "Constant" > 1< / span > ,wav)
2010-10-14 13:30:15 +00:00
< / pre >
< p > Et en une seule étape ma structure de donnée a été remplie avec les valeurs souhaitées. Magique !< / p >
< p > Ensuite, récupérer un entier à partir de deux octets n’ est pas non plus une opération naturelle dans les nouveaux langages de programmation.
Alors qu’ en < code > C< / code > . Pour récupérer un entier codé sur 16 bits il suffit d’ écrire :< / p >
< pre class = "twilight" >
2010-10-15 13:11:51 +00:00
< span class = "Storage" > short< / span > value=< span class = "Constant" > 0< / span > ;
2010-10-14 13:30:15 +00:00
< span class = "Keyword" > while< / span > ( < span class = "SupportFunction" > fread< / span > (& value,< span class = "Keyword" > sizeof< / span > (value),< span class = "Constant" > 1< / span > ,wav) ) {
< span class = "Comment" > < span class = "Comment" > //< / span > do something with value< / span >
}
< / pre >
< p > Finallement je suis arrivé au code suivant, sachant que le format de wav était connu, avec notamment échantillonage sur 16 bits en 48000Hz :< / p >
< div class = "code" > < div class = "file" > < a href = "/Scratch/fr/blog/2010-10-14-Fun-with-wav/code/wavsum.c" > ➥ wavsum.c < / a > < / div > < div class = "withfile" >
< pre class = "twilight" >
< span class = "CCCPreprocessorLine" > #< span class = "CCCPreprocessorDirective" > include< / span > < span class = "String" > < span class = "String" > < < / span > stdio.h< span class = "String" > > < / span > < / span > < / span >
< span class = "CCCPreprocessorLine" > #< span class = "CCCPreprocessorDirective" > include< / span > < span class = "String" > < span class = "String" > < < / span > stdlib.h< span class = "String" > > < / span > < / span > < / span >
2010-10-14 14:30:48 +00:00
< span class = "CCCPreprocessorLine" > #< span class = "CCCPreprocessorDirective" > include< / span > < span class = "String" > < span class = "String" > < < / span > stdint.h< span class = "String" > > < / span > < / span > < / span >
2010-10-14 13:30:15 +00:00
< span class = "Storage" > struct< / span > wavfile
{
2010-10-14 22:33:07 +00:00
< span class = "Storage" > char< / span > id[< span class = "Constant" > 4< / span > ]; < span class = "Comment" > < span class = "Comment" > //< / span > should always contain " RIFF" < / span >
2010-10-15 13:11:51 +00:00
< span class = "Storage" > int< / span > totallength; < span class = "Comment" > < span class = "Comment" > //< / span > total file length minus 8< / span >
2010-10-14 22:33:07 +00:00
< span class = "Storage" > char< / span > wavefmt[< span class = "Constant" > 8< / span > ]; < span class = "Comment" > < span class = "Comment" > //< / span > should be " WAVEfmt " < / span >
2010-10-15 13:11:51 +00:00
< span class = "Storage" > int< / span > format; < span class = "Comment" > < span class = "Comment" > //< / span > 16 for PCM format< / span >
< span class = "Storage" > short< / span > pcm; < span class = "Comment" > < span class = "Comment" > //< / span > 1 for PCM format< / span >
< span class = "Storage" > short< / span > channels; < span class = "Comment" > < span class = "Comment" > //< / span > channels< / span >
< span class = "Storage" > int< / span > frequency; < span class = "Comment" > < span class = "Comment" > //< / span > sampling frequency< / span >
< span class = "Storage" > int< / span > bytes_per_second;
< span class = "Storage" > short< / span > bytes_by_capture;
< span class = "Storage" > short< / span > bits_per_sample;
2010-10-14 22:33:07 +00:00
< span class = "Storage" > char< / span > data[< span class = "Constant" > 4< / span > ]; < span class = "Comment" > < span class = "Comment" > //< / span > should always contain " data" < / span >
2010-10-15 13:11:51 +00:00
< span class = "Storage" > int< / span > bytes_in_data;
2010-10-14 13:30:15 +00:00
};
< span class = "Storage" > int< / span > < span class = "Entity" > ma< span class = "Entity" > in< / span > < / span > (< span class = "Storage" > int< / span > argc, < span class = "Storage" > char< / span > *argv[]) {
< span class = "Storage" > char< / span > *filename=argv[< span class = "Constant" > 1< / span > ];
FILE *wav = < span class = "SupportFunction" > fopen< / span > (filename,< span class = "String" > < span class = "String" > " < / span > rb< span class = "String" > " < / span > < / span > );
< span class = "Storage" > struct< / span > wavfile header;
< span class = "Keyword" > if< / span > ( wav == < span class = "Constant" > NULL< / span > ) {
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > Can't open input file < span class = "StringConstant" > %s< / span > < span class = "String" > " < / span > < / span > , filename);
< span class = "SupportFunction" > exit< / span > (< span class = "Constant" > 1< / span > );
}
< span class = "Comment" > < span class = "Comment" > //< / span > read header< / span >
2010-10-14 22:26:39 +00:00
< span class = "Keyword" > if< / span > ( < span class = "SupportFunction" > fread< / span > (& header,< span class = "Keyword" > sizeof< / span > (header),< span class = "Constant" > 1< / span > ,wav) < < span class = "Constant" > 1< / span > )
2010-10-14 13:30:15 +00:00
{
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > Can't read file header< span class = "StringConstant" > \n< / span > < span class = "String" > " < / span > < / span > );
< span class = "SupportFunction" > exit< / span > (< span class = "Constant" > 1< / span > );
}
< span class = "Keyword" > if< / span > ( header.id[< span class = "Constant" > 0< / span > ] != < span class = "String" > < span class = "String" > '< / span > R< span class = "String" > '< / span > < / span >
|| header.id[< span class = "Constant" > 1< / span > ] != < span class = "String" > < span class = "String" > '< / span > I< span class = "String" > '< / span > < / span >
|| header.id[< span class = "Constant" > 2< / span > ] != < span class = "String" > < span class = "String" > '< / span > F< span class = "String" > '< / span > < / span >
|| header.id[< span class = "Constant" > 3< / span > ] != < span class = "String" > < span class = "String" > '< / span > F< span class = "String" > '< / span > < / span > ) {
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > ERROR: Not wav format< span class = "StringConstant" > \n< / span > < span class = "String" > " < / span > < / span > );
< span class = "SupportFunction" > exit< / span > (< span class = "Constant" > 1< / span > );
}
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > wav format< span class = "StringConstant" > \n< / span > < span class = "String" > " < / span > < / span > );
< span class = "Comment" > < span class = "Comment" > //< / span > read data< / span >
< span class = "Storage" > long< / span > sum=< span class = "Constant" > 0< / span > ;
2010-10-15 13:11:51 +00:00
< span class = "Storage" > short< / span > value=< span class = "Constant" > 0< / span > ;
2010-10-14 13:30:15 +00:00
< span class = "Keyword" > while< / span > ( < span class = "SupportFunction" > fread< / span > (& value,< span class = "Keyword" > sizeof< / span > (value),< span class = "Constant" > 1< / span > ,wav) ) {
< span class = "Comment" > < span class = "Comment" > //< / span > fprintf(stderr," %d\n" , value);< / span >
< span class = "Keyword" > if< / span > (value< < span class = "Constant" > 0< / span > ) { value=-value; }
sum += value;
}
< span class = "SupportFunction" > printf< / span > (< span class = "String" > < span class = "String" > " < / span > < span class = "StringConstant" > %ld< / span > < span class = "StringConstant" > \n< / span > < span class = "String" > " < / span > < / span > ,sum);
< span class = "SupportFunction" > exit< / span > (< span class = "Constant" > 0< / span > );
}
< / pre >
< / div > < / div >
< p > Bien entendu ce code n’ est qu’ un < em > hack< / em > .
Mais on voit bien comment on peut facilement améliorer ce code, ajouter des cas possibles par exemple.
Comme je dis souvent : le bon outil pour la bonne tâche.
On voit en effet que pour cette tâche < code > C< / code > est bien supérieur à Ruby par exemple.< / p >
2010-10-15 13:11:51 +00:00
< p > _màj : pour des raisons de compatibilité (machines 64 bits) j’ ai utilisé < code > int16_t< / code > au lieu de < code > short< / code > et < code > int< / code > au lieu de < code > int< / code > .< / p >
2010-10-14 14:23:07 +00:00
2010-10-14 13:30:15 +00:00
< p > Je serai curieux de savoir s’ il existe un manière plus propre en Ruby que je ne connais pas.
Certainement qu’ en Python ça doit être la cas.< / p >
2010-10-15 13:11:51 +00:00
< div class = "intro" >
2010-10-15 14:31:42 +00:00
< p > Màj (2) : après toutes les remarques concernant la portabilité.
2010-10-15 13:11:51 +00:00
J’ ai fait une nouvelle version qui devrait être plus portable.
Elle fait aussi plus de test pour vérifier le fichier.
Cependant j’ utilise une assertion spécifique à < code > gcc< / code > pour être certain que la structure de donnée n’ ai pas de “ trou” :< / p >
< pre class = "twilight" >
__attribute__((__packed__))
< / pre >
< p > Le nouveau code n’ utilise pas mmap et devrait être plus compatible.< br / >
Voici le dernier résultat :< / p >
< / div >
2010-10-26 14:49:21 +00:00
< div class = "code" > < div class = "file" > < a href = "/Scratch/fr/blog/2010-10-14-Fun-with-wav/code/wavsum2.c" > ➥ wavsum2.c < / a > < / div > < div class = "withfile" >
2010-10-15 13:11:51 +00:00
< pre class = "twilight" >
< span class = "CCCPreprocessorLine" > #< span class = "CCCPreprocessorDirective" > include< / span > < span class = "String" > < span class = "String" > < < / span > stdio.h< span class = "String" > > < / span > < / span > < / span >
< span class = "CCCPreprocessorLine" > #< span class = "CCCPreprocessorDirective" > include< / span > < span class = "String" > < span class = "String" > < < / span > stdlib.h< span class = "String" > > < / span > < / span > < / span >
< span class = "CCCPreprocessorLine" > #< span class = "CCCPreprocessorDirective" > include< / span > < span class = "String" > < span class = "String" > < < / span > string.h< span class = "String" > > < / span > < / span > < / span > < span class = "Comment" > < span class = "Comment" > //< / span > for memcmp< / span >
< span class = "CCCPreprocessorLine" > #< span class = "CCCPreprocessorDirective" > include< / span > < span class = "String" > < span class = "String" > < < / span > stdint.h< span class = "String" > > < / span > < / span > < / span > < span class = "Comment" > < span class = "Comment" > //< / span > for int16_t and int32_t< / span >
< span class = "Storage" > struct< / span > wavfile
{
< span class = "Storage" > char< / span > id[< span class = "Constant" > 4< / span > ]; < span class = "Comment" > < span class = "Comment" > //< / span > should always contain " RIFF" < / span >
< span class = "Support" > int32_t< / span > totallength; < span class = "Comment" > < span class = "Comment" > //< / span > total file length minus 8< / span >
< span class = "Storage" > char< / span > wavefmt[< span class = "Constant" > 8< / span > ]; < span class = "Comment" > < span class = "Comment" > //< / span > should be " WAVEfmt " < / span >
< span class = "Support" > int32_t< / span > format; < span class = "Comment" > < span class = "Comment" > //< / span > 16 for PCM format< / span >
< span class = "Support" > int16_t< / span > pcm; < span class = "Comment" > < span class = "Comment" > //< / span > 1 for PCM format< / span >
< span class = "Support" > int16_t< / span > channels; < span class = "Comment" > < span class = "Comment" > //< / span > channels< / span >
< span class = "Support" > int32_t< / span > frequency; < span class = "Comment" > < span class = "Comment" > //< / span > sampling frequency< / span >
< span class = "Support" > int32_t< / span > bytes_per_second;
< span class = "Support" > int16_t< / span > bytes_by_capture;
< span class = "Support" > int16_t< / span > bits_per_sample;
< span class = "Storage" > char< / span > data[< span class = "Constant" > 4< / span > ]; < span class = "Comment" > < span class = "Comment" > //< / span > should always contain " data" < / span >
< span class = "Support" > int32_t< / span > bytes_in_data;
} __attribute__((__packed__));
< span class = "Storage" > int< / span > is_big_endian(< span class = "Storage" > void< / span > ) {
< span class = "Storage" > union< / span > {
< span class = "Support" > uint32_t< / span > i;
< span class = "Storage" > char< / span > c[< span class = "Constant" > 4< / span > ];
} bint = {< span class = "Constant" > 0x01000000< / span > };
< span class = "Keyword" > return< / span > bint.c[< span class = "Constant" > 0< / span > ]==< span class = "Constant" > 1< / span > ;
}
< span class = "Storage" > int< / span > < span class = "Entity" > ma< span class = "Entity" > in< / span > < / span > (< span class = "Storage" > int< / span > argc, < span class = "Storage" > char< / span > *argv[]) {
< span class = "Storage" > char< / span > *filename=argv[< span class = "Constant" > 1< / span > ];
FILE *wav = < span class = "SupportFunction" > fopen< / span > (filename,< span class = "String" > < span class = "String" > " < / span > rb< span class = "String" > " < / span > < / span > );
< span class = "Storage" > struct< / span > wavfile header;
< span class = "Keyword" > if< / span > ( wav == < span class = "Constant" > NULL< / span > ) {
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > Can't open input file < span class = "StringConstant" > %s< / span > < span class = "StringConstant" > \n< / span > < span class = "String" > " < / span > < / span > , filename);
< span class = "SupportFunction" > exit< / span > (< span class = "Constant" > 1< / span > );
}
< span class = "Comment" > < span class = "Comment" > //< / span > read header< / span >
< span class = "Keyword" > if< / span > ( < span class = "SupportFunction" > fread< / span > (& header,< span class = "Keyword" > sizeof< / span > (header),< span class = "Constant" > 1< / span > ,wav) < < span class = "Constant" > 1< / span > ) {
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > Can't read input file header < span class = "StringConstant" > %s< / span > < span class = "StringConstant" > \n< / span > < span class = "String" > " < / span > < / span > , filename);
< span class = "SupportFunction" > exit< / span > (< span class = "Constant" > 1< / span > );
}
< span class = "Comment" > < span class = "Comment" > //< / span > if wav file isn't the same endianness than the current environment< / span >
< span class = "Comment" > < span class = "Comment" > //< / span > we quit< / span >
< span class = "Keyword" > if< / span > ( is_big_endian() ) {
< span class = "Keyword" > if< / span > ( < span class = "SupportFunction" > memcmp< / span > ( header.id,< span class = "String" > < span class = "String" > " < / span > RIFX< span class = "String" > " < / span > < / span > , < span class = "Constant" > 4< / span > ) != < span class = "Constant" > 0< / span > ) {
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > ERROR: < span class = "StringConstant" > %s< / span > is not a big endian wav file< span class = "StringConstant" > \n< / span > < span class = "String" > " < / span > < / span > , filename);
< span class = "SupportFunction" > exit< / span > (< span class = "Constant" > 1< / span > );
}
} < span class = "Keyword" > else< / span > {
< span class = "Keyword" > if< / span > ( < span class = "SupportFunction" > memcmp< / span > ( header.id,< span class = "String" > < span class = "String" > " < / span > RIFF< span class = "String" > " < / span > < / span > , < span class = "Constant" > 4< / span > ) != < span class = "Constant" > 0< / span > ) {
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > ERROR: < span class = "StringConstant" > %s< / span > is not a little endian wav file< span class = "StringConstant" > \n< / span > < span class = "String" > " < / span > < / span > , filename);
< span class = "SupportFunction" > exit< / span > (< span class = "Constant" > 1< / span > );
}
}
< span class = "Keyword" > if< / span > ( < span class = "SupportFunction" > memcmp< / span > ( header.wavefmt, < span class = "String" > < span class = "String" > " < / span > WAVEfmt < span class = "String" > " < / span > < / span > , < span class = "Constant" > 8< / span > ) != < span class = "Constant" > 0< / span >
|| < span class = "SupportFunction" > memcmp< / span > ( header.data, < span class = "String" > < span class = "String" > " < / span > data< span class = "String" > " < / span > < / span > , < span class = "Constant" > 4< / span > ) != < span class = "Constant" > 0< / span >
) {
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > ERROR: Not wav format< span class = "StringConstant" > \n< / span > < span class = "String" > " < / span > < / span > );
< span class = "SupportFunction" > exit< / span > (< span class = "Constant" > 1< / span > );
}
< span class = "Keyword" > if< / span > (header.format != < span class = "Constant" > 16< / span > ) {
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > < span class = "StringConstant" > \n< / span > ERROR: not 16 bit wav format.< span class = "String" > " < / span > < / span > );
< span class = "SupportFunction" > exit< / span > (< span class = "Constant" > 1< / span > );
}
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > format: < span class = "StringConstant" > %d< / span > bits< span class = "String" > " < / span > < / span > , header.format);
< span class = "Keyword" > if< / span > (header.format == < span class = "Constant" > 16< / span > ) {
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > , PCM< span class = "String" > " < / span > < / span > );
} < span class = "Keyword" > else< / span > {
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > , not PCM (< span class = "StringConstant" > %d< / span > )< span class = "String" > " < / span > < / span > , header.format);
}
< span class = "Keyword" > if< / span > (header.pcm == < span class = "Constant" > 1< / span > ) {
< span class = "SupportFunction" > fprintf< / span > (stderr, < span class = "String" > < span class = "String" > " < / span > uncompressed< span class = "String" > " < / span > < / span > );
} < span class = "Keyword" > else< / span > {
< span class = "SupportFunction" > fprintf< / span > (stderr, < span class = "String" > < span class = "String" > " < / span > compressed< span class = "String" > " < / span > < / span > );
}
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > , channel < span class = "StringConstant" > %d< / span > < span class = "String" > " < / span > < / span > , header.pcm);
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > , freq < span class = "StringConstant" > %d< / span > < span class = "String" > " < / span > < / span > , header.frequency );
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > , < span class = "StringConstant" > %d< / span > bytes per sec< span class = "String" > " < / span > < / span > , header.bytes_per_second );
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > , < span class = "StringConstant" > %d< / span > bytes by capture< span class = "String" > " < / span > < / span > , header.bytes_by_capture );
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > , < span class = "StringConstant" > %d< / span > bits per sample< span class = "String" > " < / span > < / span > , header.bytes_by_capture );
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > < span class = "StringConstant" > \n< / span > < span class = "String" > " < / span > < / span > );
< span class = "Keyword" > if< / span > ( < span class = "SupportFunction" > memcmp< / span > ( header.data, < span class = "String" > < span class = "String" > " < / span > data< span class = "String" > " < / span > < / span > , < span class = "Constant" > 4< / span > ) != < span class = "Constant" > 0< / span > ) {
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > ERROR: Prrroblem?< span class = "StringConstant" > \n< / span > < span class = "String" > " < / span > < / span > );
< span class = "SupportFunction" > exit< / span > (< span class = "Constant" > 1< / span > );
}
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > wav format< span class = "StringConstant" > \n< / span > < span class = "String" > " < / span > < / span > );
< span class = "Comment" > < span class = "Comment" > //< / span > read data< / span >
< span class = "Storage" > long< / span > < span class = "Storage" > long< / span > sum=< span class = "Constant" > 0< / span > ;
< span class = "Support" > int16_t< / span > value;
< span class = "Storage" > int< / span > i=< span class = "Constant" > 0< / span > ;
< span class = "SupportFunction" > fprintf< / span > (stderr,< span class = "String" > < span class = "String" > " < / span > ---< span class = "StringConstant" > \n< / span > < span class = "String" > " < / span > < / span > , value);
< span class = "Keyword" > while< / span > ( < span class = "SupportFunction" > fread< / span > (& value,< span class = "Keyword" > sizeof< / span > (value),< span class = "Constant" > 1< / span > ,wav) ) {
< span class = "Keyword" > if< / span > (value< < span class = "Constant" > 0< / span > ) { value=-value; }
sum += value;
}
< span class = "SupportFunction" > printf< / span > (< span class = "String" > < span class = "String" > " < / span > < span class = "StringConstant" > %lld< / span > < span class = "StringConstant" > \n< / span > < span class = "String" > " < / span > < / span > ,sum);
< span class = "SupportFunction" > exit< / span > (< span class = "Constant" > 0< / span > );
}
< / pre >
2010-10-15 14:31:42 +00:00
< / div > < / div >
< p > Màj(3) :
Sur < a href = "http://reddit.com" > reddit< / a >
< a href = "http://www.reddit.com/user/Bogdanp" > Bogdanp< / a >
a proposé une version en Python :< / p >
< div class = "code" > < div class = "file" > < a href = "/Scratch/fr/blog/2010-10-14-Fun-with-wav/code/wavsum.py" > ➥ wavsum.py < / a > < / div > < div class = "withfile" >
< pre class = "twilight" >
< span class = "Comment" > < span class = "Comment" > #< / span > !/usr/bin/env python< / span >
< span class = "Keyword" > from< / span > struct < span class = "Keyword" > import< / span > calcsize, unpack
< span class = "Keyword" > from< / span > sys < span class = "Keyword" > import< / span > argv, exit
< span class = "Storage" > def< / span > < span class = "Entity" > word_iter< / span > (< span class = "Variable" > f< / span > ):
< span class = "Keyword" > while< / span > < span class = "Constant" > True< / span > :
_bytes < span class = "Keyword" > =< / span > f.read(< span class = "Constant" > 2< / span > )
< span class = "Keyword" > if< / span > < span class = "SupportFunction" > len< / span > (_bytes) < span class = "Keyword" > !=< / span > < span class = "Constant" > 2< / span > :
< span class = "Keyword" > raise< / span > < span class = "Support" > StopIteration< / span >
< span class = "Keyword" > yield< / span > unpack(< span class = "String" > < span class = "String" > " < / span > =h< span class = "String" > " < / span > < / span > , _bytes)[< span class = "Constant" > 0< / span > ]
< span class = "Keyword" > try< / span > :
< span class = "Keyword" > with< / span > < span class = "Support" > open< / span > (argv[< span class = "Constant" > 1< / span > ], < span class = "String" > < span class = "String" > " < / span > rb< span class = "String" > " < / span > < / span > ) < span class = "Keyword" > as< / span > f:
wav < span class = "Keyword" > =< / span > < span class = "String" > < span class = "String" > " < / span > =4ci8cihhiihh4ci< span class = "String" > " < / span > < / span >
wav_size < span class = "Keyword" > =< / span > calcsize(wav)
metadata < span class = "Keyword" > =< / span > unpack(wav, f.read(wav_size))
< span class = "Keyword" > if< / span > < span class = "String" > < span class = "String" > " < / span > < span class = "String" > < span class = "String" > " < / span > < / span > < / span > .join(metadata[:< span class = "Constant" > 4< / span > ]) < span class = "Keyword" > !=< / span > < span class = "String" > < span class = "String" > " < / span > RIFF< span class = "String" > " < / span > < / span > :
< span class = "Keyword" > print< / span > < span class = "String" > < span class = "String" > " < / span > error: not wav file.< span class = "String" > " < / span > < / span >
exit(< span class = "Constant" > 1< / span > )
< span class = "Keyword" > print< / span > < span class = "SupportFunction" > sum< / span > (< span class = "SupportFunction" > abs< / span > (word) < span class = "Keyword" > for< / span > word < span class = "Keyword" > in< / span > word_iter(f))
< span class = "Keyword" > except< / span > < span class = "Support" > IOError< / span > :
< span class = "Keyword" > print< / span > < span class = "String" > < span class = "String" > " < / span > error: can't open input file '< span class = "StringConstant" > %s< / span > '.< span class = "String" > " < / span > < / span > < span class = "Keyword" > %< / span > argv[< span class = "Constant" > 1< / span > ]
exit(< span class = "Constant" > 1< / span > )
< / pre >
< / div > < / div >
< p > et < a href = "http://www.reddit.com/user/luikore" > luikore< / a > a proposé une version Ruby assez impressionnante :< / p >
< div class = "code" > < div class = "file" > < a href = "/Scratch/fr/blog/2010-10-14-Fun-with-wav/code/wavsum.rb" > ➥ wavsum.rb < / a > < / div > < div class = "withfile" >
< pre class = "twilight" >
data < span class = "Keyword" > =< / span > < span class = "Variable" > ARGF< / span > .< span class = "Entity" > read< / span >
keys < span class = "Keyword" > =< / span > < span class = "String" > < span class = "String" > %w[< / span > id totallength wavefmt format< / span >
< span class = "String" > pcm channels frequency bytes_per_second< / span >
< span class = "String" > bytes_by_capture bits_per_sample< / span >
< span class = "String" > data bytes_in_data sum< / span >
< span class = "String" > < span class = "String" > ]< / span > < / span >
values < span class = "Keyword" > =< / span > data.< span class = "Entity" > unpack< / span > < span class = "String" > < span class = "String" > '< / span > Z4 i Z8 i s s i i s s Z4 i s*< span class = "String" > '< / span > < / span >
sum < span class = "Keyword" > =< / span > values.< span class = "Entity" > drop< / span > (< span class = "Constant" > 12< / span > ).< span class = "Entity" > map< / span > (< span class = "Keyword" > & < / span > < span class = "Constant" > < span class = "Constant" > :< / span > abs< / span > ).< span class = "Entity" > inject< / span > (< span class = "Constant" > < span class = "Constant" > :< / span > +< / span > )
keys.< span class = "Entity" > zip< / span > (values.< span class = "Entity" > take< / span > (< span class = "Constant" > 12< / span > ) < span class = "Keyword" > < < < / span > sum) {|< span class = "Variable" > k< / span > , < span class = "Variable" > v< / span > |
puts < span class = "String" > < span class = "String" > " < / span > < span class = "StringEmbeddedSource" > < span class = "StringEmbeddedSource" > #{< / span > k< span class = "StringEmbeddedSource" > < span class = "StringEmbeddedSource" > .< / span > < span class = "Entity" > ljust< / span > < / span > < span class = "StringConstant" > 17< / span > < span class = "StringEmbeddedSource" > }< / span > < / span > : < span class = "StringEmbeddedSource" > < span class = "StringEmbeddedSource" > #{< / span > v< span class = "StringEmbeddedSource" > }< / span > < / span > < span class = "String" > " < / span > < / span >
}
< / pre >
2010-10-15 13:11:51 +00:00
< / div > < / div >
2010-10-14 13:30:15 +00:00
< / div >
2010-12-21 15:47:55 +00:00
< div class = "navigation" >
< div class = "navigationprev" > < a href = "/Scratch/fr/blog/2010-10-10-Secure-eMail-on-Mac-in-few-steps/" > < span class = "nicer" > «< / span > précédent< / a > < / div >
< div class = "navigationnext" > < a href = "/Scratch/fr/blog/2010-10-26-LaTeX-like-macro-and-markdown/" > suivant < span class = "nicer" > »< / span > < / a > < / div >
< / div >
< div class = "flush" > < / div >
2010-10-14 13:30:15 +00:00
< div id = "choixrss" >
< a id = "rss" href = "http://feeds.feedburner.com/yannespositocomfr" >
s'abonner
< / a >
< / div >
< script type = "text/javascript" >
$(document).ready(function(){
$('#comment').hide();
$('#clickcomment').click(showComments);
});
function showComments() {
$('#comment').show();
$('#clickcomment').fadeOut();
}
document.write('< div id = "clickcomment" > Commentaires< / div > ');
< / script >
< div class = "flush" > < / div >
< div class = "corps" id = "comment" >
< h2 class = "first" > commentaires< / h2 >
< noscript >
2010-10-26 14:49:21 +00:00
Vous devez activer javascript pour commenter.
2010-10-14 13:30:15 +00:00
< / noscript >
< script type = "text/javascript" >
var idcomments_acct = 'a307f0044511ff1b5cfca573fc0a52e7';
2010-12-21 15:47:55 +00:00
var idcomments_post_id = '/Scratch/fr/blog/';
var idcomments_post_url = 'http://yannesposito.com/Scratch/fr/blog/';
2010-10-14 13:30:15 +00:00
< / script >
< span id = "IDCommentsPostTitle" style = "display:none" > < / span >
< script type = 'text/javascript' src = '/Scratch/js/genericCommentWrapperV2.js' > < / script >
< / div >
< div id = "entete" class = "corps_spaced" >
< div id = "liens" >
< ul > < li > < a href = "/Scratch/fr/" > Accueil< / a > < / li >
< li > < a href = "/Scratch/fr/blog/" > Blog< / a > < / li >
< li > < a href = "/Scratch/fr/softwares/" > Softwares< / a > < / li >
< li > < a href = "/Scratch/fr/about/" > À propos< / a > < / li > < / ul >
< / div >
< div class = "flush" > < / div >
< hr / >
< div id = "next_before_articles" >
< div id = "previous_articles" >
articles précédents
< / div >
< div id = "next_articles" >
articles suivants
2010-10-26 14:49:21 +00:00
< div class = "next_article" >
2010-12-21 15:47:55 +00:00
< a href = "/Scratch/fr/softwares/" > Softwares < span class = "nicer" > »< / span > < / a >
2010-10-26 14:49:21 +00:00
< / div >
2010-10-14 13:30:15 +00:00
2010-12-21 15:47:55 +00:00
< div class = "next_article" >
< a href = "/Scratch/fr/about/" > À propos < span class = "nicer" > »< / span > < / a >
< / div >
2010-10-14 13:30:15 +00:00
< / div >
< div class = "flush" > < / div >
< / div >
< / div >
< div id = "bottom" >
< div >
< a rel = "license" href = "http://creativecommons.org/licenses/by-sa/3.0/deed.fr" > Droits de reproduction ©, Yann Esposito< / a >
< / div >
< div id = "lastmod" >
Écrit le : 14/10/2010
2010-10-26 15:01:00 +00:00
modifié le : 26/10/2010
2010-10-14 13:30:15 +00:00
< / div >
< div >
Site entièrement réalisé avec
< a href = "http://www.vim.org" > Vim< / a >
et
< a href = "http://nanoc.stoneship.org" > nanoc< / a >
< / div >
< div >
< a href = "/Scratch/fr/validation/" > Validation< / a >
< a href = "http://validator.w3.org/check?uri=referer" > [xhtml] < / a >
.
< a href = "http://jigsaw.w3.org/css-validator/check/referer?profile=css3" > [css] < / a >
.
< a href = "http://validator.w3.org/feed/check.cgi?url=http%3A//yannesposito.com/Scratch/fr/blog/feed/feed.xml" > [rss]< / a >
< / div >
< / div >
< div class = "clear" > < / div >
< / div >
< / body >
< / html >