changeset 6304:78a3254741b2

[project @ 2007-02-14 21:22:59 by jwe]
author jwe
date Wed, 14 Feb 2007 21:22:59 +0000
parents df89e87a1d2e
children 48f8af442b8a
files scripts/ChangeLog scripts/audio/wavread.m scripts/audio/wavwrite.m
diffstat 3 files changed, 69 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ChangeLog	Tue Feb 13 09:11:53 2007 +0000
+++ b/scripts/ChangeLog	Wed Feb 14 21:22:59 2007 +0000
@@ -1,3 +1,8 @@
+2007-02-14  Thomas Weber  <thomas.weber.mail@gmail.com>
+
+	* audio/wavread.m, audio/wavwrite.m: Use types with specific sizes
+	for reading and writing data.  New tests.  Improve rounding.
+
 2007-02-13  John W. Eaton  <jwe@octave.org>
 
 	* plot/stem.m: New file, adapted from OctPlot.
--- a/scripts/audio/wavread.m	Tue Feb 13 09:11:53 2007 +0000
+++ b/scripts/audio/wavread.m	Wed Feb 14 21:22:59 2007 +0000
@@ -84,24 +84,24 @@
   endwhile
 
   ## format chunk size
-  ck_size = fread (fid, 1, "ulong", 0, BYTEORDER);         
+  ck_size = fread (fid, 1, "uint32", 0, BYTEORDER);         
   
   ## sample format code
-  format_tag = fread (fid, 1, "short", 0, BYTEORDER);
+  format_tag = fread (fid, 1, "uint16", 0, BYTEORDER);
   if (format_tag != FORMAT_PCM && format_tag != FORMAT_IEEE_FLOAT)
     fclose (fid);
     error ("wavread: sample format %#x is not supported", format_tag);
   endif
 
   ## number of interleaved channels  
-  channels = fread (fid, 1, "short", 0, BYTEORDER);
+  channels = fread (fid, 1, "uint16", 0, BYTEORDER);
 
   ## sample rate
-  samples_per_sec = fread (fid, 1, "ulong", 0, BYTEORDER);
+  samples_per_sec = fread (fid, 1, "uint32", 0, BYTEORDER);
 
   ## bits per sample
   fseek (fid, 6, SEEK_CUR);
-  bits_per_sample = fread (fid, 1, "short", 0, BYTEORDER);
+  bits_per_sample = fread (fid, 1, "uint16", 0, BYTEORDER);
 
   ## ignore the rest of the chunk
   fseek (fid, ck_size-16, SEEK_CUR);
@@ -119,7 +119,7 @@
   end
 
   ## data chunk size
-  ck_size = fread (fid, 1, "ulong", 0, BYTEORDER);
+  ck_size = fread (fid, 1, "uint32", 0, BYTEORDER);
   
   ## determine sample data type
   if (format_tag == FORMAT_PCM)
@@ -134,7 +134,8 @@
         format = "int32";
       otherwise
         fclose (fid);
-        error ("wavread: %d bits sample resolution is not supported with PCM", bits_per_sample);
+        error ("wavread: %d bits sample resolution is not supported with PCM",
+	       bits_per_sample);
     endswitch
   else
     switch (bits_per_sample)
@@ -144,7 +145,8 @@
         format = "float64";
       otherwise
         fclose (fid);
-        error ("wavread: %d bits sample resolution is not supported with IEEE float", bits_per_sample);
+        error ("wavread: %d bits sample resolution is not supported with IEEE float",
+	       bits_per_sample);
     endswitch
   endif
   
@@ -179,6 +181,12 @@
   [yi, n] = fread (fid, length, format, 0, BYTEORDER);
   fclose (fid);
 
+  ## check data
+  if (mod (numel (yi), channels) != 0)
+    error ("wavread: data in %s doesn't match the number of channels",
+	   filename);
+  endif
+
   if (bits_per_sample == 24)
     yi = reshape (yi, 3, rows(yi)/3)';
     yi(yi(:,3) >= 128, 3) -= 256;
--- a/scripts/audio/wavwrite.m	Tue Feb 13 09:11:53 2007 +0000
+++ b/scripts/audio/wavwrite.m	Wed Feb 14 21:22:59 2007 +0000
@@ -42,17 +42,23 @@
     print_usage ();
   endif
 
+  ## test arguments
+  if (columns (y) < 1)
+    error ("wavwrite: Y must have at least one column");
+  endif
+  if (columns (y) > 2^15-1)
+    error ("wavwrite: Y has more than 32767 columns (too many for a WAV-file)");
+  endif
+
   ## parse arguments
   if (nargin < 3)
-    warning ("wavwrite: sample rate set to 8000 Hz");
     samples_per_sec = 8000;
   endif
 
   if (nargin < 4)
-    warning ("wavwrite: sample resolution set to 16-bit");
     bits_per_sample = 16;
   endif
-  
+
   ## determine sample format
   switch (bits_per_sample)
     case 8  
@@ -62,12 +68,11 @@
     case 32 
       format = "int32";
     otherwise
-      error ("wavread: sample resolution not supported");
+      error ("wavwrite: sample resolution not supported");
   endswitch
   
   ## calculate filesize
-  channels = size(y)(2);
-  n = size(y)(1);
+  [n, channels] = size(y);
 
   ## size of data chunk
   ck_size = n*channels*(bits_per_sample/8);
@@ -88,35 +93,35 @@
   c += fwrite (fid, "RIFF", "uchar");
 
   ## file size - 8
-  c += fwrite (fid, ck_size + 36, "ulong", 0, BYTEORDER);
+  c += fwrite (fid, ck_size + 36, "uint32", 0, BYTEORDER);
   c += fwrite (fid, "WAVEfmt ", "uchar");
 
   ## size of fmt chunk
-  c += fwrite (fid, 16, "ulong", 0, BYTEORDER);
+  c += fwrite (fid, 16, "uint32", 0, BYTEORDER);
 
   ## sample format code (PCM)
-  c += fwrite (fid, 0x0001, "short", 0, BYTEORDER);
+  c += fwrite (fid, 1, "uint16", 0, BYTEORDER);
 
   ## channels
-  c += fwrite (fid, channels, "short", 0, BYTEORDER);
+  c += fwrite (fid, channels, "uint16", 0, BYTEORDER);
 
   ## sample rate
-  c += fwrite (fid, samples_per_sec, "ulong", 0, BYTEORDER);
+  c += fwrite (fid, samples_per_sec, "uint32", 0, BYTEORDER);
 
   ## bytes per second
   bps = samples_per_sec*channels*bits_per_sample/8;
-  c += fwrite (fid, bps, "ulong", 0, BYTEORDER);
+  c += fwrite (fid, bps, "uint32", 0, BYTEORDER);
 
   ## block align
-  c += fwrite (fid, channels*bits_per_sample/8, "short", 0, BYTEORDER);
+  c += fwrite (fid, channels*bits_per_sample/8, "uint16", 0, BYTEORDER);
 
-  c += fwrite (fid, bits_per_sample, "short", 0, BYTEORDER);   
+  c += fwrite (fid, bits_per_sample, "uint16", 0, BYTEORDER);   
   c += fwrite (fid, "data", "uchar");
-  c += fwrite (fid, ck_size, "ulong", 0, BYTEORDER);
+  c += fwrite (fid, ck_size, "uint32", 0, BYTEORDER);
   
   if (c < 25)
     fclose (fid);
-    error ("wavread: writing to file failed");
+    error ("wavwrite: writing to file failed");
   endif
   
   ## interleave samples
@@ -125,11 +130,11 @@
   ## scale samples
   switch (bits_per_sample)
     case 8
-      yi = round (yi*127.5 + 127.5);
+      yi = round (yi*128 + 128);
     case 16
-      yi = floor (yi*32767.5);
+      yi = round (yi*32768);
     case 32
-      yi = floor (yi*2147483647.5);
+      yi = round (yi*2147483648);
   endswitch
   
   ## write to file
@@ -138,3 +143,27 @@
   fclose (fid);
   
 endfunction
+
+%!test
+%! A = [1:10; 1:10]/10;
+%! wavwrite("a.wav", A);
+%! [B, samples_per_sec, bits_per_sample] = wavread("a.wav");
+%! assert(A,B, 10^(-4));
+%! assert(samples_per_sec, 8000);
+%! assert(bits_per_sample, 16);
+%
+%!test
+%! A=[1:10; 1:10] / 10;
+%! wavwrite("a.wav", A, 4000);
+%! [B, samples_per_sec, bits_per_sample] = wavread("a.wav");
+%! assert(A,B, 10^(-4));
+%! assert(samples_per_sec, 4000);
+%! assert(bits_per_sample, 16);
+%
+%!test
+%! A=[1:10; 1:10] / 10;
+%! wavwrite("a.wav", A, 4000, 8);
+%! [B, samples_per_sec, bits_per_sample] = wavread("a.wav");
+%! assert(A,B, 10^(-2));
+%! assert(samples_per_sec, 4000);
+%! assert(bits_per_sample, 8);