]>
Commit | Line | Data |
---|---|---|
8529da43 MG |
1 | /* |
2 | ** Copyright (c) 2003-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 <string.h> | |
12 | #include <math.h> | |
13 | ||
14 | #include <samplerate.h> | |
15 | ||
16 | #include "util.h" | |
17 | ||
18 | #define BUFFER_LEN 10000 | |
19 | #define CB_READ_LEN 256 | |
20 | ||
21 | static void callback_test (int converter, double ratio) ; | |
22 | static void end_of_stream_test (int converter) ; | |
23 | ||
24 | int | |
25 | main (void) | |
26 | { static double src_ratios [] = | |
27 | { 1.0, 0.099, 0.1, 0.33333333, 0.789, 1.0001, 1.9, 3.1, 9.9 | |
28 | } ; | |
29 | ||
30 | int k ; | |
31 | ||
32 | puts ("") ; | |
33 | ||
34 | puts (" Zero Order Hold interpolator :") ; | |
35 | for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) | |
36 | callback_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ; | |
37 | ||
38 | puts (" Linear interpolator :") ; | |
39 | for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) | |
40 | callback_test (SRC_LINEAR, src_ratios [k]) ; | |
41 | ||
42 | puts (" Sinc interpolator :") ; | |
43 | for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) | |
44 | callback_test (SRC_SINC_FASTEST, src_ratios [k]) ; | |
45 | ||
46 | puts ("") ; | |
47 | ||
48 | puts (" End of stream test :") ; | |
49 | end_of_stream_test (SRC_ZERO_ORDER_HOLD) ; | |
50 | end_of_stream_test (SRC_LINEAR) ; | |
51 | end_of_stream_test (SRC_SINC_FASTEST) ; | |
52 | ||
53 | puts ("") ; | |
54 | return 0 ; | |
55 | } /* main */ | |
56 | ||
57 | /*===================================================================================== | |
58 | */ | |
59 | ||
60 | typedef struct | |
61 | { int channels ; | |
62 | long count, total ; | |
63 | int end_of_data ; | |
64 | float data [BUFFER_LEN] ; | |
65 | } TEST_CB_DATA ; | |
66 | ||
67 | static long | |
68 | test_callback_func (void *cb_data, float **data) | |
69 | { TEST_CB_DATA *pcb_data ; | |
70 | ||
71 | long frames ; | |
72 | ||
73 | if ((pcb_data = cb_data) == NULL) | |
74 | return 0 ; | |
75 | ||
76 | if (data == NULL) | |
77 | return 0 ; | |
78 | ||
79 | if (pcb_data->total - pcb_data->count > CB_READ_LEN) | |
80 | frames = CB_READ_LEN / pcb_data->channels ; | |
81 | else | |
82 | frames = (pcb_data->total - pcb_data->count) / pcb_data->channels ; | |
83 | ||
84 | *data = pcb_data->data + pcb_data->count ; | |
85 | pcb_data->count += frames ; | |
86 | ||
87 | return frames ; | |
88 | } /* test_callback_func */ | |
89 | ||
90 | ||
91 | static void | |
92 | callback_test (int converter, double src_ratio) | |
93 | { static TEST_CB_DATA test_callback_data ; | |
94 | static float output [BUFFER_LEN] ; | |
95 | ||
96 | SRC_STATE *src_state ; | |
97 | ||
98 | long read_count, read_total ; | |
99 | int error ; | |
100 | ||
101 | printf ("\tcallback_test (SRC ratio = %6.4f) ........... ", src_ratio) ; | |
102 | fflush (stdout) ; | |
103 | ||
104 | test_callback_data.channels = 2 ; | |
105 | test_callback_data.count = 0 ; | |
106 | test_callback_data.end_of_data = 0 ; | |
107 | test_callback_data.total = ARRAY_LEN (test_callback_data.data) ; | |
108 | ||
109 | if ((src_state = src_callback_new (test_callback_func, converter, test_callback_data.channels, &error, &test_callback_data)) == NULL) | |
110 | { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | |
111 | exit (1) ; | |
112 | } ; | |
113 | ||
114 | read_total = 0 ; | |
115 | do | |
116 | { /* We will be throwing away output data, so just grab as much as possible. */ | |
117 | read_count = ARRAY_LEN (output) / test_callback_data.channels ; | |
118 | read_count = src_callback_read (src_state, src_ratio, read_count, output) ; | |
119 | read_total += read_count ; | |
120 | } | |
121 | while (read_count > 0) ; | |
122 | ||
123 | if ((error = src_error (src_state)) != 0) | |
124 | { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | |
125 | exit (1) ; | |
126 | } ; | |
127 | ||
128 | src_state = src_delete (src_state) ; | |
129 | ||
130 | if (fabs (read_total / src_ratio - ARRAY_LEN (test_callback_data.data)) > 2.0) | |
131 | { printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ; | |
132 | printf (" input len : %d\n", ARRAY_LEN (test_callback_data.data)) ; | |
133 | printf (" output len : %ld (should be %g +/- 2)\n\n", read_total, | |
134 | floor (0.5 + src_ratio * ARRAY_LEN (test_callback_data.data))) ; | |
135 | exit (1) ; | |
136 | } ; | |
137 | ||
138 | puts ("ok") ; | |
139 | ||
140 | return ; | |
141 | } /* callback_test */ | |
142 | ||
143 | /*===================================================================================== | |
144 | */ | |
145 | ||
146 | static long | |
147 | eos_callback_func (void *cb_data, float **data) | |
148 | { | |
149 | TEST_CB_DATA *pcb_data ; | |
150 | long frames ; | |
151 | ||
152 | if (data == NULL) | |
153 | return 0 ; | |
154 | ||
155 | if ((pcb_data = cb_data) == NULL) | |
156 | return 0 ; | |
157 | ||
158 | /* | |
159 | ** Return immediately if there is no more data. | |
160 | ** In this case, the output pointer 'data' will not be set and | |
161 | ** valgrind should not warn about it. | |
162 | */ | |
163 | if (pcb_data->end_of_data) | |
164 | return 0 ; | |
165 | ||
166 | if (pcb_data->total - pcb_data->count > CB_READ_LEN) | |
167 | frames = CB_READ_LEN / pcb_data->channels ; | |
168 | else | |
169 | frames = (pcb_data->total - pcb_data->count) / pcb_data->channels ; | |
170 | ||
171 | *data = pcb_data->data + pcb_data->count ; | |
172 | pcb_data->count += frames ; | |
173 | ||
174 | /* | |
175 | ** Set end_of_data so that the next call to the callback function will | |
176 | ** return zero ocunt without setting the 'data' pointer. | |
177 | */ | |
178 | if (pcb_data->total < 2 * pcb_data->count) | |
179 | pcb_data->end_of_data = 1 ; | |
180 | ||
181 | return frames ; | |
182 | } /* eos_callback_data */ | |
183 | ||
184 | ||
185 | static void | |
186 | end_of_stream_test (int converter) | |
187 | { static TEST_CB_DATA test_callback_data ; | |
188 | static float output [BUFFER_LEN] ; | |
189 | ||
190 | SRC_STATE *src_state ; | |
191 | ||
192 | double src_ratio = 0.3 ; | |
193 | long read_count, read_total ; | |
194 | int error ; | |
195 | ||
196 | printf ("\t%-30s ........... ", src_get_name (converter)) ; | |
197 | fflush (stdout) ; | |
198 | ||
199 | test_callback_data.channels = 2 ; | |
200 | test_callback_data.count = 0 ; | |
201 | test_callback_data.end_of_data = 0 ; | |
202 | test_callback_data.total = ARRAY_LEN (test_callback_data.data) ; | |
203 | ||
204 | if ((src_state = src_callback_new (eos_callback_func, converter, test_callback_data.channels, &error, &test_callback_data)) == NULL) | |
205 | { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | |
206 | exit (1) ; | |
207 | } ; | |
208 | ||
209 | read_total = 0 ; | |
210 | do | |
211 | { /* We will be throwing away output data, so just grab as much as possible. */ | |
212 | read_count = ARRAY_LEN (output) / test_callback_data.channels ; | |
213 | read_count = src_callback_read (src_state, src_ratio, read_count, output) ; | |
214 | read_total += read_count ; | |
215 | } | |
216 | while (read_count > 0) ; | |
217 | ||
218 | if ((error = src_error (src_state)) != 0) | |
219 | { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; | |
220 | exit (1) ; | |
221 | } ; | |
222 | ||
223 | src_state = src_delete (src_state) ; | |
224 | ||
225 | if (test_callback_data.end_of_data == 0) | |
226 | { printf ("\n\nLine %d : test_callback_data.end_of_data should not be 0." | |
227 | " This is a bug in the test.\n\n", __LINE__) ; | |
228 | exit (1) ; | |
229 | } ; | |
230 | ||
231 | puts ("ok") ; | |
232 | return ; | |
233 | } /* end_of_stream_test */ |