annotate src/libsamplerate-0.1.8/examples/varispeed-play.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 <stdio.h>
Chris@0 20 #include <stdlib.h>
Chris@0 21 #include <unistd.h>
Chris@0 22 #include <string.h>
Chris@0 23
Chris@0 24 #include "config.h"
Chris@0 25
Chris@0 26 #include <float_cast.h>
Chris@0 27
Chris@0 28 #if (HAVE_SNDFILE)
Chris@0 29
Chris@0 30 #include <samplerate.h>
Chris@0 31 #include <sndfile.h>
Chris@0 32
Chris@0 33 #include "audio_out.h"
Chris@0 34
Chris@0 35 #define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0])))
Chris@0 36
Chris@0 37 #define BUFFER_LEN 4096
Chris@0 38 #define INPUT_FRAMES 100
Chris@0 39
Chris@0 40 #define MIN(a,b) ((a) < (b) ? (a) : (b))
Chris@0 41
Chris@0 42 #define MAGIC_NUMBER ((int) ('S' << 16) + ('R' << 8) + ('C'))
Chris@0 43
Chris@0 44 #ifndef M_PI
Chris@0 45 #define M_PI 3.14159265358979323846264338
Chris@0 46 #endif
Chris@0 47
Chris@0 48
Chris@0 49 typedef struct
Chris@0 50 { int magic ;
Chris@0 51
Chris@0 52 SNDFILE *sndfile ;
Chris@0 53 SF_INFO sfinfo ;
Chris@0 54
Chris@0 55 SRC_STATE *src_state ;
Chris@0 56 SRC_DATA src_data ;
Chris@0 57
Chris@0 58 int freq_point ;
Chris@0 59 int buffer_out_start, buffer_out_end ;
Chris@0 60
Chris@0 61 float buffer_in [BUFFER_LEN] ;
Chris@0 62 float buffer_out [BUFFER_LEN] ;
Chris@0 63 } CALLBACK_DATA ;
Chris@0 64
Chris@0 65 static int varispeed_get_data (CALLBACK_DATA *data, float *samples, int frames) ;
Chris@0 66 static void varispeed_play (const char *filename, int converter) ;
Chris@0 67
Chris@0 68 int
Chris@0 69 main (int argc, char *argv [])
Chris@0 70 { const char *cptr, *progname, *filename ;
Chris@0 71 int k, converter ;
Chris@0 72
Chris@0 73 converter = SRC_SINC_FASTEST ;
Chris@0 74
Chris@0 75 progname = argv [0] ;
Chris@0 76
Chris@0 77 if ((cptr = strrchr (progname, '/')) != NULL)
Chris@0 78 progname = cptr + 1 ;
Chris@0 79
Chris@0 80 if ((cptr = strrchr (progname, '\\')) != NULL)
Chris@0 81 progname = cptr + 1 ;
Chris@0 82
Chris@0 83 printf ("\n"
Chris@0 84 " %s\n"
Chris@0 85 "\n"
Chris@0 86 " This is a demo program which plays the given file at a slowly \n"
Chris@0 87 " varying speed. Lots of fun with drum loops and full mixes.\n"
Chris@0 88 "\n"
Chris@0 89 " It uses Secret Rabbit Code (aka libsamplerate) to perform the \n"
Chris@0 90 " vari-speeding and libsndfile for file I/O.\n"
Chris@0 91 "\n", progname) ;
Chris@0 92
Chris@0 93 if (argc == 2)
Chris@0 94 filename = argv [1] ;
Chris@0 95 else if (argc == 4 && strcmp (argv [1], "-c") == 0)
Chris@0 96 { filename = argv [3] ;
Chris@0 97 converter = atoi (argv [2]) ;
Chris@0 98 }
Chris@0 99 else
Chris@0 100 { printf (" Usage :\n\n %s [-c <number>] <input file>\n\n", progname) ;
Chris@0 101 puts (
Chris@0 102 " The optional -c argument allows the converter type to be chosen from\n"
Chris@0 103 " the following list :"
Chris@0 104 "\n"
Chris@0 105 ) ;
Chris@0 106
Chris@0 107 for (k = 0 ; (cptr = src_get_name (k)) != NULL ; k++)
Chris@0 108 printf (" %d : %s\n", k, cptr) ;
Chris@0 109
Chris@0 110 puts ("") ;
Chris@0 111 exit (1) ;
Chris@0 112 } ;
Chris@0 113
Chris@0 114 varispeed_play (filename, converter) ;
Chris@0 115
Chris@0 116 return 0 ;
Chris@0 117 } /* main */
Chris@0 118
Chris@0 119 /*==============================================================================
Chris@0 120 */
Chris@0 121
Chris@0 122 static void
Chris@0 123 varispeed_play (const char *filename, int converter)
Chris@0 124 { CALLBACK_DATA *data ;
Chris@0 125 AUDIO_OUT *audio_out ;
Chris@0 126 int error ;
Chris@0 127
Chris@0 128 /* Allocate memory for the callback data. */
Chris@0 129 if ((data = calloc (1, sizeof (CALLBACK_DATA))) == NULL)
Chris@0 130 { printf ("\n\n%s:%d Calloc failed!\n", __FILE__, __LINE__) ;
Chris@0 131 exit (1) ;
Chris@0 132 } ;
Chris@0 133
Chris@0 134 data->magic = MAGIC_NUMBER ;
Chris@0 135
Chris@0 136 if ((data->sndfile = sf_open (filename, SFM_READ, &data->sfinfo)) == NULL)
Chris@0 137 { puts (sf_strerror (NULL)) ;
Chris@0 138 exit (1) ;
Chris@0 139 } ;
Chris@0 140
Chris@0 141 /* Initialize the sample rate converter. */
Chris@0 142 if ((data->src_state = src_new (converter, data->sfinfo.channels, &error)) == NULL)
Chris@0 143 { printf ("\n\nError : src_new() failed : %s.\n\n", src_strerror (error)) ;
Chris@0 144 exit (1) ;
Chris@0 145 } ;
Chris@0 146
Chris@0 147 printf (
Chris@0 148
Chris@0 149 " Playing : %s\n"
Chris@0 150 " Converter : %s\n"
Chris@0 151 "\n"
Chris@0 152 " Press <control-c> to exit.\n"
Chris@0 153 "\n",
Chris@0 154 filename, src_get_name (converter)) ;
Chris@0 155
Chris@0 156 if ((audio_out = audio_open (data->sfinfo.channels, data->sfinfo.samplerate)) == NULL)
Chris@0 157 { printf ("\n\nError : audio_open () failed.\n") ;
Chris@0 158 exit (1) ;
Chris@0 159 } ;
Chris@0 160
Chris@0 161 /* Set up sample rate converter info. */
Chris@0 162 data->src_data.end_of_input = 0 ; /* Set this later. */
Chris@0 163
Chris@0 164 /* Start with zero to force load in while loop. */
Chris@0 165 data->src_data.input_frames = 0 ;
Chris@0 166 data->src_data.data_in = data->buffer_in ;
Chris@0 167
Chris@0 168 /* Start with output frames also zero. */
Chris@0 169 data->src_data.output_frames_gen = 0 ;
Chris@0 170
Chris@0 171 data->buffer_out_start = data->buffer_out_end = 0 ;
Chris@0 172 data->src_data.src_ratio = 1.0 ;
Chris@0 173
Chris@0 174 /* Pass the data and the callbacl function to audio_play */
Chris@0 175 audio_play ((get_audio_callback_t) varispeed_get_data, audio_out, data) ;
Chris@0 176
Chris@0 177 /* Cleanup */
Chris@0 178 audio_close (audio_out) ;
Chris@0 179 sf_close (data->sndfile) ;
Chris@0 180 src_delete (data->src_state) ;
Chris@0 181
Chris@0 182 free (data) ;
Chris@0 183
Chris@0 184 } /* varispeed_play */
Chris@0 185
Chris@0 186 /*==============================================================================
Chris@0 187 */
Chris@0 188
Chris@0 189 static int
Chris@0 190 varispeed_get_data (CALLBACK_DATA *data, float *samples, int frames)
Chris@0 191 { int error, readframes, frame_count, direct_out ;
Chris@0 192
Chris@0 193 if (data->magic != MAGIC_NUMBER)
Chris@0 194 { printf ("\n\n%s:%d Eeeek, something really bad happened!\n", __FILE__, __LINE__) ;
Chris@0 195 exit (1) ;
Chris@0 196 } ;
Chris@0 197
Chris@0 198 frame_count = 0 ;
Chris@0 199
Chris@0 200 if (data->buffer_out_start < data->buffer_out_end)
Chris@0 201 { frame_count = MIN (data->buffer_out_end - data->buffer_out_start, frames) ;
Chris@0 202 memcpy (samples, data->buffer_out + data->sfinfo.channels * data->buffer_out_start, data->sfinfo.channels * frame_count * sizeof (float)) ;
Chris@0 203 data->buffer_out_start += frame_count ;
Chris@0 204 } ;
Chris@0 205
Chris@0 206 data->buffer_out_start = data->buffer_out_end = 0 ;
Chris@0 207
Chris@0 208 while (frame_count < frames)
Chris@0 209 {
Chris@0 210 /* Read INPUT_FRAMES frames worth looping at end of file. */
Chris@0 211 for (readframes = 0 ; readframes < INPUT_FRAMES ; )
Chris@0 212 { sf_count_t position ;
Chris@0 213
Chris@0 214 readframes += sf_readf_float (data->sndfile, data->buffer_in + data->sfinfo.channels * readframes, INPUT_FRAMES - readframes) ;
Chris@0 215
Chris@0 216 position = sf_seek (data->sndfile, 0, SEEK_CUR) ;
Chris@0 217
Chris@0 218 if (position < 0 || position == data->sfinfo.frames)
Chris@0 219 sf_seek (data->sndfile, 0, SEEK_SET) ;
Chris@0 220 } ;
Chris@0 221
Chris@0 222 data->src_data.input_frames = readframes ;
Chris@0 223
Chris@0 224 data->src_data.src_ratio = 1.0 - 0.5 * sin (data->freq_point * 2 * M_PI / 20000) ;
Chris@0 225 data->freq_point ++ ;
Chris@0 226
Chris@0 227 direct_out = (data->src_data.src_ratio * readframes < frames - frame_count) ? 1 : 0 ;
Chris@0 228
Chris@0 229 if (direct_out)
Chris@0 230 { data->src_data.data_out = samples + frame_count * data->sfinfo.channels ;
Chris@0 231 data->src_data.output_frames = frames - frame_count ;
Chris@0 232 }
Chris@0 233 else
Chris@0 234 { data->src_data.data_out = data->buffer_out ;
Chris@0 235 data->src_data.output_frames = BUFFER_LEN / data->sfinfo.channels ;
Chris@0 236 } ;
Chris@0 237
Chris@0 238 if ((error = src_process (data->src_state, &data->src_data)))
Chris@0 239 { printf ("\nError : %s\n\n", src_strerror (error)) ;
Chris@0 240 exit (1) ;
Chris@0 241 } ;
Chris@0 242
Chris@0 243 if (direct_out)
Chris@0 244 { frame_count += data->src_data.output_frames_gen ;
Chris@0 245 continue ;
Chris@0 246 } ;
Chris@0 247
Chris@0 248 memcpy (samples + frame_count * data->sfinfo.channels, data->buffer_out, (frames - frame_count) * data->sfinfo.channels * sizeof (float)) ;
Chris@0 249
Chris@0 250 data->buffer_out_start = frames - frame_count ;
Chris@0 251 data->buffer_out_end = data->src_data.output_frames_gen ;
Chris@0 252
Chris@0 253 frame_count += frames - frame_count ;
Chris@0 254 } ;
Chris@0 255
Chris@0 256 return frame_count ;
Chris@0 257 } /* varispeed_get_data */
Chris@0 258
Chris@0 259 /*==============================================================================
Chris@0 260 */
Chris@0 261
Chris@0 262 #else /* (HAVE_SNFILE == 0) */
Chris@0 263
Chris@0 264 /* Alternative main function when libsndfile is not available. */
Chris@0 265
Chris@0 266 int
Chris@0 267 main (void)
Chris@0 268 { puts (
Chris@0 269 "\n"
Chris@0 270 "****************************************************************\n"
Chris@0 271 " This example program was compiled without libsndfile \n"
Chris@0 272 " (http://www.zip.com.au/~erikd/libsndfile/).\n"
Chris@0 273 " It is therefore completely broken and non-functional.\n"
Chris@0 274 "****************************************************************\n"
Chris@0 275 "\n"
Chris@0 276 ) ;
Chris@0 277
Chris@0 278 return 0 ;
Chris@0 279 } /* main */
Chris@0 280
Chris@0 281 #endif
Chris@0 282