mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-13 23:54:35 +00:00
Initial commit
added libraries: opus flac libsndfile updated: libvorbis libogg openal - Everything works as expected for now. Bare in mind libsndfile needed the check for whether or not it could find the xiph libraries removed in order for this to work.
This commit is contained in:
parent
05a083ca6f
commit
a745fc3757
1954 changed files with 431332 additions and 21037 deletions
503
Engine/lib/libsndfile/programs/common.c
Normal file
503
Engine/lib/libsndfile/programs/common.c
Normal file
|
|
@ -0,0 +1,503 @@
|
|||
/*
|
||||
** Copyright (C) 1999-2019 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2008 George Blood Audio
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the author nor the names of any contributors may be used
|
||||
** to endorse or promote products derived from this software without
|
||||
** specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define BUFFER_LEN 4096
|
||||
|
||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
int
|
||||
sfe_copy_data_fp (SNDFILE *outfile, SNDFILE *infile, int channels, int normalize)
|
||||
{ static double data [BUFFER_LEN], max ;
|
||||
sf_count_t frames, readcount, k ;
|
||||
|
||||
frames = BUFFER_LEN / channels ;
|
||||
readcount = frames ;
|
||||
|
||||
sf_command (infile, SFC_CALC_SIGNAL_MAX, &max, sizeof (max)) ;
|
||||
if (!isnormal (max)) /* neither zero, subnormal, infinite, nor NaN */
|
||||
return 1 ;
|
||||
|
||||
if (!normalize && max < 1.0)
|
||||
{ while (readcount > 0)
|
||||
{ readcount = sf_readf_double (infile, data, frames) ;
|
||||
sf_writef_double (outfile, data, readcount) ;
|
||||
} ;
|
||||
}
|
||||
else
|
||||
{ sf_command (infile, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
|
||||
|
||||
while (readcount > 0)
|
||||
{ readcount = sf_readf_double (infile, data, frames) ;
|
||||
for (k = 0 ; k < readcount * channels ; k++)
|
||||
{ data [k] /= max ;
|
||||
|
||||
if (!isfinite (data [k])) /* infinite or NaN */
|
||||
return 1 ;
|
||||
}
|
||||
sf_writef_double (outfile, data, readcount) ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* sfe_copy_data_fp */
|
||||
|
||||
void
|
||||
sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels)
|
||||
{ static int data [BUFFER_LEN] ;
|
||||
int frames, readcount ;
|
||||
|
||||
frames = BUFFER_LEN / channels ;
|
||||
readcount = frames ;
|
||||
|
||||
while (readcount > 0)
|
||||
{ readcount = (int) sf_readf_int (infile, data, frames) ;
|
||||
sf_writef_int (outfile, data, readcount) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* sfe_copy_data_int */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
static int
|
||||
merge_broadcast_info (SNDFILE * infile, SNDFILE * outfile, int format, const METADATA_INFO * info)
|
||||
{ SF_BROADCAST_INFO_2K binfo ;
|
||||
int infileminor ;
|
||||
|
||||
memset (&binfo, 0, sizeof (binfo)) ;
|
||||
|
||||
if ((SF_FORMAT_TYPEMASK & format) != SF_FORMAT_WAV)
|
||||
{ printf ("Error : This is not a WAV file and hence broadcast info cannot be added to it.\n\n") ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
infileminor = SF_FORMAT_SUBMASK & format ;
|
||||
|
||||
switch (infileminor)
|
||||
{ case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_24 :
|
||||
case SF_FORMAT_PCM_32 :
|
||||
case SF_FORMAT_MPEG_LAYER_III :
|
||||
break ;
|
||||
|
||||
default :
|
||||
printf (
|
||||
"Warning : The EBU Technical Recommendation R68-2000 states that the only\n"
|
||||
" allowed encodings are Linear PCM and MPEG3. This file is not in\n"
|
||||
" the right format.\n\n"
|
||||
) ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
if (sf_command (infile, SFC_GET_BROADCAST_INFO, &binfo, sizeof (binfo)) == 0)
|
||||
{ if (infile == outfile)
|
||||
{ printf (
|
||||
"Error : Attempting in-place broadcast info update, but file does not\n"
|
||||
" have a 'bext' chunk to modify. The solution is to specify both\n"
|
||||
" input and output files on the command line.\n\n"
|
||||
) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
#define REPLACE_IF_NEW(x) \
|
||||
if (info->x != NULL) \
|
||||
{ memset (binfo.x, 0, sizeof (binfo.x)) ; \
|
||||
memcpy (binfo.x, info->x, MIN (strlen (info->x), sizeof (binfo.x))) ; \
|
||||
} ;
|
||||
|
||||
REPLACE_IF_NEW (description) ;
|
||||
REPLACE_IF_NEW (originator) ;
|
||||
REPLACE_IF_NEW (originator_reference) ;
|
||||
REPLACE_IF_NEW (origination_date) ;
|
||||
REPLACE_IF_NEW (origination_time) ;
|
||||
REPLACE_IF_NEW (umid) ;
|
||||
|
||||
/* Special case loudness values */
|
||||
#define REPLACE_IF_NEW_INT(x) \
|
||||
if (info->x != NULL) \
|
||||
{ binfo.x = round (atof (info->x) * 100.0) ; \
|
||||
} ;
|
||||
|
||||
REPLACE_IF_NEW_INT (loudness_value) ;
|
||||
REPLACE_IF_NEW_INT (loudness_range) ;
|
||||
REPLACE_IF_NEW_INT (max_true_peak_level) ;
|
||||
REPLACE_IF_NEW_INT (max_momentary_loudness) ;
|
||||
REPLACE_IF_NEW_INT (max_shortterm_loudness) ;
|
||||
|
||||
/* Special case for Time Ref. */
|
||||
if (info->time_ref != NULL)
|
||||
{ uint64_t ts = atoll (info->time_ref) ;
|
||||
|
||||
binfo.time_reference_high = (ts >> 32) ;
|
||||
binfo.time_reference_low = (ts & 0xffffffff) ;
|
||||
} ;
|
||||
|
||||
/* Special case for coding_history because we may want to append. */
|
||||
if (info->coding_history != NULL)
|
||||
{ if (info->coding_hist_append)
|
||||
{ int slen = (int) strlen (binfo.coding_history) ;
|
||||
|
||||
while (slen > 1 && isspace (binfo.coding_history [slen - 1]))
|
||||
slen -- ;
|
||||
|
||||
memcpy (binfo.coding_history + slen, info->coding_history, sizeof (binfo.coding_history) - slen) ;
|
||||
}
|
||||
else
|
||||
{ size_t slen = MIN (strlen (info->coding_history), sizeof (binfo.coding_history)) ;
|
||||
|
||||
memset (binfo.coding_history, 0, sizeof (binfo.coding_history)) ;
|
||||
memcpy (binfo.coding_history, info->coding_history, slen) ;
|
||||
binfo.coding_history_size = (uint32_t) slen ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (sf_command (outfile, SFC_SET_BROADCAST_INFO, &binfo, sizeof (binfo)) == 0)
|
||||
{ printf ("Error : Setting of broadcast info chunks failed.\n\n") ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* merge_broadcast_info*/
|
||||
|
||||
static void
|
||||
update_strings (SNDFILE * outfile, const METADATA_INFO * info)
|
||||
{
|
||||
if (info->title != NULL)
|
||||
sf_set_string (outfile, SF_STR_TITLE, info->title) ;
|
||||
|
||||
if (info->copyright != NULL)
|
||||
sf_set_string (outfile, SF_STR_COPYRIGHT, info->copyright) ;
|
||||
|
||||
if (info->artist != NULL)
|
||||
sf_set_string (outfile, SF_STR_ARTIST, info->artist) ;
|
||||
|
||||
if (info->comment != NULL)
|
||||
sf_set_string (outfile, SF_STR_COMMENT, info->comment) ;
|
||||
|
||||
if (info->date != NULL)
|
||||
sf_set_string (outfile, SF_STR_DATE, info->date) ;
|
||||
|
||||
if (info->album != NULL)
|
||||
sf_set_string (outfile, SF_STR_ALBUM, info->album) ;
|
||||
|
||||
if (info->license != NULL)
|
||||
sf_set_string (outfile, SF_STR_LICENSE, info->license) ;
|
||||
|
||||
} /* update_strings */
|
||||
|
||||
|
||||
|
||||
void
|
||||
sfe_apply_metadata_changes (const char * filenames [2], const METADATA_INFO * info)
|
||||
{ SNDFILE *infile = NULL, *outfile = NULL ;
|
||||
SF_INFO sfinfo ;
|
||||
METADATA_INFO tmpinfo ;
|
||||
int error_code = 0 ;
|
||||
|
||||
memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
memset (&tmpinfo, 0, sizeof (tmpinfo)) ;
|
||||
|
||||
if (filenames [1] == NULL)
|
||||
infile = outfile = sf_open (filenames [0], SFM_RDWR, &sfinfo) ;
|
||||
else
|
||||
{ infile = sf_open (filenames [0], SFM_READ, &sfinfo) ;
|
||||
|
||||
/* Output must be WAV. */
|
||||
sfinfo.format = SF_FORMAT_WAV | (SF_FORMAT_SUBMASK & sfinfo.format) ;
|
||||
outfile = sf_open (filenames [1], SFM_WRITE, &sfinfo) ;
|
||||
} ;
|
||||
|
||||
if (infile == NULL)
|
||||
{ printf ("Error : Not able to open input file '%s' : %s\n", filenames [0], sf_strerror (infile)) ;
|
||||
error_code = 1 ;
|
||||
goto cleanup_exit ;
|
||||
} ;
|
||||
|
||||
if (outfile == NULL)
|
||||
{ printf ("Error : Not able to open output file '%s' : %s\n", filenames [1], sf_strerror (outfile)) ;
|
||||
error_code = 1 ;
|
||||
goto cleanup_exit ;
|
||||
} ;
|
||||
|
||||
if (info->has_bext_fields && merge_broadcast_info (infile, outfile, sfinfo.format, info))
|
||||
{ error_code = 1 ;
|
||||
goto cleanup_exit ;
|
||||
} ;
|
||||
|
||||
if (infile != outfile)
|
||||
{ int infileminor = SF_FORMAT_SUBMASK & sfinfo.format ;
|
||||
|
||||
/* If the input file is not the same as the output file, copy the data. */
|
||||
if ((infileminor == SF_FORMAT_DOUBLE) || (infileminor == SF_FORMAT_FLOAT))
|
||||
{ if (sfe_copy_data_fp (outfile, infile, sfinfo.channels, SF_FALSE) != 0)
|
||||
{ printf ("Error : Not able to decode input file '%s'\n", filenames [0]) ;
|
||||
error_code = 1 ;
|
||||
goto cleanup_exit ;
|
||||
} ;
|
||||
}
|
||||
else
|
||||
sfe_copy_data_int (outfile, infile, sfinfo.channels) ;
|
||||
} ;
|
||||
|
||||
update_strings (outfile, info) ;
|
||||
|
||||
cleanup_exit :
|
||||
|
||||
if (outfile != NULL && outfile != infile)
|
||||
sf_close (outfile) ;
|
||||
|
||||
if (infile != NULL)
|
||||
sf_close (infile) ;
|
||||
|
||||
if (error_code)
|
||||
exit (error_code) ;
|
||||
|
||||
return ;
|
||||
} /* sfe_apply_metadata_changes */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ const char *ext ;
|
||||
int len ;
|
||||
int format ;
|
||||
} OUTPUT_FORMAT_MAP ;
|
||||
|
||||
/* Map a file name extension to a container format. */
|
||||
static OUTPUT_FORMAT_MAP format_map [] =
|
||||
{
|
||||
{ "wav", 0, SF_FORMAT_WAV },
|
||||
{ "aif", 3, SF_FORMAT_AIFF },
|
||||
{ "au", 0, SF_FORMAT_AU },
|
||||
{ "snd", 0, SF_FORMAT_AU },
|
||||
{ "raw", 0, SF_FORMAT_RAW },
|
||||
{ "gsm", 0, SF_FORMAT_RAW | SF_FORMAT_GSM610 },
|
||||
{ "vox", 0, SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM },
|
||||
{ "paf", 0, SF_FORMAT_PAF | SF_ENDIAN_BIG },
|
||||
{ "fap", 0, SF_FORMAT_PAF | SF_ENDIAN_LITTLE },
|
||||
{ "svx", 0, SF_FORMAT_SVX },
|
||||
{ "nist", 0, SF_FORMAT_NIST },
|
||||
{ "sph", 0, SF_FORMAT_NIST },
|
||||
{ "voc", 0, SF_FORMAT_VOC },
|
||||
{ "ircam", 0, SF_FORMAT_IRCAM },
|
||||
{ "sf", 0, SF_FORMAT_IRCAM },
|
||||
{ "w64", 0, SF_FORMAT_W64 },
|
||||
{ "mat", 0, SF_FORMAT_MAT4 },
|
||||
{ "mat4", 0, SF_FORMAT_MAT4 },
|
||||
{ "mat5", 0, SF_FORMAT_MAT5 },
|
||||
{ "pvf", 0, SF_FORMAT_PVF },
|
||||
{ "xi", 0, SF_FORMAT_XI },
|
||||
{ "htk", 0, SF_FORMAT_HTK },
|
||||
{ "sds", 0, SF_FORMAT_SDS },
|
||||
{ "avr", 0, SF_FORMAT_AVR },
|
||||
{ "wavex", 0, SF_FORMAT_WAVEX },
|
||||
{ "sd2", 0, SF_FORMAT_SD2 },
|
||||
{ "flac", 0, SF_FORMAT_FLAC },
|
||||
{ "caf", 0, SF_FORMAT_CAF },
|
||||
{ "wve", 0, SF_FORMAT_WVE },
|
||||
{ "prc", 0, SF_FORMAT_WVE },
|
||||
{ "oga", 0, SF_FORMAT_OGG },
|
||||
{ "ogg", 0, SF_FORMAT_OGG | SF_FORMAT_VORBIS },
|
||||
{ "opus", 0, SF_FORMAT_OGG | SF_FORMAT_OPUS },
|
||||
{ "mpc", 0, SF_FORMAT_MPC2K },
|
||||
{ "rf64", 0, SF_FORMAT_RF64 },
|
||||
{ "mp3", 0, SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III },
|
||||
} ; /* format_map */
|
||||
|
||||
int
|
||||
sfe_file_type_of_ext (const char *str, int format)
|
||||
{ char buffer [16], *cptr ;
|
||||
int k ;
|
||||
|
||||
format &= SF_FORMAT_SUBMASK ;
|
||||
|
||||
if ((cptr = strrchr (str, '.')) == NULL)
|
||||
return 0 ;
|
||||
|
||||
strncpy (buffer, cptr + 1, 15) ;
|
||||
buffer [15] = 0 ;
|
||||
|
||||
for (k = 0 ; buffer [k] ; k++)
|
||||
buffer [k] = tolower ((buffer [k])) ;
|
||||
|
||||
for (k = 0 ; k < (int) (sizeof (format_map) / sizeof (format_map [0])) ; k++)
|
||||
{ if ((format_map [k].len > 0 && strncmp (buffer, format_map [k].ext, format_map [k].len) == 0) ||
|
||||
(strcmp (buffer, format_map [k].ext) == 0))
|
||||
{ if (format_map [k].format & SF_FORMAT_SUBMASK)
|
||||
return format_map [k].format ;
|
||||
else
|
||||
return format_map [k].format | format ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
/* Default if all the above fails. */
|
||||
return (SF_FORMAT_WAV | SF_FORMAT_PCM_24) ;
|
||||
} /* sfe_file_type_of_ext */
|
||||
|
||||
void
|
||||
sfe_dump_format_map (void)
|
||||
{ SF_FORMAT_INFO info ;
|
||||
int k ;
|
||||
|
||||
for (k = 0 ; k < ARRAY_LEN (format_map) ; k++)
|
||||
{ info.format = format_map [k].format ;
|
||||
sf_command (NULL, SFC_GET_FORMAT_INFO, &info, sizeof (info)) ;
|
||||
printf (" %-10s : %s", format_map [k].ext, info.name == NULL ? "????" : info.name) ;
|
||||
if (format_map [k].format & SF_FORMAT_SUBMASK)
|
||||
{ info.format = format_map [k].format & SF_FORMAT_SUBMASK ;
|
||||
sf_command (NULL, SFC_GET_FORMAT_INFO, &info, sizeof (info)) ;
|
||||
printf (" %s", info.name == NULL ? "????" : info.name) ;
|
||||
} ;
|
||||
putchar ('\n') ;
|
||||
|
||||
} ;
|
||||
|
||||
} /* sfe_dump_format_map */
|
||||
|
||||
const char *
|
||||
program_name (const char * argv0)
|
||||
{ const char * tmp ;
|
||||
|
||||
tmp = strrchr (argv0, '/') ;
|
||||
argv0 = tmp ? tmp + 1 : argv0 ;
|
||||
|
||||
/* Remove leading libtool name mangling. */
|
||||
if (strstr (argv0, "lt-") == argv0)
|
||||
return argv0 + 3 ;
|
||||
|
||||
return argv0 ;
|
||||
} /* program_name */
|
||||
|
||||
const char *
|
||||
sfe_endian_name (int format)
|
||||
{
|
||||
switch (format & SF_FORMAT_ENDMASK)
|
||||
{ case SF_ENDIAN_FILE : return "file" ;
|
||||
case SF_ENDIAN_LITTLE : return "little" ;
|
||||
case SF_ENDIAN_BIG : return "big" ;
|
||||
case SF_ENDIAN_CPU : return "cpu" ;
|
||||
default : break ;
|
||||
} ;
|
||||
|
||||
return "unknown" ;
|
||||
} /* sfe_endian_name */
|
||||
|
||||
const char *
|
||||
sfe_container_name (int format)
|
||||
{
|
||||
switch (format & SF_FORMAT_TYPEMASK)
|
||||
{ case SF_FORMAT_WAV : return "WAV" ;
|
||||
case SF_FORMAT_AIFF : return "AIFF" ;
|
||||
case SF_FORMAT_AU : return "AU" ;
|
||||
case SF_FORMAT_RAW : return "RAW" ;
|
||||
case SF_FORMAT_PAF : return "PAF" ;
|
||||
case SF_FORMAT_SVX : return "SVX" ;
|
||||
case SF_FORMAT_NIST : return "NIST" ;
|
||||
case SF_FORMAT_VOC : return "VOC" ;
|
||||
case SF_FORMAT_IRCAM : return "IRCAM" ;
|
||||
case SF_FORMAT_W64 : return "W64" ;
|
||||
case SF_FORMAT_MAT4 : return "MAT4" ;
|
||||
case SF_FORMAT_MAT5 : return "MAT5" ;
|
||||
case SF_FORMAT_PVF : return "PVF" ;
|
||||
case SF_FORMAT_XI : return "XI" ;
|
||||
case SF_FORMAT_HTK : return "HTK" ;
|
||||
case SF_FORMAT_SDS : return "SDS" ;
|
||||
case SF_FORMAT_AVR : return "AVR" ;
|
||||
case SF_FORMAT_WAVEX : return "WAVEX" ;
|
||||
case SF_FORMAT_SD2 : return "SD2" ;
|
||||
case SF_FORMAT_FLAC : return "FLAC" ;
|
||||
case SF_FORMAT_CAF : return "CAF" ;
|
||||
case SF_FORMAT_WVE : return "WVE" ;
|
||||
case SF_FORMAT_OGG : return "OGG" ;
|
||||
case SF_FORMAT_MPC2K : return "MPC2K" ;
|
||||
case SF_FORMAT_RF64 : return "RF64" ;
|
||||
case SF_FORMAT_MPEG : return "MPEG" ;
|
||||
default : break ;
|
||||
} ;
|
||||
|
||||
return "unknown" ;
|
||||
} /* sfe_container_name */
|
||||
|
||||
const char *
|
||||
sfe_codec_name (int format)
|
||||
{
|
||||
switch (format & SF_FORMAT_SUBMASK)
|
||||
{ case SF_FORMAT_PCM_S8 : return "signed 8 bit PCM" ;
|
||||
case SF_FORMAT_PCM_16 : return "16 bit PCM" ;
|
||||
case SF_FORMAT_PCM_24 : return "24 bit PCM" ;
|
||||
case SF_FORMAT_PCM_32 : return "32 bit PCM" ;
|
||||
case SF_FORMAT_PCM_U8 : return "unsigned 8 bit PCM" ;
|
||||
case SF_FORMAT_FLOAT : return "32 bit float" ;
|
||||
case SF_FORMAT_DOUBLE : return "64 bit double" ;
|
||||
case SF_FORMAT_ULAW : return "u-law" ;
|
||||
case SF_FORMAT_ALAW : return "a-law" ;
|
||||
case SF_FORMAT_IMA_ADPCM : return "IMA ADPCM" ;
|
||||
case SF_FORMAT_MS_ADPCM : return "MS ADPCM" ;
|
||||
case SF_FORMAT_GSM610 : return "gsm610" ;
|
||||
case SF_FORMAT_VOX_ADPCM : return "Vox ADPCM" ;
|
||||
case SF_FORMAT_G721_32 : return "g721 32kbps" ;
|
||||
case SF_FORMAT_G723_24 : return "g723 24kbps" ;
|
||||
case SF_FORMAT_G723_40 : return "g723 40kbps" ;
|
||||
case SF_FORMAT_DWVW_12 : return "12 bit DWVW" ;
|
||||
case SF_FORMAT_DWVW_16 : return "16 bit DWVW" ;
|
||||
case SF_FORMAT_DWVW_24 : return "14 bit DWVW" ;
|
||||
case SF_FORMAT_DWVW_N : return "DWVW" ;
|
||||
case SF_FORMAT_DPCM_8 : return "8 bit DPCM" ;
|
||||
case SF_FORMAT_DPCM_16 : return "16 bit DPCM" ;
|
||||
case SF_FORMAT_VORBIS : return "Vorbis" ;
|
||||
case SF_FORMAT_ALAC_16 : return "16 bit ALAC" ;
|
||||
case SF_FORMAT_ALAC_20 : return "20 bit ALAC" ;
|
||||
case SF_FORMAT_ALAC_24 : return "24 bit ALAC" ;
|
||||
case SF_FORMAT_ALAC_32 : return "32 bit ALAC" ;
|
||||
case SF_FORMAT_OPUS : return "Opus" ;
|
||||
case SF_FORMAT_MPEG_LAYER_I : return "MPEG layer 1" ;
|
||||
case SF_FORMAT_MPEG_LAYER_II : return "MPEG layer 2" ;
|
||||
case SF_FORMAT_MPEG_LAYER_III : return "MPEG layer 3" ;
|
||||
default : break ;
|
||||
} ;
|
||||
return "unknown" ;
|
||||
} /* sfe_codec_name */
|
||||
82
Engine/lib/libsndfile/programs/common.h
Normal file
82
Engine/lib/libsndfile/programs/common.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
** Copyright (C) 1999-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the author nor the names of any contributors may be used
|
||||
** to endorse or promote products derived from this software without
|
||||
** specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof (x [0])))
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
typedef struct
|
||||
{ const char * title ;
|
||||
const char * copyright ;
|
||||
const char * artist ;
|
||||
const char * comment ;
|
||||
const char * date ;
|
||||
const char * album ;
|
||||
const char * license ;
|
||||
|
||||
|
||||
/* Stuff to go in the 'bext' chunk of WAV files. */
|
||||
int has_bext_fields ;
|
||||
int coding_hist_append ;
|
||||
|
||||
const char * description ;
|
||||
const char * originator ;
|
||||
const char * originator_reference ;
|
||||
const char * origination_date ;
|
||||
const char * origination_time ;
|
||||
const char * umid ;
|
||||
const char * loudness_value ;
|
||||
const char * loudness_range ;
|
||||
const char * max_true_peak_level ;
|
||||
const char * max_momentary_loudness ;
|
||||
const char * max_shortterm_loudness ;
|
||||
const char * coding_history ;
|
||||
const char * time_ref ;
|
||||
} METADATA_INFO ;
|
||||
|
||||
typedef SF_BROADCAST_INFO_VAR (2048) SF_BROADCAST_INFO_2K ;
|
||||
|
||||
void sfe_apply_metadata_changes (const char * filenames [2], const METADATA_INFO * info) ;
|
||||
|
||||
int sfe_copy_data_fp (SNDFILE *outfile, SNDFILE *infile, int channels, int normalize) ;
|
||||
|
||||
void sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels) ;
|
||||
|
||||
int sfe_file_type_of_ext (const char *filename, int format) ;
|
||||
|
||||
void sfe_dump_format_map (void) ;
|
||||
|
||||
const char * program_name (const char * argv0) ;
|
||||
|
||||
const char * sfe_endian_name (int format) ;
|
||||
const char * sfe_container_name (int format) ;
|
||||
const char * sfe_codec_name (int format) ;
|
||||
155
Engine/lib/libsndfile/programs/sndfile-cmp.c
Normal file
155
Engine/lib/libsndfile/programs/sndfile-cmp.c
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
** Copyright (C) 2008-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2008 Conrad Parker <conrad@metadecks.org>
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the author nor the names of any contributors may be used
|
||||
** to endorse or promote products derived from this software without
|
||||
** specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* Length of comparison data buffers in units of items */
|
||||
#define BUFLEN 65536
|
||||
|
||||
static const char * progname = NULL ;
|
||||
static char * filename1 = NULL, * filename2 = NULL ;
|
||||
|
||||
static int
|
||||
comparison_error (const char * what, sf_count_t frame_offset)
|
||||
{ char buffer [128] ;
|
||||
|
||||
if (frame_offset >= 0)
|
||||
snprintf (buffer, sizeof (buffer), " (at frame offset %" PRId64 ")", frame_offset) ;
|
||||
else
|
||||
buffer [0] = 0 ;
|
||||
|
||||
printf ("%s: %s of files %s and %s differ%s.\n", progname, what, filename1, filename2, buffer) ;
|
||||
return 1 ;
|
||||
} /* comparison_error */
|
||||
|
||||
static int
|
||||
compare (void)
|
||||
{
|
||||
double buf1 [BUFLEN], buf2 [BUFLEN] ;
|
||||
SF_INFO sfinfo1, sfinfo2 ;
|
||||
SNDFILE * sf1 = NULL, * sf2 = NULL ;
|
||||
sf_count_t items, i, nread1, nread2, offset = 0 ;
|
||||
int retval = 0 ;
|
||||
|
||||
memset (&sfinfo1, 0, sizeof (SF_INFO)) ;
|
||||
sf1 = sf_open (filename1, SFM_READ, &sfinfo1) ;
|
||||
if (sf1 == NULL)
|
||||
{ printf ("Error opening %s.\n", filename1) ;
|
||||
retval = 1 ;
|
||||
goto out ;
|
||||
} ;
|
||||
|
||||
memset (&sfinfo2, 0, sizeof (SF_INFO)) ;
|
||||
sf2 = sf_open (filename2, SFM_READ, &sfinfo2) ;
|
||||
if (sf2 == NULL)
|
||||
{ printf ("Error opening %s.\n", filename2) ;
|
||||
retval = 1 ;
|
||||
goto out ;
|
||||
} ;
|
||||
|
||||
if (sfinfo1.samplerate != sfinfo2.samplerate)
|
||||
{ retval = comparison_error ("Samplerates", -1) ;
|
||||
goto out ;
|
||||
} ;
|
||||
|
||||
if (sfinfo1.channels != sfinfo2.channels)
|
||||
{ retval = comparison_error ("Number of channels", -1) ;
|
||||
goto out ;
|
||||
} ;
|
||||
|
||||
/* Calculate the framecount that will fit in our data buffers */
|
||||
items = BUFLEN / sfinfo1.channels ;
|
||||
|
||||
while ((nread1 = sf_readf_double (sf1, buf1, items)) > 0)
|
||||
{ nread2 = sf_readf_double (sf2, buf2, nread1) ;
|
||||
if (nread2 != nread1)
|
||||
{ retval = comparison_error ("PCM data lengths", -1) ;
|
||||
goto out ;
|
||||
} ;
|
||||
for (i = 0 ; i < nread1 * sfinfo1.channels ; i++)
|
||||
{ if (buf1 [i] != buf2 [i])
|
||||
{ retval = comparison_error ("PCM data", offset + i / sfinfo1.channels) ;
|
||||
goto out ;
|
||||
} ;
|
||||
} ;
|
||||
offset += nread1 ;
|
||||
} ;
|
||||
|
||||
if ((nread2 = sf_readf_double (sf2, buf2, items)) != 0)
|
||||
{ retval = comparison_error ("PCM data lengths", -1) ;
|
||||
goto out ;
|
||||
} ;
|
||||
|
||||
out :
|
||||
sf_close (sf1) ;
|
||||
sf_close (sf2) ;
|
||||
|
||||
return retval ;
|
||||
} /* compare */
|
||||
|
||||
static void
|
||||
usage_exit (void)
|
||||
{
|
||||
printf ("Usage : %s <filename> <filename>\n", progname) ;
|
||||
printf (" Compare the PCM data of two sound files.\n\n") ;
|
||||
printf ("Using %s.\n\n", sf_version_string ()) ;
|
||||
exit (1) ;
|
||||
} /* usage_exit */
|
||||
|
||||
int
|
||||
main (int argc, char *argv [])
|
||||
{
|
||||
progname = program_name (argv [0]) ;
|
||||
|
||||
if (argc != 3)
|
||||
usage_exit () ;
|
||||
|
||||
filename1 = argv [argc - 2] ;
|
||||
filename2 = argv [argc - 1] ;
|
||||
|
||||
if (strcmp (filename1, filename2) == 0)
|
||||
{ printf ("Error : Input filenames are the same.\n\n") ;
|
||||
usage_exit () ;
|
||||
} ;
|
||||
|
||||
return compare () ;
|
||||
} /* main */
|
||||
170
Engine/lib/libsndfile/programs/sndfile-concat.c
Normal file
170
Engine/lib/libsndfile/programs/sndfile-concat.c
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
** Copyright (C) 1999-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the author nor the names of any contributors may be used
|
||||
** to endorse or promote products derived from this software without
|
||||
** specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define BUFFER_LEN (1 << 16)
|
||||
|
||||
|
||||
static void concat_data_fp (SNDFILE *wfile, SNDFILE *rofile, int channels) ;
|
||||
static void concat_data_int (SNDFILE *wfile, SNDFILE *rofile, int channels) ;
|
||||
|
||||
static void
|
||||
usage_exit (const char *progname)
|
||||
{
|
||||
printf ("\nUsage : %s <infile1> <infile2> ... <outfile>\n\n", progname) ;
|
||||
puts (
|
||||
" Create a new output file <outfile> containing the concatenated\n"
|
||||
" audio data from froms <infile1> <infile2> ....\n"
|
||||
"\n"
|
||||
" The joined file will be encoded in the same format as the data\n"
|
||||
" in infile1, with all the data in subsequent files automatically\n"
|
||||
" converted to the correct encoding.\n"
|
||||
"\n"
|
||||
" The only restriction is that the two files must have the same\n"
|
||||
" number of channels.\n"
|
||||
) ;
|
||||
|
||||
exit (1) ;
|
||||
} /* usage_exit */
|
||||
|
||||
int
|
||||
main (int argc, char *argv [])
|
||||
{ const char *progname, *outfilename ;
|
||||
SNDFILE *outfile, **infiles ;
|
||||
SF_INFO sfinfo_out, sfinfo_in ;
|
||||
void (*func) (SNDFILE*, SNDFILE*, int) ;
|
||||
int k ;
|
||||
|
||||
progname = program_name (argv [0]) ;
|
||||
|
||||
if (argc < 4)
|
||||
usage_exit (progname) ;
|
||||
|
||||
argv ++ ;
|
||||
argc -- ;
|
||||
|
||||
argc -- ;
|
||||
outfilename = argv [argc] ;
|
||||
|
||||
if ((infiles = calloc (argc, sizeof (SNDFILE*))) == NULL)
|
||||
{ printf ("\nError : Malloc failed.\n\n") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
memset (&sfinfo_in, 0, sizeof (sfinfo_in)) ;
|
||||
|
||||
if ((infiles [0] = sf_open (argv [0], SFM_READ, &sfinfo_in)) == NULL)
|
||||
{ printf ("\nError : failed to open file '%s'.\n\n", argv [0]) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
sfinfo_out = sfinfo_in ;
|
||||
|
||||
for (k = 1 ; k < argc ; k++)
|
||||
{ if ((infiles [k] = sf_open (argv [k], SFM_READ, &sfinfo_in)) == NULL)
|
||||
{ printf ("\nError : failed to open file '%s'.\n\n", argv [k]) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
if (sfinfo_in.channels != sfinfo_out.channels)
|
||||
{ printf ("\nError : File '%s' has %d channels (should have %d).\n\n", argv [k], sfinfo_in.channels, sfinfo_out.channels) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if ((outfile = sf_open (outfilename, SFM_WRITE, &sfinfo_out)) == NULL)
|
||||
{ printf ("\nError : Not able to open input file %s.\n", outfilename) ;
|
||||
puts (sf_strerror (NULL)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
if ((sfinfo_out.format & SF_FORMAT_SUBMASK) == SF_FORMAT_DOUBLE ||
|
||||
(sfinfo_out.format & SF_FORMAT_SUBMASK) == SF_FORMAT_FLOAT)
|
||||
func = concat_data_fp ;
|
||||
else
|
||||
func = concat_data_int ;
|
||||
|
||||
for (k = 0 ; k < argc ; k++)
|
||||
{ func (outfile, infiles [k], sfinfo_out.channels) ;
|
||||
sf_close (infiles [k]) ;
|
||||
} ;
|
||||
|
||||
sf_close (outfile) ;
|
||||
free (infiles) ;
|
||||
|
||||
return 0 ;
|
||||
} /* main */
|
||||
|
||||
static void
|
||||
concat_data_fp (SNDFILE *wfile, SNDFILE *rofile, int channels)
|
||||
{ static double data [BUFFER_LEN] ;
|
||||
int frames, readcount ;
|
||||
|
||||
frames = BUFFER_LEN / channels ;
|
||||
readcount = frames ;
|
||||
|
||||
sf_seek (wfile, 0, SEEK_END) ;
|
||||
|
||||
while (readcount > 0)
|
||||
{ readcount = (int) sf_readf_double (rofile, data, frames) ;
|
||||
sf_writef_double (wfile, data, readcount) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* concat_data_fp */
|
||||
|
||||
static void
|
||||
concat_data_int (SNDFILE *wfile, SNDFILE *rofile, int channels)
|
||||
{ static int data [BUFFER_LEN] ;
|
||||
int frames, readcount ;
|
||||
|
||||
frames = BUFFER_LEN / channels ;
|
||||
readcount = frames ;
|
||||
|
||||
sf_seek (wfile, 0, SEEK_END) ;
|
||||
|
||||
while (readcount > 0)
|
||||
{ readcount = (int) sf_readf_int (rofile, data, frames) ;
|
||||
sf_writef_int (wfile, data, readcount) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* concat_data_int */
|
||||
|
||||
410
Engine/lib/libsndfile/programs/sndfile-convert.c
Normal file
410
Engine/lib/libsndfile/programs/sndfile-convert.c
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
/*
|
||||
** Copyright (C) 1999-2019 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the author nor the names of any contributors may be used
|
||||
** to endorse or promote products derived from this software without
|
||||
** specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{ char *infilename, *outfilename ;
|
||||
SF_INFO infileinfo, outfileinfo ;
|
||||
} OptionData ;
|
||||
|
||||
static void copy_metadata (SNDFILE *outfile, SNDFILE *infile, int channels) ;
|
||||
|
||||
static void
|
||||
usage_exit (const char *progname)
|
||||
{
|
||||
printf ("\nUsage : %s [options] [encoding] <input file> <output file>\n", progname) ;
|
||||
puts ("\n"
|
||||
" where [option] may be:\n\n"
|
||||
" -override-sample-rate=X : force sample rate of input to X\n"
|
||||
" -endian=little : force output file to little endian data\n"
|
||||
" -endian=big : force output file to big endian data\n"
|
||||
" -endian=cpu : force output file same endian-ness as the CPU\n"
|
||||
" -normalize : normalize the data in the output file\n"
|
||||
) ;
|
||||
|
||||
puts (
|
||||
" where [encoding] may be one of the following:\n\n"
|
||||
" -pcms8 : signed 8 bit pcm\n"
|
||||
" -pcmu8 : unsigned 8 bit pcm\n"
|
||||
" -pcm16 : 16 bit pcm\n"
|
||||
" -pcm24 : 24 bit pcm\n"
|
||||
" -pcm32 : 32 bit pcm\n"
|
||||
" -float32 : 32 bit floating point\n"
|
||||
" -float64 : 64 bit floating point\n"
|
||||
" -ulaw : ULAW\n"
|
||||
" -alaw : ALAW\n"
|
||||
" -alac16 : 16 bit ALAC (CAF only)\n"
|
||||
" -alac20 : 20 bit ALAC (CAF only)\n"
|
||||
" -alac24 : 24 bit ALAC (CAF only)\n"
|
||||
" -alac32 : 32 bit ALAC (CAF only)\n"
|
||||
" -ima-adpcm : IMA ADPCM (WAV only)\n"
|
||||
" -ms-adpcm : MS ADPCM (WAV only)\n"
|
||||
" -gsm610 : GSM6.10 (WAV only)\n"
|
||||
" -dwvw12 : 12 bit DWVW (AIFF only)\n"
|
||||
" -dwvw16 : 16 bit DWVW (AIFF only)\n"
|
||||
" -dwvw24 : 24 bit DWVW (AIFF only)\n"
|
||||
" -vorbis : Vorbis (OGG only)\n"
|
||||
" -opus : Opus (OGG only)\n"
|
||||
) ;
|
||||
|
||||
puts (
|
||||
" If no encoding is specified, the program will try to use the encoding\n"
|
||||
" of the input file in the output file. This will not always work as\n"
|
||||
" most container formats (eg WAV, AIFF etc) only support a small subset\n"
|
||||
" of codec formats (eg 16 bit PCM, a-law, Vorbis etc).\n"
|
||||
) ;
|
||||
|
||||
puts (
|
||||
" The format of the output file is determined by the file extension of the\n"
|
||||
" output file name. The following extensions are currently understood:\n"
|
||||
) ;
|
||||
|
||||
sfe_dump_format_map () ;
|
||||
|
||||
puts ("") ;
|
||||
exit (1) ;
|
||||
} /* usage_exit */
|
||||
|
||||
static void
|
||||
report_format_error_exit (const char * argv0, SF_INFO * sfinfo)
|
||||
{ int old_format = sfinfo->format ;
|
||||
int endian = sfinfo->format & SF_FORMAT_ENDMASK ;
|
||||
int channels = sfinfo->channels ;
|
||||
|
||||
sfinfo->format = old_format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ;
|
||||
|
||||
if (endian && sf_format_check (sfinfo))
|
||||
{ printf ("Error : output file format does not support %s endian-ness.\n", sfe_endian_name (endian)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
sfinfo->channels = 1 ;
|
||||
if (sf_format_check (sfinfo))
|
||||
{ printf ("Error : output file format does not support %d channels.\n", channels) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
printf ("\n"
|
||||
"Error : output file format is invalid.\n"
|
||||
"The '%s' container does not support '%s' codec data.\n"
|
||||
"Run '%s --help' for clues.\n\n",
|
||||
sfe_container_name (sfinfo->format), sfe_codec_name (sfinfo->format), program_name (argv0)) ;
|
||||
exit (1) ;
|
||||
} /* report_format_error_exit */
|
||||
|
||||
int
|
||||
main (int argc, char * argv [])
|
||||
{ const char *progname, *infilename, *outfilename ;
|
||||
SNDFILE *infile = NULL, *outfile = NULL ;
|
||||
SF_INFO sfinfo ;
|
||||
int k, outfilemajor, outfileminor = 0, infileminor ;
|
||||
int override_sample_rate = 0 ; /* assume no sample rate override. */
|
||||
int endian = SF_ENDIAN_FILE, normalize = SF_FALSE ;
|
||||
|
||||
progname = program_name (argv [0]) ;
|
||||
|
||||
if (argc < 3 || argc > 5)
|
||||
usage_exit (progname) ;
|
||||
|
||||
infilename = argv [argc-2] ;
|
||||
outfilename = argv [argc-1] ;
|
||||
|
||||
if (strcmp (infilename, outfilename) == 0)
|
||||
{ printf ("Error : Input and output filenames are the same.\n\n") ;
|
||||
usage_exit (progname) ;
|
||||
} ;
|
||||
|
||||
if (strlen (infilename) > 1 && infilename [0] == '-')
|
||||
{ printf ("Error : Input filename (%s) looks like an option.\n\n", infilename) ;
|
||||
usage_exit (progname) ;
|
||||
} ;
|
||||
|
||||
if (outfilename [0] == '-')
|
||||
{ printf ("Error : Output filename (%s) looks like an option.\n\n", outfilename) ;
|
||||
usage_exit (progname) ;
|
||||
} ;
|
||||
|
||||
for (k = 1 ; k < argc - 2 ; k++)
|
||||
{ if (! strcmp (argv [k], "-pcms8"))
|
||||
{ outfileminor = SF_FORMAT_PCM_S8 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-pcmu8"))
|
||||
{ outfileminor = SF_FORMAT_PCM_U8 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-pcm16"))
|
||||
{ outfileminor = SF_FORMAT_PCM_16 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-pcm24"))
|
||||
{ outfileminor = SF_FORMAT_PCM_24 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-pcm32"))
|
||||
{ outfileminor = SF_FORMAT_PCM_32 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-float32"))
|
||||
{ outfileminor = SF_FORMAT_FLOAT ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-float64"))
|
||||
{ outfileminor = SF_FORMAT_DOUBLE ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-ulaw"))
|
||||
{ outfileminor = SF_FORMAT_ULAW ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-alaw"))
|
||||
{ outfileminor = SF_FORMAT_ALAW ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-alac16"))
|
||||
{ outfileminor = SF_FORMAT_ALAC_16 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-alac20"))
|
||||
{ outfileminor = SF_FORMAT_ALAC_20 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-alac24"))
|
||||
{ outfileminor = SF_FORMAT_ALAC_24 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-alac32"))
|
||||
{ outfileminor = SF_FORMAT_ALAC_32 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-ima-adpcm"))
|
||||
{ outfileminor = SF_FORMAT_IMA_ADPCM ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-ms-adpcm"))
|
||||
{ outfileminor = SF_FORMAT_MS_ADPCM ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-gsm610"))
|
||||
{ outfileminor = SF_FORMAT_GSM610 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-dwvw12"))
|
||||
{ outfileminor = SF_FORMAT_DWVW_12 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-dwvw16"))
|
||||
{ outfileminor = SF_FORMAT_DWVW_16 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-dwvw24"))
|
||||
{ outfileminor = SF_FORMAT_DWVW_24 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-vorbis"))
|
||||
{ outfileminor = SF_FORMAT_VORBIS ;
|
||||
continue ;
|
||||
} ;
|
||||
if (! strcmp (argv [k], "-opus"))
|
||||
{ outfileminor = SF_FORMAT_OPUS ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (strstr (argv [k], "-override-sample-rate=") == argv [k])
|
||||
{ const char *ptr ;
|
||||
|
||||
ptr = argv [k] + strlen ("-override-sample-rate=") ;
|
||||
override_sample_rate = atoi (ptr) ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (! strcmp (argv [k], "-endian=little"))
|
||||
{ endian = SF_ENDIAN_LITTLE ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (! strcmp (argv [k], "-endian=big"))
|
||||
{ endian = SF_ENDIAN_BIG ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (! strcmp (argv [k], "-endian=cpu"))
|
||||
{ endian = SF_ENDIAN_CPU ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (! strcmp (argv [k], "-endian=file"))
|
||||
{ endian = SF_ENDIAN_FILE ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (! strcmp (argv [k], "-normalize"))
|
||||
{ normalize = SF_TRUE ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
printf ("Error : Not able to decode argument '%s'.\n", argv [k]) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
|
||||
if ((infile = sf_open (infilename, SFM_READ, &sfinfo)) == NULL)
|
||||
{ printf ("Not able to open input file %s.\n", infilename) ;
|
||||
puts (sf_strerror (NULL)) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
/* Update sample rate if forced to something else. */
|
||||
if (override_sample_rate)
|
||||
sfinfo.samplerate = override_sample_rate ;
|
||||
|
||||
infileminor = sfinfo.format & SF_FORMAT_SUBMASK ;
|
||||
|
||||
if ((sfinfo.format = sfe_file_type_of_ext (outfilename, sfinfo.format)) == 0)
|
||||
{ printf ("Error : Not able to determine output file type for %s.\n", outfilename) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
outfilemajor = sfinfo.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_ENDMASK) ;
|
||||
|
||||
if (outfileminor == 0)
|
||||
outfileminor = sfinfo.format & SF_FORMAT_SUBMASK ;
|
||||
|
||||
if (outfileminor != 0)
|
||||
sfinfo.format = outfilemajor | outfileminor ;
|
||||
else
|
||||
sfinfo.format = outfilemajor | (sfinfo.format & SF_FORMAT_SUBMASK) ;
|
||||
|
||||
sfinfo.format |= endian ;
|
||||
|
||||
if ((sfinfo.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_XI)
|
||||
switch (sfinfo.format & SF_FORMAT_SUBMASK)
|
||||
{ case SF_FORMAT_PCM_16 :
|
||||
sfinfo.format = outfilemajor | SF_FORMAT_DPCM_16 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_S8 :
|
||||
case SF_FORMAT_PCM_U8 :
|
||||
sfinfo.format = outfilemajor | SF_FORMAT_DPCM_8 ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
if (sf_format_check (&sfinfo) == 0)
|
||||
{ sf_close (infile) ;
|
||||
report_format_error_exit (argv [0], &sfinfo) ;
|
||||
} ;
|
||||
|
||||
if ((sfinfo.format & SF_FORMAT_SUBMASK) == SF_FORMAT_GSM610 && sfinfo.samplerate != 8000)
|
||||
{ printf (
|
||||
"WARNING: GSM 6.10 data format only supports 8kHz sample rate. The converted\n"
|
||||
"ouput file will contain the input data converted to the GSM 6.10 data format\n"
|
||||
"but not re-sampled.\n"
|
||||
) ;
|
||||
} ;
|
||||
|
||||
/* Open the output file. */
|
||||
if ((outfile = sf_open (outfilename, SFM_WRITE, &sfinfo)) == NULL)
|
||||
{ printf ("Not able to open output file %s : %s\n", outfilename, sf_strerror (NULL)) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
/* Copy the metadata */
|
||||
copy_metadata (outfile, infile, sfinfo.channels) ;
|
||||
|
||||
if (normalize
|
||||
|| (outfileminor == SF_FORMAT_DOUBLE) || (outfileminor == SF_FORMAT_FLOAT)
|
||||
|| (infileminor == SF_FORMAT_DOUBLE) || (infileminor == SF_FORMAT_FLOAT)
|
||||
|| (infileminor == SF_FORMAT_OPUS) || (outfileminor == SF_FORMAT_OPUS)
|
||||
|| (infileminor == SF_FORMAT_VORBIS) || (outfileminor == SF_FORMAT_VORBIS)
|
||||
|| (infileminor == SF_FORMAT_MPEG_LAYER_I)
|
||||
|| (infileminor == SF_FORMAT_MPEG_LAYER_II)
|
||||
|| (infileminor == SF_FORMAT_MPEG_LAYER_III) || (outfileminor == SF_FORMAT_MPEG_LAYER_III))
|
||||
{ if (sfe_copy_data_fp (outfile, infile, sfinfo.channels, normalize) != 0)
|
||||
{ printf ("Error : Not able to decode input file %s.\n", infilename) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
}
|
||||
else
|
||||
sfe_copy_data_int (outfile, infile, sfinfo.channels) ;
|
||||
|
||||
sf_close (infile) ;
|
||||
sf_close (outfile) ;
|
||||
|
||||
return 0 ;
|
||||
} /* main */
|
||||
|
||||
static void
|
||||
copy_metadata (SNDFILE *outfile, SNDFILE *infile, int channels)
|
||||
{ SF_INSTRUMENT inst ;
|
||||
SF_CUES cues ;
|
||||
SF_BROADCAST_INFO_2K binfo ;
|
||||
const char *str ;
|
||||
int k, chanmap [256] ;
|
||||
|
||||
for (k = SF_STR_FIRST ; k <= SF_STR_LAST ; k++)
|
||||
{ str = sf_get_string (infile, k) ;
|
||||
if (str != NULL)
|
||||
sf_set_string (outfile, k, str) ;
|
||||
} ;
|
||||
|
||||
memset (&inst, 0, sizeof (inst)) ;
|
||||
memset (&cues, 0, sizeof (cues)) ;
|
||||
memset (&binfo, 0, sizeof (binfo)) ;
|
||||
|
||||
if (channels < ARRAY_LEN (chanmap))
|
||||
{ int size = channels * sizeof (chanmap [0]) ;
|
||||
|
||||
if (sf_command (infile, SFC_GET_CHANNEL_MAP_INFO, chanmap, size) == SF_TRUE)
|
||||
sf_command (outfile, SFC_SET_CHANNEL_MAP_INFO, chanmap, size) ;
|
||||
} ;
|
||||
|
||||
if (sf_command (infile, SFC_GET_CUE, &cues, sizeof (cues)) == SF_TRUE)
|
||||
sf_command (outfile, SFC_SET_CUE, &cues, sizeof (cues)) ;
|
||||
|
||||
if (sf_command (infile, SFC_GET_INSTRUMENT, &inst, sizeof (inst)) == SF_TRUE)
|
||||
sf_command (outfile, SFC_SET_INSTRUMENT, &inst, sizeof (inst)) ;
|
||||
|
||||
if (sf_command (infile, SFC_GET_BROADCAST_INFO, &binfo, sizeof (binfo)) == SF_TRUE)
|
||||
sf_command (outfile, SFC_SET_BROADCAST_INFO, &binfo, sizeof (binfo)) ;
|
||||
|
||||
} /* copy_metadata */
|
||||
|
||||
222
Engine/lib/libsndfile/programs/sndfile-deinterleave.c
Normal file
222
Engine/lib/libsndfile/programs/sndfile-deinterleave.c
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
** Copyright (C) 2009-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the author nor the names of any contributors may be used
|
||||
** to endorse or promote products derived from this software without
|
||||
** specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sndfile.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define BUFFER_LEN 4096
|
||||
#define MAX_CHANNELS 16
|
||||
|
||||
|
||||
typedef struct
|
||||
{ SNDFILE * infile ;
|
||||
SNDFILE * outfile [MAX_CHANNELS] ;
|
||||
|
||||
union
|
||||
{ double d [MAX_CHANNELS * BUFFER_LEN] ;
|
||||
int i [MAX_CHANNELS * BUFFER_LEN] ;
|
||||
} din ;
|
||||
|
||||
union
|
||||
{ double d [BUFFER_LEN] ;
|
||||
int i [BUFFER_LEN] ;
|
||||
} dout ;
|
||||
|
||||
int channels ;
|
||||
} STATE ;
|
||||
|
||||
static void usage_exit (void) ;
|
||||
|
||||
static void deinterleave_int (STATE * state) ;
|
||||
static void deinterleave_double (STATE * state) ;
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{ STATE *state = NULL ;
|
||||
SF_INFO sfinfo ;
|
||||
char pathname [512], ext [32], *cptr ;
|
||||
int ch, double_split, ret = 1 ;
|
||||
|
||||
if (argc != 2)
|
||||
{ if (argc != 1)
|
||||
puts ("\nError : need a single input file.\n") ;
|
||||
usage_exit () ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
state = calloc (1, sizeof (*state)) ;
|
||||
if (!state)
|
||||
{ printf ("\nError : Out of memory.\n") ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
|
||||
if ((state->infile = sf_open (argv [1], SFM_READ, &sfinfo)) == NULL)
|
||||
{ printf ("\nError : Not able to open input file '%s'\n%s\n", argv [1], sf_strerror (NULL)) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if (sfinfo.channels < 2)
|
||||
{ printf ("\nError : Input file '%s' only has one channel.\n", argv [1]) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if (sfinfo.channels > MAX_CHANNELS)
|
||||
{ printf ("\nError : Input file '%s' has too many (%d) channels. Limit is %d.\n",
|
||||
argv [1], sfinfo.channels, MAX_CHANNELS) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
|
||||
state->channels = sfinfo.channels ;
|
||||
sfinfo.channels = 1 ;
|
||||
|
||||
if (snprintf (pathname, sizeof (pathname), "%s", argv [1]) > (int) sizeof (pathname))
|
||||
{ printf ("\nError : Length of provided filename '%s' exceeds MAX_PATH (%d).\n", argv [1], (int) sizeof (pathname)) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if ((cptr = strrchr (pathname, '.')) == NULL)
|
||||
ext [0] = 0 ;
|
||||
else
|
||||
{ snprintf (ext, sizeof (ext), "%s", cptr) ;
|
||||
cptr [0] = 0 ;
|
||||
} ;
|
||||
|
||||
printf ("Input file : %s\n", pathname) ;
|
||||
puts ("Output files :") ;
|
||||
|
||||
for (ch = 0 ; ch < state->channels ; ch++)
|
||||
{ char filename [520] ;
|
||||
size_t count ;
|
||||
|
||||
count = snprintf (filename, sizeof (filename), "%s_%02d%s", pathname, ch, ext) ;
|
||||
|
||||
if (count >= sizeof (filename))
|
||||
{ printf ("File name truncated to %s\n", filename) ;
|
||||
} ;
|
||||
|
||||
if ((state->outfile [ch] = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
|
||||
{ printf ("Not able to open output file '%s'\n%s\n", filename, sf_strerror (NULL)) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
printf (" %s\n", filename) ;
|
||||
} ;
|
||||
|
||||
switch (sfinfo.format & SF_FORMAT_SUBMASK)
|
||||
{ case SF_FORMAT_FLOAT :
|
||||
case SF_FORMAT_DOUBLE :
|
||||
case SF_FORMAT_VORBIS :
|
||||
double_split = 1 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
double_split = 0 ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
if (double_split)
|
||||
deinterleave_double (state) ;
|
||||
else
|
||||
deinterleave_int (state) ;
|
||||
|
||||
ret = 0 ;
|
||||
|
||||
cleanup :
|
||||
|
||||
if (state != NULL)
|
||||
{ sf_close (state->infile) ;
|
||||
for (ch = 0 ; ch < MAX_CHANNELS ; ch++)
|
||||
if (state->outfile [ch] != NULL)
|
||||
sf_close (state->outfile [ch]) ;
|
||||
} ;
|
||||
|
||||
free (state) ;
|
||||
|
||||
return ret ;
|
||||
} /* main */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
usage_exit (void)
|
||||
{ puts ("\nUsage : sndfile-deinterleave <filename>\n") ;
|
||||
puts (
|
||||
"Split a mutli-channel file into a set of mono files.\n"
|
||||
"\n"
|
||||
"If the input file is named 'a.wav', the output files will be named\n"
|
||||
"a_00.wav, a_01.wav and so on.\n"
|
||||
) ;
|
||||
printf ("Using %s.\n\n", sf_version_string ()) ;
|
||||
} /* usage_exit */
|
||||
|
||||
static void
|
||||
deinterleave_int (STATE * state)
|
||||
{ int read_len ;
|
||||
int ch, k ;
|
||||
|
||||
do
|
||||
{ read_len = (int) sf_readf_int (state->infile, state->din.i, BUFFER_LEN) ;
|
||||
|
||||
for (ch = 0 ; ch < state->channels ; ch ++)
|
||||
{ for (k = 0 ; k < read_len ; k++)
|
||||
state->dout.i [k] = state->din.i [k * state->channels + ch] ;
|
||||
sf_write_int (state->outfile [ch], state->dout.i, read_len) ;
|
||||
} ;
|
||||
}
|
||||
while (read_len > 0) ;
|
||||
|
||||
} /* deinterleave_int */
|
||||
|
||||
static void
|
||||
deinterleave_double (STATE * state)
|
||||
{ int read_len ;
|
||||
int ch, k ;
|
||||
|
||||
do
|
||||
{ read_len = (int) sf_readf_double (state->infile, state->din.d, BUFFER_LEN) ;
|
||||
|
||||
for (ch = 0 ; ch < state->channels ; ch ++)
|
||||
{ for (k = 0 ; k < read_len ; k++)
|
||||
state->dout.d [k] = state->din.d [k * state->channels + ch] ;
|
||||
sf_write_double (state->outfile [ch], state->dout.d, read_len) ;
|
||||
} ;
|
||||
}
|
||||
while (read_len > 0) ;
|
||||
|
||||
} /* deinterleave_double */
|
||||
529
Engine/lib/libsndfile/programs/sndfile-info.c
Normal file
529
Engine/lib/libsndfile/programs/sndfile-info.c
Normal file
|
|
@ -0,0 +1,529 @@
|
|||
/*
|
||||
** Copyright (C) 1999-2019 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the author nor the names of any contributors may be used
|
||||
** to endorse or promote products derived from this software without
|
||||
** specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define BUFFER_LEN (1 << 16)
|
||||
|
||||
#if (defined (WIN32) || defined (_WIN32))
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
static void usage_exit (const char *progname) ;
|
||||
|
||||
static void info_dump (const char *filename) ;
|
||||
static int instrument_dump (const char *filename) ;
|
||||
static int broadcast_dump (const char *filename) ;
|
||||
static int chanmap_dump (const char *filename) ;
|
||||
static int cart_dump (const char *filename) ;
|
||||
static void total_dump (void) ;
|
||||
|
||||
static double total_seconds = 0.0 ;
|
||||
|
||||
int
|
||||
main (int argc, char *argv [])
|
||||
{ int k ;
|
||||
|
||||
if (argc < 2 || strcmp (argv [1], "--help") == 0 || strcmp (argv [1], "-h") == 0)
|
||||
usage_exit (program_name (argv [0])) ;
|
||||
|
||||
if (strcmp (argv [1], "--instrument") == 0)
|
||||
{ int error = 0 ;
|
||||
|
||||
for (k = 2 ; k < argc ; k++)
|
||||
error += instrument_dump (argv [k]) ;
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
if (strcmp (argv [1], "--broadcast") == 0)
|
||||
{ int error = 0 ;
|
||||
|
||||
for (k = 2 ; k < argc ; k++)
|
||||
error += broadcast_dump (argv [k]) ;
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
if (strcmp (argv [1], "--channel-map") == 0)
|
||||
{ int error = 0 ;
|
||||
|
||||
for (k = 2 ; k < argc ; k++)
|
||||
error += chanmap_dump (argv [k]) ;
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
if (strcmp (argv [1], "--cart") == 0)
|
||||
{ int error = 0 ;
|
||||
|
||||
for (k = 2 ; k < argc ; k++)
|
||||
error += cart_dump (argv [k]) ;
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
for (k = 1 ; k < argc ; k++)
|
||||
info_dump (argv [k]) ;
|
||||
|
||||
if (argc > 2)
|
||||
total_dump () ;
|
||||
|
||||
return 0 ;
|
||||
} /* main */
|
||||
|
||||
/*==============================================================================
|
||||
** Print version and usage.
|
||||
*/
|
||||
|
||||
static void
|
||||
usage_exit (const char *progname)
|
||||
{ printf ("Usage :\n %s <file> ...\n", progname) ;
|
||||
printf (" Prints out information about one or more sound files.\n\n") ;
|
||||
printf (" %s --instrument <file>\n", progname) ;
|
||||
printf (" Prints out the instrument data for the given file.\n\n") ;
|
||||
printf (" %s --broadcast <file>\n", progname) ;
|
||||
printf (" Prints out the broadcast WAV info for the given file.\n\n") ;
|
||||
printf (" %s --channel-map <file>\n", progname) ;
|
||||
printf (" Prints out the channel map for the given file.\n\n") ;
|
||||
printf (" %s --cart <file>\n", progname) ;
|
||||
printf (" Prints out the cart chunk WAV info for the given file.\n\n") ;
|
||||
|
||||
printf ("Using %s.\n\n", sf_version_string ()) ;
|
||||
#if (defined (_WIN32) || defined (WIN32))
|
||||
printf ("This is a Unix style command line application which\n"
|
||||
"should be run in a MSDOS box or Command Shell window.\n\n") ;
|
||||
printf ("Sleeping for 5 seconds before exiting.\n\n") ;
|
||||
fflush (stdout) ;
|
||||
|
||||
Sleep (5 * 1000) ;
|
||||
#endif
|
||||
exit (1) ;
|
||||
} /* usage_exit */
|
||||
|
||||
/*==============================================================================
|
||||
** Dumping of sndfile info.
|
||||
*/
|
||||
|
||||
static double data [BUFFER_LEN] ;
|
||||
|
||||
static double
|
||||
calc_decibels (SF_INFO * sfinfo, double max)
|
||||
{ double decibels ;
|
||||
|
||||
switch (sfinfo->format & SF_FORMAT_SUBMASK)
|
||||
{ case SF_FORMAT_PCM_U8 :
|
||||
case SF_FORMAT_PCM_S8 :
|
||||
decibels = max / 0x80 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_16 :
|
||||
decibels = max / 0x8000 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_24 :
|
||||
decibels = max / 0x800000 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_32 :
|
||||
decibels = max / 0x80000000 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_FLOAT :
|
||||
case SF_FORMAT_DOUBLE :
|
||||
case SF_FORMAT_VORBIS :
|
||||
case SF_FORMAT_OPUS :
|
||||
decibels = max / 1.0 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
decibels = max / 0x8000 ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return 20.0 * log10 (decibels) ;
|
||||
} /* calc_decibels */
|
||||
|
||||
static const char *
|
||||
format_duration_str (double seconds)
|
||||
{ static char str [128] ;
|
||||
int hrs, min ;
|
||||
double sec ;
|
||||
|
||||
memset (str, 0, sizeof (str)) ;
|
||||
|
||||
hrs = (int) (seconds / 3600.0) ;
|
||||
min = (int) ((seconds - (hrs * 3600.0)) / 60.0) ;
|
||||
sec = seconds - (hrs * 3600.0) - (min * 60.0) ;
|
||||
|
||||
snprintf (str, sizeof (str) - 1, "%02d:%02d:%06.3f", hrs, min, sec) ;
|
||||
|
||||
return str ;
|
||||
} /* format_duration_str */
|
||||
|
||||
static const char *
|
||||
generate_duration_str (SF_INFO *sfinfo)
|
||||
{
|
||||
double seconds ;
|
||||
|
||||
if (sfinfo->samplerate < 1)
|
||||
return NULL ;
|
||||
|
||||
if (sfinfo->frames / sfinfo->samplerate > 0x7FFFFFFF)
|
||||
return "unknown" ;
|
||||
|
||||
seconds = (1.0 * sfinfo->frames) / sfinfo->samplerate ;
|
||||
|
||||
/* Accumulate the total of all known file durations */
|
||||
total_seconds += seconds ;
|
||||
|
||||
return format_duration_str (seconds) ;
|
||||
} /* generate_duration_str */
|
||||
|
||||
static void
|
||||
info_dump (const char *filename)
|
||||
{ static char strbuffer [BUFFER_LEN] ;
|
||||
SNDFILE *file ;
|
||||
SF_INFO sfinfo ;
|
||||
double signal_max, decibels ;
|
||||
|
||||
memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
|
||||
if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
|
||||
{ printf ("Error : Not able to open input file %s.\n", filename) ;
|
||||
fflush (stdout) ;
|
||||
memset (data, 0, sizeof (data)) ;
|
||||
sf_command (file, SFC_GET_LOG_INFO, strbuffer, BUFFER_LEN) ;
|
||||
puts (strbuffer) ;
|
||||
puts (sf_strerror (NULL)) ;
|
||||
return ;
|
||||
} ;
|
||||
|
||||
printf ("========================================\n") ;
|
||||
sf_command (file, SFC_GET_LOG_INFO, strbuffer, BUFFER_LEN) ;
|
||||
puts (strbuffer) ;
|
||||
printf ("----------------------------------------\n") ;
|
||||
|
||||
printf ("Sample Rate : %d\n", sfinfo.samplerate) ;
|
||||
|
||||
if (sfinfo.frames == SF_COUNT_MAX)
|
||||
printf ("Frames : unknown\n") ;
|
||||
else
|
||||
printf ("Frames : %" PRId64 "\n", sfinfo.frames) ;
|
||||
|
||||
printf ("Channels : %d\n", sfinfo.channels) ;
|
||||
printf ("Format : 0x%08X\n", sfinfo.format) ;
|
||||
printf ("Sections : %d\n", sfinfo.sections) ;
|
||||
printf ("Seekable : %s\n", (sfinfo.seekable ? "TRUE" : "FALSE")) ;
|
||||
printf ("Duration : %s\n", generate_duration_str (&sfinfo)) ;
|
||||
|
||||
if (sfinfo.frames < 100 * 1024 * 1024)
|
||||
{ /* Do not use sf_signal_max because it doesn't work for non-seekable files . */
|
||||
sf_command (file, SFC_CALC_SIGNAL_MAX, &signal_max, sizeof (signal_max)) ;
|
||||
decibels = calc_decibels (&sfinfo, signal_max) ;
|
||||
printf ("Signal Max : %g (%4.2f dB)\n", signal_max, decibels) ;
|
||||
} ;
|
||||
putchar ('\n') ;
|
||||
|
||||
sf_close (file) ;
|
||||
|
||||
} /* info_dump */
|
||||
|
||||
/*==============================================================================
|
||||
** Dumping of SF_INSTRUMENT data.
|
||||
*/
|
||||
|
||||
static const char *
|
||||
str_of_type (int mode)
|
||||
{ switch (mode)
|
||||
{ case SF_LOOP_NONE : return "none" ;
|
||||
case SF_LOOP_FORWARD : return "fwd " ;
|
||||
case SF_LOOP_BACKWARD : return "back" ;
|
||||
case SF_LOOP_ALTERNATING : return "alt " ;
|
||||
default : break ;
|
||||
} ;
|
||||
|
||||
return "????" ;
|
||||
} /* str_of_mode */
|
||||
|
||||
static int
|
||||
instrument_dump (const char *filename)
|
||||
{ SNDFILE *file ;
|
||||
SF_INFO sfinfo ;
|
||||
SF_INSTRUMENT inst ;
|
||||
int got_inst, k ;
|
||||
|
||||
memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
|
||||
if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
|
||||
{ printf ("Error : Not able to open input file %s.\n", filename) ;
|
||||
fflush (stdout) ;
|
||||
memset (data, 0, sizeof (data)) ;
|
||||
puts (sf_strerror (NULL)) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
got_inst = sf_command (file, SFC_GET_INSTRUMENT, &inst, sizeof (inst)) ;
|
||||
sf_close (file) ;
|
||||
|
||||
if (got_inst == SF_FALSE)
|
||||
{ printf ("Error : File '%s' does not contain instrument data.\n\n", filename) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
printf ("Instrument : %s\n\n", filename) ;
|
||||
printf (" Gain : %d\n", inst.gain) ;
|
||||
printf (" Base note : %d\n", inst.basenote) ;
|
||||
printf (" Velocity : %d - %d\n", (int) inst.velocity_lo, (int) inst.velocity_hi) ;
|
||||
printf (" Key : %d - %d\n", (int) inst.key_lo, (int) inst.key_hi) ;
|
||||
printf (" Loop points : %d\n", inst.loop_count) ;
|
||||
|
||||
for (k = 0 ; k < inst.loop_count ; k++)
|
||||
printf (" %-2d Mode : %s Start : %6" PRIu32 " End : %6" PRIu32
|
||||
" Count : %6" PRIu32 "\n", k, str_of_type (inst.loops [k].mode),
|
||||
inst.loops [k].start, inst.loops [k].end, inst.loops [k].count) ;
|
||||
|
||||
putchar ('\n') ;
|
||||
return 0 ;
|
||||
} /* instrument_dump */
|
||||
|
||||
static int
|
||||
broadcast_dump (const char *filename)
|
||||
{ SNDFILE *file ;
|
||||
SF_INFO sfinfo ;
|
||||
SF_BROADCAST_INFO_2K bext ;
|
||||
double time_ref_sec ;
|
||||
int got_bext ;
|
||||
|
||||
memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
|
||||
if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
|
||||
{ printf ("Error : Not able to open input file %s.\n", filename) ;
|
||||
fflush (stdout) ;
|
||||
memset (data, 0, sizeof (data)) ;
|
||||
puts (sf_strerror (NULL)) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
memset (&bext, 0, sizeof (SF_BROADCAST_INFO_2K)) ;
|
||||
|
||||
got_bext = sf_command (file, SFC_GET_BROADCAST_INFO, &bext, sizeof (bext)) ;
|
||||
sf_close (file) ;
|
||||
|
||||
if (got_bext == SF_FALSE)
|
||||
{ printf ("Error : File '%s' does not contain broadcast information.\n\n", filename) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
/*
|
||||
** From : http://www.ebu.ch/en/technical/publications/userguides/bwf_user_guide.php
|
||||
**
|
||||
** Time Reference:
|
||||
** This field is a count from midnight in samples to the first sample
|
||||
** of the audio sequence.
|
||||
*/
|
||||
|
||||
time_ref_sec = ((pow (2.0, 32) * bext.time_reference_high) + (1.0 * bext.time_reference_low)) / sfinfo.samplerate ;
|
||||
|
||||
printf ("Description : %.*s\n", (int) sizeof (bext.description), bext.description) ;
|
||||
printf ("Originator : %.*s\n", (int) sizeof (bext.originator), bext.originator) ;
|
||||
printf ("Origination ref : %.*s\n", (int) sizeof (bext.originator_reference), bext.originator_reference) ;
|
||||
printf ("Origination date : %.*s\n", (int) sizeof (bext.origination_date), bext.origination_date) ;
|
||||
printf ("Origination time : %.*s\n", (int) sizeof (bext.origination_time), bext.origination_time) ;
|
||||
|
||||
if (bext.time_reference_high == 0 && bext.time_reference_low == 0)
|
||||
printf ("Time ref : 0\n") ;
|
||||
else
|
||||
printf ("Time ref : 0x%x%08x (%.6f seconds)\n", bext.time_reference_high, bext.time_reference_low, time_ref_sec) ;
|
||||
|
||||
printf ("BWF version : %d\n", bext.version) ;
|
||||
|
||||
if (bext.version >= 1)
|
||||
printf ("UMID : %.*s\n", (int) sizeof (bext.umid), bext.umid) ;
|
||||
|
||||
if (bext.version >= 2)
|
||||
{ /* 0x7fff shall be used to designate an unused value */
|
||||
/* valid range: -99.99 .. 99.99 */
|
||||
printf ("Loudness value : %6.2f LUFS\n", bext.loudness_value / 100.0) ;
|
||||
/* valid range: 0.00 .. 99.99 */
|
||||
printf ("Loudness range : %6.2f LU\n", bext.loudness_range / 100.0) ;
|
||||
/* valid range: -99.99 .. 99.99 */
|
||||
printf ("Max. true peak level : %6.2f dBTP\n", bext.max_true_peak_level / 100.0) ;
|
||||
printf ("Max. momentary loudness : %6.2f LUFS\n", bext.max_momentary_loudness / 100.0) ;
|
||||
printf ("Max. short term loudness : %6.2f LUFS\n", bext.max_shortterm_loudness / 100.0) ;
|
||||
} ;
|
||||
|
||||
printf ("Coding history : %.*s\n", bext.coding_history_size, bext.coding_history) ;
|
||||
|
||||
return 0 ;
|
||||
} /* broadcast_dump */
|
||||
|
||||
static int
|
||||
chanmap_dump (const char *filename)
|
||||
{ SNDFILE *file ;
|
||||
SF_INFO sfinfo ;
|
||||
int * channel_map ;
|
||||
int got_chanmap, k ;
|
||||
|
||||
memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
|
||||
if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
|
||||
{ printf ("Error : Not able to open input file %s.\n", filename) ;
|
||||
fflush (stdout) ;
|
||||
memset (data, 0, sizeof (data)) ;
|
||||
puts (sf_strerror (NULL)) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
if ((channel_map = calloc (sfinfo.channels, sizeof (int))) == NULL)
|
||||
{ printf ("Error : malloc failed.\n\n") ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
got_chanmap = sf_command (file, SFC_GET_CHANNEL_MAP_INFO, channel_map, sfinfo.channels * sizeof (int)) ;
|
||||
sf_close (file) ;
|
||||
|
||||
if (got_chanmap == SF_FALSE)
|
||||
{ printf ("Error : File '%s' does not contain channel map information.\n\n", filename) ;
|
||||
free (channel_map) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
printf ("File : %s\n\n", filename) ;
|
||||
|
||||
puts (" Chan Position") ;
|
||||
for (k = 0 ; k < sfinfo.channels ; k ++)
|
||||
{ const char * name ;
|
||||
|
||||
#define CASE_NAME(x) case x : name = #x ; break ;
|
||||
switch (channel_map [k])
|
||||
{ CASE_NAME (SF_CHANNEL_MAP_INVALID) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_MONO) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_LEFT) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_RIGHT) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_CENTER) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_FRONT_LEFT) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_FRONT_RIGHT) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_FRONT_CENTER) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_REAR_CENTER) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_REAR_LEFT) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_REAR_RIGHT) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_LFE) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_SIDE_LEFT) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_SIDE_RIGHT) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_TOP_CENTER) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_TOP_FRONT_LEFT) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_TOP_FRONT_RIGHT) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_TOP_FRONT_CENTER) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_TOP_REAR_LEFT) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_TOP_REAR_RIGHT) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_TOP_REAR_CENTER) ;
|
||||
CASE_NAME (SF_CHANNEL_MAP_MAX) ;
|
||||
default : name = "default" ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
printf (" %3d %s\n", k, name) ;
|
||||
} ;
|
||||
|
||||
putchar ('\n') ;
|
||||
free (channel_map) ;
|
||||
|
||||
return 0 ;
|
||||
} /* chanmap_dump */
|
||||
|
||||
static int
|
||||
cart_dump (const char *filename)
|
||||
{ SNDFILE *file ;
|
||||
SF_INFO sfinfo ;
|
||||
SF_CART_INFO_VAR (1024) cart ;
|
||||
int got_cart, k ;
|
||||
|
||||
memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
memset (&cart, 0, sizeof (cart)) ;
|
||||
|
||||
if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
|
||||
{ printf ("Error : Not able to open input file %s.\n", filename) ;
|
||||
fflush (stdout) ;
|
||||
memset (data, 0, sizeof (data)) ;
|
||||
puts (sf_strerror (NULL)) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
got_cart = sf_command (file, SFC_GET_CART_INFO, &cart, sizeof (cart)) ;
|
||||
sf_close (file) ;
|
||||
|
||||
if (got_cart == SF_FALSE)
|
||||
{ printf ("Error : File '%s' does not contain cart information.\n\n", filename) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
printf ("Version : %.*s\n", (int) sizeof (cart.version), cart.version) ;
|
||||
printf ("Title : %.*s\n", (int) sizeof (cart.title), cart.title) ;
|
||||
printf ("Artist : %.*s\n", (int) sizeof (cart.artist), cart.artist) ;
|
||||
printf ("Cut id : %.*s\n", (int) sizeof (cart.cut_id), cart.cut_id) ;
|
||||
printf ("Category : %.*s\n", (int) sizeof (cart.category), cart.category) ;
|
||||
printf ("Classification : %.*s\n", (int) sizeof (cart.classification), cart.classification) ;
|
||||
printf ("Out cue : %.*s\n", (int) sizeof (cart.out_cue), cart.out_cue) ;
|
||||
printf ("Start date : %.*s\n", (int) sizeof (cart.start_date), cart.start_date) ;
|
||||
printf ("Start time : %.*s\n", (int) sizeof (cart.start_time), cart.start_time) ;
|
||||
printf ("End date : %.*s\n", (int) sizeof (cart.end_date), cart.end_date) ;
|
||||
printf ("End time : %.*s\n", (int) sizeof (cart.end_time), cart.end_time) ;
|
||||
printf ("App id : %.*s\n", (int) sizeof (cart.producer_app_id), cart.producer_app_id) ;
|
||||
printf ("App version : %.*s\n", (int) sizeof (cart.producer_app_version), cart.producer_app_version) ;
|
||||
printf ("User defined : %.*s\n", (int) sizeof (cart.user_def), cart.user_def) ;
|
||||
printf ("Level ref. : %d\n", cart.level_reference) ;
|
||||
printf ("Post timers :\n") ;
|
||||
|
||||
for (k = 0 ; k < ARRAY_LEN (cart.post_timers) ; k++)
|
||||
if (cart.post_timers [k].usage [0])
|
||||
printf (" %d %.*s %d\n", k, (int) sizeof (cart.post_timers [k].usage), cart.post_timers [k].usage, cart.post_timers [k].value) ;
|
||||
|
||||
printf ("Reserved : %.*s\n", (int) sizeof (cart.reserved), cart.reserved) ;
|
||||
printf ("Url : %.*s\n", (int) sizeof (cart.url), cart.url) ;
|
||||
printf ("Tag text : %.*s\n", cart.tag_text_size, cart.tag_text) ;
|
||||
|
||||
return 0 ;
|
||||
} /* cart_dump */
|
||||
|
||||
static void
|
||||
total_dump (void)
|
||||
{ printf ("========================================\n") ;
|
||||
printf ("Total Duration : %s\n", format_duration_str (total_seconds)) ;
|
||||
} /* total_dump */
|
||||
217
Engine/lib/libsndfile/programs/sndfile-interleave.c
Normal file
217
Engine/lib/libsndfile/programs/sndfile-interleave.c
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
** Copyright (C) 2009-2015 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the author nor the names of any contributors may be used
|
||||
** to endorse or promote products derived from this software without
|
||||
** specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sndfile.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define BUFFER_LEN 4096
|
||||
#define MAX_INPUTS 16
|
||||
|
||||
|
||||
typedef struct
|
||||
{ SNDFILE * infile [MAX_INPUTS] ;
|
||||
SNDFILE * outfile ;
|
||||
|
||||
union
|
||||
{ double d [BUFFER_LEN] ;
|
||||
int i [BUFFER_LEN] ;
|
||||
} din ;
|
||||
|
||||
union
|
||||
|
||||
{ double d [MAX_INPUTS * BUFFER_LEN] ;
|
||||
int i [MAX_INPUTS * BUFFER_LEN] ;
|
||||
} dout ;
|
||||
|
||||
int channels ;
|
||||
} STATE ;
|
||||
|
||||
|
||||
static void print_usage (void) ;
|
||||
static void interleave_int (STATE * state) ;
|
||||
static void interleave_double (STATE * state) ;
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{ STATE *state = NULL ;
|
||||
SF_INFO sfinfo ;
|
||||
int k, double_merge = 0 ;
|
||||
int ret = 1 ;
|
||||
|
||||
if (argc < 5)
|
||||
{ if (argc > 1)
|
||||
puts ("\nError : need at least 2 input files.") ;
|
||||
print_usage () ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if (strcmp (argv [argc - 2], "-o") != 0)
|
||||
{ puts ("\nError : second last command line parameter should be '-o'.\n") ;
|
||||
print_usage () ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if (argc - 3 > MAX_INPUTS)
|
||||
{ printf ("\nError : Cannot handle more than %d input channels.\n\n", MAX_INPUTS) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
state = calloc (1, sizeof (STATE)) ;
|
||||
if (state == NULL)
|
||||
{ puts ("\nError : out of memory.\n") ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
|
||||
for (k = 1 ; k < argc - 2 ; k++)
|
||||
{
|
||||
if ((state->infile [k - 1] = sf_open (argv [k], SFM_READ, &sfinfo)) == NULL)
|
||||
{ printf ("\nError : Not able to open input file '%s'\n%s\n", argv [k], sf_strerror (NULL)) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if (sfinfo.channels != 1)
|
||||
{ printf ("\bError : Input file '%s' should be mono (has %d channels).\n", argv [k], sfinfo.channels) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
switch (sfinfo.format & SF_FORMAT_SUBMASK)
|
||||
{ case SF_FORMAT_FLOAT :
|
||||
case SF_FORMAT_DOUBLE :
|
||||
case SF_FORMAT_VORBIS :
|
||||
double_merge = 1 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
break ;
|
||||
} ;
|
||||
|
||||
state->channels ++ ;
|
||||
} ;
|
||||
|
||||
sfinfo.channels = state->channels ;
|
||||
sfinfo.format = sfe_file_type_of_ext (argv [argc - 1], sfinfo.format) ;
|
||||
|
||||
if ((state->outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL)
|
||||
{ printf ("Not able to open output file '%s'\n%s\n", argv [argc - 1], sf_strerror (NULL)) ;
|
||||
goto cleanup ;
|
||||
} ;
|
||||
|
||||
if (double_merge)
|
||||
interleave_double (state) ;
|
||||
else
|
||||
interleave_int (state) ;
|
||||
|
||||
ret = 0 ;
|
||||
|
||||
cleanup :
|
||||
|
||||
if (state != NULL)
|
||||
{ for (k = 0 ; k < MAX_INPUTS ; k++)
|
||||
if (state->infile [k] != NULL)
|
||||
sf_close (state->infile [k]) ;
|
||||
sf_close (state->outfile) ;
|
||||
}
|
||||
|
||||
free (state) ;
|
||||
|
||||
return ret ;
|
||||
} /* main */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
static void
|
||||
print_usage (void)
|
||||
{ puts ("\nUsage : sndfile-interleave <input 1> <input 2> ... -o <output file>\n") ;
|
||||
puts ("Merge two or more mono files into a single multi-channel file.\n") ;
|
||||
printf ("Using %s.\n\n", sf_version_string ()) ;
|
||||
} /* print_usage */
|
||||
|
||||
|
||||
static void
|
||||
interleave_int (STATE * state)
|
||||
{ int max_read_len, read_len ;
|
||||
int ch, k ;
|
||||
|
||||
do
|
||||
{ max_read_len = 0 ;
|
||||
|
||||
for (ch = 0 ; ch < state->channels ; ch ++)
|
||||
{ read_len = (int) sf_read_int (state->infile [ch], state->din.i, BUFFER_LEN) ;
|
||||
if (read_len < BUFFER_LEN)
|
||||
memset (state->din.i + read_len, 0, sizeof (state->din.i [0]) * (BUFFER_LEN - read_len)) ;
|
||||
|
||||
for (k = 0 ; k < BUFFER_LEN ; k++)
|
||||
state->dout.i [k * state->channels + ch] = state->din.i [k] ;
|
||||
|
||||
max_read_len = MAX (max_read_len, read_len) ;
|
||||
} ;
|
||||
|
||||
sf_writef_int (state->outfile, state->dout.i, max_read_len) ;
|
||||
}
|
||||
while (max_read_len > 0) ;
|
||||
|
||||
} /* interleave_int */
|
||||
|
||||
|
||||
static void
|
||||
interleave_double (STATE * state)
|
||||
{ int max_read_len, read_len ;
|
||||
int ch, k ;
|
||||
|
||||
do
|
||||
{ max_read_len = 0 ;
|
||||
|
||||
for (ch = 0 ; ch < state->channels ; ch ++)
|
||||
{ read_len = (int) sf_read_double (state->infile [ch], state->din.d, BUFFER_LEN) ;
|
||||
if (read_len < BUFFER_LEN)
|
||||
memset (state->din.d + read_len, 0, sizeof (state->din.d [0]) * (BUFFER_LEN - read_len)) ;
|
||||
|
||||
for (k = 0 ; k < BUFFER_LEN ; k++)
|
||||
state->dout.d [k * state->channels + ch] = state->din.d [k] ;
|
||||
|
||||
max_read_len = MAX (max_read_len, read_len) ;
|
||||
} ;
|
||||
|
||||
sf_writef_double (state->outfile, state->dout.d, max_read_len) ;
|
||||
}
|
||||
while (max_read_len > 0) ;
|
||||
|
||||
} /* interleave_double */
|
||||
197
Engine/lib/libsndfile/programs/sndfile-metadata-get.c
Normal file
197
Engine/lib/libsndfile/programs/sndfile-metadata-get.c
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
** Copyright (C) 2008-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2008-2010 George Blood Audio
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the author nor the names of any contributors may be used
|
||||
** to endorse or promote products derived from this software without
|
||||
** specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define BUFFER_LEN (1 << 16)
|
||||
|
||||
static void usage_exit (const char *progname, int exit_code) ;
|
||||
static void process_args (SNDFILE * file, const SF_BROADCAST_INFO_2K * binfo, int argc, char * argv []) ;
|
||||
|
||||
int
|
||||
main (int argc, char *argv [])
|
||||
{ SNDFILE *file ;
|
||||
SF_INFO sfinfo ;
|
||||
SF_BROADCAST_INFO_2K binfo ;
|
||||
const char *progname ;
|
||||
const char * filename = NULL ;
|
||||
int start ;
|
||||
|
||||
/* Store the program name. */
|
||||
progname = program_name (argv [0]) ;
|
||||
|
||||
/* Check if we've been asked for help. */
|
||||
if (argc < 2 || strcmp (argv [1], "--help") == 0 || strcmp (argv [1], "-h") == 0)
|
||||
usage_exit (progname, 0) ;
|
||||
|
||||
if (argv [argc - 1][0] != '-')
|
||||
{ filename = argv [argc - 1] ;
|
||||
start = 1 ;
|
||||
}
|
||||
else if (argv [1][0] != '-')
|
||||
{ filename = argv [1] ;
|
||||
start = 2 ;
|
||||
}
|
||||
else
|
||||
{ printf ("Error : Either the first or the last command line parameter should be a filename.\n\n") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
if ((file = sf_open (filename, SFM_READ, &sfinfo)) == NULL)
|
||||
{ printf ("Error : Open of file '%s' failed : %s\n\n", filename, sf_strerror (file)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
memset (&binfo, 0, sizeof (binfo)) ;
|
||||
if (sf_command (file, SFC_GET_BROADCAST_INFO, &binfo, sizeof (binfo)) == 0)
|
||||
memset (&binfo, 0, sizeof (binfo)) ;
|
||||
|
||||
process_args (file, &binfo, argc - 2, argv + start) ;
|
||||
|
||||
sf_close (file) ;
|
||||
return 0 ;
|
||||
} /* main */
|
||||
|
||||
/*==============================================================================
|
||||
** Print version and usage.
|
||||
*/
|
||||
|
||||
static void
|
||||
usage_exit (const char *progname, int exit_code)
|
||||
{ printf ("\nUsage :\n %s [options] <file>\n\nOptions:\n", progname) ;
|
||||
|
||||
puts (
|
||||
" --bext-description Print the 'bext' description.\n"
|
||||
" --bext-originator Print the 'bext' originator info.\n"
|
||||
" --bext-orig-ref Print the 'bext' origination reference.\n"
|
||||
" --bext-umid Print the 'bext' UMID.\n"
|
||||
" --bext-orig-date Print the 'bext' origination date.\n"
|
||||
" --bext-orig-time Print the 'bext' origination time.\n"
|
||||
" --bext-loudness-value Print the 'bext' loudness value.\n"
|
||||
" --bext-loudness-range Print the 'bext' loudness range.\n"
|
||||
" --bext-max-truepeak Print the 'bext' max. true peak level\n"
|
||||
" --bext-max-momentary Print the 'bext' max. momentary loudness\n"
|
||||
" --bext-max-shortterm Print the 'bext' max. short term loudness\n"
|
||||
" --bext-coding-hist Print the 'bext' coding history.\n"
|
||||
) ;
|
||||
|
||||
puts (
|
||||
" --str-title Print the title metadata.\n"
|
||||
" --str-copyright Print the copyright metadata.\n"
|
||||
" --str-artist Print the artist metadata.\n"
|
||||
" --str-comment Print the comment metadata.\n"
|
||||
" --str-date Print the creation date metadata.\n"
|
||||
" --str-album Print the album metadata.\n"
|
||||
" --str-license Print the license metadata.\n"
|
||||
) ;
|
||||
|
||||
printf ("Using %s.\n\n", sf_version_string ()) ;
|
||||
exit (exit_code) ;
|
||||
} /* usage_exit */
|
||||
|
||||
static void
|
||||
process_args (SNDFILE * file, const SF_BROADCAST_INFO_2K * binfo, int argc, char * argv [])
|
||||
{ const char * str ;
|
||||
int k, do_all = 0 ;
|
||||
|
||||
#define HANDLE_BEXT_ARG(cmd, name, field) \
|
||||
if (do_all || strcmp (argv [k], cmd) == 0) \
|
||||
{ printf ("%-22s : %.*s\n", name, (int) sizeof (binfo->field), binfo->field) ; \
|
||||
if (! do_all) \
|
||||
continue ; \
|
||||
} ;
|
||||
|
||||
#define HANDLE_BEXT_ARG_INT(cmd, name, field) \
|
||||
if (do_all || strcmp (argv [k], cmd) == 0) \
|
||||
{ printf ("%-22s : %6.2f\n", name, binfo->field / 100.0) ; \
|
||||
if (! do_all) \
|
||||
continue ; \
|
||||
} ;
|
||||
|
||||
#define HANDLE_STR_ARG(cmd, name, id) \
|
||||
if (do_all || strcmp (argv [k], cmd) == 0) \
|
||||
{ str = sf_get_string (file, id) ; \
|
||||
printf ("%-22s : %s\n", name, str ? str : "") ; \
|
||||
if (! do_all) continue ; \
|
||||
} ;
|
||||
|
||||
if (argc == 0)
|
||||
{ do_all = 1 ;
|
||||
argc = 1 ;
|
||||
} ;
|
||||
|
||||
for (k = 0 ; k < argc ; k++)
|
||||
{ if (do_all || strcmp (argv [k], "--all") == 0)
|
||||
do_all = 1 ;
|
||||
|
||||
HANDLE_BEXT_ARG ("--bext-description", "Description", description) ;
|
||||
HANDLE_BEXT_ARG ("--bext-originator", "Originator", originator) ;
|
||||
HANDLE_BEXT_ARG ("--bext-orig-ref", "Origination ref", originator_reference) ;
|
||||
HANDLE_BEXT_ARG ("--bext-umid", "UMID", umid) ;
|
||||
HANDLE_BEXT_ARG ("--bext-orig-date", "Origination date", origination_date) ;
|
||||
HANDLE_BEXT_ARG ("--bext-orig-time", "Origination time", origination_time) ;
|
||||
HANDLE_BEXT_ARG_INT ("--bext-loudness-value", "Loudness value", loudness_value) ;
|
||||
HANDLE_BEXT_ARG_INT ("--bext-loudness-range", "Loudness range", loudness_range) ;
|
||||
HANDLE_BEXT_ARG_INT ("--bext-max-truepeak", "Max. true peak level", max_true_peak_level) ;
|
||||
HANDLE_BEXT_ARG_INT ("--bext-max-momentary", "Max. momentary level", max_momentary_loudness) ;
|
||||
HANDLE_BEXT_ARG_INT ("--bext-max-shortterm", "Max. short term level", max_shortterm_loudness) ;
|
||||
HANDLE_BEXT_ARG ("--bext-coding-hist", "Coding history", coding_history) ;
|
||||
|
||||
HANDLE_STR_ARG ("--str-title", "Name", SF_STR_TITLE) ;
|
||||
HANDLE_STR_ARG ("--str-copyright", "Copyright", SF_STR_COPYRIGHT) ;
|
||||
HANDLE_STR_ARG ("--str-artist", "Artist", SF_STR_ARTIST) ;
|
||||
HANDLE_STR_ARG ("--str-comment", "Comment", SF_STR_COMMENT) ;
|
||||
HANDLE_STR_ARG ("--str-date", "Create date", SF_STR_DATE) ;
|
||||
HANDLE_STR_ARG ("--str-album", "Album", SF_STR_ALBUM) ;
|
||||
HANDLE_STR_ARG ("--str-license", "License", SF_STR_LICENSE) ;
|
||||
|
||||
if (! do_all)
|
||||
{ printf ("Error : Don't know what to do with command line arg '%s'.\n\n", argv [k]) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* process_args */
|
||||
298
Engine/lib/libsndfile/programs/sndfile-metadata-set.c
Normal file
298
Engine/lib/libsndfile/programs/sndfile-metadata-set.c
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
** Copyright (C) 2008-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2008-2010 George Blood Audio
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the author nor the names of any contributors may be used
|
||||
** to endorse or promote products derived from this software without
|
||||
** specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define BUFFER_LEN (1 << 16)
|
||||
|
||||
|
||||
static void usage_exit (const char *progname, int exit_code) ;
|
||||
static void missing_param (const char * option) ;
|
||||
static void read_localtime (struct tm * timedata) ;
|
||||
static int has_bext_fields_set (const METADATA_INFO * info) ;
|
||||
|
||||
int
|
||||
main (int argc, char *argv [])
|
||||
{ METADATA_INFO info ;
|
||||
struct tm timedata ;
|
||||
const char *progname ;
|
||||
const char * filenames [2] = { NULL, NULL } ;
|
||||
char date [128], time [128] ;
|
||||
int k ;
|
||||
|
||||
/* Store the program name. */
|
||||
progname = program_name (argv [0]) ;
|
||||
|
||||
/* Check if we've been asked for help. */
|
||||
if (argc < 3 || strcmp (argv [1], "--help") == 0 || strcmp (argv [1], "-h") == 0)
|
||||
usage_exit (progname, 0) ;
|
||||
|
||||
/* Set all fields of the struct to zero bytes. */
|
||||
memset (&info, 0, sizeof (info)) ;
|
||||
|
||||
/* Get the time in case we need it later. */
|
||||
read_localtime (&timedata) ;
|
||||
|
||||
for (k = 1 ; k < argc ; k++)
|
||||
{ if (argv [k][0] != '-')
|
||||
{ if (filenames [0] == NULL)
|
||||
filenames [0] = argv [k] ;
|
||||
else if (filenames [1] == NULL)
|
||||
filenames [1] = argv [k] ;
|
||||
else
|
||||
{ printf ("Error : Already have two file names on the command line and then found '%s'.\n\n", argv [k]) ;
|
||||
usage_exit (progname, 1) ;
|
||||
} ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
#define HANDLE_BEXT_ARG(cmd, field) \
|
||||
if (strcmp (argv [k], cmd) == 0) \
|
||||
{ k ++ ; \
|
||||
if (k == argc) missing_param (argv [k - 1]) ; \
|
||||
info.field = argv [k] ; \
|
||||
continue ; \
|
||||
} ;
|
||||
|
||||
HANDLE_BEXT_ARG ("--bext-description", description) ;
|
||||
HANDLE_BEXT_ARG ("--bext-originator", originator) ;
|
||||
HANDLE_BEXT_ARG ("--bext-orig-ref", originator_reference) ;
|
||||
HANDLE_BEXT_ARG ("--bext-umid", umid) ;
|
||||
HANDLE_BEXT_ARG ("--bext-orig-date", origination_date) ;
|
||||
HANDLE_BEXT_ARG ("--bext-orig-time", origination_time) ;
|
||||
HANDLE_BEXT_ARG ("--bext-loudness-value", loudness_value) ;
|
||||
HANDLE_BEXT_ARG ("--bext-loudness-range", loudness_range) ;
|
||||
HANDLE_BEXT_ARG ("--bext-max-truepeak", max_true_peak_level) ;
|
||||
HANDLE_BEXT_ARG ("--bext-max-momentary", max_momentary_loudness) ;
|
||||
HANDLE_BEXT_ARG ("--bext-max-shortterm", max_shortterm_loudness) ;
|
||||
HANDLE_BEXT_ARG ("--bext-coding-hist", coding_history) ;
|
||||
HANDLE_BEXT_ARG ("--bext-time-ref", time_ref) ;
|
||||
|
||||
#define HANDLE_STR_ARG(cmd, field) \
|
||||
if (strcmp (argv [k], cmd) == 0) \
|
||||
{ k ++ ; \
|
||||
if (k == argc) missing_param (argv [k - 1]) ; \
|
||||
info.field = argv [k] ; \
|
||||
continue ; \
|
||||
} ;
|
||||
|
||||
HANDLE_STR_ARG ("--str-comment", comment) ;
|
||||
HANDLE_STR_ARG ("--str-title", title) ;
|
||||
HANDLE_STR_ARG ("--str-copyright", copyright) ;
|
||||
HANDLE_STR_ARG ("--str-artist", artist) ;
|
||||
HANDLE_STR_ARG ("--str-date", date) ;
|
||||
HANDLE_STR_ARG ("--str-album", album) ;
|
||||
HANDLE_STR_ARG ("--str-license", license) ;
|
||||
|
||||
/* Following options do not take an argument. */
|
||||
if (strcmp (argv [k], "--bext-auto-time-date") == 0)
|
||||
{ snprintf (time, sizeof (time), "%02d:%02d:%02d", timedata.tm_hour, timedata.tm_min, timedata.tm_sec) ;
|
||||
info.origination_time = time ;
|
||||
|
||||
snprintf (date, sizeof (date), "%04d-%02d-%02d", timedata.tm_year + 1900, timedata.tm_mon + 1, timedata.tm_mday) ;
|
||||
info.origination_date = date ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (strcmp (argv [k], "--bext-auto-time") == 0)
|
||||
{ snprintf (time, sizeof (time), "%02d:%02d:%02d", timedata.tm_hour, timedata.tm_min, timedata.tm_sec) ;
|
||||
info.origination_time = time ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (strcmp (argv [k], "--bext-auto-date") == 0)
|
||||
{ snprintf (date, sizeof (date), "%04d-%02d-%02d", timedata.tm_year + 1900, timedata.tm_mon + 1, timedata.tm_mday) ;
|
||||
info.origination_date = strdup (date) ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (strcmp (argv [k], "--str-auto-date") == 0)
|
||||
{ snprintf (date, sizeof (date), "%04d-%02d-%02d", timedata.tm_year + 1900, timedata.tm_mon + 1, timedata.tm_mday) ;
|
||||
|
||||
info.date = strdup (date) ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
printf ("Error : Don't know what to do with command line arg '%s'.\n\n", argv [k]) ;
|
||||
usage_exit (progname, 1) ;
|
||||
} ;
|
||||
|
||||
/* Find out if any of the 'bext' fields are set. */
|
||||
info.has_bext_fields = has_bext_fields_set (&info) ;
|
||||
|
||||
if (filenames [0] == NULL)
|
||||
{ printf ("Error : No input file specificed.\n\n") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
if (filenames [1] != NULL && strcmp (filenames [0], filenames [1]) == 0)
|
||||
{ printf ("Error : Input and output files are the same.\n\n") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
if (info.coding_history != NULL && filenames [1] == NULL)
|
||||
{ printf ("\n"
|
||||
"Error : Trying to update coding history of an existing file which unfortunately\n"
|
||||
" is not supported. Instead, create a new file using :\n"
|
||||
"\n"
|
||||
" %s --bext-coding-hist \"Coding history\" old_file.wav new_file.wav\n"
|
||||
"\n",
|
||||
progname) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
sfe_apply_metadata_changes (filenames, &info) ;
|
||||
|
||||
return 0 ;
|
||||
} /* main */
|
||||
|
||||
/*==============================================================================
|
||||
** Print version and usage.
|
||||
*/
|
||||
|
||||
static void
|
||||
usage_exit (const char *progname, int exit_code)
|
||||
{ printf ("\nUsage :\n\n"
|
||||
" %s [options] <file>\n"
|
||||
" %s [options] <input file> <output file>\n"
|
||||
"\n",
|
||||
progname, progname) ;
|
||||
|
||||
puts (
|
||||
"Where an option is made up of a pair of a field to set (one of\n"
|
||||
"the 'bext' or metadata fields below) and a string. Fields are\n"
|
||||
"as follows :\n"
|
||||
) ;
|
||||
|
||||
puts (
|
||||
" --bext-description Set the 'bext' description.\n"
|
||||
" --bext-originator Set the 'bext' originator.\n"
|
||||
" --bext-orig-ref Set the 'bext' originator reference.\n"
|
||||
" --bext-umid Set the 'bext' UMID.\n"
|
||||
" --bext-orig-date Set the 'bext' origination date.\n"
|
||||
" --bext-orig-time Set the 'bext' origination time.\n"
|
||||
" --bext-loudness-value Set the 'bext' loudness value.\n"
|
||||
" --bext-loudness-range Set the 'bext' loudness range.\n"
|
||||
" --bext-max-truepeak Set the 'bext' max. true peak level\n"
|
||||
" --bext-max-momentary Set the 'bext' max. momentary loudness\n"
|
||||
" --bext-max-shortterm Set the 'bext' max. short term loudness\n"
|
||||
" --bext-coding-hist Set the 'bext' coding history.\n"
|
||||
" --bext-time-ref Set the 'bext' Time ref.\n"
|
||||
"\n"
|
||||
" --str-comment Set the metadata comment.\n"
|
||||
" --str-title Set the metadata title.\n"
|
||||
" --str-copyright Set the metadata copyright.\n"
|
||||
" --str-artist Set the metadata artist.\n"
|
||||
" --str-date Set the metadata date.\n"
|
||||
" --str-album Set the metadata album.\n"
|
||||
" --str-license Set the metadata license.\n"
|
||||
) ;
|
||||
|
||||
puts (
|
||||
"There are also the following arguments which do not take a\n"
|
||||
"parameter :\n\n"
|
||||
" --bext-auto-time-date Set the 'bext' time and date to current time/date.\n"
|
||||
" --bext-auto-time Set the 'bext' time to current time.\n"
|
||||
" --bext-auto-date Set the 'bext' date to current date.\n"
|
||||
" --str-auto-date Set the metadata date to current date.\n"
|
||||
) ;
|
||||
|
||||
puts (
|
||||
"Most of the above operations can be done in-place on an existing\n"
|
||||
"file. If any operation cannot be performed, the application will\n"
|
||||
"exit with an appropriate error message.\n"
|
||||
) ;
|
||||
|
||||
printf ("Using %s.\n\n", sf_version_string ()) ;
|
||||
exit (exit_code) ;
|
||||
} /* usage_exit */
|
||||
|
||||
static void
|
||||
missing_param (const char * option)
|
||||
{
|
||||
printf ("Error : Option '%s' needs a parameter but doesn't seem to have one.\n\n", option) ;
|
||||
exit (1) ;
|
||||
} /* missing_param */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
static int
|
||||
has_bext_fields_set (const METADATA_INFO * info)
|
||||
{
|
||||
if (info->description || info->originator || info->originator_reference)
|
||||
return 1 ;
|
||||
|
||||
if (info->origination_date || info->origination_time || info->umid || info->coding_history || info->time_ref)
|
||||
return 1 ;
|
||||
|
||||
if (info->loudness_value || info->loudness_range || info->max_true_peak_level || info->max_momentary_loudness || info->max_shortterm_loudness)
|
||||
return 1 ;
|
||||
|
||||
return 0 ;
|
||||
} /* has_bext_fields_set */
|
||||
|
||||
static void
|
||||
read_localtime (struct tm * timedata)
|
||||
{ time_t current ;
|
||||
|
||||
time (¤t) ;
|
||||
memset (timedata, 0, sizeof (struct tm)) ;
|
||||
|
||||
#if defined (_WIN32)
|
||||
/* If the re-entrant version is available, use it. */
|
||||
localtime_s (timedata, ¤t) ;
|
||||
#elif defined (HAVE_LOCALTIME_R)
|
||||
/* If the re-entrant version is available, use it. */
|
||||
localtime_r (¤t, timedata) ;
|
||||
#elif defined (HAVE_LOCALTIME)
|
||||
{
|
||||
struct tm *tmptr ;
|
||||
/* Otherwise use the standard one and copy the data to local storage. */
|
||||
if ((tmptr = localtime (¤t)) != NULL)
|
||||
memcpy (timedata, tmptr, sizeof (struct tm)) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ;
|
||||
} /* read_localtime */
|
||||
860
Engine/lib/libsndfile/programs/sndfile-play.c
Normal file
860
Engine/lib/libsndfile/programs/sndfile-play.c
Normal file
|
|
@ -0,0 +1,860 @@
|
|||
/*
|
||||
** Copyright (C) 1999-2018 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the author nor the names of any contributors may be used
|
||||
** to endorse or promote products derived from this software without
|
||||
** specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include "sf_unistd.h"
|
||||
#endif
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if HAVE_ALSA_ASOUNDLIB_H
|
||||
#define ALSA_PCM_NEW_HW_PARAMS_API
|
||||
#define ALSA_PCM_NEW_SW_PARAMS_API
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#if defined (__ANDROID__)
|
||||
|
||||
#elif defined (__linux__) || defined (__FreeBSD_kernel__) || defined (__FreeBSD__) || defined (__riscos__)
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/soundcard.h>
|
||||
|
||||
#elif HAVE_SNDIO_H
|
||||
#include <sndio.h>
|
||||
|
||||
#elif (defined (sun) && defined (unix)) || defined(__NetBSD__)
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/audioio.h>
|
||||
|
||||
#elif (OS_IS_WIN32 == 1)
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
#endif
|
||||
|
||||
#define SIGNED_SIZEOF(x) ((int) sizeof (x))
|
||||
#define BUFFER_LEN (2048)
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Linux/OSS functions for playing a sound.
|
||||
*/
|
||||
|
||||
#if HAVE_ALSA_ASOUNDLIB_H
|
||||
|
||||
static snd_pcm_t * alsa_open (int channels, unsigned srate, int realtime) ;
|
||||
static int alsa_write_float (snd_pcm_t *alsa_dev, float *data, int frames, int channels) ;
|
||||
|
||||
static void
|
||||
alsa_play (int argc, char *argv [])
|
||||
{ static float buffer [BUFFER_LEN] ;
|
||||
SNDFILE *sndfile ;
|
||||
SF_INFO sfinfo ;
|
||||
snd_pcm_t * alsa_dev ;
|
||||
int k, readcount, subformat ;
|
||||
|
||||
for (k = 1 ; k < argc ; k++)
|
||||
{ memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
|
||||
printf ("Playing %s\n", argv [k]) ;
|
||||
if (! (sndfile = sf_open (argv [k], SFM_READ, &sfinfo)))
|
||||
{ puts (sf_strerror (NULL)) ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (sfinfo.channels < 1 || sfinfo.channels > 2)
|
||||
{ printf ("Error : channels = %d.\n", sfinfo.channels) ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if ((alsa_dev = alsa_open (sfinfo.channels, (unsigned) sfinfo.samplerate, SF_FALSE)) == NULL)
|
||||
continue ;
|
||||
|
||||
subformat = sfinfo.format & SF_FORMAT_SUBMASK ;
|
||||
|
||||
if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE)
|
||||
{ double scale ;
|
||||
int m ;
|
||||
|
||||
sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ;
|
||||
if (scale > 1.0)
|
||||
scale = 1.0 / scale ;
|
||||
else
|
||||
scale = 1.0 ;
|
||||
|
||||
while ((readcount = sf_read_float (sndfile, buffer, BUFFER_LEN)))
|
||||
{ for (m = 0 ; m < readcount ; m++)
|
||||
buffer [m] *= scale ;
|
||||
alsa_write_float (alsa_dev, buffer, BUFFER_LEN / sfinfo.channels, sfinfo.channels) ;
|
||||
} ;
|
||||
}
|
||||
else
|
||||
{ while ((readcount = sf_read_float (sndfile, buffer, BUFFER_LEN)))
|
||||
alsa_write_float (alsa_dev, buffer, BUFFER_LEN / sfinfo.channels, sfinfo.channels) ;
|
||||
} ;
|
||||
|
||||
snd_pcm_drain (alsa_dev) ;
|
||||
snd_pcm_close (alsa_dev) ;
|
||||
|
||||
sf_close (sndfile) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* alsa_play */
|
||||
|
||||
static snd_pcm_t *
|
||||
alsa_open (int channels, unsigned samplerate, int realtime)
|
||||
{ const char * device = "default" ;
|
||||
snd_pcm_t *alsa_dev = NULL ;
|
||||
snd_pcm_hw_params_t *hw_params ;
|
||||
snd_pcm_uframes_t buffer_size ;
|
||||
snd_pcm_uframes_t alsa_period_size, alsa_buffer_frames ;
|
||||
snd_pcm_sw_params_t *sw_params ;
|
||||
|
||||
int err ;
|
||||
|
||||
if (realtime)
|
||||
{ alsa_period_size = 256 ;
|
||||
alsa_buffer_frames = 3 * alsa_period_size ;
|
||||
}
|
||||
else
|
||||
{ alsa_period_size = 1024 ;
|
||||
alsa_buffer_frames = 4 * alsa_period_size ;
|
||||
} ;
|
||||
|
||||
if ((err = snd_pcm_open (&alsa_dev, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
|
||||
{ fprintf (stderr, "cannot open audio device \"%s\" (%s)\n", device, snd_strerror (err)) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
snd_pcm_nonblock (alsa_dev, 0) ;
|
||||
|
||||
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0)
|
||||
{ fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
if ((err = snd_pcm_hw_params_any (alsa_dev, hw_params)) < 0)
|
||||
{ fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_access (alsa_dev, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
|
||||
{ fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_format (alsa_dev, hw_params, SND_PCM_FORMAT_FLOAT)) < 0)
|
||||
{ fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_rate_near (alsa_dev, hw_params, &samplerate, 0)) < 0)
|
||||
{ fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_channels (alsa_dev, hw_params, channels)) < 0)
|
||||
{ fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_buffer_size_near (alsa_dev, hw_params, &alsa_buffer_frames)) < 0)
|
||||
{ fprintf (stderr, "cannot set buffer size (%s)\n", snd_strerror (err)) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_period_size_near (alsa_dev, hw_params, &alsa_period_size, 0)) < 0)
|
||||
{ fprintf (stderr, "cannot set period size (%s)\n", snd_strerror (err)) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
if ((err = snd_pcm_hw_params (alsa_dev, hw_params)) < 0)
|
||||
{ fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err)) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
/* extra check: if we have only one period, this code won't work */
|
||||
snd_pcm_hw_params_get_period_size (hw_params, &alsa_period_size, 0) ;
|
||||
snd_pcm_hw_params_get_buffer_size (hw_params, &buffer_size) ;
|
||||
if (alsa_period_size == buffer_size)
|
||||
{ fprintf (stderr, "Can't use period equal to buffer size (%lu == %lu)", alsa_period_size, buffer_size) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
snd_pcm_hw_params_free (hw_params) ;
|
||||
|
||||
if ((err = snd_pcm_sw_params_malloc (&sw_params)) != 0)
|
||||
{ fprintf (stderr, "%s: snd_pcm_sw_params_malloc: %s", __func__, snd_strerror (err)) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
if ((err = snd_pcm_sw_params_current (alsa_dev, sw_params)) != 0)
|
||||
{ fprintf (stderr, "%s: snd_pcm_sw_params_current: %s", __func__, snd_strerror (err)) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
/* note: set start threshold to delay start until the ring buffer is full */
|
||||
snd_pcm_sw_params_current (alsa_dev, sw_params) ;
|
||||
|
||||
if ((err = snd_pcm_sw_params_set_start_threshold (alsa_dev, sw_params, buffer_size)) < 0)
|
||||
{ fprintf (stderr, "cannot set start threshold (%s)\n", snd_strerror (err)) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
if ((err = snd_pcm_sw_params (alsa_dev, sw_params)) != 0)
|
||||
{ fprintf (stderr, "%s: snd_pcm_sw_params: %s", __func__, snd_strerror (err)) ;
|
||||
goto catch_error ;
|
||||
} ;
|
||||
|
||||
snd_pcm_sw_params_free (sw_params) ;
|
||||
|
||||
snd_pcm_reset (alsa_dev) ;
|
||||
|
||||
catch_error :
|
||||
|
||||
if (err < 0 && alsa_dev != NULL)
|
||||
{ snd_pcm_close (alsa_dev) ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
return alsa_dev ;
|
||||
} /* alsa_open */
|
||||
|
||||
static int
|
||||
alsa_write_float (snd_pcm_t *alsa_dev, float *data, int frames, int channels)
|
||||
{ static int epipe_count = 0 ;
|
||||
|
||||
int total = 0 ;
|
||||
int retval ;
|
||||
|
||||
if (epipe_count > 0)
|
||||
epipe_count -- ;
|
||||
|
||||
while (total < frames)
|
||||
{ retval = snd_pcm_writei (alsa_dev, data + total * channels, frames - total) ;
|
||||
|
||||
if (retval >= 0)
|
||||
{ total += retval ;
|
||||
if (total == frames)
|
||||
return total ;
|
||||
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
switch (retval)
|
||||
{ case -EAGAIN :
|
||||
puts ("alsa_write_float: EAGAIN") ;
|
||||
continue ;
|
||||
break ;
|
||||
|
||||
case -EPIPE :
|
||||
if (epipe_count > 0)
|
||||
{ printf ("alsa_write_float: EPIPE %d\n", epipe_count) ;
|
||||
if (epipe_count > 140)
|
||||
return retval ;
|
||||
} ;
|
||||
epipe_count += 100 ;
|
||||
|
||||
#if 0
|
||||
if (0)
|
||||
{ snd_pcm_status_t *status ;
|
||||
|
||||
snd_pcm_status_alloca (&status) ;
|
||||
if ((retval = snd_pcm_status (alsa_dev, status)) < 0)
|
||||
fprintf (stderr, "alsa_out: xrun. can't determine length\n") ;
|
||||
else if (snd_pcm_status_get_state (status) == SND_PCM_STATE_XRUN)
|
||||
{ struct timeval now, diff, tstamp ;
|
||||
|
||||
gettimeofday (&now, 0) ;
|
||||
snd_pcm_status_get_trigger_tstamp (status, &tstamp) ;
|
||||
timersub (&now, &tstamp, &diff) ;
|
||||
|
||||
fprintf (stderr, "alsa_write_float xrun: of at least %.3f msecs. resetting stream\n",
|
||||
diff.tv_sec * 1000 + diff.tv_usec / 1000.0) ;
|
||||
}
|
||||
else
|
||||
fprintf (stderr, "alsa_write_float: xrun. can't determine length\n") ;
|
||||
} ;
|
||||
#endif
|
||||
|
||||
snd_pcm_prepare (alsa_dev) ;
|
||||
break ;
|
||||
|
||||
case -EBADFD :
|
||||
fprintf (stderr, "alsa_write_float: Bad PCM state.n") ;
|
||||
return 0 ;
|
||||
break ;
|
||||
|
||||
#if defined ESTRPIPE && ESTRPIPE != EPIPE
|
||||
case -ESTRPIPE :
|
||||
fprintf (stderr, "alsa_write_float: Suspend event.n") ;
|
||||
return 0 ;
|
||||
break ;
|
||||
#endif
|
||||
|
||||
case -EIO :
|
||||
puts ("alsa_write_float: EIO") ;
|
||||
return 0 ;
|
||||
|
||||
default :
|
||||
fprintf (stderr, "alsa_write_float: retval = %d\n", retval) ;
|
||||
return 0 ;
|
||||
break ;
|
||||
} ; /* switch */
|
||||
} ; /* while */
|
||||
|
||||
return total ;
|
||||
} /* alsa_write_float */
|
||||
|
||||
#endif /* HAVE_ALSA_ASOUNDLIB_H */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Linux/OSS functions for playing a sound.
|
||||
*/
|
||||
|
||||
#if !defined (__ANDROID__) && (defined (__linux__) || defined (__FreeBSD_kernel__) || defined (__FreeBSD__) || defined (__riscos__))
|
||||
|
||||
static int opensoundsys_open_device (int channels, int srate) ;
|
||||
|
||||
static int
|
||||
opensoundsys_play (int argc, char *argv [])
|
||||
{ static short buffer [BUFFER_LEN] ;
|
||||
SNDFILE *sndfile ;
|
||||
SF_INFO sfinfo ;
|
||||
int k, audio_device, readcount, writecount, subformat ;
|
||||
|
||||
for (k = 1 ; k < argc ; k++)
|
||||
{ memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
|
||||
printf ("Playing %s\n", argv [k]) ;
|
||||
if (! (sndfile = sf_open (argv [k], SFM_READ, &sfinfo)))
|
||||
{ puts (sf_strerror (NULL)) ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (sfinfo.channels < 1 || sfinfo.channels > 2)
|
||||
{ printf ("Error : channels = %d.\n", sfinfo.channels) ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
audio_device = opensoundsys_open_device (sfinfo.channels, sfinfo.samplerate) ;
|
||||
|
||||
subformat = sfinfo.format & SF_FORMAT_SUBMASK ;
|
||||
|
||||
if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE)
|
||||
{ static float float_buffer [BUFFER_LEN] ;
|
||||
double scale ;
|
||||
int m ;
|
||||
|
||||
sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ;
|
||||
if (scale < 1e-10)
|
||||
scale = 1.0 ;
|
||||
else
|
||||
scale = 32700.0 / scale ;
|
||||
|
||||
while ((readcount = sf_read_float (sndfile, float_buffer, BUFFER_LEN)))
|
||||
{ for (m = 0 ; m < readcount ; m++)
|
||||
buffer [m] = scale * float_buffer [m] ;
|
||||
writecount = write (audio_device, buffer, readcount * sizeof (short)) ;
|
||||
} ;
|
||||
}
|
||||
else
|
||||
{ while ((readcount = sf_read_short (sndfile, buffer, BUFFER_LEN)))
|
||||
writecount = write (audio_device, buffer, readcount * sizeof (short)) ;
|
||||
} ;
|
||||
|
||||
if (ioctl (audio_device, SNDCTL_DSP_POST, 0) == -1)
|
||||
perror ("ioctl (SNDCTL_DSP_POST) ") ;
|
||||
|
||||
if (ioctl (audio_device, SNDCTL_DSP_SYNC, 0) == -1)
|
||||
perror ("ioctl (SNDCTL_DSP_SYNC) ") ;
|
||||
|
||||
close (audio_device) ;
|
||||
|
||||
sf_close (sndfile) ;
|
||||
} ;
|
||||
|
||||
return writecount ;
|
||||
} /* opensoundsys_play */
|
||||
|
||||
static int
|
||||
opensoundsys_open_device (int channels, int srate)
|
||||
{ int fd, stereo, fmt ;
|
||||
|
||||
if ((fd = open ("/dev/dsp", O_WRONLY, 0)) == -1 &&
|
||||
(fd = open ("/dev/sound/dsp", O_WRONLY, 0)) == -1)
|
||||
{ perror ("opensoundsys_open_device : open ") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
stereo = 0 ;
|
||||
if (ioctl (fd, SNDCTL_DSP_STEREO, &stereo) == -1)
|
||||
{ /* Fatal error */
|
||||
perror ("opensoundsys_open_device : stereo ") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
if (ioctl (fd, SNDCTL_DSP_RESET, 0))
|
||||
{ perror ("opensoundsys_open_device : reset ") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
fmt = CPU_IS_BIG_ENDIAN ? AFMT_S16_BE : AFMT_S16_LE ;
|
||||
if (ioctl (fd, SNDCTL_DSP_SETFMT, &fmt) != 0)
|
||||
{ perror ("opensoundsys_open_device : set format ") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
if (ioctl (fd, SNDCTL_DSP_CHANNELS, &channels) != 0)
|
||||
{ perror ("opensoundsys_open_device : channels ") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
if (ioctl (fd, SNDCTL_DSP_SPEED, &srate) != 0)
|
||||
{ perror ("opensoundsys_open_device : sample rate ") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
if (ioctl (fd, SNDCTL_DSP_SYNC, 0) != 0)
|
||||
{ perror ("opensoundsys_open_device : sync ") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
return fd ;
|
||||
} /* opensoundsys_open_device */
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Mac OS X functions for playing a sound.
|
||||
*/
|
||||
|
||||
/* MacOSX 10.8 use a new Audio API. Someone needs to write some code for it. */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Win32 functions for playing a sound.
|
||||
**
|
||||
** This API sucks. Its needlessly complicated and is *WAY* too loose with
|
||||
** passing pointers around in integers and using char* pointers to
|
||||
** point to data instead of short*. It plain sucks!
|
||||
*/
|
||||
|
||||
#if (OS_IS_WIN32 == 1)
|
||||
|
||||
#define WIN32_BUFFER_LEN (1 << 15)
|
||||
|
||||
typedef struct
|
||||
{ HWAVEOUT hwave ;
|
||||
WAVEHDR whdr [2] ;
|
||||
|
||||
CRITICAL_SECTION mutex ; /* to control access to BuffersInUSe */
|
||||
HANDLE Event ; /* signal that a buffer is free */
|
||||
|
||||
short buffer [WIN32_BUFFER_LEN / sizeof (short)] ;
|
||||
int current, bufferlen ;
|
||||
int BuffersInUse ;
|
||||
|
||||
SNDFILE *sndfile ;
|
||||
SF_INFO sfinfo ;
|
||||
|
||||
sf_count_t remaining ;
|
||||
} Win32_Audio_Data ;
|
||||
|
||||
|
||||
static void
|
||||
win32_play_data (Win32_Audio_Data *audio_data)
|
||||
{ int thisread, readcount ;
|
||||
|
||||
/* fill a buffer if there is more data and we can read it sucessfully */
|
||||
readcount = (audio_data->remaining > audio_data->bufferlen) ? audio_data->bufferlen : (int) audio_data->remaining ;
|
||||
|
||||
short *lpData = (short *) (void *) audio_data->whdr [audio_data->current].lpData ;
|
||||
thisread = (int) sf_read_short (audio_data->sndfile, lpData, readcount) ;
|
||||
|
||||
audio_data->remaining -= thisread ;
|
||||
|
||||
if (thisread > 0)
|
||||
{ /* Fix buffer length if this is only a partial block. */
|
||||
if (thisread < audio_data->bufferlen)
|
||||
audio_data->whdr [audio_data->current].dwBufferLength = thisread * sizeof (short) ;
|
||||
|
||||
/* Queue the WAVEHDR */
|
||||
waveOutWrite (audio_data->hwave, (LPWAVEHDR) &(audio_data->whdr [audio_data->current]), sizeof (WAVEHDR)) ;
|
||||
|
||||
/* count another buffer in use */
|
||||
EnterCriticalSection (&audio_data->mutex) ;
|
||||
audio_data->BuffersInUse ++ ;
|
||||
LeaveCriticalSection (&audio_data->mutex) ;
|
||||
|
||||
/* use the other buffer next time */
|
||||
audio_data->current = (audio_data->current + 1) % 2 ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* win32_play_data */
|
||||
|
||||
static void CALLBACK
|
||||
win32_audio_out_callback (HWAVEOUT hwave, UINT msg, DWORD_PTR data, DWORD param1, DWORD param2)
|
||||
{ Win32_Audio_Data *audio_data ;
|
||||
|
||||
/* Prevent compiler warnings. */
|
||||
(void) hwave ;
|
||||
(void) param1 ;
|
||||
(void) param2 ;
|
||||
|
||||
if (data == 0)
|
||||
return ;
|
||||
|
||||
/*
|
||||
** I consider this technique of passing a pointer via an integer as
|
||||
** fundamentally broken but thats the way microsoft has defined the
|
||||
** interface.
|
||||
*/
|
||||
audio_data = (Win32_Audio_Data*) data ;
|
||||
|
||||
/* let main loop know a buffer is free */
|
||||
if (msg == MM_WOM_DONE)
|
||||
{ EnterCriticalSection (&audio_data->mutex) ;
|
||||
audio_data->BuffersInUse -- ;
|
||||
LeaveCriticalSection (&audio_data->mutex) ;
|
||||
SetEvent (audio_data->Event) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* win32_audio_out_callback */
|
||||
|
||||
static void
|
||||
win32_play (int argc, char *argv [])
|
||||
{ Win32_Audio_Data audio_data ;
|
||||
|
||||
WAVEFORMATEX wf ;
|
||||
int k, error ;
|
||||
|
||||
audio_data.sndfile = NULL ;
|
||||
audio_data.hwave = 0 ;
|
||||
|
||||
for (k = 1 ; k < argc ; k++)
|
||||
{ printf ("Playing %s\n", argv [k]) ;
|
||||
|
||||
if (! (audio_data.sndfile = sf_open (argv [k], SFM_READ, &(audio_data.sfinfo))))
|
||||
{ puts (sf_strerror (NULL)) ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
audio_data.remaining = audio_data.sfinfo.frames * audio_data.sfinfo.channels ;
|
||||
audio_data.current = 0 ;
|
||||
|
||||
InitializeCriticalSection (&audio_data.mutex) ;
|
||||
audio_data.Event = CreateEvent (0, FALSE, FALSE, 0) ;
|
||||
|
||||
wf.nChannels = audio_data.sfinfo.channels ;
|
||||
wf.wFormatTag = WAVE_FORMAT_PCM ;
|
||||
wf.cbSize = 0 ;
|
||||
wf.wBitsPerSample = 16 ;
|
||||
|
||||
wf.nSamplesPerSec = audio_data.sfinfo.samplerate ;
|
||||
|
||||
wf.nBlockAlign = audio_data.sfinfo.channels * sizeof (short) ;
|
||||
|
||||
wf.nAvgBytesPerSec = wf.nBlockAlign * wf.nSamplesPerSec ;
|
||||
|
||||
error = waveOutOpen (&(audio_data.hwave), WAVE_MAPPER, &wf, (DWORD_PTR) win32_audio_out_callback,
|
||||
(DWORD_PTR) &audio_data, CALLBACK_FUNCTION) ;
|
||||
if (error)
|
||||
{ puts ("waveOutOpen failed.") ;
|
||||
audio_data.hwave = 0 ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
audio_data.whdr [0].lpData = (char*) audio_data.buffer ;
|
||||
audio_data.whdr [1].lpData = ((char*) audio_data.buffer) + sizeof (audio_data.buffer) / 2 ;
|
||||
|
||||
audio_data.whdr [0].dwBufferLength = sizeof (audio_data.buffer) / 2 ;
|
||||
audio_data.whdr [1].dwBufferLength = sizeof (audio_data.buffer) / 2 ;
|
||||
|
||||
audio_data.whdr [0].dwFlags = 0 ;
|
||||
audio_data.whdr [1].dwFlags = 0 ;
|
||||
|
||||
/* length of each audio buffer in samples */
|
||||
audio_data.bufferlen = sizeof (audio_data.buffer) / 2 / sizeof (short) ;
|
||||
|
||||
/* Prepare the WAVEHDRs */
|
||||
if ((error = waveOutPrepareHeader (audio_data.hwave, &(audio_data.whdr [0]), sizeof (WAVEHDR))))
|
||||
{ printf ("waveOutPrepareHeader [0] failed : %08X\n", error) ;
|
||||
waveOutClose (audio_data.hwave) ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if ((error = waveOutPrepareHeader (audio_data.hwave, &(audio_data.whdr [1]), sizeof (WAVEHDR))))
|
||||
{ printf ("waveOutPrepareHeader [1] failed : %08X\n", error) ;
|
||||
waveOutUnprepareHeader (audio_data.hwave, &(audio_data.whdr [0]), sizeof (WAVEHDR)) ;
|
||||
waveOutClose (audio_data.hwave) ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
/* Fill up both buffers with audio data */
|
||||
audio_data.BuffersInUse = 0 ;
|
||||
win32_play_data (&audio_data) ;
|
||||
win32_play_data (&audio_data) ;
|
||||
|
||||
/* loop until both buffers are released */
|
||||
while (audio_data.BuffersInUse > 0)
|
||||
{
|
||||
/* wait for buffer to be released */
|
||||
WaitForSingleObject (audio_data.Event, INFINITE) ;
|
||||
|
||||
/* refill the buffer if there is more data to play */
|
||||
win32_play_data (&audio_data) ;
|
||||
} ;
|
||||
|
||||
waveOutUnprepareHeader (audio_data.hwave, &(audio_data.whdr [0]), sizeof (WAVEHDR)) ;
|
||||
waveOutUnprepareHeader (audio_data.hwave, &(audio_data.whdr [1]), sizeof (WAVEHDR)) ;
|
||||
|
||||
waveOutClose (audio_data.hwave) ;
|
||||
audio_data.hwave = 0 ;
|
||||
|
||||
DeleteCriticalSection (&audio_data.mutex) ;
|
||||
|
||||
sf_close (audio_data.sndfile) ;
|
||||
} ;
|
||||
|
||||
} /* win32_play */
|
||||
|
||||
#endif /* Win32 */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** OpenBSD's sndio.
|
||||
*/
|
||||
|
||||
#if HAVE_SNDIO_H
|
||||
|
||||
static void
|
||||
sndio_play (int argc, char *argv [])
|
||||
{ struct sio_hdl *hdl ;
|
||||
struct sio_par par ;
|
||||
short buffer [BUFFER_LEN] ;
|
||||
SNDFILE *sndfile ;
|
||||
SF_INFO sfinfo ;
|
||||
int k, readcount ;
|
||||
|
||||
for (k = 1 ; k < argc ; k++)
|
||||
{ printf ("Playing %s\n", argv [k]) ;
|
||||
if (! (sndfile = sf_open (argv [k], SFM_READ, &sfinfo)))
|
||||
{ puts (sf_strerror (NULL)) ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (sfinfo.channels < 1 || sfinfo.channels > 2)
|
||||
{ printf ("Error : channels = %d.\n", sfinfo.channels) ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if ((hdl = sio_open (NULL, SIO_PLAY, 0)) == NULL)
|
||||
{ fprintf (stderr, "open sndio device failed") ;
|
||||
return ;
|
||||
} ;
|
||||
|
||||
sio_initpar (&par) ;
|
||||
par.rate = sfinfo.samplerate ;
|
||||
par.pchan = sfinfo.channels ;
|
||||
par.bits = 16 ;
|
||||
par.sig = 1 ;
|
||||
par.le = SIO_LE_NATIVE ;
|
||||
|
||||
if (! sio_setpar (hdl, &par) || ! sio_getpar (hdl, &par))
|
||||
{ fprintf (stderr, "set sndio params failed") ;
|
||||
return ;
|
||||
} ;
|
||||
|
||||
if (! sio_start (hdl))
|
||||
{ fprintf (stderr, "sndio start failed") ;
|
||||
return ;
|
||||
} ;
|
||||
|
||||
while ((readcount = sf_read_short (sndfile, buffer, BUFFER_LEN)))
|
||||
sio_write (hdl, buffer, readcount * sizeof (short)) ;
|
||||
|
||||
sio_close (hdl) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* sndio_play */
|
||||
|
||||
#endif /* sndio */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Solaris.
|
||||
*/
|
||||
|
||||
#if (defined (sun) && defined (unix)) || defined(__NetBSD__)
|
||||
|
||||
static void
|
||||
solaris_play (int argc, char *argv [])
|
||||
{ static short buffer [BUFFER_LEN] ;
|
||||
audio_info_t audio_info ;
|
||||
SNDFILE *sndfile ;
|
||||
SF_INFO sfinfo ;
|
||||
unsigned long delay_time ;
|
||||
long k, start_count, output_count, write_count, read_count ;
|
||||
int audio_fd, error, done ;
|
||||
|
||||
for (k = 1 ; k < argc ; k++)
|
||||
{ printf ("Playing %s\n", argv [k]) ;
|
||||
if (! (sndfile = sf_open (argv [k], SFM_READ, &sfinfo)))
|
||||
{ puts (sf_strerror (NULL)) ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (sfinfo.channels < 1 || sfinfo.channels > 2)
|
||||
{ printf ("Error : channels = %d.\n", sfinfo.channels) ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
/* open the audio device - write only, non-blocking */
|
||||
if ((audio_fd = open ("/dev/audio", O_WRONLY | O_NONBLOCK)) < 0)
|
||||
{ perror ("open (/dev/audio) failed") ;
|
||||
return ;
|
||||
} ;
|
||||
|
||||
/* Retrive standard values. */
|
||||
AUDIO_INITINFO (&audio_info) ;
|
||||
|
||||
audio_info.play.sample_rate = sfinfo.samplerate ;
|
||||
audio_info.play.channels = sfinfo.channels ;
|
||||
audio_info.play.precision = 16 ;
|
||||
audio_info.play.encoding = AUDIO_ENCODING_LINEAR ;
|
||||
|
||||
if ((error = ioctl (audio_fd, AUDIO_SETINFO, &audio_info)))
|
||||
{ perror ("ioctl (AUDIO_SETINFO) failed") ;
|
||||
return ;
|
||||
} ;
|
||||
|
||||
/* Delay time equal to 1/4 of a buffer in microseconds. */
|
||||
delay_time = (BUFFER_LEN * 1000000) / (audio_info.play.sample_rate * 4) ;
|
||||
|
||||
done = 0 ;
|
||||
while (! done)
|
||||
{ read_count = sf_read_short (sndfile, buffer, BUFFER_LEN) ;
|
||||
if (read_count < BUFFER_LEN)
|
||||
{ memset (&(buffer [read_count]), 0, (BUFFER_LEN - read_count) * sizeof (short)) ;
|
||||
/* Tell the main application to terminate. */
|
||||
done = SF_TRUE ;
|
||||
} ;
|
||||
|
||||
start_count = 0 ;
|
||||
output_count = BUFFER_LEN * sizeof (short) ;
|
||||
|
||||
while (output_count > 0)
|
||||
{ /* write as much data as possible */
|
||||
write_count = write (audio_fd, &(buffer [start_count]), output_count) ;
|
||||
if (write_count > 0)
|
||||
{ output_count -= write_count ;
|
||||
start_count += write_count ;
|
||||
}
|
||||
else
|
||||
{ /* Give the audio output time to catch up. */
|
||||
usleep (delay_time) ;
|
||||
} ;
|
||||
} ; /* while (outpur_count > 0) */
|
||||
} ; /* while (! done) */
|
||||
|
||||
close (audio_fd) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* solaris_play */
|
||||
|
||||
#endif /* Solaris or NetBSD */
|
||||
|
||||
/*==============================================================================
|
||||
** Main function.
|
||||
*/
|
||||
|
||||
int
|
||||
main (int argc, char *argv [])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
printf ("\nUsage : %s <input sound file>\n\n", program_name (argv [0])) ;
|
||||
printf ("Using %s.\n\n", sf_version_string ()) ;
|
||||
#if (OS_IS_WIN32 == 1)
|
||||
printf ("This is a Unix style command line application which\n"
|
||||
"should be run in a MSDOS box or Command Shell window.\n\n") ;
|
||||
printf ("Sleeping for 5 seconds before exiting.\n\n") ;
|
||||
|
||||
Sleep (5 * 1000) ;
|
||||
#endif
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
#if defined (__ANDROID__)
|
||||
puts ("*** Playing sound not yet supported on Android.") ;
|
||||
puts ("*** Please feel free to submit a patch.") ;
|
||||
return 1 ;
|
||||
#elif defined (__linux__)
|
||||
#if HAVE_ALSA_ASOUNDLIB_H
|
||||
if (access ("/proc/asound/cards", R_OK) == 0)
|
||||
alsa_play (argc, argv) ;
|
||||
else
|
||||
#endif
|
||||
opensoundsys_play (argc, argv) ;
|
||||
#elif defined (__FreeBSD_kernel__) || defined (__FreeBSD__) || defined (__riscos__)
|
||||
opensoundsys_play (argc, argv) ;
|
||||
#elif HAVE_SNDIO_H
|
||||
sndio_play (argc, argv) ;
|
||||
#elif (defined (sun) && defined (unix)) || defined(__NetBSD__)
|
||||
solaris_play (argc, argv) ;
|
||||
#elif (OS_IS_WIN32 == 1)
|
||||
win32_play (argc, argv) ;
|
||||
#else
|
||||
puts ("*** Playing sound not supported on this platform.") ;
|
||||
puts ("*** Please feel free to submit a patch.") ;
|
||||
return 1 ;
|
||||
#endif
|
||||
|
||||
return 0 ;
|
||||
} /* main */
|
||||
|
||||
302
Engine/lib/libsndfile/programs/sndfile-salvage.c
Normal file
302
Engine/lib/libsndfile/programs/sndfile-salvage.c
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
** Copyright (C) 2010-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the author nor the names of any contributors may be used
|
||||
** to endorse or promote products derived from this software without
|
||||
** specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include "sf_unistd.h"
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define BUFFER_LEN (1 << 16)
|
||||
|
||||
#define NOT(x) (! (x))
|
||||
|
||||
#ifndef _WIN32
|
||||
typedef off_t sf_off_t ;
|
||||
#else
|
||||
typedef long long sf_off_t ;
|
||||
#endif
|
||||
|
||||
|
||||
static void usage_exit (const char *progname) ;
|
||||
static void salvage_file (const char * broken_wav, const char * fixed_w64) ;
|
||||
|
||||
int
|
||||
main (int argc, char *argv [])
|
||||
{
|
||||
if (argc != 3)
|
||||
usage_exit (program_name (argv [0])) ;
|
||||
|
||||
salvage_file (argv [1], argv [2]) ;
|
||||
|
||||
return 0 ;
|
||||
} /* main */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
static void lseek_or_die (int fd, sf_off_t offset, int whence) ;
|
||||
static sf_off_t get_file_length (int fd, const char * name) ;
|
||||
static sf_count_t find_data_offset (int fd, int format) ;
|
||||
static void copy_data (int fd, SNDFILE * sndfile, int readsize) ;
|
||||
|
||||
|
||||
static void
|
||||
usage_exit (const char *progname)
|
||||
{ printf ("Usage :\n\n %s <broken wav file> <fixed w64 file>\n\n", progname) ;
|
||||
puts ("Salvages the audio data from WAV files which are more than 4G in length.\n") ;
|
||||
printf ("Using %s.\n\n", sf_version_string ()) ;
|
||||
exit (1) ;
|
||||
} /* usage_exit */
|
||||
|
||||
static void
|
||||
salvage_file (const char * broken_wav, const char * fixed_w64)
|
||||
{ SNDFILE * sndfile ;
|
||||
SF_INFO sfinfo ;
|
||||
sf_count_t broken_len, data_offset ;
|
||||
int fd, read_size ;
|
||||
|
||||
if (strcmp (broken_wav, fixed_w64) == 0)
|
||||
{ printf ("Error : Input and output files must be different.\n\n") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
if ((fd = open (broken_wav, O_RDONLY)) < 0)
|
||||
{ printf ("Error : Not able to open file '%s' : %s\n", broken_wav, strerror (errno)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
broken_len = get_file_length (fd, broken_wav) ;
|
||||
if (broken_len <= 0xffffffff)
|
||||
printf ("File is not greater than 4Gig but salvaging anyway.\n") ;
|
||||
|
||||
/* Grab the format info from the broken file. */
|
||||
memset (&sfinfo, 0, sizeof (sfinfo)) ;
|
||||
if ((sndfile = sf_open (broken_wav, SFM_READ, &sfinfo)) == NULL)
|
||||
{ printf ("sf_open ('%s') failed : %s\n", broken_wav, sf_strerror (NULL)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
sf_close (sndfile) ;
|
||||
|
||||
data_offset = find_data_offset (fd, sfinfo.format & SF_FORMAT_TYPEMASK) ;
|
||||
|
||||
printf ("Offset to audio data : %" PRId64 "\n", data_offset) ;
|
||||
|
||||
switch (sfinfo.format & SF_FORMAT_TYPEMASK)
|
||||
{ case SF_FORMAT_WAV :
|
||||
case SF_FORMAT_WAVEX :
|
||||
sfinfo.format = SF_FORMAT_W64 | (sfinfo.format & SF_FORMAT_SUBMASK) ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
printf ("Don't currently support this file type.\n") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
switch (sfinfo.format & SF_FORMAT_SUBMASK)
|
||||
{ case SF_FORMAT_PCM_U8 :
|
||||
case SF_FORMAT_PCM_S8 :
|
||||
read_size = 1 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_16 :
|
||||
read_size = 2 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_24 :
|
||||
read_size = 3 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_32 :
|
||||
case SF_FORMAT_FLOAT :
|
||||
read_size = 4 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DOUBLE :
|
||||
read_size = 8 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
printf ("Sorry, don't currently support this file encoding type.\n") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
read_size *= sfinfo.channels ;
|
||||
|
||||
if ((sndfile = sf_open (fixed_w64, SFM_WRITE, &sfinfo)) == NULL)
|
||||
{ printf ("sf_open ('%s') failed : %s\n", fixed_w64, sf_strerror (NULL)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
lseek_or_die (fd, data_offset, SEEK_SET) ;
|
||||
|
||||
copy_data (fd, sndfile, read_size) ;
|
||||
|
||||
sf_close (sndfile) ;
|
||||
|
||||
puts ("Done!") ;
|
||||
} /* salvage_file */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
lseek_or_die (int fd, sf_off_t offset, int whence)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
if (lseek (fd, offset, whence) < 0)
|
||||
#else
|
||||
if (_lseeki64 (fd, offset, whence) < 0)
|
||||
#endif
|
||||
{ printf ("lseek failed : %s\n", strerror (errno)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* lseek_or_die */
|
||||
|
||||
|
||||
static sf_off_t
|
||||
get_file_length (int fd, const char * name)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
struct stat sbuf ;
|
||||
#else
|
||||
struct _stat64 sbuf ;
|
||||
#endif
|
||||
|
||||
if (sizeof (sbuf.st_size) != 8)
|
||||
{ puts ("Error : sizeof (sbuf.st_size) != 8. Was program compiled with\n"
|
||||
" 64 bit file offsets?\n") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
#ifndef _WIN32
|
||||
if (fstat (fd, &sbuf) != 0)
|
||||
#else
|
||||
if (_fstat64 (fd, &sbuf) != 0)
|
||||
#endif
|
||||
{ printf ("Error : fstat ('%s') failed : %s\n", name, strerror (errno)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
return sbuf.st_size ;
|
||||
} /* get_file_length */
|
||||
|
||||
static sf_count_t
|
||||
find_data_offset (int fd, int format)
|
||||
{ char buffer [8192], *cptr ;
|
||||
const char * target = "XXXX" ;
|
||||
sf_count_t offset = -1, extra ;
|
||||
int rlen, slen ;
|
||||
|
||||
switch (format)
|
||||
{ case SF_FORMAT_WAV :
|
||||
case SF_FORMAT_WAVEX :
|
||||
target = "data" ;
|
||||
extra = 8 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_AIFF :
|
||||
target = "SSND" ;
|
||||
extra = 16 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
puts ("Error : Sorry, don't handle this input file format.\n") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
slen = (int) strlen (target) ;
|
||||
|
||||
lseek_or_die (fd, 0, SEEK_SET) ;
|
||||
|
||||
printf ("Searching for '%s' maker.\n", target) ;
|
||||
|
||||
if ((rlen = read (fd, buffer, sizeof (buffer))) < 0)
|
||||
{ printf ("Error : failed read : %s\n", strerror (errno)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
cptr = memchr (buffer, target [0], rlen - slen) ;
|
||||
if (cptr && memcmp (cptr, target, slen) == 0)
|
||||
offset = cptr - buffer ;
|
||||
else
|
||||
{ printf ("Error : Could not find data offset.\n") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
return offset + extra ;
|
||||
} /* find_data_offset */
|
||||
|
||||
static void
|
||||
copy_data (int fd, SNDFILE * sndfile, int readsize)
|
||||
{ static char * buffer ;
|
||||
sf_count_t readlen, count ;
|
||||
int bufferlen, done = 0 ;
|
||||
|
||||
bufferlen = readsize * 1024 ;
|
||||
buffer = malloc (bufferlen) ;
|
||||
|
||||
while (NOT (done) && (readlen = read (fd, buffer, bufferlen)) >= 0)
|
||||
{ if (readlen < bufferlen)
|
||||
{ readlen -= readlen % readsize ;
|
||||
done = 1 ;
|
||||
} ;
|
||||
|
||||
if ((count = sf_write_raw (sndfile, buffer, readlen)) != readlen)
|
||||
{ printf ("Error : sf_write_raw returned %" PRId64 " : %s\n", count, sf_strerror (sndfile)) ;
|
||||
return ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
free (buffer) ;
|
||||
|
||||
return ;
|
||||
} /* copy_data */
|
||||
|
||||
198
Engine/lib/libsndfile/programs/test-sndfile-metadata-set.py
Normal file
198
Engine/lib/libsndfile/programs/test-sndfile-metadata-set.py
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (C) 2008-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the author nor the names of any contributors may be used
|
||||
# to endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# Simple test script for the sndfile-metadata-set program.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
try:
|
||||
# py2
|
||||
import commands
|
||||
except ImportError:
|
||||
# py3
|
||||
import subprocess as commands
|
||||
|
||||
import os, sys
|
||||
import time, datetime
|
||||
|
||||
class Programs:
|
||||
def __init__ (self, needs_exe):
|
||||
if needs_exe:
|
||||
extension = ".exe"
|
||||
else:
|
||||
extension = ""
|
||||
self.meta_set_prog = "./sndfile-metadata-set" + extension
|
||||
self.meta_get_prog = "./sndfile-metadata-get" + extension
|
||||
self.make_sine_prog = "../examples/make_sine" + extension
|
||||
|
||||
def _run_command (self, should_fail, cmd):
|
||||
status, output = commands.getstatusoutput (cmd)
|
||||
if should_fail and not status:
|
||||
print("\n\nError : command '%s' should have failed." % cmd)
|
||||
print(output)
|
||||
print()
|
||||
sys.exit (1)
|
||||
if not should_fail and status:
|
||||
print("\n\nError : command '%s' should not have failed." % cmd)
|
||||
print(output)
|
||||
print()
|
||||
sys.exit (1)
|
||||
return output
|
||||
|
||||
def meta_set (self, should_fail, args):
|
||||
return self._run_command (should_fail, self.meta_set_prog + " " + args)
|
||||
|
||||
def meta_get (self, should_fail, args):
|
||||
return self._run_command (should_fail, self.meta_get_prog + " " + args)
|
||||
|
||||
def make_sine (self):
|
||||
return os.system (self.make_sine_prog)
|
||||
|
||||
def check_executables (self):
|
||||
for name in [ self.meta_set_prog, self.meta_get_prog, self.make_sine_prog ]:
|
||||
if not (os.path.isfile (name)):
|
||||
print("\n\nError : Can't find executable '%s'. Have you run make?" % name)
|
||||
sys.exit (1)
|
||||
|
||||
|
||||
def print_test_name (name):
|
||||
print(" %-30s :" % name, end="")
|
||||
|
||||
def assert_info (programs, filename, arg, value):
|
||||
output = programs.meta_get (False, "%s %s" % (arg, filename))
|
||||
if output.find (value) < 0:
|
||||
print("\n\nError : not able to find '%s'." % value)
|
||||
print(output)
|
||||
sys.exit (1)
|
||||
return
|
||||
|
||||
|
||||
def test_empty_fail (programs):
|
||||
print_test_name ("Empty fail test")
|
||||
output = programs.meta_set (True, "--bext-description Alpha sine.wav")
|
||||
print("ok")
|
||||
|
||||
def test_copy (programs):
|
||||
print_test_name ("Copy test")
|
||||
output = programs.meta_set (False, "--bext-description \"First Try\" sine.wav output.wav")
|
||||
assert_info (programs, "output.wav", "--bext-description", "First Try")
|
||||
print("ok")
|
||||
|
||||
def test_update (programs, tests):
|
||||
print_test_name ("Update test")
|
||||
for arg, value in tests:
|
||||
output = programs.meta_set (False, "%s \"%s\" output.wav" % (arg, value))
|
||||
assert_info (programs, "output.wav", arg, value)
|
||||
print("ok")
|
||||
|
||||
def test_post_mod (programs, tests):
|
||||
print_test_name ("Post mod test")
|
||||
for arg, value in tests:
|
||||
assert_info (programs, "output.wav", arg, value)
|
||||
print("ok")
|
||||
|
||||
def test_auto_date (programs):
|
||||
print_test_name ("Auto date test")
|
||||
output = programs.meta_set (False, "--bext-auto-time-date sine.wav date-time.wav")
|
||||
target = datetime.date.today ().__str__ ()
|
||||
assert_info (programs, "date-time.wav", "--bext-orig-date", target)
|
||||
print("ok")
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def test_coding_history (programs):
|
||||
print_test_name ("Coding history test")
|
||||
output = programs.meta_set (False, "--bext-coding-hist \"alpha beta\" output.wav")
|
||||
output = programs.meta_get (False, "--bext-coding-hist output.wav")
|
||||
print("ok")
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def test_rewrite (programs):
|
||||
print_test_name ("Rewrite test")
|
||||
output = programs.meta_set (False, "--bext-originator \"Really, really long string\" output.wav")
|
||||
output = programs.meta_set (False, "--bext-originator \"Short\" output.wav")
|
||||
output = programs.meta_get (False, "--bext-originator output.wav")
|
||||
if output.find ("really long") > 0:
|
||||
print("\n\nError : output '%s' should not contain 'really long'." % output)
|
||||
sys.exit (1)
|
||||
print("ok")
|
||||
|
||||
#===============================================================================
|
||||
|
||||
test_dir = "programs"
|
||||
|
||||
print("\nTesting WAV metadata manipulation:")
|
||||
|
||||
if os.path.isdir (test_dir):
|
||||
os.chdir (test_dir)
|
||||
|
||||
if len (sys.argv) >= 1 and sys.argv [1].endswith ("mingw32"):
|
||||
needs_exe = True
|
||||
else:
|
||||
needs_exe = False
|
||||
|
||||
programs = Programs (needs_exe)
|
||||
|
||||
programs.check_executables ()
|
||||
|
||||
programs.make_sine ()
|
||||
if not os.path.isfile ("sine.wav"):
|
||||
print("\n\nError : Can't file file 'sine.wav'.")
|
||||
sys.exit (1)
|
||||
|
||||
test_empty_fail (programs)
|
||||
test_copy (programs)
|
||||
|
||||
tests = [
|
||||
("--bext-description", "Alpha"), ("--bext-originator", "Beta"), ("--bext-orig-ref", "Charlie"),
|
||||
("--bext-umid", "Delta"), ("--bext-orig-date", "2001-10-01"), ("--bext-orig-time", "01:02:03"),
|
||||
("--str-title", "Echo"), ("--str-artist", "Fox trot")
|
||||
]
|
||||
|
||||
test_auto_date (programs)
|
||||
test_update (programs, tests)
|
||||
test_post_mod (programs, tests)
|
||||
|
||||
test_update (programs, [ ("--str-artist", "Fox") ])
|
||||
|
||||
# This never worked.
|
||||
# test_coding_history ()
|
||||
|
||||
test_rewrite (programs)
|
||||
|
||||
|
||||
print()
|
||||
|
||||
sys.exit (0)
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue