annotate src/libsamplerate-0.1.9/examples/sndfile-resample.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 481f5f8c5634
children
rev   line source
Chris@41 1 /*
Chris@41 2 ** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com>
Chris@41 3 ** All rights reserved.
Chris@41 4 **
Chris@41 5 ** This code is released under 2-clause BSD license. Please see the
Chris@41 6 ** file at : https://github.com/erikd/libsamplerate/blob/master/COPYING
Chris@41 7 */
Chris@41 8
Chris@41 9 #include "config.h"
Chris@41 10
Chris@41 11 #include <stdio.h>
Chris@41 12 #include <stdlib.h>
Chris@41 13 #include <unistd.h>
Chris@41 14 #include <string.h>
Chris@41 15 #include <math.h>
Chris@41 16
Chris@41 17 #if (HAVE_SNDFILE)
Chris@41 18
Chris@41 19 #include <samplerate.h>
Chris@41 20 #include <sndfile.h>
Chris@41 21
Chris@41 22 #define DEFAULT_CONVERTER SRC_SINC_MEDIUM_QUALITY
Chris@41 23
Chris@41 24 #define BUFFER_LEN 4096 /*-(1<<16)-*/
Chris@41 25
Chris@41 26 static void usage_exit (const char *progname) ;
Chris@41 27 static sf_count_t sample_rate_convert (SNDFILE *infile, SNDFILE *outfile, int converter, double src_ratio, int channels, double * gain, int normalize) ;
Chris@41 28 static double apply_gain (float * data, long frames, int channels, double max, double gain) ;
Chris@41 29
Chris@41 30 int
Chris@41 31 main (int argc, char *argv [])
Chris@41 32 { SNDFILE *infile, *outfile = NULL ;
Chris@41 33 SF_INFO sfinfo ;
Chris@41 34
Chris@41 35 int normalize = 1 ;
Chris@41 36 sf_count_t count ;
Chris@41 37 double src_ratio = -1.0, gain = 1.0 ;
Chris@41 38 int new_sample_rate = -1, k, converter, max_speed = SF_FALSE ;
Chris@41 39
Chris@41 40 if (argc == 2 && strcmp (argv [1], "--version") == 0)
Chris@41 41 { char buffer [64], *cptr ;
Chris@41 42
Chris@41 43 if ((cptr = strrchr (argv [0], '/')) != NULL)
Chris@41 44 argv [0] = cptr + 1 ;
Chris@41 45 if ((cptr = strrchr (argv [0], '\\')) != NULL)
Chris@41 46 argv [0] = cptr + 1 ;
Chris@41 47
Chris@41 48 sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer)) ;
Chris@41 49
Chris@41 50 printf ("%s (%s,%s)\n", argv [0], src_get_version (), buffer) ;
Chris@41 51 exit (0) ;
Chris@41 52 } ;
Chris@41 53
Chris@41 54 if (argc != 5 && argc != 7 && argc != 8)
Chris@41 55 usage_exit (argv [0]) ;
Chris@41 56
Chris@41 57 /* Set default converter. */
Chris@41 58 converter = DEFAULT_CONVERTER ;
Chris@41 59
Chris@41 60 for (k = 1 ; k < argc - 2 ; k++)
Chris@41 61 { if (strcmp (argv [k], "--max-speed") == 0)
Chris@41 62 max_speed = SF_TRUE ;
Chris@41 63 else if (strcmp (argv [k], "--no-normalize") == 0)
Chris@41 64 normalize = 0 ;
Chris@41 65 else if (strcmp (argv [k], "-to") == 0)
Chris@41 66 { k ++ ;
Chris@41 67 new_sample_rate = atoi (argv [k]) ;
Chris@41 68 }
Chris@41 69 else if (strcmp (argv [k], "-by") == 0)
Chris@41 70 { k ++ ;
Chris@41 71 src_ratio = atof (argv [k]) ;
Chris@41 72 }
Chris@41 73 else if (strcmp (argv [k], "-c") == 0)
Chris@41 74 { k ++ ;
Chris@41 75 converter = atoi (argv [k]) ;
Chris@41 76 }
Chris@41 77 else
Chris@41 78 usage_exit (argv [0]) ;
Chris@41 79 } ;
Chris@41 80
Chris@41 81 if (new_sample_rate <= 0 && src_ratio <= 0.0)
Chris@41 82 usage_exit (argv [0]) ;
Chris@41 83
Chris@41 84 if (src_get_name (converter) == NULL)
Chris@41 85 { printf ("Error : bad converter number.\n") ;
Chris@41 86 usage_exit (argv [0]) ;
Chris@41 87 } ;
Chris@41 88
Chris@41 89 if (strcmp (argv [argc - 2], argv [argc - 1]) == 0)
Chris@41 90 { printf ("Error : input and output file names are the same.\n") ;
Chris@41 91 exit (1) ;
Chris@41 92 } ;
Chris@41 93
Chris@41 94 if ((infile = sf_open (argv [argc - 2], SFM_READ, &sfinfo)) == NULL)
Chris@41 95 { printf ("Error : Not able to open input file '%s'\n", argv [argc - 2]) ;
Chris@41 96 exit (1) ;
Chris@41 97 } ;
Chris@41 98
Chris@41 99 printf ("Input File : %s\n", argv [argc - 2]) ;
Chris@41 100 printf ("Sample Rate : %d\n", sfinfo.samplerate) ;
Chris@41 101 printf ("Input Frames : %ld\n\n", (long) sfinfo.frames) ;
Chris@41 102
Chris@41 103 if (new_sample_rate > 0)
Chris@41 104 { src_ratio = (1.0 * new_sample_rate) / sfinfo.samplerate ;
Chris@41 105 sfinfo.samplerate = new_sample_rate ;
Chris@41 106 }
Chris@41 107 else if (src_is_valid_ratio (src_ratio))
Chris@41 108 sfinfo.samplerate = (int) floor (sfinfo.samplerate * src_ratio) ;
Chris@41 109 else
Chris@41 110 { printf ("Not able to determine new sample rate. Exiting.\n") ;
Chris@41 111 sf_close (infile) ;
Chris@41 112 exit (1) ;
Chris@41 113 } ;
Chris@41 114
Chris@41 115 if (fabs (src_ratio - 1.0) < 1e-20)
Chris@41 116 { printf ("Target samplerate and input samplerate are the same. Exiting.\n") ;
Chris@41 117 sf_close (infile) ;
Chris@41 118 exit (0) ;
Chris@41 119 } ;
Chris@41 120
Chris@41 121 printf ("SRC Ratio : %f\n", src_ratio) ;
Chris@41 122 printf ("Converter : %s\n\n", src_get_name (converter)) ;
Chris@41 123
Chris@41 124 if (src_is_valid_ratio (src_ratio) == 0)
Chris@41 125 { printf ("Error : Sample rate change out of valid range.\n") ;
Chris@41 126 sf_close (infile) ;
Chris@41 127 exit (1) ;
Chris@41 128 } ;
Chris@41 129
Chris@41 130 /* Delete the output file length to zero if already exists. */
Chris@41 131 remove (argv [argc - 1]) ;
Chris@41 132
Chris@41 133 printf ("Output file : %s\n", argv [argc - 1]) ;
Chris@41 134 printf ("Sample Rate : %d\n", sfinfo.samplerate) ;
Chris@41 135
Chris@41 136 do
Chris@41 137 { sf_close (outfile) ;
Chris@41 138
Chris@41 139 if ((outfile = sf_open (argv [argc - 1], SFM_WRITE, &sfinfo)) == NULL)
Chris@41 140 { printf ("Error : Not able to open output file '%s'\n", argv [argc - 1]) ;
Chris@41 141 sf_close (infile) ;
Chris@41 142 exit (1) ;
Chris@41 143 } ;
Chris@41 144
Chris@41 145 if (max_speed)
Chris@41 146 { /* This is mainly for the comparison program tests/src-evaluate.c */
Chris@41 147 sf_command (outfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
Chris@41 148 }
Chris@41 149 else
Chris@41 150 { /* Update the file header after every write. */
Chris@41 151 sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
Chris@41 152 } ;
Chris@41 153
Chris@41 154 sf_command (outfile, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
Chris@41 155
Chris@41 156 count = sample_rate_convert (infile, outfile, converter, src_ratio, sfinfo.channels, &gain, normalize) ;
Chris@41 157 }
Chris@41 158 while (count < 0) ;
Chris@41 159
Chris@41 160 printf ("Output Frames : %ld\n\n", (long) count) ;
Chris@41 161
Chris@41 162 sf_close (infile) ;
Chris@41 163 sf_close (outfile) ;
Chris@41 164
Chris@41 165 return 0 ;
Chris@41 166 } /* main */
Chris@41 167
Chris@41 168 /*==============================================================================
Chris@41 169 */
Chris@41 170
Chris@41 171 static sf_count_t
Chris@41 172 sample_rate_convert (SNDFILE *infile, SNDFILE *outfile, int converter, double src_ratio, int channels, double * gain, int normalize)
Chris@41 173 { static float input [BUFFER_LEN] ;
Chris@41 174 static float output [BUFFER_LEN] ;
Chris@41 175
Chris@41 176 SRC_STATE *src_state ;
Chris@41 177 SRC_DATA src_data ;
Chris@41 178 int error ;
Chris@41 179 double max = 0.0 ;
Chris@41 180 sf_count_t output_count = 0 ;
Chris@41 181
Chris@41 182 sf_seek (infile, 0, SEEK_SET) ;
Chris@41 183 sf_seek (outfile, 0, SEEK_SET) ;
Chris@41 184
Chris@41 185 /* Initialize the sample rate converter. */
Chris@41 186 if ((src_state = src_new (converter, channels, &error)) == NULL)
Chris@41 187 { printf ("\n\nError : src_new() failed : %s.\n\n", src_strerror (error)) ;
Chris@41 188 exit (1) ;
Chris@41 189 } ;
Chris@41 190
Chris@41 191 src_data.end_of_input = 0 ; /* Set this later. */
Chris@41 192
Chris@41 193 /* Start with zero to force load in while loop. */
Chris@41 194 src_data.input_frames = 0 ;
Chris@41 195 src_data.data_in = input ;
Chris@41 196
Chris@41 197 src_data.src_ratio = src_ratio ;
Chris@41 198
Chris@41 199 src_data.data_out = output ;
Chris@41 200 src_data.output_frames = BUFFER_LEN /channels ;
Chris@41 201
Chris@41 202 while (1)
Chris@41 203 {
Chris@41 204 /* If the input buffer is empty, refill it. */
Chris@41 205 if (src_data.input_frames == 0)
Chris@41 206 { src_data.input_frames = sf_readf_float (infile, input, BUFFER_LEN / channels) ;
Chris@41 207 src_data.data_in = input ;
Chris@41 208
Chris@41 209 /* The last read will not be a full buffer, so snd_of_input. */
Chris@41 210 if (src_data.input_frames < BUFFER_LEN / channels)
Chris@41 211 src_data.end_of_input = SF_TRUE ;
Chris@41 212 } ;
Chris@41 213
Chris@41 214 if ((error = src_process (src_state, &src_data)))
Chris@41 215 { printf ("\nError : %s\n", src_strerror (error)) ;
Chris@41 216 exit (1) ;
Chris@41 217 } ;
Chris@41 218
Chris@41 219 /* Terminate if done. */
Chris@41 220 if (src_data.end_of_input && src_data.output_frames_gen == 0)
Chris@41 221 break ;
Chris@41 222
Chris@41 223 max = apply_gain (src_data.data_out, src_data.output_frames_gen, channels, max, *gain) ;
Chris@41 224
Chris@41 225 /* Write output. */
Chris@41 226 sf_writef_float (outfile, output, src_data.output_frames_gen) ;
Chris@41 227 output_count += src_data.output_frames_gen ;
Chris@41 228
Chris@41 229 src_data.data_in += src_data.input_frames_used * channels ;
Chris@41 230 src_data.input_frames -= src_data.input_frames_used ;
Chris@41 231 } ;
Chris@41 232
Chris@41 233 src_delete (src_state) ;
Chris@41 234
Chris@41 235 if (normalize && max > 1.0)
Chris@41 236 { *gain = 1.0 / max ;
Chris@41 237 printf ("\nOutput has clipped. Restarting conversion to prevent clipping.\n\n") ;
Chris@41 238 return -1 ;
Chris@41 239 } ;
Chris@41 240
Chris@41 241 return output_count ;
Chris@41 242 } /* sample_rate_convert */
Chris@41 243
Chris@41 244 static double
Chris@41 245 apply_gain (float * data, long frames, int channels, double max, double gain)
Chris@41 246 {
Chris@41 247 long k ;
Chris@41 248
Chris@41 249 for (k = 0 ; k < frames * channels ; k++)
Chris@41 250 { data [k] *= gain ;
Chris@41 251
Chris@41 252 if (fabs (data [k]) > max)
Chris@41 253 max = fabs (data [k]) ;
Chris@41 254 } ;
Chris@41 255
Chris@41 256 return max ;
Chris@41 257 } /* apply_gain */
Chris@41 258
Chris@41 259 static void
Chris@41 260 usage_exit (const char *progname)
Chris@41 261 { char lsf_ver [128] ;
Chris@41 262 const char *cptr ;
Chris@41 263 int k ;
Chris@41 264
Chris@41 265 if ((cptr = strrchr (progname, '/')) != NULL)
Chris@41 266 progname = cptr + 1 ;
Chris@41 267
Chris@41 268 if ((cptr = strrchr (progname, '\\')) != NULL)
Chris@41 269 progname = cptr + 1 ;
Chris@41 270
Chris@41 271
Chris@41 272 sf_command (NULL, SFC_GET_LIB_VERSION, lsf_ver, sizeof (lsf_ver)) ;
Chris@41 273
Chris@41 274 printf ("\n"
Chris@41 275 " A Sample Rate Converter using libsndfile for file I/O and Secret \n"
Chris@41 276 " Rabbit Code (aka libsamplerate) for performing the conversion.\n"
Chris@41 277 " It works on any file format supported by libsndfile with any \n"
Chris@41 278 " number of channels (limited only by host memory).\n"
Chris@41 279 "\n"
Chris@41 280 " %s\n"
Chris@41 281 " %s\n"
Chris@41 282 "\n"
Chris@41 283 " Usage : \n"
Chris@41 284 " %s -to <new sample rate> [-c <number>] <input file> <output file>\n"
Chris@41 285 " %s -by <amount> [-c <number>] <input file> <output file>\n"
Chris@41 286 "\n", src_get_version (), lsf_ver, progname, progname) ;
Chris@41 287
Chris@41 288 puts (
Chris@41 289 " The optional -c argument allows the converter type to be chosen from\n"
Chris@41 290 " the following list :"
Chris@41 291 "\n"
Chris@41 292 ) ;
Chris@41 293
Chris@41 294 for (k = 0 ; (cptr = src_get_name (k)) != NULL ; k++)
Chris@41 295 printf (" %d : %s%s\n", k, cptr, k == DEFAULT_CONVERTER ? " (default)" : "") ;
Chris@41 296
Chris@41 297 puts ("\n"
Chris@41 298 " The --no-normalize option disables clipping check and normalization.") ;
Chris@41 299
Chris@41 300 puts ("") ;
Chris@41 301
Chris@41 302 exit (1) ;
Chris@41 303 } /* usage_exit */
Chris@41 304
Chris@41 305 /*==============================================================================
Chris@41 306 */
Chris@41 307
Chris@41 308 #else /* (HAVE_SNFILE == 0) */
Chris@41 309
Chris@41 310 /* Alternative main function when libsndfile is not available. */
Chris@41 311
Chris@41 312 int
Chris@41 313 main (void)
Chris@41 314 { puts (
Chris@41 315 "\n"
Chris@41 316 "****************************************************************\n"
Chris@41 317 " This example program was compiled without libsndfile \n"
Chris@41 318 " (http://www.mega-nerd.com/libsndfile/).\n"
Chris@41 319 " It is therefore completely broken and non-functional.\n"
Chris@41 320 "****************************************************************\n"
Chris@41 321 "\n"
Chris@41 322 ) ;
Chris@41 323
Chris@41 324 return 0 ;
Chris@41 325 } /* main */
Chris@41 326
Chris@41 327 #endif
Chris@41 328