changeset 19577:5f313345912f

avoid indexing before beginning of string * load-path.cc (load_path::do_find_matching_dirs): Avoid indexing before beginning of string.
author John W. Eaton <jwe@octave.org>
date Wed, 07 Jan 2015 18:07:12 -0500
parents b9cb664404b9
children 827394ba8eb2
files libinterp/corefcn/load-path.cc libinterp/dldfcn/audiodevinfo.cc libinterp/dldfcn/audioread.cc
diffstat 3 files changed, 334 insertions(+), 124 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/load-path.cc	Wed Jan 07 18:02:17 2015 -0500
+++ b/libinterp/corefcn/load-path.cc	Wed Jan 07 18:07:12 2015 -0500
@@ -1430,7 +1430,7 @@
 
           size_t dir_len = dir.length ();
 
-          if (dname_len >= dir_len
+          if (dname_len > dir_len
               && file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
               && dir.compare (dname.substr (dname_len - dir_len)) == 0)
             {
--- a/libinterp/dldfcn/audiodevinfo.cc	Wed Jan 07 18:02:17 2015 -0500
+++ b/libinterp/dldfcn/audiodevinfo.cc	Wed Jan 07 18:07:12 2015 -0500
@@ -458,8 +458,8 @@
   void set_y (octave_function *fn);
   void set_y (std::string fn);
   Matrix& get_y (void);
-  RowVector *get_left (void);
-  RowVector *get_right (void);
+  RowVector get_left (void) const;
+  RowVector get_right (void) const;
   void set_fs (int fs);
   int get_fs (void);
   void set_nbits (int nbits);
@@ -510,7 +510,7 @@
   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
 };
 
-#define BUFFER_SIZE 512
+#define BUFFER_SIZE 8192
 
 DEFINE_OCTAVE_ALLOCATOR (audioplayer);
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (audioplayer, "audioplayer", "audioplayer");
@@ -532,66 +532,125 @@
                       PaStreamCallbackFlags, void *data)
 {
   audioplayer *player = static_cast<audioplayer *> (data);
-  int big_endian = is_big_endian ();
-  octave_value_list args, retval;
-  args(0) = frames;
-  retval = feval (player->octave_callback_function, args, 1);
-  RowVector sound_l, sound_r;
+
+  if (! player)
+    {
+      error ("audio player callback function called without player");
+      return paAbort;
+    }
+  
+  octave_value_list retval = feval (player->octave_callback_function,
+                                    ovl (static_cast<double> (frames)), 1);
+
+  if (error_state || retval.length () < 2)
+    {
+      error ("audio player callback function failed");
+      return paAbort;
+    }
+  
   Matrix sound = retval(0).matrix_value ();
   int return_status = retval(1).int_value ();
-  sound_l.resize (frames);
-  sound_r.resize (frames);
-  if (sound.cols () == 1)
+
+  if (error_state || frames != sound.rows ()
+      || sound.columns () < 1 || sound.columns () > 2)
     {
-      for (unsigned long i = 0; i < frames; i++)
-        {
-          sound_l(i) = sound(i, 0);
-          sound_r(i) = sound(i, 0);
-        }
+      error ("audio player callback function failed");
+      return paAbort;
     }
-  else if (sound.cols () == 2)
+
+  double scale_factor = 1.0;
+
+  switch (player->get_nbits ())
     {
-      for (unsigned long i = 0; i < frames; i++)
-        {
-          sound_l(i) = sound(i, 0);
-          sound_r(i) = sound(i, 1);
-        }
+    case 8:
+      scale_factor = pow (2.0, 7) - 1.0;
+      break;
+
+    case 16:
+      scale_factor = pow (2.0, 15) - 1.0;
+      break;
+
+    case 24:
+      scale_factor = pow (2.0, 23) - 1.0;
+      break;
+
+    default:
+      error ("invalid player bit depth in callback function");
+      break;
     }
-  else
-    return paAbort;
-
-  for (unsigned long i = 0; i < frames; i++)
+
+  sound = sound * scale_factor;
+
+  const RowVector sound_l = (sound.column (0)).transpose ();
+
+  const RowVector sound_r = (sound.columns () == 1)
+    ? sound_l : (sound.column (1)).transpose ();
+
+  const double *p_l = sound_l.data ();
+  const double *p_r = sound_r.data ();
+
+  switch (player->get_nbits ())
     {
-      if (player->get_nbits () == 8)
-        {
-          int8_t *buffer = static_cast<int8_t *> (output);
-          buffer[2 * i] = sound_l.elem (i) * (pow (2.0, 7) - 1);
-          buffer[2 * i + 1] = sound_r.elem (i) * (pow (2.0, 7) - 1);
-        }
-      else if (player->get_nbits () == 16)
-        {
-          int16_t *buffer = static_cast<int16_t *> (output);
-          buffer[2 * i] = sound_l.elem (i) * (pow (2.0, 15) - 1);
-          buffer[2 * i + 1] = sound_r.elem (i) * (pow (2.0, 15) - 1);
-        }
-      else if (player->get_nbits () == 24)
-        {
-          uint8_t *buffer = static_cast<uint8_t *> (output);
-          int32_t sample_l = sound_l.elem (i) * (pow (2.0, 23) - 1);
-          int32_t sample_r = sound_r.elem (i) * (pow (2.0, 23) - 1);
-          sample_l &= 0x00ffffff;
-          sample_r &= 0x00ffffff;
-          // FIXME: Would a mask work better?
-          uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);
-          uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);
-          buffer[i * 6 + 0] = _sample_l[0 + big_endian];
-          buffer[i * 6 + 1] = _sample_l[1 + big_endian];
-          buffer[i * 6 + 2] = _sample_l[2 + big_endian];
-          buffer[i * 6 + 3] = _sample_r[0 + big_endian];
-          buffer[i * 6 + 4] = _sample_r[1 + big_endian];
-          buffer[i * 6 + 5] = _sample_r[2 + big_endian];
-        }
+    case 8:
+      {
+        int8_t *buffer = static_cast<int8_t *> (output);
+
+        for (unsigned long i = 0; i < frames; i++)
+          {
+            buffer[2*i] = p_l[i];
+            buffer[2*i+1] = p_r[i];
+          }
+      }
+      break;
+
+    case 16:
+      {
+        int16_t *buffer = static_cast<int16_t *> (output);
+
+        for (unsigned long i = 0; i < frames; i++)
+          {
+            buffer[2*i] = p_l[i];
+            buffer[2*i+1] = p_r[i];
+          }
+      }
+      break;
+
+    case 24:
+      {
+        int big_endian = is_big_endian ();
+
+        uint8_t *buffer = static_cast<uint8_t *> (output);
+
+        for (unsigned long i = 0; i < frames; i++)
+          {
+            int32_t sample_l = p_l[i];
+            int32_t sample_r = p_r[i];
+
+            sample_l &= 0x00ffffff;
+            sample_r &= 0x00ffffff;
+
+            // FIXME: Would a mask work better?
+            uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);
+            uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);
+
+            unsigned long offset = i * 6;
+
+            buffer[offset+0] = _sample_l[0+big_endian];
+            buffer[offset+1] = _sample_l[1+big_endian];
+            buffer[offset+2] = _sample_l[2+big_endian];
+
+            buffer[offset+3] = _sample_r[0+big_endian];
+            buffer[offset+4] = _sample_r[1+big_endian];
+            buffer[offset+5] = _sample_r[2+big_endian];
+          }
+      }
+      break;
+
+    default:
+      error ("invalid player bit depth in callback function");
+      break;
     }
+
   return return_status;
 }
 
@@ -601,74 +660,187 @@
                          PaStreamCallbackFlags, void *data)
 {
   audioplayer *player = static_cast<audioplayer *> (data);
-  int big_endian = is_big_endian ();
-  int channels = player->get_channels ();
-  RowVector *sound_l = player->get_left ();
-  RowVector *sound_r;
-
-  if (channels > 1)
-    sound_r = player->get_right ();
-  else
-    sound_r = sound_l;
-
-  for (unsigned long j = 0, k = 0; j < frames; j++, k += 2)
+
+  if (! player)
+    {
+      error ("audio player callback function called without player");
+      return paAbort;
+    }
+  
+  double scale_factor = 1.0;
+
+  switch (player->get_nbits ())
     {
-      unsigned int sample_number = player->get_sample_number ();
-      if (sample_number > player->get_end_sample ())
-        return paAbort;
-
-      if (player->get_type () == DOUBLE)
+    case 8:
+      scale_factor = pow (2.0, 7) - 1.0;
+      break;
+
+    case 16:
+      scale_factor = pow (2.0, 15) - 1.0;
+      break;
+
+    case 24:
+      scale_factor = pow (2.0, 23) - 1.0;
+      break;
+
+    default:
+      error ("invalid player bit depth in callback function");
+      break;
+    }
+
+  const RowVector sound_l = player->get_left () * scale_factor;
+  const RowVector sound_r = player->get_right () * scale_factor;
+
+  const double *pl = sound_l.data ();
+  const double *pr = sound_l.data ();
+
+  if (player->get_type () == DOUBLE)
+    {
+      switch (player->get_nbits ())
         {
-          if (player->get_nbits () == 8)
-            {
-              int8_t *buffer = static_cast<int8_t *> (output);
-              buffer[k] = sound_l->elem (sample_number) * (pow (2.0, 7) - 1);
-              buffer[k + 1] = sound_r->elem (sample_number) * (pow (2.0, 7) - 1);
-            }
-          else if (player->get_nbits () == 16)
-            {
-              int16_t *buffer = static_cast<int16_t *> (output);
-              buffer[k] = sound_l->elem (sample_number) * (pow (2.0, 15) - 1);
-              buffer[k + 1] = sound_r->elem (sample_number) * (pow (2.0, 15) - 1);
-            }
-          else if (player->get_nbits () == 24)
-            {
-              uint8_t *buffer = static_cast<uint8_t *> (output);
-              int32_t sample_l = sound_l->elem (sample_number) * (pow (2.0, 23) - 1);
-              int32_t sample_r = sound_r->elem (sample_number) * (pow (2.0, 23) - 1);
-              sample_l &= 0x00ffffff;
-              sample_r &= 0x00ffffff;
-              // FIXME: Would a mask work better?
-              uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);
-              uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);
-              buffer[j * 6 + 0] = _sample_l[0 + big_endian];
-              buffer[j * 6 + 1] = _sample_l[1 + big_endian];
-              buffer[j * 6 + 2] = _sample_l[2 + big_endian];
-              buffer[j * 6 + 3] = _sample_r[0 + big_endian];
-              buffer[j * 6 + 4] = _sample_r[1 + big_endian];
-              buffer[j * 6 + 5] = _sample_r[2 + big_endian];
-            }
+        case 8:
+          {
+            int8_t *buffer = static_cast<int8_t *> (output);
+
+            for (unsigned long j = 0; j < frames; j++)
+              {
+                unsigned int sample_number = player->get_sample_number ();
+
+                if (sample_number >= player->get_end_sample ())
+                  return paComplete;
+
+                unsigned long offset = j * 2;
+
+                buffer[offset+0] = pl[sample_number];
+                buffer[offset+1] = pr[sample_number];
+
+                player->set_sample_number (sample_number + 1);
+              }
+          }
+          break;
+
+        case 16:
+          {
+            int16_t *buffer = static_cast<int16_t *> (output);
+
+            for (unsigned long j = 0; j < frames; j++)
+              {
+                unsigned int sample_number = player->get_sample_number ();
+
+                if (sample_number >= player->get_end_sample ())
+                  return paComplete;
+
+                unsigned long offset = j * 2;
+
+                buffer[offset+0] = pl[sample_number];
+                buffer[offset+1] = pr[sample_number];
+
+                player->set_sample_number (sample_number + 1);
+              }
+          }
+          break;
+
+        case 24:
+          {
+            uint8_t *buffer = static_cast<uint8_t *> (output);
+
+            for (unsigned long j = 0; j < frames; j++)
+              {
+                unsigned int sample_number = player->get_sample_number ();
+
+                if (sample_number >= player->get_end_sample ())
+                  return paComplete;
+
+                int32_t sample_l = pl[sample_number];
+                int32_t sample_r = pr[sample_number];
+
+                sample_l &= 0x00ffffff;
+                sample_r &= 0x00ffffff;
+
+                int big_endian = is_big_endian ();
+
+                // FIXME: Would a mask work better?
+                uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l);
+                uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r);
+
+                unsigned long offset = j * 6;
+
+                buffer[offset+0] = _sample_l[0+big_endian];
+                buffer[offset+1] = _sample_l[1+big_endian];
+                buffer[offset+2] = _sample_l[2+big_endian];
+
+                buffer[offset+3] = _sample_r[0+big_endian];
+                buffer[offset+4] = _sample_r[1+big_endian];
+                buffer[offset+5] = _sample_r[2+big_endian];
+
+                player->set_sample_number (sample_number + 1);
+              }
+          }
+          break;
+
+        default:
+          error ("invalid player bit depth in callback function");
+          break;
         }
-      else if (player->get_type () == INT8)
+    }
+  else if (player->get_type () == INT8)
+    {
+      int8_t *buffer = static_cast<int8_t *> (output);
+
+      for (unsigned long j = 0; j < frames; j++)
         {
-          int8_t *buffer = static_cast<int8_t *> (output);
-          buffer[k] = sound_l->elem (sample_number);
-          buffer[k + 1] = sound_r->elem (sample_number);
+          unsigned int sample_number = player->get_sample_number ();
+
+          if (sample_number >= player->get_end_sample ())
+            return paComplete;
+
+          unsigned long offset = j * 2;
+
+          buffer[offset+0] = pl[sample_number];
+          buffer[offset+1] = pr[sample_number];
+
+          player->set_sample_number (sample_number + 1);
         }
-      else if (player->get_type () == UINT8)
+    }
+  else if (player->get_type () == UINT8)
+    {
+      uint8_t *buffer = static_cast<uint8_t *> (output);
+
+      for (unsigned long j = 0; j < frames; j++)
         {
-          uint8_t *buffer = static_cast<uint8_t *> (output);
-          buffer[k] = sound_l->elem (sample_number);
-          buffer[k + 1] = sound_r->elem (sample_number);
+          unsigned int sample_number = player->get_sample_number ();
+
+          if (sample_number >= player->get_end_sample ())
+            return paComplete;
+
+          unsigned long offset = j * 2;
+
+          buffer[offset+0] = pl[sample_number];
+          buffer[offset+1] = pr[sample_number];
+
+          player->set_sample_number (sample_number + 1);
         }
-      else if (player->get_type () == INT16)
+    }
+  else if (player->get_type () == INT16)
+    {
+      int16_t *buffer = static_cast<int16_t *> (output);
+
+      for (unsigned long j = 0; j < frames; j++)
         {
-          int16_t *buffer = static_cast<int16_t *> (output);
-          buffer[k] = sound_l->elem (sample_number);
-          buffer[k + 1] = sound_r->elem (sample_number);
+          unsigned int sample_number = player->get_sample_number ();
+
+          if (sample_number >= player->get_end_sample ())
+            return paComplete;
+
+          unsigned long offset = j * 2;
+
+          buffer[offset+0] = pl[sample_number];
+          buffer[offset+1] = pr[sample_number];
+
+          player->set_sample_number (sample_number + 1);
         }
-      player->set_sample_number (sample_number + 1);
     }
+
   return paContinue;
 }
 
@@ -801,16 +973,16 @@
   return y;
 }
 
-RowVector *
-audioplayer::get_left (void)
+RowVector
+audioplayer::get_left (void) const
 {
-  return &(left);
+  return left;
 }
 
-RowVector *
-audioplayer::get_right (void)
+RowVector
+audioplayer::get_right (void) const
 {
-  return &(right);
+  return channels == 1 ? left : right;
 }
 
 void
@@ -2178,6 +2350,12 @@
 
   int nargin = args.length ();
 
+  if (nargin < 2)
+    {
+      print_usage ();
+      return retval;
+    }
+
   audioplayer* recorder = new audioplayer ();
 
   bool is_function = args(0).is_string () || args(0).is_function_handle () || args(0).is_inline_function ();
@@ -2194,6 +2372,7 @@
     case 3:
       recorder->set_nbits (args(2).int_value ());
       break;
+
     case 4:
       recorder->set_nbits (args(2).int_value ());
       recorder->set_id (args(3).int_value ());
--- a/libinterp/dldfcn/audioread.cc	Wed Jan 07 18:02:17 2015 -0500
+++ b/libinterp/dldfcn/audioread.cc	Wed Jan 07 18:07:12 2015 -0500
@@ -24,6 +24,8 @@
 #include <config.h>
 #endif
 
+#define BOUNDS_CHECKING 1
+
 #include <string>
 #include <map>
 
@@ -247,14 +249,19 @@
   SNDFILE *file;
   SF_INFO info;
 
+  memset (&info, 0, sizeof (info));
+
   OCTAVE_LOCAL_BUFFER (float, data, audio.rows () * audio.cols ());
 
-  for (int i = 0; i < audio.cols (); i++)
+  size_t idx = 0;
+  for (octave_idx_type j = 0; j < audio.rows (); j++)
     {
-      for (int j = 0; j < audio.rows (); j++)
-        data[j * audio.cols () + i] = audio(j, i);
+      for (octave_idx_type i = 0; i < audio.cols (); i++)
+        data[idx++] = audio(j, i);
     }
 
+  std::cerr << "idx: " << idx << std::endl;
+
   if (extension == "ogg")
     info.format = SF_FORMAT_VORBIS;
   else
@@ -308,6 +315,14 @@
   info.channels = audio.cols ();
   info.format |= extension_to_format[extension];
 
+  std::cerr << extension << std::endl;
+  std::cerr << extension_to_format[extension] << std::endl;
+  std::cerr << info.format << std::endl;
+  std::cerr << SF_FORMAT_OGG << std::endl;
+  std::cerr << SF_FORMAT_VORBIS << std::endl;
+
+  //  info.format = SF_FORMAT_OGG;
+
   file = sf_open (filename.c_str (), SFM_WRITE, &info);
 
   if (title != "")
@@ -319,9 +334,24 @@
   if (comment != "")
     sf_set_string (file, SF_STR_COMMENT, comment.c_str ());
 
-  sf_write_float (file, data, audio.rows () * audio.cols ());
+  sf_count_t items_to_write = audio.rows () * audio.cols ();
+
+  memset (&info, 0, sizeof (info)) ;
+  info.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
+  info.channels = 2 ;
+  info.samplerate = 44100 ;
+
+  sf_count_t items_written = sf_write_float (file, data, items_to_write);
+
   sf_close (file);
 
+  if (items_written != items_to_write)
+    {
+      error ("expected to write %ld items, wrote %ld items",
+             items_to_write, items_written);
+      return retval;
+    }
+  
 #else
 
   error ("sndfile not found on your system and thus audiowrite is not functional");
@@ -358,6 +388,7 @@
   result.assign ("NumChannels", info.channels);
   result.assign ("SampleRate", info.samplerate);
   result.assign ("TotalSamples", info.frames);
+  result.assign ("Format", info.format);
 
   double dframes = info.frames;
   double drate = info.samplerate;