26 #if defined (HAVE_CONFIG_H)
48 #if defined (HAVE_SNDFILE)
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));
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");
118 if (dstart < 1 || dstart > dend || dend > info.frames
121 error (
"audioread: invalid specification for range of frames");
127 sf_count_t items = end - start;
129 Matrix audio (items, info.channels);
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");
196 #if defined (HAVE_SNDFILE)
199 extension_to_format (
const std::string& ext)
201 static bool initialized =
false;
203 static std::map<std::string, int> table;
207 table[
"wav"] = SF_FORMAT_WAV;
208 table[
"aiff"] = SF_FORMAT_AIFF;
209 table[
"au"] = SF_FORMAT_AU;
210 table[
"raw"] = SF_FORMAT_RAW;
211 table[
"paf"] = SF_FORMAT_PAF;
212 table[
"svx"] = SF_FORMAT_SVX;
213 table[
"nist"] = SF_FORMAT_NIST;
214 table[
"voc"] = SF_FORMAT_VOC;
215 table[
"ircam"] = SF_FORMAT_IRCAM;
216 table[
"w64"] = SF_FORMAT_W64;
217 table[
"mat4"] = SF_FORMAT_MAT4;
218 table[
"mat5"] = SF_FORMAT_MAT5;
219 table[
"pvf"] = SF_FORMAT_PVF;
220 table[
"xi"] = SF_FORMAT_XI;
221 table[
"htk"] = SF_FORMAT_HTK;
222 table[
"sds"] = SF_FORMAT_SDS;
223 table[
"avr"] = SF_FORMAT_AVR;
224 table[
"wavex"] = SF_FORMAT_WAVEX;
225 table[
"sd2"] = SF_FORMAT_SD2;
226 table[
"flac"] = SF_FORMAT_FLAC;
227 table[
"caf"] = SF_FORMAT_CAF;
228 table[
"wve"] = SF_FORMAT_WVE;
229 table[
"ogg"] = SF_FORMAT_OGG;
230 table[
"mpc2k"] = SF_FORMAT_MPC2K;
231 table[
"rf64"] = SF_FORMAT_RF64;
232 #if defined (HAVE_LIB_SNDFILE_FORMAT_MP3)
233 table[
"m1a"] = SF_FORMAT_MPEG;
239 std::map<std::string, int>::const_iterator it = table.find (ext);
241 return (it != table.end ()) ? it->second : 0;
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;
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));
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));
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");
719 #if defined (HAVE_SNDFILE)
722 audio_sub_formats (
int format)
725 sf_command (
nullptr, SFC_GET_FORMAT_SUBTYPE_COUNT, &count,
sizeof (
int));
727 for (
int i = 0; i < count; i++)
731 sf_command (
nullptr, SFC_GET_FORMAT_SUBTYPE, &info,
sizeof (info));
734 memset (&sfinfo, 0,
sizeof (sfinfo));
736 sfinfo.format = (
format & SF_FORMAT_TYPEMASK) | info.format;
738 if (sf_format_check (&sfinfo))
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;
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");
808 OCTAVE_END_NAMESPACE(
octave)
charNDArray max(char d, const charNDArray &m)
charNDArray min(char d, const charNDArray &m)
T * fortran_vec()
Size of the specified dimension.
octave_idx_type rows() const
octave_idx_type columns() const
T & xelem(octave_idx_type n)
Size of the specified dimension.
int int_value(bool req_int=false, bool frc_str_conv=false) const
bool is_scalar_type() const
double xdouble_value(const char *fmt,...) const
std::string string_value(bool force=false) const
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define DEFUN_DLD(name, args_name, nargout_name, doc)
Macro to define an at run time dynamically loadable builtin function.
void warning_with_id(const char *id, const char *fmt,...)
void() error(const char *fmt,...)
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
void err_wrong_type_arg(const char *name, const char *s)
void scale(Matrix &m, double x, double y, double z)
ColumnVector transform(const Matrix &m, double x, double y, double z)
intNDArray< octave_int16 > int16NDArray
intNDArray< octave_int32 > int32NDArray
intNDArray< octave_int8 > int8NDArray
std::string canonicalize_file_name(const std::string &name)
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
intNDArray< octave_uint8 > uint8NDArray
std::size_t format(std::ostream &os, const char *fmt,...)