Mercurial > hg > sv-dependency-builds
diff src/libsamplerate-0.1.8/examples/varispeed-play.c @ 0:c7265573341e
Import initial set of sources
author | Chris Cannam |
---|---|
date | Mon, 18 Mar 2013 14:12:14 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libsamplerate-0.1.8/examples/varispeed-play.c Mon Mar 18 14:12:14 2013 +0000 @@ -0,0 +1,282 @@ +/* +** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com> +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include "config.h" + +#include <float_cast.h> + +#if (HAVE_SNDFILE) + +#include <samplerate.h> +#include <sndfile.h> + +#include "audio_out.h" + +#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0]))) + +#define BUFFER_LEN 4096 +#define INPUT_FRAMES 100 + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +#define MAGIC_NUMBER ((int) ('S' << 16) + ('R' << 8) + ('C')) + +#ifndef M_PI +#define M_PI 3.14159265358979323846264338 +#endif + + +typedef struct +{ int magic ; + + SNDFILE *sndfile ; + SF_INFO sfinfo ; + + SRC_STATE *src_state ; + SRC_DATA src_data ; + + int freq_point ; + int buffer_out_start, buffer_out_end ; + + float buffer_in [BUFFER_LEN] ; + float buffer_out [BUFFER_LEN] ; +} CALLBACK_DATA ; + +static int varispeed_get_data (CALLBACK_DATA *data, float *samples, int frames) ; +static void varispeed_play (const char *filename, int converter) ; + +int +main (int argc, char *argv []) +{ const char *cptr, *progname, *filename ; + int k, converter ; + + converter = SRC_SINC_FASTEST ; + + progname = argv [0] ; + + if ((cptr = strrchr (progname, '/')) != NULL) + progname = cptr + 1 ; + + if ((cptr = strrchr (progname, '\\')) != NULL) + progname = cptr + 1 ; + + printf ("\n" + " %s\n" + "\n" + " This is a demo program which plays the given file at a slowly \n" + " varying speed. Lots of fun with drum loops and full mixes.\n" + "\n" + " It uses Secret Rabbit Code (aka libsamplerate) to perform the \n" + " vari-speeding and libsndfile for file I/O.\n" + "\n", progname) ; + + if (argc == 2) + filename = argv [1] ; + else if (argc == 4 && strcmp (argv [1], "-c") == 0) + { filename = argv [3] ; + converter = atoi (argv [2]) ; + } + else + { printf (" Usage :\n\n %s [-c <number>] <input file>\n\n", progname) ; + puts ( + " The optional -c argument allows the converter type to be chosen from\n" + " the following list :" + "\n" + ) ; + + for (k = 0 ; (cptr = src_get_name (k)) != NULL ; k++) + printf (" %d : %s\n", k, cptr) ; + + puts ("") ; + exit (1) ; + } ; + + varispeed_play (filename, converter) ; + + return 0 ; +} /* main */ + +/*============================================================================== +*/ + +static void +varispeed_play (const char *filename, int converter) +{ CALLBACK_DATA *data ; + AUDIO_OUT *audio_out ; + int error ; + + /* Allocate memory for the callback data. */ + if ((data = calloc (1, sizeof (CALLBACK_DATA))) == NULL) + { printf ("\n\n%s:%d Calloc failed!\n", __FILE__, __LINE__) ; + exit (1) ; + } ; + + data->magic = MAGIC_NUMBER ; + + if ((data->sndfile = sf_open (filename, SFM_READ, &data->sfinfo)) == NULL) + { puts (sf_strerror (NULL)) ; + exit (1) ; + } ; + + /* Initialize the sample rate converter. */ + if ((data->src_state = src_new (converter, data->sfinfo.channels, &error)) == NULL) + { printf ("\n\nError : src_new() failed : %s.\n\n", src_strerror (error)) ; + exit (1) ; + } ; + + printf ( + + " Playing : %s\n" + " Converter : %s\n" + "\n" + " Press <control-c> to exit.\n" + "\n", + filename, src_get_name (converter)) ; + + if ((audio_out = audio_open (data->sfinfo.channels, data->sfinfo.samplerate)) == NULL) + { printf ("\n\nError : audio_open () failed.\n") ; + exit (1) ; + } ; + + /* Set up sample rate converter info. */ + data->src_data.end_of_input = 0 ; /* Set this later. */ + + /* Start with zero to force load in while loop. */ + data->src_data.input_frames = 0 ; + data->src_data.data_in = data->buffer_in ; + + /* Start with output frames also zero. */ + data->src_data.output_frames_gen = 0 ; + + data->buffer_out_start = data->buffer_out_end = 0 ; + data->src_data.src_ratio = 1.0 ; + + /* Pass the data and the callbacl function to audio_play */ + audio_play ((get_audio_callback_t) varispeed_get_data, audio_out, data) ; + + /* Cleanup */ + audio_close (audio_out) ; + sf_close (data->sndfile) ; + src_delete (data->src_state) ; + + free (data) ; + +} /* varispeed_play */ + +/*============================================================================== +*/ + +static int +varispeed_get_data (CALLBACK_DATA *data, float *samples, int frames) +{ int error, readframes, frame_count, direct_out ; + + if (data->magic != MAGIC_NUMBER) + { printf ("\n\n%s:%d Eeeek, something really bad happened!\n", __FILE__, __LINE__) ; + exit (1) ; + } ; + + frame_count = 0 ; + + if (data->buffer_out_start < data->buffer_out_end) + { frame_count = MIN (data->buffer_out_end - data->buffer_out_start, frames) ; + memcpy (samples, data->buffer_out + data->sfinfo.channels * data->buffer_out_start, data->sfinfo.channels * frame_count * sizeof (float)) ; + data->buffer_out_start += frame_count ; + } ; + + data->buffer_out_start = data->buffer_out_end = 0 ; + + while (frame_count < frames) + { + /* Read INPUT_FRAMES frames worth looping at end of file. */ + for (readframes = 0 ; readframes < INPUT_FRAMES ; ) + { sf_count_t position ; + + readframes += sf_readf_float (data->sndfile, data->buffer_in + data->sfinfo.channels * readframes, INPUT_FRAMES - readframes) ; + + position = sf_seek (data->sndfile, 0, SEEK_CUR) ; + + if (position < 0 || position == data->sfinfo.frames) + sf_seek (data->sndfile, 0, SEEK_SET) ; + } ; + + data->src_data.input_frames = readframes ; + + data->src_data.src_ratio = 1.0 - 0.5 * sin (data->freq_point * 2 * M_PI / 20000) ; + data->freq_point ++ ; + + direct_out = (data->src_data.src_ratio * readframes < frames - frame_count) ? 1 : 0 ; + + if (direct_out) + { data->src_data.data_out = samples + frame_count * data->sfinfo.channels ; + data->src_data.output_frames = frames - frame_count ; + } + else + { data->src_data.data_out = data->buffer_out ; + data->src_data.output_frames = BUFFER_LEN / data->sfinfo.channels ; + } ; + + if ((error = src_process (data->src_state, &data->src_data))) + { printf ("\nError : %s\n\n", src_strerror (error)) ; + exit (1) ; + } ; + + if (direct_out) + { frame_count += data->src_data.output_frames_gen ; + continue ; + } ; + + memcpy (samples + frame_count * data->sfinfo.channels, data->buffer_out, (frames - frame_count) * data->sfinfo.channels * sizeof (float)) ; + + data->buffer_out_start = frames - frame_count ; + data->buffer_out_end = data->src_data.output_frames_gen ; + + frame_count += frames - frame_count ; + } ; + + return frame_count ; +} /* varispeed_get_data */ + +/*============================================================================== +*/ + +#else /* (HAVE_SNFILE == 0) */ + +/* Alternative main function when libsndfile is not available. */ + +int +main (void) +{ puts ( + "\n" + "****************************************************************\n" + " This example program was compiled without libsndfile \n" + " (http://www.zip.com.au/~erikd/libsndfile/).\n" + " It is therefore completely broken and non-functional.\n" + "****************************************************************\n" + "\n" + ) ; + + return 0 ; +} /* main */ + +#endif +