Mercurial > hg > sv-dependency-builds
comparison src/libsamplerate-0.1.9/examples/varispeed-play.c @ 41:481f5f8c5634
Current libsamplerate source
author | Chris Cannam |
---|---|
date | Tue, 18 Oct 2016 13:24:45 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
40:1df64224f5ac | 41:481f5f8c5634 |
---|---|
1 /* | |
2 ** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> | |
3 ** All rights reserved. | |
4 ** | |
5 ** This code is released under 2-clause BSD license. Please see the | |
6 ** file at : https://github.com/erikd/libsamplerate/blob/master/COPYING | |
7 */ | |
8 | |
9 #include <stdio.h> | |
10 #include <stdlib.h> | |
11 #include <unistd.h> | |
12 #include <string.h> | |
13 | |
14 #include "config.h" | |
15 | |
16 #include <float_cast.h> | |
17 | |
18 #if (HAVE_SNDFILE) | |
19 | |
20 #include <samplerate.h> | |
21 #include <sndfile.h> | |
22 | |
23 #include "audio_out.h" | |
24 | |
25 #define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0]))) | |
26 | |
27 #define BUFFER_LEN 4096 | |
28 #define VARISPEED_BLOCK_LEN 64 | |
29 | |
30 #define MIN(a,b) ((a) < (b) ? (a) : (b)) | |
31 | |
32 #define SRC_MAGIC ((int) ('S' << 16) + ('R' << 8) + ('C')) | |
33 #define SNDFILE_MAGIC ((int) ('s' << 24) + ('n' << 20) + ('d' << 16) + ('f' << 12) + ('i' << 8) + ('l' << 4) + 'e') | |
34 | |
35 #ifndef M_PI | |
36 #define M_PI 3.14159265358979323846264338 | |
37 #endif | |
38 | |
39 | |
40 typedef struct | |
41 { int magic ; | |
42 SNDFILE *sndfile ; | |
43 SF_INFO sfinfo ; | |
44 | |
45 float buffer [BUFFER_LEN] ; | |
46 } SNDFILE_CB_DATA ; | |
47 | |
48 typedef struct | |
49 { int magic ; | |
50 | |
51 SNDFILE_CB_DATA sf ; | |
52 | |
53 int freq_point ; | |
54 | |
55 SRC_STATE *src_state ; | |
56 | |
57 } SRC_CB_DATA ; | |
58 | |
59 static int varispeed_get_data (SRC_CB_DATA *data, float *samples, int frames) ; | |
60 static void varispeed_play (const char *filename, int converter) ; | |
61 | |
62 static long src_input_callback (void *cb_data, float **data) ; | |
63 | |
64 int | |
65 main (int argc, char *argv []) | |
66 { const char *cptr, *progname, *filename ; | |
67 int k, converter ; | |
68 | |
69 converter = SRC_SINC_FASTEST ; | |
70 | |
71 progname = argv [0] ; | |
72 | |
73 if ((cptr = strrchr (progname, '/')) != NULL) | |
74 progname = cptr + 1 ; | |
75 | |
76 if ((cptr = strrchr (progname, '\\')) != NULL) | |
77 progname = cptr + 1 ; | |
78 | |
79 printf ("\n" | |
80 " %s\n" | |
81 "\n" | |
82 " This is a demo program which plays the given file at a slowly \n" | |
83 " varying speed. Lots of fun with drum loops and full mixes.\n" | |
84 "\n" | |
85 " It uses Secret Rabbit Code (aka libsamplerate) to perform the \n" | |
86 " vari-speeding and libsndfile for file I/O.\n" | |
87 "\n", progname) ; | |
88 | |
89 if (argc == 2) | |
90 filename = argv [1] ; | |
91 else if (argc == 4 && strcmp (argv [1], "-c") == 0) | |
92 { filename = argv [3] ; | |
93 converter = atoi (argv [2]) ; | |
94 } | |
95 else | |
96 { printf (" Usage :\n\n %s [-c <number>] <input file>\n\n", progname) ; | |
97 puts ( | |
98 " The optional -c argument allows the converter type to be chosen from\n" | |
99 " the following list :" | |
100 "\n" | |
101 ) ; | |
102 | |
103 for (k = 0 ; (cptr = src_get_name (k)) != NULL ; k++) | |
104 printf (" %d : %s\n", k, cptr) ; | |
105 | |
106 puts ("") ; | |
107 exit (1) ; | |
108 } ; | |
109 | |
110 varispeed_play (filename, converter) ; | |
111 | |
112 return 0 ; | |
113 } /* main */ | |
114 | |
115 /*============================================================================== | |
116 */ | |
117 | |
118 static void | |
119 varispeed_play (const char *filename, int converter) | |
120 { SRC_CB_DATA data ; | |
121 AUDIO_OUT *audio_out ; | |
122 int error ; | |
123 | |
124 memset (&data, 0, sizeof (data)) ; | |
125 | |
126 data.magic = SRC_MAGIC ; | |
127 data.sf.magic = SNDFILE_MAGIC ; | |
128 | |
129 if ((data.sf.sndfile = sf_open (filename, SFM_READ, &data.sf.sfinfo)) == NULL) | |
130 { puts (sf_strerror (NULL)) ; | |
131 exit (1) ; | |
132 } ; | |
133 | |
134 /* Initialize the sample rate converter. */ | |
135 if ((data.src_state = src_callback_new (src_input_callback, converter, data.sf.sfinfo.channels, &error, &data.sf)) == NULL) | |
136 { printf ("\n\nError : src_new() failed : %s.\n\n", src_strerror (error)) ; | |
137 exit (1) ; | |
138 } ; | |
139 | |
140 printf ( | |
141 | |
142 " Playing : %s\n" | |
143 " Converter : %s\n" | |
144 "\n" | |
145 " Press <control-c> to exit.\n" | |
146 "\n", | |
147 filename, src_get_name (converter)) ; | |
148 | |
149 if ((audio_out = audio_open (data.sf.sfinfo.channels, data.sf.sfinfo.samplerate)) == NULL) | |
150 { printf ("\n\nError : audio_open () failed.\n") ; | |
151 exit (1) ; | |
152 } ; | |
153 | |
154 /* Pass the data and the callbacl function to audio_play */ | |
155 audio_play ((get_audio_callback_t) varispeed_get_data, audio_out, &data) ; | |
156 | |
157 /* Cleanup */ | |
158 audio_close (audio_out) ; | |
159 sf_close (data.sf.sndfile) ; | |
160 src_delete (data.src_state) ; | |
161 | |
162 } /* varispeed_play */ | |
163 | |
164 static long | |
165 src_input_callback (void *cb_data, float **audio) | |
166 { SNDFILE_CB_DATA * data = (SNDFILE_CB_DATA *) cb_data ; | |
167 const int input_frames = ARRAY_LEN (data->buffer) / data->sfinfo.channels ; | |
168 int read_frames ; | |
169 | |
170 if (data->magic != SNDFILE_MAGIC) | |
171 { printf ("\n\n%s:%d Eeeek, something really bad happened!\n", __FILE__, __LINE__) ; | |
172 exit (1) ; | |
173 } ; | |
174 | |
175 for (read_frames = 0 ; read_frames < input_frames ; ) | |
176 { sf_count_t position ; | |
177 | |
178 read_frames += sf_readf_float (data->sndfile, data->buffer + read_frames * data->sfinfo.channels, input_frames - read_frames) ; | |
179 | |
180 position = sf_seek (data->sndfile, 0, SEEK_CUR) ; | |
181 | |
182 if (position < 0 || position == data->sfinfo.frames) | |
183 sf_seek (data->sndfile, 0, SEEK_SET) ; | |
184 } ; | |
185 | |
186 *audio = & (data->buffer [0]) ; | |
187 | |
188 return input_frames ; | |
189 } /* src_input_callback */ | |
190 | |
191 | |
192 /*============================================================================== | |
193 */ | |
194 | |
195 static int | |
196 varispeed_get_data (SRC_CB_DATA *data, float *samples, int out_frames) | |
197 { float *output ; | |
198 int rc, out_frame_count ; | |
199 | |
200 if (data->magic != SRC_MAGIC) | |
201 { printf ("\n\n%s:%d Eeeek, something really bad happened!\n", __FILE__, __LINE__) ; | |
202 exit (1) ; | |
203 } ; | |
204 | |
205 for (out_frame_count = 0 ; out_frame_count < out_frames ; out_frame_count += VARISPEED_BLOCK_LEN) | |
206 { double src_ratio = 1.0 - 0.5 * sin (data->freq_point * 2 * M_PI / 20000) ; | |
207 | |
208 data->freq_point ++ ; | |
209 | |
210 output = samples + out_frame_count * data->sf.sfinfo.channels ; | |
211 | |
212 if ((rc = src_callback_read (data->src_state, src_ratio, VARISPEED_BLOCK_LEN, output)) < VARISPEED_BLOCK_LEN) | |
213 { printf ("\nError : src_callback_read short output (%d instead of %d)\n\n", rc, VARISPEED_BLOCK_LEN) ; | |
214 exit (1) ; | |
215 } ; | |
216 } ; | |
217 | |
218 return out_frames ; | |
219 } /* varispeed_get_data */ | |
220 | |
221 /*============================================================================== | |
222 */ | |
223 | |
224 #else /* (HAVE_SNFILE == 0) */ | |
225 | |
226 /* Alternative main function when libsndfile is not available. */ | |
227 | |
228 int | |
229 main (void) | |
230 { puts ( | |
231 "\n" | |
232 "****************************************************************\n" | |
233 " This example program was compiled without libsndfile \n" | |
234 " (http://www.zip.com.au/~erikd/libsndfile/).\n" | |
235 " It is therefore completely broken and non-functional.\n" | |
236 "****************************************************************\n" | |
237 "\n" | |
238 ) ; | |
239 | |
240 return 0 ; | |
241 } /* main */ | |
242 | |
243 #endif | |
244 |