Mercurial > hg > octave-nkf
changeset 19740: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 +++ b/libinterp/corefcn/load-path.cc @@ -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 +++ b/libinterp/dldfcn/audiodevinfo.cc @@ -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 +++ b/libinterp/dldfcn/audioread.cc @@ -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;