ref: 697a6ce45e7140d72578b03b6163bf6066b6d9ad
parent: 34bb50a4b07dc68cbab4d8130ebfce2ee449774e
author: Erik de Castro Lopo <erikd@mega-nerd.com>
date: Sat Nov 5 09:46:45 EDT 2011
examples/varispeed-play.c : Rewrite to use the callback version of the API.
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,10 @@
* src/samplerate.h
Removed unused typedef struct SRC_CB_DATA.
+ * examples/varispeed-play.c
+ Rewrite to use the callback version of the API. This new version is far
+ simpler and far easier to understand.
+
2011-11-02 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
* configure.ac examples/Makefile.am
--- a/examples/varispeed-play.c
+++ b/examples/varispeed-play.c
@@ -34,12 +34,13 @@
#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0])))
-#define BUFFER_LEN 4096
-#define INPUT_FRAMES 100
+#define BUFFER_LEN 4096
+#define VARISPEED_BLOCK_LEN 64
#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAGIC_NUMBER ((int) ('S' << 16) + ('R' << 8) + ('C'))
+#define SRC_MAGIC ((int) ('S' << 16) + ('R' << 8) + ('C'))
+#define SNDFILE_MAGIC ((int) ('s' << 24) + ('n' << 20) + ('d' << 16) + ('f' << 12) + ('i' << 8) + ('l' << 4) + 'e')
#ifndef M_PI
#define M_PI 3.14159265358979323846264338
@@ -48,23 +49,28 @@
typedef struct
{ int magic ;
-
SNDFILE *sndfile ;
SF_INFO sfinfo ;
- SRC_STATE *src_state ;
- SRC_DATA src_data ;
+ float buffer [BUFFER_LEN] ;
+} SNDFILE_CB_DATA ;
+typedef struct
+{ int magic ;
+
+ SNDFILE_CB_DATA sf ;
+
int freq_point ;
- int buffer_out_start, buffer_out_end ;
- float buffer_in [BUFFER_LEN] ;
- float buffer_out [BUFFER_LEN] ;
-} CALLBACK_DATA ;
+ SRC_STATE *src_state ;
-static int varispeed_get_data (CALLBACK_DATA *data, float *samples, int frames) ;
+} SRC_CB_DATA ;
+
+static int varispeed_get_data (SRC_CB_DATA *data, float *samples, int frames) ;
static void varispeed_play (const char *filename, int converter) ;
+static long src_input_callback (void *cb_data, float **data) ;
+
int
main (int argc, char *argv [])
{ const char *cptr, *progname, *filename ;
@@ -121,25 +127,22 @@
static void
varispeed_play (const char *filename, int converter)
-{ CALLBACK_DATA *data ;
+{ SRC_CB_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) ;
- } ;
+ memset (&data, 0, sizeof (data)) ;
- data->magic = MAGIC_NUMBER ;
+ data.magic = SRC_MAGIC ;
+ data.sf.magic = SNDFILE_MAGIC ;
- if ((data->sndfile = sf_open (filename, SFM_READ, &data->sfinfo)) == NULL)
+ if ((data.sf.sndfile = sf_open (filename, SFM_READ, &data.sf.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)
+ if ((data.src_state = src_callback_new (src_input_callback, converter, data.sf.sfinfo.channels, &error, &data.sf)) == NULL)
{ printf ("\n\nError : src_new() failed : %s.\n\n", src_strerror (error)) ;
exit (1) ;
} ;
@@ -153,107 +156,76 @@
"\n",
filename, src_get_name (converter)) ;
- if ((audio_out = audio_open (data->sfinfo.channels, data->sfinfo.samplerate)) == NULL)
+ if ((audio_out = audio_open (data.sf.sfinfo.channels, data.sf.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) ;
+ 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) ;
+ sf_close (data.sf.sndfile) ;
+ src_delete (data.src_state) ;
- free (data) ;
-
} /* varispeed_play */
-/*==============================================================================
-*/
+static long
+src_input_callback (void *cb_data, float **audio)
+{ SNDFILE_CB_DATA * data = (SNDFILE_CB_DATA *) cb_data ;
+ const int input_frames = ARRAY_LEN (data->buffer) / data->sfinfo.channels ;
+ int read_frames ;
-static int
-varispeed_get_data (CALLBACK_DATA *data, float *samples, int frames)
-{ int error, readframes, frame_count, direct_out ;
-
- if (data->magic != MAGIC_NUMBER)
+ if (data->magic != SNDFILE_MAGIC)
{ printf ("\n\n%s:%d Eeeek, something really bad happened!\n", __FILE__, __LINE__) ;
exit (1) ;
} ;
- frame_count = 0 ;
+ for (read_frames = 0 ; read_frames < input_frames ; )
+ { sf_count_t position ;
- 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 ;
+ read_frames += sf_readf_float (data->sndfile, data->buffer + read_frames * data->sfinfo.channels, input_frames - read_frames) ;
+
+ position = sf_seek (data->sndfile, 0, SEEK_CUR) ;
+
+ if (position < 0 || position == data->sfinfo.frames)
+ sf_seek (data->sndfile, 0, SEEK_SET) ;
} ;
- data->buffer_out_start = data->buffer_out_end = 0 ;
+ *audio = & (data->buffer [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 ;
+ return input_frames ;
+} /* src_input_callback */
- 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) ;
- } ;
+static int
+varispeed_get_data (SRC_CB_DATA *data, float *samples, int out_frames)
+{ float *output ;
+ int rc, out_frame_count ;
- data->src_data.input_frames = readframes ;
+ if (data->magic != SRC_MAGIC)
+ { printf ("\n\n%s:%d Eeeek, something really bad happened!\n", __FILE__, __LINE__) ;
+ exit (1) ;
+ } ;
- data->src_data.src_ratio = 1.0 - 0.5 * sin (data->freq_point * 2 * M_PI / 20000) ;
+ for (out_frame_count = 0 ; out_frame_count < out_frames ; out_frame_count += VARISPEED_BLOCK_LEN)
+ { double 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 ;
+ output = samples + out_frame_count * data->sf.sfinfo.channels ;
- 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)) ;
+ if ((rc = src_callback_read (data->src_state, src_ratio, VARISPEED_BLOCK_LEN, output)) < VARISPEED_BLOCK_LEN)
+ { printf ("\nError : src_callback_read short output (%d instead of %d)\n\n", rc, VARISPEED_BLOCK_LEN) ;
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 ;
+ return out_frames ;
} /* varispeed_get_data */
/*==============================================================================