76#if defined (HAVE_SNDFILE)
78 int nargin = args.length ();
80 if (nargin < 1 || nargin > 3)
83 std::string filename = args(0).xstring_value (
"audioread: FILENAME must be a string");
87 SNDFILE *file = sf_open (filename.c_str (), SFM_READ, &info);
90 error (
"audioread: failed to open input file '%s': %s",
91 filename.c_str (), sf_strerror (file));
93 unwind_action close_open_file ([file] () { sf_close (file); });
98 if (info.frames == SF_COUNT_MAX)
99 error (
"audioread: malformed header does not specify number of samples");
103 sf_read_double (file, data, info.frames * info.channels);
105 sf_count_t start = 0;
106 sf_count_t end = info.frames;
108 if ((nargin == 2 && ! args(1).is_string ()) || nargin == 3)
112 if (
range.numel () != 2)
113 error (
"audioread: invalid specification for range of frames");
115 double dstart = (math::isinf (
range(0)) ? info.frames :
range(0));
116 double dend = (math::isinf (
range(1)) ? info.frames :
range(1));
118 if (dstart < 1 || dstart > dend || dend > info.frames
119 || math::x_nint (dstart) != dstart
120 || math::x_nint (dend) != dend)
121 error (
"audioread: invalid specification for range of frames");
127 sf_count_t items = end - start;
129 Matrix audio (items, info.channels);
131 double *paudio = audio.
rwdata ();
133 data += start * info.channels;
135 for (
int i = 0; i < items; i++)
137 for (
int channel = 0; channel < info.channels; channel++)
138 paudio[items*channel+i] = *data++;
143 if ((nargin == 2 && args(1).is_string ()) || nargin == 3)
149 type = args(1).string_value ();
151 if (type ==
"native")
153 switch (info.format & SF_FORMAT_SUBMASK)
155 case SF_FORMAT_PCM_S8:
158 case SF_FORMAT_PCM_U8:
161 case SF_FORMAT_PCM_16:
164 case SF_FORMAT_PCM_24:
167 case SF_FORMAT_PCM_32:
170 case SF_FORMAT_FLOAT:
184 return ovl (ret_audio, info.samplerate);
188 octave_unused_parameter (args);
191 "reading and writing sound files through libsndfile");
281#if defined (HAVE_SNDFILE)
283 int nargin = args.length ();
288 std::string filename = args(0).xstring_value (
"audiowrite: FILENAME must be a string");
293 if (args(1).is_uint8_type ())
294 bias =
scale = 127.5;
295 else if (args(1).is_int16_type ())
297 else if (args(1).is_int32_type ())
302 Matrix audio = args(1).matrix_value ();
304 if (! args(2).is_scalar_type () || ! args(2).isnumeric ())
305 error (
"audiowrite: sample rate FS must be a positive scalar integer");
306 int samplerate = args(2).int_value ();
308 error (
"audiowrite: sample rate FS must be a positive scalar integer");
311 std::size_t dotpos = filename.find_last_of (
'.');
312 if (dotpos != std::string::npos)
313 ext = filename.substr (dotpos + 1);
314 std::transform (ext.begin (), ext.end (), ext.begin (), ::tolower);
316 sf_count_t items_to_write = audio.
rows () * audio.
columns ();
318 if (audio.
rows () == 1)
324 for (
int i = 0; i < audio.
rows (); i++)
326 for (
int j = 0; j < audio.
columns (); j++)
328 double elem = (audio.
xelem (i, j) - bias) /
scale;
329 data[idx++] = std::min (std::max (elem, -1.0), 1.0);
335 memset (&info, 0,
sizeof (info));
337 sf_count_t chunk_size = 0;
341 info.format = SF_FORMAT_VORBIS;
347 chunk_size = 0x100000;
349#if defined (HAVE_LIB_SNDFILE_FORMAT_MP3)
350 else if (ext ==
"mp1")
351 info.format = SF_FORMAT_MPEG|SF_FORMAT_MPEG_LAYER_I;
352 else if (ext ==
"mp2")
353 info.format = SF_FORMAT_MPEG|SF_FORMAT_MPEG_LAYER_II;
354 else if (ext ==
"mp3")
355 info.format = SF_FORMAT_MPEG|SF_FORMAT_MPEG_LAYER_III;
358 info.format = SF_FORMAT_PCM_16;
360 info.channels = audio.
columns ();
361 info.samplerate = samplerate;
362 info.format |= extension_to_format (ext);
364 std::string title =
"";
365 std::string artist =
"";
366 std::string comment =
"";
367 double quality = 0.75;
369 for (
int i = 3; i < nargin; i += 2)
372 error (
"audiowrite: invalid number of arguments");
374 std::string keyword_orig = args(i).string_value ();
375 std::string keyword = args(i).xtolower ().string_value ();
378 if (keyword ==
"bitspersample")
380 info.format &= ~SF_FORMAT_SUBMASK;
384 if ((info.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV)
385 info.format |= SF_FORMAT_PCM_U8;
387 info.format |= SF_FORMAT_PCM_S8;
390 info.format |= SF_FORMAT_PCM_16;
393 if ((info.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV)
394 info.format |= SF_FORMAT_PCM_32;
396 info.format |= SF_FORMAT_PCM_24;
400 if ((info.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV
401 && args(1).isfloat ())
402 info.format |= SF_FORMAT_FLOAT;
404 info.format |= SF_FORMAT_PCM_32;
407 info.format |= SF_FORMAT_DOUBLE;
409 error (
"audiowrite: wrong number of bits specified");
411 else if (keyword ==
"bitrate")
413 "audiowrite: 'BitRate' accepted for Matlab "
414 "compatibility, but is ignored");
415 else if (keyword ==
"quality")
418 error (
"audiowrite: Quality value must be a scalar");
421 value_arg.
xdouble_value (
"audiowrite: Quality value must be a numeric scalar between 0 and 100");
423 if (math::isnan (value) || value < 0 || value > 100)
424 error (
"audiowrite: Quality value must be a number between 0 and 100");
426 quality = value / 100;
428 else if (keyword ==
"title")
430 else if (keyword ==
"artist")
432 else if (keyword ==
"comment")
435 error (
"audiowrite: unrecognized option: '%s'", keyword_orig.c_str ());
438 SNDFILE *file = sf_open (filename.c_str (), SFM_WRITE, &info);
441 error (
"audiowrite: failed to open output file '%s': %s",
442 filename.c_str (), sf_strerror (file));
444 unwind_action close_open_file ([file] () { sf_close (file); });
446 sf_command (file, SFC_SET_NORM_DOUBLE,
nullptr, SF_TRUE);
447 sf_command (file, SFC_SET_CLIPPING,
nullptr, SF_TRUE) ;
448 sf_command (file, SFC_SET_VBR_ENCODING_QUALITY, &quality,
sizeof (quality));
451 sf_set_string (file, SF_STR_TITLE, title.c_str ());
454 sf_set_string (file, SF_STR_ARTIST, artist.c_str ());
457 sf_set_string (file, SF_STR_COMMENT, comment.c_str ());
459 sf_count_t total_items_written = 0;
460 sf_count_t offset = 0;
463 chunk_size = items_to_write;
465 while (total_items_written < items_to_write)
467 if (items_to_write - offset < chunk_size)
468 chunk_size = items_to_write - offset;
470 sf_count_t items_written = sf_write_double (file, data+offset, chunk_size);
472 if (items_written != chunk_size)
473 error (
"audiowrite: write failed, wrote %" PRId64
" of %" PRId64
474 " items\n", items_written, chunk_size);
476 total_items_written += items_written;
477 offset += chunk_size;
487 octave_unused_parameter (args);
490 "reading and writing sound files through libsndfile");
628#if defined (HAVE_SNDFILE)
630 if (args.length () != 1)
633 std::string filename = args(0).xstring_value (
"audioinfo: FILENAME must be a string");
635 sys::file_stat fs (filename);
637 error (
"audioinfo: FILENAME '%s' not found", filename.c_str ());
641 SNDFILE *file = sf_open (filename.c_str (), SFM_READ, &info);
644 error (
"audioinfo: failed to open input file '%s': %s",
645 filename.c_str (), sf_strerror (file));
647 unwind_action close_open_file ([file] () { sf_close (file); });
651 std::string full_name = sys::canonicalize_file_name (filename);
653 result.assign (
"Filename", full_name);
654 result.assign (
"CompressionMethod",
"");
655 result.assign (
"NumChannels", info.channels);
656 result.assign (
"SampleRate", info.samplerate);
658 if (info.frames != SF_COUNT_MAX)
659 dframes = info.frames;
662 result.assign (
"TotalSamples", dframes);
666 double drate = info.samplerate;
667 result.assign (
"Duration", dframes / drate);
670 result.assign (
"Duration", -1);
673 switch (info.format & SF_FORMAT_SUBMASK)
675 case SF_FORMAT_PCM_S8:
678 case SF_FORMAT_PCM_U8:
681 case SF_FORMAT_PCM_16:
684 case SF_FORMAT_PCM_24:
687 case SF_FORMAT_PCM_32:
690 case SF_FORMAT_FLOAT:
693 case SF_FORMAT_DOUBLE:
701 result.assign (
"BitsPerSample", bits);
702 result.assign (
"BitRate", -1);
703 result.assign (
"Title", sf_get_string (file, SF_STR_TITLE));
704 result.assign (
"Artist", sf_get_string (file, SF_STR_ARTIST));
705 result.assign (
"Comment", sf_get_string (file, SF_STR_COMMENT));
711 octave_unused_parameter (args);
714 "reading and writing sound files through libsndfile");
756#if defined (HAVE_SNDFILE)
758 if (args.length () > 1)
761 std::string search =
"";
762 if (args.length () > 0)
764 search = args(0).string_value ();
765 std::transform (search.begin (), search.end (), search.begin (), tolower);
769 sf_command (
nullptr, SFC_GET_FORMAT_MAJOR_COUNT, &count,
sizeof (
int));
771 for (
int i = 0; i < count; i++)
775 sf_command (
nullptr, SFC_GET_FORMAT_MAJOR, &info,
sizeof (info));
778 if (! search.empty ())
780 std::string nm = info.name;
781 std::transform (nm.begin (), nm.end (), nm.begin (), tolower);
782 match = nm.compare (0, search.length (), search) == 0;
788 octave_stdout <<
"extension: " << info.extension << std::endl;
792 audio_sub_formats (info.format);
800 octave_unused_parameter (args);
803 "getting sound formats through libsndfile");