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