2021-04-18 10:23:24 +00:00
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "utf-8" >
< title > YBlog - Fun with wav< / title >
< meta name = "keywords" content = "wav, C, format, programming" / >
< link rel = "shortcut icon" type = "image/x-icon" href = "../../../../Scratch/img/favicon.ico" / >
2021-05-25 20:25:47 +00:00
< link rel = "stylesheet" type = "text/css" href = "/css/y.css" / >
< link rel = "stylesheet" type = "text/css" href = "/css/legacy.css" / >
< link rel = "alternate" type = "application/rss+xml" title = "RSS" href = "/rss.xml" / >
2021-04-18 10:23:24 +00:00
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< link rel = "apple-touch-icon" href = "../../../../Scratch/img/about/FlatAvatar@2x.png" / >
<!-- [if lt IE 9]>
< script src = "http://ie7-js.googlecode.com/svn/version/2.1(beta4)/IE9.js" > < / script >
<![endif]-->
<!-- IndieAuth -->
< link href = "https://twitter.com/yogsototh" rel = "me" >
< link href = "https://github.com/yogsototh" rel = "me" >
< link href = "mailto:yann.esposito@gmail.com" rel = "me" >
< link rel = "pgpkey" href = "../../../../pubkey.txt" >
< / head >
< body lang = "en" class = "article" >
< div id = "content" >
< div id = "header" >
< div id = "choix" >
< span id = "choixlang" >
< a href = "../../../../Scratch/fr/blog/2010-10-14-Fun-with-wav/" > French< / a >
< / span >
< span class = "tomenu" > < a href = "#navigation" > ↓ Menu ↓< / a > < / span >
< span class = "flush" > < / span >
< / div >
< / div >
< div id = "titre" >
< h1 > Fun with wav< / h1 >
< / div >
< div class = "flush" > < / div >
< div id = "afterheader" class = "article" >
< div class = "corps" >
< div class = "intro" >
< p > < span class = "sc" > < abbr title = "Too long; didn't read" > tl;dr< / abbr > : < / span > Played to process a < code > wav< / code > file. < code > C< / code > was easier and cleaner than Ruby.< / p >
< p > edit: I wanted this program to work only on one specific machine (a x86 on a 32 bit Ubuntu). Therefore I didn’ t had any portability consideration. This is only a < em > hack< / em > .< / p >
< / div >
< p > I had to compute the sum of the absolute values of data of a < code > .wav< / code > file. For efficiency (and fun) reasons, I had chosen < code > C< / code > language.< / p >
< p > I didn’ t programmed in < code > C< / code > for a long time. From my memory it was a pain to read and write to files. But in the end I was really impressed by the code I get. It was really clean. This is even more impressive knowing I used mostly low level functions.< / p >
< p > A < code > wav< / code > file has an header containing many metadata. This header was optimized to take as few space as possible. The header is then a block of packed bytes.< / p >
< ul >
< li > The 4th first bytes must contains < code > RIFF< / code > in ASCII,< / li >
< li > the following 4th Bytes is an 32 bits integer giving the size of the file minus 8, etc…< / li >
< / ul >
< p > Surprisingly, I believe that reading this kind of file is easier in < code > C< / code > than in most higher level language. Proof: I only have to search on the web the complete header format and write it in a struct.< / p >
< div class = "sourceCode" id = "cb1" > < pre class = "sourceCode c" > < code class = "sourceCode c" > < a class = "sourceLine" id = "cb1-1" title = "1" > < span class = "kw" > struct< / span > wavfile< / a >
< a class = "sourceLine" id = "cb1-2" title = "2" > {< / a >
< a class = "sourceLine" id = "cb1-3" title = "3" > < span class = "dt" > char< / span > id[< span class = "dv" > 4< / span > ]; < span class = "co" > // should always contain " RIFF" < / span > < / a >
< a class = "sourceLine" id = "cb1-4" title = "4" > < span class = "dt" > int< / span > totallength; < span class = "co" > // total file length minus 8< / span > < / a >
< a class = "sourceLine" id = "cb1-5" title = "5" > < span class = "dt" > char< / span > wavefmt[< span class = "dv" > 8< / span > ]; < span class = "co" > // should be " WAVEfmt " < / span > < / a >
< a class = "sourceLine" id = "cb1-6" title = "6" > < span class = "dt" > int< / span > format; < span class = "co" > // 16 for PCM format< / span > < / a >
< a class = "sourceLine" id = "cb1-7" title = "7" > < span class = "dt" > short< / span > pcm; < span class = "co" > // 1 for PCM format< / span > < / a >
< a class = "sourceLine" id = "cb1-8" title = "8" > < span class = "dt" > short< / span > channels; < span class = "co" > // channels< / span > < / a >
< a class = "sourceLine" id = "cb1-9" title = "9" > < span class = "dt" > int< / span > frequency; < span class = "co" > // sampling frequency< / span > < / a >
< a class = "sourceLine" id = "cb1-10" title = "10" > < span class = "dt" > int< / span > bytes_per_second;< / a >
< a class = "sourceLine" id = "cb1-11" title = "11" > < span class = "dt" > short< / span > bytes_by_capture;< / a >
< a class = "sourceLine" id = "cb1-12" title = "12" > < span class = "dt" > short< / span > bits_per_sample;< / a >
< a class = "sourceLine" id = "cb1-13" title = "13" > < span class = "dt" > char< / span > data[< span class = "dv" > 4< / span > ]; < span class = "co" > // should always contain " data" < / span > < / a >
< a class = "sourceLine" id = "cb1-14" title = "14" > < span class = "dt" > int< / span > bytes_in_data;< / a >
< a class = "sourceLine" id = "cb1-15" title = "15" > };< / a > < / code > < / pre > < / div >
< p > To read this kind of data in Ruby, I certainly had to write a block of code for each element in the struct. But in < code > C< / code > I simply written:< / p >
< div class = "sourceCode" id = "cb2" > < pre class = "sourceCode c" > < code class = "sourceCode c" > < a class = "sourceLine" id = "cb2-1" title = "1" > fread(& header,< span class = "kw" > sizeof< / span > (header),< span class = "dv" > 1< / span > ,wav)< / a > < / code > < / pre > < / div >
< p > Only one step to fill my data structure. Magic!< / p >
< p > Then, get an int value coded on two Bytes is also not a natural operation for high level language. In < code > C< / code > , to read a sequence of 2 Bytes numbers I only had to write:< / p >
< div class = "sourceCode" id = "cb3" > < pre class = "sourceCode c" > < code class = "sourceCode c" > < a class = "sourceLine" id = "cb3-1" title = "1" > < span class = "dt" > short< / span > value=< span class = "dv" > 0< / span > ;< / a >
< a class = "sourceLine" id = "cb3-2" title = "2" > < span class = "cf" > while< / span > ( fread(& value,< span class = "kw" > sizeof< / span > (value),< span class = "dv" > 1< / span > ,wav) ) {< / a >
< a class = "sourceLine" id = "cb3-3" title = "3" > < span class = "co" > // do something with value< / span > < / a >
< a class = "sourceLine" id = "cb3-4" title = "4" > }< / a > < / code > < / pre > < / div >
< p > Finally I ended with the following code. Remark I know the wav format (16 bit / 48000Hz):< / p >
< div class = "sourceCode" id = "cb4" > < pre class = "sourceCode c" > < code class = "sourceCode c" > < a class = "sourceLine" id = "cb4-1" title = "1" > < span class = "pp" > #include < / span > < span class = "im" > < stdio.h> < / span > < / a >
< a class = "sourceLine" id = "cb4-2" title = "2" > < span class = "pp" > #include < / span > < span class = "im" > < stdlib.h> < / span > < / a >
< a class = "sourceLine" id = "cb4-3" title = "3" > < span class = "pp" > #include < / span > < span class = "im" > < stdint.h> < / span > < / a >
< a class = "sourceLine" id = "cb4-4" title = "4" > < / a >
< a class = "sourceLine" id = "cb4-5" title = "5" > < span class = "kw" > struct< / span > wavfile< / a >
< a class = "sourceLine" id = "cb4-6" title = "6" > {< / a >
< a class = "sourceLine" id = "cb4-7" title = "7" > < span class = "dt" > char< / span > id[< span class = "dv" > 4< / span > ]; < span class = "co" > // should always contain " RIFF" < / span > < / a >
< a class = "sourceLine" id = "cb4-8" title = "8" > < span class = "dt" > int< / span > totallength; < span class = "co" > // total file length minus 8< / span > < / a >
< a class = "sourceLine" id = "cb4-9" title = "9" > < span class = "dt" > char< / span > wavefmt[< span class = "dv" > 8< / span > ]; < span class = "co" > // should be " WAVEfmt " < / span > < / a >
< a class = "sourceLine" id = "cb4-10" title = "10" > < span class = "dt" > int< / span > format; < span class = "co" > // 16 for PCM format< / span > < / a >
< a class = "sourceLine" id = "cb4-11" title = "11" > < span class = "dt" > short< / span > pcm; < span class = "co" > // 1 for PCM format< / span > < / a >
< a class = "sourceLine" id = "cb4-12" title = "12" > < span class = "dt" > short< / span > channels; < span class = "co" > // channels< / span > < / a >
< a class = "sourceLine" id = "cb4-13" title = "13" > < span class = "dt" > int< / span > frequency; < span class = "co" > // sampling frequency< / span > < / a >
< a class = "sourceLine" id = "cb4-14" title = "14" > < span class = "dt" > int< / span > bytes_per_second;< / a >
< a class = "sourceLine" id = "cb4-15" title = "15" > < span class = "dt" > short< / span > bytes_by_capture;< / a >
< a class = "sourceLine" id = "cb4-16" title = "16" > < span class = "dt" > short< / span > bits_per_sample;< / a >
< a class = "sourceLine" id = "cb4-17" title = "17" > < span class = "dt" > char< / span > data[< span class = "dv" > 4< / span > ]; < span class = "co" > // should always contain " data" < / span > < / a >
< a class = "sourceLine" id = "cb4-18" title = "18" > < span class = "dt" > int< / span > bytes_in_data;< / a >
< a class = "sourceLine" id = "cb4-19" title = "19" > };< / a >
< a class = "sourceLine" id = "cb4-20" title = "20" > < / a >
< a class = "sourceLine" id = "cb4-21" title = "21" > < span class = "dt" > int< / span > main(< span class = "dt" > int< / span > argc, < span class = "dt" > char< / span > *argv[]) {< / a >
< a class = "sourceLine" id = "cb4-22" title = "22" > < span class = "dt" > char< / span > *filename=argv[< span class = "dv" > 1< / span > ];< / a >
< a class = "sourceLine" id = "cb4-23" title = "23" > < span class = "dt" > FILE< / span > *wav = fopen(filename,< span class = "st" > " rb" < / span > );< / a >
< a class = "sourceLine" id = "cb4-24" title = "24" > < span class = "kw" > struct< / span > wavfile header;< / a >
< a class = "sourceLine" id = "cb4-25" title = "25" > < / a >
< a class = "sourceLine" id = "cb4-26" title = "26" > < span class = "cf" > if< / span > ( wav == NULL ) {< / a >
< a class = "sourceLine" id = "cb4-27" title = "27" > fprintf(stderr,< span class = "st" > " Can't open input file %s" < / span > , filename);< / a >
< a class = "sourceLine" id = "cb4-28" title = "28" > exit(< span class = "dv" > 1< / span > );< / a >
< a class = "sourceLine" id = "cb4-29" title = "29" > }< / a >
< a class = "sourceLine" id = "cb4-30" title = "30" > < / a >
< a class = "sourceLine" id = "cb4-31" title = "31" > < span class = "co" > // read header< / span > < / a >
< a class = "sourceLine" id = "cb4-32" title = "32" > < span class = "cf" > if< / span > ( fread(& header,< span class = "kw" > sizeof< / span > (header),< span class = "dv" > 1< / span > ,wav) < < span class = "dv" > 1< / span > )< / a >
< a class = "sourceLine" id = "cb4-33" title = "33" > {< / a >
< a class = "sourceLine" id = "cb4-34" title = "34" > fprintf(stderr,< span class = "st" > " Can't read file header< / span > < span class = "sc" > \n< / span > < span class = "st" > " < / span > );< / a >
< a class = "sourceLine" id = "cb4-35" title = "35" > exit(< span class = "dv" > 1< / span > );< / a >
< a class = "sourceLine" id = "cb4-36" title = "36" > }< / a >
< a class = "sourceLine" id = "cb4-37" title = "37" > < span class = "cf" > if< / span > ( header.id[< span class = "dv" > 0< / span > ] != < span class = "ch" > 'R'< / span > < / a >
< a class = "sourceLine" id = "cb4-38" title = "38" > || header.id[< span class = "dv" > 1< / span > ] != < span class = "ch" > 'I'< / span > < / a >
< a class = "sourceLine" id = "cb4-39" title = "39" > || header.id[< span class = "dv" > 2< / span > ] != < span class = "ch" > 'F'< / span > < / a >
< a class = "sourceLine" id = "cb4-40" title = "40" > || header.id[< span class = "dv" > 3< / span > ] != < span class = "ch" > 'F'< / span > ) { < / a >
< a class = "sourceLine" id = "cb4-41" title = "41" > fprintf(stderr,< span class = "st" > " ERROR: Not wav format< / span > < span class = "sc" > \n< / span > < span class = "st" > " < / span > ); < / a >
< a class = "sourceLine" id = "cb4-42" title = "42" > exit(< span class = "dv" > 1< / span > ); < / a >
< a class = "sourceLine" id = "cb4-43" title = "43" > }< / a >
< a class = "sourceLine" id = "cb4-44" title = "44" > < / a >
< a class = "sourceLine" id = "cb4-45" title = "45" > fprintf(stderr,< span class = "st" > " wav format< / span > < span class = "sc" > \n< / span > < span class = "st" > " < / span > );< / a >
< a class = "sourceLine" id = "cb4-46" title = "46" > < / a >
< a class = "sourceLine" id = "cb4-47" title = "47" > < span class = "co" > // read data< / span > < / a >
< a class = "sourceLine" id = "cb4-48" title = "48" > < span class = "dt" > long< / span > sum=< span class = "dv" > 0< / span > ;< / a >
< a class = "sourceLine" id = "cb4-49" title = "49" > < span class = "dt" > short< / span > value=< span class = "dv" > 0< / span > ;< / a >
< a class = "sourceLine" id = "cb4-50" title = "50" > < span class = "cf" > while< / span > ( fread(& value,< span class = "kw" > sizeof< / span > (value),< span class = "dv" > 1< / span > ,wav) ) {< / a >
< a class = "sourceLine" id = "cb4-51" title = "51" > < span class = "co" > // fprintf(stderr," %d\n" , value);< / span > < / a >
< a class = "sourceLine" id = "cb4-52" title = "52" > < span class = "cf" > if< / span > (value< < span class = "dv" > 0< / span > ) { value=-value; }< / a >
< a class = "sourceLine" id = "cb4-53" title = "53" > sum += value;< / a >
< a class = "sourceLine" id = "cb4-54" title = "54" > }< / a >
< a class = "sourceLine" id = "cb4-55" title = "55" > printf(< span class = "st" > " %ld< / span > < span class = "sc" > \n< / span > < span class = "st" > " < / span > ,sum);< / a >
< a class = "sourceLine" id = "cb4-56" title = "56" > exit(< span class = "dv" > 0< / span > );< / a >
< a class = "sourceLine" id = "cb4-57" title = "57" > }< / a > < / code > < / pre > < / div >
< p > Of course it is only a hack. But we can see how easy and clean it should be to improve. As I say often: the right tool for your need instead of the same tool for all your needs. Because here < code > C< / code > is clearly far superior than Ruby to handle this simple tasks.< / p >
< p > I am curious to know if somebody know a nice way to do this with Ruby or Python.< / p >
< p > < em > edit: for compatibility reasons (64bit machines) used < code > int16_t< / code > instead of < code > short< / code > and < code > int< / code > instead of < code > int< / code > .< / em > < / p >
< div class = "intro" >
< p > Edit (2): after most consideration about portability I made an < em > hopefully< / em > more portable version. But I must confess this task was a bit tedious. The code remain as readable as before. But I had to use some compiler specific declaration to force the structure to be packed:< / p >
< div class = "sourceCode" id = "cb5" > < pre class = "sourceCode c" > < code class = "sourceCode c" > < a class = "sourceLine" id = "cb5-1" title = "1" > __attribute__((__packed__))< / a > < / code > < / pre > < / div >
< p > Therefore this implementation should for big and little endian architecture. However, it must be compiled with < code > gcc< / code > . The new code make more tests but still don’ t use < code > mmap< / code > . Here it is:< / p >
< / div >
< div class = "sourceCode" id = "cb6" > < pre class = "sourceCode c" > < code class = "sourceCode c" > < a class = "sourceLine" id = "cb6-1" title = "1" > < span class = "pp" > #include < / span > < span class = "im" > < stdio.h> < / span > < / a >
< a class = "sourceLine" id = "cb6-2" title = "2" > < span class = "pp" > #include < / span > < span class = "im" > < stdlib.h> < / span > < / a >
< a class = "sourceLine" id = "cb6-3" title = "3" > < span class = "pp" > #include < / span > < span class = "im" > < string.h> < / span > < span class = "pp" > < / span > < span class = "co" > // for memcmp< / span > < / a >
< a class = "sourceLine" id = "cb6-4" title = "4" > < span class = "pp" > #include < / span > < span class = "im" > < stdint.h> < / span > < span class = "pp" > < / span > < span class = "co" > // for int16_t and int32_t< / span > < / a >
< a class = "sourceLine" id = "cb6-5" title = "5" > < / a >
< a class = "sourceLine" id = "cb6-6" title = "6" > < span class = "kw" > struct< / span > wavfile< / a >
< a class = "sourceLine" id = "cb6-7" title = "7" > {< / a >
< a class = "sourceLine" id = "cb6-8" title = "8" > < span class = "dt" > char< / span > id[< span class = "dv" > 4< / span > ]; < span class = "co" > // should always contain " RIFF" < / span > < / a >
< a class = "sourceLine" id = "cb6-9" title = "9" > < span class = "dt" > int32_t< / span > totallength; < span class = "co" > // total file length minus 8< / span > < / a >
< a class = "sourceLine" id = "cb6-10" title = "10" > < span class = "dt" > char< / span > wavefmt[< span class = "dv" > 8< / span > ]; < span class = "co" > // should be " WAVEfmt " < / span > < / a >
< a class = "sourceLine" id = "cb6-11" title = "11" > < span class = "dt" > int32_t< / span > format; < span class = "co" > // 16 for PCM format< / span > < / a >
< a class = "sourceLine" id = "cb6-12" title = "12" > < span class = "dt" > int16_t< / span > pcm; < span class = "co" > // 1 for PCM format< / span > < / a >
< a class = "sourceLine" id = "cb6-13" title = "13" > < span class = "dt" > int16_t< / span > channels; < span class = "co" > // channels< / span > < / a >
< a class = "sourceLine" id = "cb6-14" title = "14" > < span class = "dt" > int32_t< / span > frequency; < span class = "co" > // sampling frequency< / span > < / a >
< a class = "sourceLine" id = "cb6-15" title = "15" > < span class = "dt" > int32_t< / span > bytes_per_second;< / a >
< a class = "sourceLine" id = "cb6-16" title = "16" > < span class = "dt" > int16_t< / span > bytes_by_capture;< / a >
< a class = "sourceLine" id = "cb6-17" title = "17" > < span class = "dt" > int16_t< / span > bits_per_sample;< / a >
< a class = "sourceLine" id = "cb6-18" title = "18" > < span class = "dt" > char< / span > data[< span class = "dv" > 4< / span > ]; < span class = "co" > // should always contain " data" < / span > < / a >
< a class = "sourceLine" id = "cb6-19" title = "19" > < span class = "dt" > int32_t< / span > bytes_in_data;< / a >
< a class = "sourceLine" id = "cb6-20" title = "20" > } __attribute__((__packed__));< / a >
< a class = "sourceLine" id = "cb6-21" title = "21" > < / a >
< a class = "sourceLine" id = "cb6-22" title = "22" > < span class = "dt" > int< / span > is_big_endian(< span class = "dt" > void< / span > ) {< / a >
< a class = "sourceLine" id = "cb6-23" title = "23" > < span class = "kw" > union< / span > {< / a >
< a class = "sourceLine" id = "cb6-24" title = "24" > < span class = "dt" > uint32_t< / span > i;< / a >
< a class = "sourceLine" id = "cb6-25" title = "25" > < span class = "dt" > char< / span > c[< span class = "dv" > 4< / span > ];< / a >
< a class = "sourceLine" id = "cb6-26" title = "26" > } bint = {< span class = "bn" > 0x01000000< / span > };< / a >
< a class = "sourceLine" id = "cb6-27" title = "27" > < span class = "cf" > return< / span > bint.c[< span class = "dv" > 0< / span > ]==< span class = "dv" > 1< / span > ;< / a >
< a class = "sourceLine" id = "cb6-28" title = "28" > }< / a >
< a class = "sourceLine" id = "cb6-29" title = "29" > < / a >
< a class = "sourceLine" id = "cb6-30" title = "30" > < span class = "dt" > int< / span > main(< span class = "dt" > int< / span > argc, < span class = "dt" > char< / span > *argv[]) {< / a >
< a class = "sourceLine" id = "cb6-31" title = "31" > < span class = "dt" > char< / span > *filename=argv[< span class = "dv" > 1< / span > ];< / a >
< a class = "sourceLine" id = "cb6-32" title = "32" > < span class = "dt" > FILE< / span > *wav = fopen(filename,< span class = "st" > " rb" < / span > );< / a >
< a class = "sourceLine" id = "cb6-33" title = "33" > < span class = "kw" > struct< / span > wavfile header;< / a >
< a class = "sourceLine" id = "cb6-34" title = "34" > < / a >
< a class = "sourceLine" id = "cb6-35" title = "35" > < span class = "cf" > if< / span > ( wav == NULL ) {< / a >
< a class = "sourceLine" id = "cb6-36" title = "36" > fprintf(stderr,< span class = "st" > " Can't open input file %s< / span > < span class = "sc" > \n< / span > < span class = "st" > " < / span > , filename);< / a >
< a class = "sourceLine" id = "cb6-37" title = "37" > exit(< span class = "dv" > 1< / span > );< / a >
< a class = "sourceLine" id = "cb6-38" title = "38" > }< / a >
< a class = "sourceLine" id = "cb6-39" title = "39" > < / a >
< a class = "sourceLine" id = "cb6-40" title = "40" > < span class = "co" > // read header< / span > < / a >
< a class = "sourceLine" id = "cb6-41" title = "41" > < span class = "cf" > if< / span > ( fread(& header,< span class = "kw" > sizeof< / span > (header),< span class = "dv" > 1< / span > ,wav) < < span class = "dv" > 1< / span > ) {< / a >
< a class = "sourceLine" id = "cb6-42" title = "42" > fprintf(stderr,< span class = "st" > " Can't read input file header %s< / span > < span class = "sc" > \n< / span > < span class = "st" > " < / span > , filename);< / a >
< a class = "sourceLine" id = "cb6-43" title = "43" > exit(< span class = "dv" > 1< / span > );< / a >
< a class = "sourceLine" id = "cb6-44" title = "44" > }< / a >
< a class = "sourceLine" id = "cb6-45" title = "45" > < / a >
< a class = "sourceLine" id = "cb6-46" title = "46" > < span class = "co" > // if wav file isn't the same endianness than the current environment< / span > < / a >
< a class = "sourceLine" id = "cb6-47" title = "47" > < span class = "co" > // we quit< / span > < / a >
< a class = "sourceLine" id = "cb6-48" title = "48" > < span class = "cf" > if< / span > ( is_big_endian() ) {< / a >
< a class = "sourceLine" id = "cb6-49" title = "49" > < span class = "cf" > if< / span > ( memcmp( header.id,< span class = "st" > " RIFX" < / span > , < span class = "dv" > 4< / span > ) != < span class = "dv" > 0< / span > ) {< / a >
< a class = "sourceLine" id = "cb6-50" title = "50" > fprintf(stderr,< span class = "st" > " ERROR: %s is not a big endian wav file< / span > < span class = "sc" > \n< / span > < span class = "st" > " < / span > , filename); < / a >
< a class = "sourceLine" id = "cb6-51" title = "51" > exit(< span class = "dv" > 1< / span > );< / a >
< a class = "sourceLine" id = "cb6-52" title = "52" > }< / a >
< a class = "sourceLine" id = "cb6-53" title = "53" > } < span class = "cf" > else< / span > {< / a >
< a class = "sourceLine" id = "cb6-54" title = "54" > < span class = "cf" > if< / span > ( memcmp( header.id,< span class = "st" > " RIFF" < / span > , < span class = "dv" > 4< / span > ) != < span class = "dv" > 0< / span > ) {< / a >
< a class = "sourceLine" id = "cb6-55" title = "55" > fprintf(stderr,< span class = "st" > " ERROR: %s is not a little endian wav file< / span > < span class = "sc" > \n< / span > < span class = "st" > " < / span > , filename); < / a >
< a class = "sourceLine" id = "cb6-56" title = "56" > exit(< span class = "dv" > 1< / span > );< / a >
< a class = "sourceLine" id = "cb6-57" title = "57" > }< / a >
< a class = "sourceLine" id = "cb6-58" title = "58" > }< / a >
< a class = "sourceLine" id = "cb6-59" title = "59" > < / a >
< a class = "sourceLine" id = "cb6-60" title = "60" > < span class = "cf" > if< / span > ( memcmp( header.wavefmt, < span class = "st" > " WAVEfmt " < / span > , < span class = "dv" > 8< / span > ) != < span class = "dv" > 0< / span > < / a >
< a class = "sourceLine" id = "cb6-61" title = "61" > || memcmp( header.data, < span class = "st" > " data" < / span > , < span class = "dv" > 4< / span > ) != < span class = "dv" > 0< / span > < / a >
< a class = "sourceLine" id = "cb6-62" title = "62" > ) {< / a >
< a class = "sourceLine" id = "cb6-63" title = "63" > fprintf(stderr,< span class = "st" > " ERROR: Not wav format< / span > < span class = "sc" > \n< / span > < span class = "st" > " < / span > ); < / a >
< a class = "sourceLine" id = "cb6-64" title = "64" > exit(< span class = "dv" > 1< / span > ); < / a >
< a class = "sourceLine" id = "cb6-65" title = "65" > }< / a >
< a class = "sourceLine" id = "cb6-66" title = "66" > < span class = "cf" > if< / span > (header.format != < span class = "dv" > 16< / span > ) {< / a >
< a class = "sourceLine" id = "cb6-67" title = "67" > fprintf(stderr,< span class = "st" > " < / span > < span class = "sc" > \n< / span > < span class = "st" > ERROR: not 16 bit wav format." < / span > );< / a >
< a class = "sourceLine" id = "cb6-68" title = "68" > exit(< span class = "dv" > 1< / span > );< / a >
< a class = "sourceLine" id = "cb6-69" title = "69" > }< / a >
< a class = "sourceLine" id = "cb6-70" title = "70" > fprintf(stderr,< span class = "st" > " format: %d bits" < / span > , header.format);< / a >
< a class = "sourceLine" id = "cb6-71" title = "71" > < span class = "cf" > if< / span > (header.format == < span class = "dv" > 16< / span > ) {< / a >
< a class = "sourceLine" id = "cb6-72" title = "72" > fprintf(stderr,< span class = "st" > " , PCM" < / span > );< / a >
< a class = "sourceLine" id = "cb6-73" title = "73" > } < span class = "cf" > else< / span > {< / a >
< a class = "sourceLine" id = "cb6-74" title = "74" > fprintf(stderr,< span class = "st" > " , not PCM (%d)" < / span > , header.format);< / a >
< a class = "sourceLine" id = "cb6-75" title = "75" > }< / a >
< a class = "sourceLine" id = "cb6-76" title = "76" > < span class = "cf" > if< / span > (header.pcm == < span class = "dv" > 1< / span > ) {< / a >
< a class = "sourceLine" id = "cb6-77" title = "77" > fprintf(stderr, < span class = "st" > " uncompressed" < / span > );< / a >
< a class = "sourceLine" id = "cb6-78" title = "78" > } < span class = "cf" > else< / span > {< / a >
< a class = "sourceLine" id = "cb6-79" title = "79" > fprintf(stderr, < span class = "st" > " compressed" < / span > );< / a >
< a class = "sourceLine" id = "cb6-80" title = "80" > }< / a >
< a class = "sourceLine" id = "cb6-81" title = "81" > fprintf(stderr,< span class = "st" > " , channel %d" < / span > , header.pcm);< / a >
< a class = "sourceLine" id = "cb6-82" title = "82" > fprintf(stderr,< span class = "st" > " , freq %d" < / span > , header.frequency );< / a >
< a class = "sourceLine" id = "cb6-83" title = "83" > fprintf(stderr,< span class = "st" > " , %d bytes per sec" < / span > , header.bytes_per_second );< / a >
< a class = "sourceLine" id = "cb6-84" title = "84" > fprintf(stderr,< span class = "st" > " , %d bytes by capture" < / span > , header.bytes_by_capture );< / a >
< a class = "sourceLine" id = "cb6-85" title = "85" > fprintf(stderr,< span class = "st" > " , %d bits per sample" < / span > , header.bytes_by_capture );< / a >
< a class = "sourceLine" id = "cb6-86" title = "86" > fprintf(stderr,< span class = "st" > " < / span > < span class = "sc" > \n< / span > < span class = "st" > " < / span > );< / a >
< a class = "sourceLine" id = "cb6-87" title = "87" > < / a >
< a class = "sourceLine" id = "cb6-88" title = "88" > < span class = "cf" > if< / span > ( memcmp( header.data, < span class = "st" > " data" < / span > , < span class = "dv" > 4< / span > ) != < span class = "dv" > 0< / span > ) { < / a >
< a class = "sourceLine" id = "cb6-89" title = "89" > fprintf(stderr,< span class = "st" > " ERROR: Prrroblem?< / span > < span class = "sc" > \n< / span > < span class = "st" > " < / span > ); < / a >
< a class = "sourceLine" id = "cb6-90" title = "90" > exit(< span class = "dv" > 1< / span > ); < / a >
< a class = "sourceLine" id = "cb6-91" title = "91" > }< / a >
< a class = "sourceLine" id = "cb6-92" title = "92" > fprintf(stderr,< span class = "st" > " wav format< / span > < span class = "sc" > \n< / span > < span class = "st" > " < / span > );< / a >
< a class = "sourceLine" id = "cb6-93" title = "93" > < / a >
< a class = "sourceLine" id = "cb6-94" title = "94" > < span class = "co" > // read data< / span > < / a >
< a class = "sourceLine" id = "cb6-95" title = "95" > < span class = "dt" > long< / span > < span class = "dt" > long< / span > sum=< span class = "dv" > 0< / span > ;< / a >
< a class = "sourceLine" id = "cb6-96" title = "96" > < span class = "dt" > int16_t< / span > value;< / a >
< a class = "sourceLine" id = "cb6-97" title = "97" > < span class = "dt" > int< / span > i=< span class = "dv" > 0< / span > ;< / a >
< a class = "sourceLine" id = "cb6-98" title = "98" > fprintf(stderr,< span class = "st" > " ---< / span > < span class = "sc" > \n< / span > < span class = "st" > " < / span > , value);< / a >
< a class = "sourceLine" id = "cb6-99" title = "99" > < span class = "cf" > while< / span > ( fread(& value,< span class = "kw" > sizeof< / span > (value),< span class = "dv" > 1< / span > ,wav) ) {< / a >
< a class = "sourceLine" id = "cb6-100" title = "100" > < span class = "cf" > if< / span > (value< < span class = "dv" > 0< / span > ) { value=-value; }< / a >
< a class = "sourceLine" id = "cb6-101" title = "101" > sum += value;< / a >
< a class = "sourceLine" id = "cb6-102" title = "102" > }< / a >
< a class = "sourceLine" id = "cb6-103" title = "103" > printf(< span class = "st" > " %lld< / span > < span class = "sc" > \n< / span > < span class = "st" > " < / span > ,sum);< / a >
< a class = "sourceLine" id = "cb6-104" title = "104" > exit(< span class = "dv" > 0< / span > );< / a >
< a class = "sourceLine" id = "cb6-105" title = "105" > }< / a > < / code > < / pre > < / div >
< p > < em > Edit(3)< / em > : On < a href = "http://reddit.com" > reddit< / a > < a href = "http://www.reddit.com/user/Bogdanp" > Bogdanp< / a > proposed a Python version:< / p >
< div class = "sourceCode" id = "cb7" > < pre class = "sourceCode python" > < code class = "sourceCode python" > < a class = "sourceLine" id = "cb7-1" title = "1" > < span class = "co" > #!/usr/bin/env python< / span > < / a >
< a class = "sourceLine" id = "cb7-2" title = "2" > < span class = "im" > from< / span > struct < span class = "im" > import< / span > calcsize, unpack< / a >
< a class = "sourceLine" id = "cb7-3" title = "3" > < span class = "im" > from< / span > sys < span class = "im" > import< / span > argv, exit< / a >
< a class = "sourceLine" id = "cb7-4" title = "4" > < / a >
< a class = "sourceLine" id = "cb7-5" title = "5" > < span class = "kw" > def< / span > word_iter(f):< / a >
< a class = "sourceLine" id = "cb7-6" title = "6" > < span class = "cf" > while< / span > < span class = "va" > True< / span > :< / a >
< a class = "sourceLine" id = "cb7-7" title = "7" > _bytes < span class = "op" > =< / span > f.read(< span class = "dv" > 2< / span > )< / a >
< a class = "sourceLine" id = "cb7-8" title = "8" > < / a >
< a class = "sourceLine" id = "cb7-9" title = "9" > < span class = "cf" > if< / span > < span class = "bu" > len< / span > (_bytes) < span class = "op" > !=< / span > < span class = "dv" > 2< / span > :< / a >
< a class = "sourceLine" id = "cb7-10" title = "10" > < span class = "cf" > raise< / span > < span class = "pp" > StopIteration< / span > < / a >
< a class = "sourceLine" id = "cb7-11" title = "11" > < / a >
< a class = "sourceLine" id = "cb7-12" title = "12" > < span class = "cf" > yield< / span > unpack(< span class = "st" > " =h" < / span > , _bytes)[< span class = "dv" > 0< / span > ]< / a >
< a class = "sourceLine" id = "cb7-13" title = "13" > < / a >
< a class = "sourceLine" id = "cb7-14" title = "14" > < span class = "cf" > try< / span > :< / a >
< a class = "sourceLine" id = "cb7-15" title = "15" > < span class = "cf" > with< / span > < span class = "bu" > open< / span > (argv[< span class = "dv" > 1< / span > ], < span class = "st" > " rb" < / span > ) < span class = "im" > as< / span > f:< / a >
< a class = "sourceLine" id = "cb7-16" title = "16" > wav < span class = "op" > =< / span > < span class = "st" > " =4ci8cihhiihh4ci" < / span > < / a >
< a class = "sourceLine" id = "cb7-17" title = "17" > wav_size < span class = "op" > =< / span > calcsize(wav)< / a >
< a class = "sourceLine" id = "cb7-18" title = "18" > metadata < span class = "op" > =< / span > unpack(wav, f.read(wav_size))< / a >
< a class = "sourceLine" id = "cb7-19" title = "19" > < / a >
< a class = "sourceLine" id = "cb7-20" title = "20" > < span class = "cf" > if< / span > < span class = "st" > " " < / span > .join(metadata[:< span class = "dv" > 4< / span > ]) < span class = "op" > !=< / span > < span class = "st" > " RIFF" < / span > :< / a >
< a class = "sourceLine" id = "cb7-21" title = "21" > < span class = "bu" > print< / span > < span class = "st" > " error: not wav file." < / span > < / a >
< a class = "sourceLine" id = "cb7-22" title = "22" > exit(< span class = "dv" > 1< / span > )< / a >
< a class = "sourceLine" id = "cb7-23" title = "23" > < / a >
< a class = "sourceLine" id = "cb7-24" title = "24" > < span class = "bu" > print< / span > < span class = "bu" > sum< / span > (< span class = "bu" > abs< / span > (word) < span class = "cf" > for< / span > word < span class = "kw" > in< / span > word_iter(f))< / a >
< a class = "sourceLine" id = "cb7-25" title = "25" > < span class = "cf" > except< / span > < span class = "pp" > IOError< / span > :< / a >
< a class = "sourceLine" id = "cb7-26" title = "26" > < span class = "bu" > print< / span > < span class = "st" > " error: can't open input file '< / span > < span class = "sc" > %s< / span > < span class = "st" > '." < / span > < span class = "op" > %< / span > argv[< span class = "dv" > 1< / span > ]< / a >
< a class = "sourceLine" id = "cb7-27" title = "27" > exit(< span class = "dv" > 1< / span > )< / a > < / code > < / pre > < / div >
< p > and < a href = "http://www.reddit.com/user/luikore" > luikore< / a > proposed an impressive Ruby version:< / p >
< div class = "sourceCode" id = "cb8" > < pre class = "sourceCode ruby" > < code class = "sourceCode ruby" > < a class = "sourceLine" id = "cb8-1" title = "1" > data = < span class = "dt" > ARGF< / span > .read< / a >
< a class = "sourceLine" id = "cb8-2" title = "2" > keys =< span class = "ot" > %w[< / span > < span class = "st" > id totallength wavefmt format< / span > < / a >
< a class = "sourceLine" id = "cb8-3" title = "3" > < span class = "st" > pcm channels frequency bytes_per_second< / span > < / a >
< a class = "sourceLine" id = "cb8-4" title = "4" > < span class = "st" > bytes_by_capture bits_per_sample< / span > < / a >
< a class = "sourceLine" id = "cb8-5" title = "5" > < span class = "st" > data bytes_in_data sum< / span > < / a >
< a class = "sourceLine" id = "cb8-6" title = "6" > < span class = "st" > < / span > < span class = "ot" > ]< / span > < / a >
< a class = "sourceLine" id = "cb8-7" title = "7" > values = data.unpack < span class = "st" > 'Z4 i Z8 i s s i i s s Z4 i s*'< / span > < / a >
< a class = "sourceLine" id = "cb8-8" title = "8" > sum = values.drop(< span class = "dv" > 12< / span > ).map(& < span class = "st" > :abs< / span > ).inject(:+)< / a >
< a class = "sourceLine" id = "cb8-9" title = "9" > keys.zip(values.take(< span class = "dv" > 12< / span > ) < < sum) {|k, v|< / a >
< a class = "sourceLine" id = "cb8-10" title = "10" > puts < span class = "st" > " < / span > < span class = "ot" > #{< / span > k.ljust < span class = "dv" > 17< / span > < span class = "ot" > }< / span > < span class = "st" > : < / span > < span class = "ot" > #{< / span > v< span class = "ot" > }< / span > < span class = "st" > " < / span > < / a >
< a class = "sourceLine" id = "cb8-11" title = "11" > }< / a > < / code > < / pre > < / div >
< / div >
< div id = "afterarticle" >
< div id = "social" >
2021-05-25 20:25:47 +00:00
< a href = "/rss.xml" target = "_blank" rel = "noopener noreferrer nofollow" class = "social" > RSS< / a >
2021-04-18 10:23:24 +00:00
·
< a href = "https://twitter.com/home?status=http%3A%2F%2Fyannesposito.com/Scratch/en/blog/2010-10-14-Fun-with-wav/%20via%20@yogsototh" target = "_blank" rel = "noopener noreferrer nofollow" class = "social" > Tweet< / a >
·
< a href = "http://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Fyannesposito.com/Scratch/en/blog/2010-10-14-Fun-with-wav/" target = "_blank" rel = "noopener noreferrer nofollow" class = "social" > FB< / a >
< br / >
< a class = "message" href = "../../../../Scratch/en/blog/Social-link-the-right-way/" > These social sharing links preserve your privacy< / a >
< / div >
< div id = "navigation" >
< a href = "../../../../" > Home< / a >
< span class = "sep" > ¦< / span >
< a href = "../../../../Scratch/en/blog" > Blog< / a >
< span class = "sep" > ¦< / span >
< a href = "../../../../Scratch/en/softwares" > Softwares< / a >
< span class = "sep" > ¦< / span >
< a href = "../../../../Scratch/en/about" > About< / a >
< / div >
< div id = "totop" > < a href = "#header" > ↑ Top ↑< / a > < / div >
< div id = "bottom" >
< div >
Published on 2010-10-14
< / div >
< div >
< a href = "https://twitter.com/yogsototh" > Follow @yogsototh< / a >
< / div >
< div >
< a rel = "license" href = "http://creativecommons.org/licenses/by/3.0/deed.en_US" > Yann Esposito©< / a >
< / div >
< div >
Done with
< a href = "http://www.vim.org" target = "_blank" rel = "noopener noreferrer nofollow" > < strike > Vim< / strike > < / a >
< a href = "http://spacemacs.org" target = "_blank" rel = "noopener noreferrer nofollow" > spacemacs< / a >
< span class = "pala" > & < / span >
< a href = "http://nanoc.ws" target = "_blank" rel = "noopener noreferrer nofollow" > < strike > nanoc< / strike > < / a >
< a href = "http://jaspervdj.be/hakyll" target = "_blank" rel = "noopener noreferrer nofollow" > Hakyll< / a >
< / div >
< hr / >
< div style = "max-width: 100%" >
< a href = "https://cardanohub.org" >
< img src = "../../../../Scratch/img/ada-logo.png" class = "simple" style = "height: 16px ;
border-radius: 50%;
vertical-align:middle;
display:inline-block;" />
ADA:
< / a >
< code style = "display:inline-block;
word-wrap:break-word;
text-align: left;
vertical-align: top;
max-width: 85%;">
DdzFFzCqrhtAvdkmATx5Fm8NPJViDy85ZBw13p4XcNzVzvQg8e3vWLXq23JQWFxPEXK6Kvhaxxe7oJt4VMYHxpA2vtCFiP8fziohN6Yp
< / code >
< / div >
< / div >
< / div >
< / div >
< / div >
< / body >
< / html >