annotate src/libsndfile-1.0.25/programs/common.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents c7265573341e
children
rev   line source
Chris@0 1 /*
Chris@0 2 ** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
Chris@0 3 ** Copyright (C) 2008 George Blood Audio
Chris@0 4 **
Chris@0 5 ** All rights reserved.
Chris@0 6 **
Chris@0 7 ** Redistribution and use in source and binary forms, with or without
Chris@0 8 ** modification, are permitted provided that the following conditions are
Chris@0 9 ** met:
Chris@0 10 **
Chris@0 11 ** * Redistributions of source code must retain the above copyright
Chris@0 12 ** notice, this list of conditions and the following disclaimer.
Chris@0 13 ** * Redistributions in binary form must reproduce the above copyright
Chris@0 14 ** notice, this list of conditions and the following disclaimer in
Chris@0 15 ** the documentation and/or other materials provided with the
Chris@0 16 ** distribution.
Chris@0 17 ** * Neither the author nor the names of any contributors may be used
Chris@0 18 ** to endorse or promote products derived from this software without
Chris@0 19 ** specific prior written permission.
Chris@0 20 **
Chris@0 21 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Chris@0 22 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
Chris@0 23 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
Chris@0 24 ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
Chris@0 25 ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Chris@0 26 ** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Chris@0 27 ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
Chris@0 28 ** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
Chris@0 29 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
Chris@0 30 ** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
Chris@0 31 ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Chris@0 32 */
Chris@0 33
Chris@0 34 #include <stdio.h>
Chris@0 35 #include <stdlib.h>
Chris@0 36 #include <string.h>
Chris@0 37 #include <ctype.h>
Chris@0 38 #include <stdint.h>
Chris@0 39
Chris@0 40 #include <sndfile.h>
Chris@0 41
Chris@0 42 #include "common.h"
Chris@0 43
Chris@0 44 #define BUFFER_LEN 4096
Chris@0 45
Chris@0 46 #define MIN(x,y) ((x) < (y) ? (x) : (y))
Chris@0 47
Chris@0 48 void
Chris@0 49 sfe_copy_data_fp (SNDFILE *outfile, SNDFILE *infile, int channels)
Chris@0 50 { static double data [BUFFER_LEN], max ;
Chris@0 51 int frames, readcount, k ;
Chris@0 52
Chris@0 53 frames = BUFFER_LEN / channels ;
Chris@0 54 readcount = frames ;
Chris@0 55
Chris@0 56 sf_command (infile, SFC_CALC_SIGNAL_MAX, &max, sizeof (max)) ;
Chris@0 57
Chris@0 58 if (max < 1.0)
Chris@0 59 { while (readcount > 0)
Chris@0 60 { readcount = sf_readf_double (infile, data, frames) ;
Chris@0 61 sf_writef_double (outfile, data, readcount) ;
Chris@0 62 } ;
Chris@0 63 }
Chris@0 64 else
Chris@0 65 { sf_command (infile, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
Chris@0 66
Chris@0 67 while (readcount > 0)
Chris@0 68 { readcount = sf_readf_double (infile, data, frames) ;
Chris@0 69 for (k = 0 ; k < readcount * channels ; k++)
Chris@0 70 data [k] /= max ;
Chris@0 71 sf_writef_double (outfile, data, readcount) ;
Chris@0 72 } ;
Chris@0 73 } ;
Chris@0 74
Chris@0 75 return ;
Chris@0 76 } /* sfe_copy_data_fp */
Chris@0 77
Chris@0 78 void
Chris@0 79 sfe_copy_data_int (SNDFILE *outfile, SNDFILE *infile, int channels)
Chris@0 80 { static int data [BUFFER_LEN] ;
Chris@0 81 int frames, readcount ;
Chris@0 82
Chris@0 83 frames = BUFFER_LEN / channels ;
Chris@0 84 readcount = frames ;
Chris@0 85
Chris@0 86 while (readcount > 0)
Chris@0 87 { readcount = sf_readf_int (infile, data, frames) ;
Chris@0 88 sf_writef_int (outfile, data, readcount) ;
Chris@0 89 } ;
Chris@0 90
Chris@0 91 return ;
Chris@0 92 } /* sfe_copy_data_int */
Chris@0 93
Chris@0 94 /*==============================================================================
Chris@0 95 */
Chris@0 96
Chris@0 97 static int
Chris@0 98 merge_broadcast_info (SNDFILE * infile, SNDFILE * outfile, int format, const METADATA_INFO * info)
Chris@0 99 { SF_BROADCAST_INFO_2K binfo ;
Chris@0 100 int infileminor ;
Chris@0 101
Chris@0 102 memset (&binfo, 0, sizeof (binfo)) ;
Chris@0 103
Chris@0 104 if ((SF_FORMAT_TYPEMASK & format) != SF_FORMAT_WAV)
Chris@0 105 { printf ("Error : This is not a WAV file and hence broadcast info cannot be added to it.\n\n") ;
Chris@0 106 return 1 ;
Chris@0 107 } ;
Chris@0 108
Chris@0 109 infileminor = SF_FORMAT_SUBMASK & format ;
Chris@0 110
Chris@0 111 switch (infileminor)
Chris@0 112 { case SF_FORMAT_PCM_16 :
Chris@0 113 case SF_FORMAT_PCM_24 :
Chris@0 114 case SF_FORMAT_PCM_32 :
Chris@0 115 break ;
Chris@0 116
Chris@0 117 default :
Chris@0 118 printf (
Chris@0 119 "Warning : The EBU Technical Recommendation R68-2000 states that the only\n"
Chris@0 120 " allowed encodings are Linear PCM and MPEG3. This file is not in\n"
Chris@0 121 " the right format.\n\n"
Chris@0 122 ) ;
Chris@0 123 break ;
Chris@0 124 } ;
Chris@0 125
Chris@0 126 if (sf_command (infile, SFC_GET_BROADCAST_INFO, &binfo, sizeof (binfo)) == 0)
Chris@0 127 { if (infile == outfile)
Chris@0 128 { printf (
Chris@0 129 "Error : Attempting in-place broadcast info update, but file does not\n"
Chris@0 130 " have a 'bext' chunk to modify. The solution is to specify both\n"
Chris@0 131 " input and output files on the command line.\n\n"
Chris@0 132 ) ;
Chris@0 133 return 1 ;
Chris@0 134 } ;
Chris@0 135 } ;
Chris@0 136
Chris@0 137 #define REPLACE_IF_NEW(x) \
Chris@0 138 if (info->x != NULL) \
Chris@0 139 { memset (binfo.x, 0, sizeof (binfo.x)) ; \
Chris@0 140 memcpy (binfo.x, info->x, MIN (strlen (info->x), sizeof (binfo.x))) ; \
Chris@0 141 } ;
Chris@0 142
Chris@0 143 REPLACE_IF_NEW (description) ;
Chris@0 144 REPLACE_IF_NEW (originator) ;
Chris@0 145 REPLACE_IF_NEW (originator_reference) ;
Chris@0 146 REPLACE_IF_NEW (origination_date) ;
Chris@0 147 REPLACE_IF_NEW (origination_time) ;
Chris@0 148 REPLACE_IF_NEW (umid) ;
Chris@0 149
Chris@0 150 /* Special case for Time Ref. */
Chris@0 151 if (info->time_ref != NULL)
Chris@0 152 { uint64_t ts = atoll (info->time_ref) ;
Chris@0 153
Chris@0 154 binfo.time_reference_high = (ts >> 32) ;
Chris@0 155 binfo.time_reference_low = (ts & 0xffffffff) ;
Chris@0 156 } ;
Chris@0 157
Chris@0 158 /* Special case for coding_history because we may want to append. */
Chris@0 159 if (info->coding_history != NULL)
Chris@0 160 { if (info->coding_hist_append)
Chris@0 161 { int slen = strlen (binfo.coding_history) ;
Chris@0 162
Chris@0 163 while (slen > 1 && isspace (binfo.coding_history [slen - 1]))
Chris@0 164 slen -- ;
Chris@0 165
Chris@0 166 memcpy (binfo.coding_history + slen, info->coding_history, sizeof (binfo.coding_history) - slen) ;
Chris@0 167 }
Chris@0 168 else
Chris@0 169 { size_t slen = MIN (strlen (info->coding_history), sizeof (binfo.coding_history)) ;
Chris@0 170
Chris@0 171 memset (binfo.coding_history, 0, sizeof (binfo.coding_history)) ;
Chris@0 172 memcpy (binfo.coding_history, info->coding_history, slen) ;
Chris@0 173 binfo.coding_history_size = slen ;
Chris@0 174 } ;
Chris@0 175 } ;
Chris@0 176
Chris@0 177 if (sf_command (outfile, SFC_SET_BROADCAST_INFO, &binfo, sizeof (binfo)) == 0)
Chris@0 178 { printf ("Error : Setting of broadcast info chunks failed.\n\n") ;
Chris@0 179 return 1 ;
Chris@0 180 } ;
Chris@0 181
Chris@0 182 return 0 ;
Chris@0 183 } /* merge_broadcast_info*/
Chris@0 184
Chris@0 185 static void
Chris@0 186 update_strings (SNDFILE * outfile, const METADATA_INFO * info)
Chris@0 187 {
Chris@0 188 if (info->title != NULL)
Chris@0 189 sf_set_string (outfile, SF_STR_TITLE, info->title) ;
Chris@0 190
Chris@0 191 if (info->copyright != NULL)
Chris@0 192 sf_set_string (outfile, SF_STR_COPYRIGHT, info->copyright) ;
Chris@0 193
Chris@0 194 if (info->artist != NULL)
Chris@0 195 sf_set_string (outfile, SF_STR_ARTIST, info->artist) ;
Chris@0 196
Chris@0 197 if (info->comment != NULL)
Chris@0 198 sf_set_string (outfile, SF_STR_COMMENT, info->comment) ;
Chris@0 199
Chris@0 200 if (info->date != NULL)
Chris@0 201 sf_set_string (outfile, SF_STR_DATE, info->date) ;
Chris@0 202
Chris@0 203 if (info->album != NULL)
Chris@0 204 sf_set_string (outfile, SF_STR_ALBUM, info->album) ;
Chris@0 205
Chris@0 206 if (info->license != NULL)
Chris@0 207 sf_set_string (outfile, SF_STR_LICENSE, info->license) ;
Chris@0 208
Chris@0 209 } /* update_strings */
Chris@0 210
Chris@0 211
Chris@0 212
Chris@0 213 void
Chris@0 214 sfe_apply_metadata_changes (const char * filenames [2], const METADATA_INFO * info)
Chris@0 215 { SNDFILE *infile = NULL, *outfile = NULL ;
Chris@0 216 SF_INFO sfinfo ;
Chris@0 217 METADATA_INFO tmpinfo ;
Chris@0 218 int error_code = 0 ;
Chris@0 219
Chris@0 220 memset (&sfinfo, 0, sizeof (sfinfo)) ;
Chris@0 221 memset (&tmpinfo, 0, sizeof (tmpinfo)) ;
Chris@0 222
Chris@0 223 if (filenames [1] == NULL)
Chris@0 224 infile = outfile = sf_open (filenames [0], SFM_RDWR, &sfinfo) ;
Chris@0 225 else
Chris@0 226 { infile = sf_open (filenames [0], SFM_READ, &sfinfo) ;
Chris@0 227
Chris@0 228 /* Output must be WAV. */
Chris@0 229 sfinfo.format = SF_FORMAT_WAV | (SF_FORMAT_SUBMASK & sfinfo.format) ;
Chris@0 230 outfile = sf_open (filenames [1], SFM_WRITE, &sfinfo) ;
Chris@0 231 } ;
Chris@0 232
Chris@0 233 if (infile == NULL)
Chris@0 234 { printf ("Error : Not able to open input file '%s' : %s\n", filenames [0], sf_strerror (infile)) ;
Chris@0 235 error_code = 1 ;
Chris@0 236 goto cleanup_exit ;
Chris@0 237 } ;
Chris@0 238
Chris@0 239 if (outfile == NULL)
Chris@0 240 { printf ("Error : Not able to open output file '%s' : %s\n", filenames [1], sf_strerror (outfile)) ;
Chris@0 241 error_code = 1 ;
Chris@0 242 goto cleanup_exit ;
Chris@0 243 } ;
Chris@0 244
Chris@0 245 if (info->has_bext_fields && merge_broadcast_info (infile, outfile, sfinfo.format, info))
Chris@0 246 { error_code = 1 ;
Chris@0 247 goto cleanup_exit ;
Chris@0 248 } ;
Chris@0 249
Chris@0 250 if (infile != outfile)
Chris@0 251 { int infileminor = SF_FORMAT_SUBMASK & sfinfo.format ;
Chris@0 252
Chris@0 253 /* If the input file is not the same as the output file, copy the data. */
Chris@0 254 if ((infileminor == SF_FORMAT_DOUBLE) || (infileminor == SF_FORMAT_FLOAT))
Chris@0 255 sfe_copy_data_fp (outfile, infile, sfinfo.channels) ;
Chris@0 256 else
Chris@0 257 sfe_copy_data_int (outfile, infile, sfinfo.channels) ;
Chris@0 258 } ;
Chris@0 259
Chris@0 260 update_strings (outfile, info) ;
Chris@0 261
Chris@0 262 cleanup_exit :
Chris@0 263
Chris@0 264 if (outfile != NULL && outfile != infile)
Chris@0 265 sf_close (outfile) ;
Chris@0 266
Chris@0 267 if (infile != NULL)
Chris@0 268 sf_close (infile) ;
Chris@0 269
Chris@0 270 if (error_code)
Chris@0 271 exit (error_code) ;
Chris@0 272
Chris@0 273 return ;
Chris@0 274 } /* sfe_apply_metadata_changes */
Chris@0 275
Chris@0 276 /*==============================================================================
Chris@0 277 */
Chris@0 278
Chris@0 279 typedef struct
Chris@0 280 { const char *ext ;
Chris@0 281 int len ;
Chris@0 282 int format ;
Chris@0 283 } OUTPUT_FORMAT_MAP ;
Chris@0 284
Chris@0 285 static OUTPUT_FORMAT_MAP format_map [] =
Chris@0 286 {
Chris@0 287 { "aif", 3, SF_FORMAT_AIFF },
Chris@0 288 { "wav", 0, SF_FORMAT_WAV },
Chris@0 289 { "au", 0, SF_FORMAT_AU },
Chris@0 290 { "caf", 0, SF_FORMAT_CAF },
Chris@0 291 { "flac", 0, SF_FORMAT_FLAC },
Chris@0 292 { "snd", 0, SF_FORMAT_AU },
Chris@0 293 { "svx", 0, SF_FORMAT_SVX },
Chris@0 294 { "paf", 0, SF_ENDIAN_BIG | SF_FORMAT_PAF },
Chris@0 295 { "fap", 0, SF_ENDIAN_LITTLE | SF_FORMAT_PAF },
Chris@0 296 { "gsm", 0, SF_FORMAT_RAW },
Chris@0 297 { "nist", 0, SF_FORMAT_NIST },
Chris@0 298 { "htk", 0, SF_FORMAT_HTK },
Chris@0 299 { "ircam", 0, SF_FORMAT_IRCAM },
Chris@0 300 { "sf", 0, SF_FORMAT_IRCAM },
Chris@0 301 { "voc", 0, SF_FORMAT_VOC },
Chris@0 302 { "w64", 0, SF_FORMAT_W64 },
Chris@0 303 { "raw", 0, SF_FORMAT_RAW },
Chris@0 304 { "mat4", 0, SF_FORMAT_MAT4 },
Chris@0 305 { "mat5", 0, SF_FORMAT_MAT5 },
Chris@0 306 { "mat", 0, SF_FORMAT_MAT4 },
Chris@0 307 { "pvf", 0, SF_FORMAT_PVF },
Chris@0 308 { "sds", 0, SF_FORMAT_SDS },
Chris@0 309 { "sd2", 0, SF_FORMAT_SD2 },
Chris@0 310 { "vox", 0, SF_FORMAT_RAW },
Chris@0 311 { "xi", 0, SF_FORMAT_XI },
Chris@0 312 { "wve", 0, SF_FORMAT_WVE },
Chris@0 313 { "oga", 0, SF_FORMAT_OGG },
Chris@0 314 { "mpc", 0, SF_FORMAT_MPC2K },
Chris@0 315 { "rf64", 0, SF_FORMAT_RF64 },
Chris@0 316 } ; /* format_map */
Chris@0 317
Chris@0 318 int
Chris@0 319 sfe_file_type_of_ext (const char *str, int format)
Chris@0 320 { char buffer [16], *cptr ;
Chris@0 321 int k ;
Chris@0 322
Chris@0 323 format &= SF_FORMAT_SUBMASK ;
Chris@0 324
Chris@0 325 if ((cptr = strrchr (str, '.')) == NULL)
Chris@0 326 return 0 ;
Chris@0 327
Chris@0 328 strncpy (buffer, cptr + 1, 15) ;
Chris@0 329 buffer [15] = 0 ;
Chris@0 330
Chris@0 331 for (k = 0 ; buffer [k] ; k++)
Chris@0 332 buffer [k] = tolower ((buffer [k])) ;
Chris@0 333
Chris@0 334 if (strcmp (buffer, "gsm") == 0)
Chris@0 335 return SF_FORMAT_RAW | SF_FORMAT_GSM610 ;
Chris@0 336
Chris@0 337 if (strcmp (buffer, "vox") == 0)
Chris@0 338 return SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM ;
Chris@0 339
Chris@0 340 for (k = 0 ; k < (int) (sizeof (format_map) / sizeof (format_map [0])) ; k++)
Chris@0 341 { if (format_map [k].len > 0 && strncmp (buffer, format_map [k].ext, format_map [k].len) == 0)
Chris@0 342 return format_map [k].format | format ;
Chris@0 343 else if (strcmp (buffer, format_map [k].ext) == 0)
Chris@0 344 return format_map [k].format | format ;
Chris@0 345 } ;
Chris@0 346
Chris@0 347 /* Default if all the above fails. */
Chris@0 348 return (SF_FORMAT_WAV | SF_FORMAT_PCM_24) ;
Chris@0 349 } /* sfe_file_type_of_ext */
Chris@0 350
Chris@0 351 void
Chris@0 352 sfe_dump_format_map (void)
Chris@0 353 { SF_FORMAT_INFO info ;
Chris@0 354 int k ;
Chris@0 355
Chris@0 356 for (k = 0 ; k < ARRAY_LEN (format_map) ; k++)
Chris@0 357 { info.format = format_map [k].format ;
Chris@0 358 sf_command (NULL, SFC_GET_FORMAT_INFO, &info, sizeof (info)) ;
Chris@0 359 printf (" %-10s : %s\n", format_map [k].ext, info.name == NULL ? "????" : info.name) ;
Chris@0 360 } ;
Chris@0 361
Chris@0 362 } /* sfe_dump_format_map */
Chris@0 363
Chris@0 364 const char *
Chris@0 365 program_name (const char * argv0)
Chris@0 366 { const char * tmp ;
Chris@0 367
Chris@0 368 tmp = strrchr (argv0, '/') ;
Chris@0 369 argv0 = tmp ? tmp + 1 : argv0 ;
Chris@0 370
Chris@0 371 tmp = strrchr (argv0, '/') ;
Chris@0 372 argv0 = tmp ? tmp + 1 : argv0 ;
Chris@0 373
Chris@0 374 /* Remove leading libtool name mangling. */
Chris@0 375 if (strstr (argv0, "lt-") == argv0)
Chris@0 376 return argv0 + 3 ;
Chris@0 377
Chris@0 378 return argv0 ;
Chris@0 379 } /* program_name */