cannam@85
|
1 /*
|
cannam@85
|
2 ** Copyright (C) 2004-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
cannam@85
|
3 **
|
cannam@85
|
4 ** This program is free software; you can redistribute it and/or modify
|
cannam@85
|
5 ** it under the terms of the GNU General Public License as published by
|
cannam@85
|
6 ** the Free Software Foundation; either version 2 of the License, or
|
cannam@85
|
7 ** (at your option) any later version.
|
cannam@85
|
8 **
|
cannam@85
|
9 ** This program is distributed in the hope that it will be useful,
|
cannam@85
|
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
cannam@85
|
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
cannam@85
|
12 ** GNU General Public License for more details.
|
cannam@85
|
13 **
|
cannam@85
|
14 ** You should have received a copy of the GNU General Public License
|
cannam@85
|
15 ** along with this program; if not, write to the Free Software
|
cannam@85
|
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
cannam@85
|
17 */
|
cannam@85
|
18
|
cannam@85
|
19 #include <stdio.h>
|
cannam@85
|
20 #include <stdlib.h>
|
cannam@85
|
21 #include <string.h>
|
cannam@85
|
22 #include <time.h>
|
cannam@85
|
23 #include <unistd.h>
|
cannam@85
|
24
|
cannam@85
|
25 #include <samplerate.h>
|
cannam@85
|
26
|
cannam@85
|
27 #include "config.h"
|
cannam@85
|
28
|
cannam@85
|
29 #include "util.h"
|
cannam@85
|
30 #include "float_cast.h"
|
cannam@85
|
31
|
cannam@85
|
32 #define BUFFER_LEN (1<<16)
|
cannam@85
|
33
|
cannam@85
|
34 static float input [BUFFER_LEN] ;
|
cannam@85
|
35 static float output [BUFFER_LEN] ;
|
cannam@85
|
36
|
cannam@85
|
37 static long
|
cannam@85
|
38 throughput_test (int converter, long best_throughput)
|
cannam@85
|
39 { SRC_DATA src_data ;
|
cannam@85
|
40 clock_t start_time, clock_time ;
|
cannam@85
|
41 double duration ;
|
cannam@85
|
42 long total_frames = 0, throughput ;
|
cannam@85
|
43 int error ;
|
cannam@85
|
44
|
cannam@85
|
45 printf (" %-30s ", src_get_name (converter)) ;
|
cannam@85
|
46 fflush (stdout) ;
|
cannam@85
|
47
|
cannam@85
|
48 src_data.data_in = input ;
|
cannam@85
|
49 src_data.input_frames = ARRAY_LEN (input) ;
|
cannam@85
|
50
|
cannam@85
|
51 src_data.data_out = output ;
|
cannam@85
|
52 src_data.output_frames = ARRAY_LEN (output) ;
|
cannam@85
|
53
|
cannam@85
|
54 src_data.src_ratio = 0.99 ;
|
cannam@85
|
55
|
cannam@85
|
56 sleep (2) ;
|
cannam@85
|
57
|
cannam@85
|
58 start_time = clock () ;
|
cannam@85
|
59
|
cannam@85
|
60 do
|
cannam@85
|
61 {
|
cannam@85
|
62 if ((error = src_simple (&src_data, converter, 1)) != 0)
|
cannam@85
|
63 { puts (src_strerror (error)) ;
|
cannam@85
|
64 exit (1) ;
|
cannam@85
|
65 } ;
|
cannam@85
|
66
|
cannam@85
|
67 total_frames += src_data.output_frames_gen ;
|
cannam@85
|
68
|
cannam@85
|
69 clock_time = clock () - start_time ;
|
cannam@85
|
70 duration = (1.0 * clock_time) / CLOCKS_PER_SEC ;
|
cannam@85
|
71 }
|
cannam@85
|
72 while (duration < 3.0) ;
|
cannam@85
|
73
|
cannam@85
|
74 if (src_data.input_frames_used != ARRAY_LEN (input))
|
cannam@85
|
75 { printf ("\n\nLine %d : input frames used %ld should be %d\n", __LINE__, src_data.input_frames_used, ARRAY_LEN (input)) ;
|
cannam@85
|
76 exit (1) ;
|
cannam@85
|
77 } ;
|
cannam@85
|
78
|
cannam@85
|
79 if (fabs (src_data.src_ratio * src_data.input_frames_used - src_data.output_frames_gen) > 2)
|
cannam@85
|
80 { printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ;
|
cannam@85
|
81 printf (" input len : %d\n", ARRAY_LEN (input)) ;
|
cannam@85
|
82 printf (" output len : %ld (should be %g +/- 2)\n\n", src_data.output_frames_gen,
|
cannam@85
|
83 floor (0.5 + src_data.src_ratio * src_data.input_frames_used)) ;
|
cannam@85
|
84 exit (1) ;
|
cannam@85
|
85 } ;
|
cannam@85
|
86
|
cannam@85
|
87 throughput = lrint (floor (total_frames / duration)) ;
|
cannam@85
|
88
|
cannam@85
|
89 if (best_throughput == 0)
|
cannam@85
|
90 { best_throughput = MAX (throughput, best_throughput) ;
|
cannam@85
|
91 printf ("%5.2f %10ld\n", duration, throughput) ;
|
cannam@85
|
92 }
|
cannam@85
|
93 else
|
cannam@85
|
94 { best_throughput = MAX (throughput, best_throughput) ;
|
cannam@85
|
95 printf ("%5.2f %10ld %10ld\n", duration, throughput, best_throughput) ;
|
cannam@85
|
96 }
|
cannam@85
|
97
|
cannam@85
|
98
|
cannam@85
|
99 return best_throughput ;
|
cannam@85
|
100 } /* throughput_test */
|
cannam@85
|
101
|
cannam@85
|
102 static void
|
cannam@85
|
103 single_run (void)
|
cannam@85
|
104 {
|
cannam@85
|
105
|
cannam@85
|
106 printf ("\n CPU name : %s\n", get_cpu_name ()) ;
|
cannam@85
|
107
|
cannam@85
|
108 puts (
|
cannam@85
|
109 "\n"
|
cannam@85
|
110 " Converter Duration Throughput\n"
|
cannam@85
|
111 " -----------------------------------------------------------"
|
cannam@85
|
112 ) ;
|
cannam@85
|
113
|
cannam@85
|
114 throughput_test (SRC_ZERO_ORDER_HOLD, 0) ;
|
cannam@85
|
115 throughput_test (SRC_LINEAR, 0) ;
|
cannam@85
|
116 throughput_test (SRC_SINC_FASTEST, 0) ;
|
cannam@85
|
117 throughput_test (SRC_SINC_MEDIUM_QUALITY, 0) ;
|
cannam@85
|
118 throughput_test (SRC_SINC_BEST_QUALITY, 0) ;
|
cannam@85
|
119
|
cannam@85
|
120 puts ("") ;
|
cannam@85
|
121 return ;
|
cannam@85
|
122 } /* single_run */
|
cannam@85
|
123
|
cannam@85
|
124 static void
|
cannam@85
|
125 multi_run (int run_count)
|
cannam@85
|
126 { long zero_order_hold = 0, linear = 0 ;
|
cannam@85
|
127 long sinc_fastest = 0, sinc_medium = 0, sinc_best = 0 ;
|
cannam@85
|
128 int k ;
|
cannam@85
|
129
|
cannam@85
|
130 puts (
|
cannam@85
|
131 "\n"
|
cannam@85
|
132 " Converter Duration Throughput Best Throughput\n"
|
cannam@85
|
133 " --------------------------------------------------------------------------------"
|
cannam@85
|
134 ) ;
|
cannam@85
|
135
|
cannam@85
|
136 for (k = 0 ; k < run_count ; k++)
|
cannam@85
|
137 { zero_order_hold = throughput_test (SRC_ZERO_ORDER_HOLD, zero_order_hold) ;
|
cannam@85
|
138 linear = throughput_test (SRC_LINEAR, linear) ;
|
cannam@85
|
139 sinc_fastest = throughput_test (SRC_SINC_FASTEST, sinc_fastest) ;
|
cannam@85
|
140 sinc_medium = throughput_test (SRC_SINC_MEDIUM_QUALITY, sinc_medium) ;
|
cannam@85
|
141 sinc_best = throughput_test (SRC_SINC_BEST_QUALITY, sinc_best) ;
|
cannam@85
|
142
|
cannam@85
|
143 puts ("") ;
|
cannam@85
|
144
|
cannam@85
|
145 /* Let the CPU cool down. We might be running on a laptop. */
|
cannam@85
|
146 sleep (10) ;
|
cannam@85
|
147 } ;
|
cannam@85
|
148
|
cannam@85
|
149 printf ("\n CPU name : %s\n", get_cpu_name ()) ;
|
cannam@85
|
150
|
cannam@85
|
151 puts (
|
cannam@85
|
152 "\n"
|
cannam@85
|
153 " Converter Best Throughput\n"
|
cannam@85
|
154 " ------------------------------------------------"
|
cannam@85
|
155 ) ;
|
cannam@85
|
156 printf (" %-30s %10ld\n", src_get_name (SRC_ZERO_ORDER_HOLD), zero_order_hold) ;
|
cannam@85
|
157 printf (" %-30s %10ld\n", src_get_name (SRC_LINEAR), linear) ;
|
cannam@85
|
158 printf (" %-30s %10ld\n", src_get_name (SRC_SINC_FASTEST), sinc_fastest) ;
|
cannam@85
|
159 printf (" %-30s %10ld\n", src_get_name (SRC_SINC_MEDIUM_QUALITY), sinc_medium) ;
|
cannam@85
|
160 printf (" %-30s %10ld\n", src_get_name (SRC_SINC_BEST_QUALITY), sinc_best) ;
|
cannam@85
|
161
|
cannam@85
|
162 puts ("") ;
|
cannam@85
|
163 } /* multi_run */
|
cannam@85
|
164
|
cannam@85
|
165 static void
|
cannam@85
|
166 usage_exit (const char * argv0)
|
cannam@85
|
167 { const char * cptr ;
|
cannam@85
|
168
|
cannam@85
|
169 if ((cptr = strrchr (argv0, '/')) != NULL)
|
cannam@85
|
170 argv0 = cptr ;
|
cannam@85
|
171
|
cannam@85
|
172 printf (
|
cannam@85
|
173 "Usage :\n"
|
cannam@85
|
174 " %s - Single run of the throughput test.\n"
|
cannam@85
|
175 " %s --best-of N - Do N runs of test a print bext result.\n"
|
cannam@85
|
176 "\n",
|
cannam@85
|
177 argv0, argv0) ;
|
cannam@85
|
178
|
cannam@85
|
179 exit (0) ;
|
cannam@85
|
180 } /* usage_exit */
|
cannam@85
|
181
|
cannam@85
|
182 int
|
cannam@85
|
183 main (int argc, char ** argv)
|
cannam@85
|
184 { double freq ;
|
cannam@85
|
185
|
cannam@85
|
186 memset (input, 0, sizeof (input)) ;
|
cannam@85
|
187 freq = 0.01 ;
|
cannam@85
|
188 gen_windowed_sines (1, &freq, 1.0, input, BUFFER_LEN) ;
|
cannam@85
|
189
|
cannam@85
|
190 if (argc == 1)
|
cannam@85
|
191 single_run () ;
|
cannam@85
|
192 else if (argc == 3 && strcmp (argv [1], "--best-of") == 0)
|
cannam@85
|
193 { int run_count = atoi (argv [2]) ;
|
cannam@85
|
194
|
cannam@85
|
195 if (run_count < 1 || run_count > 20)
|
cannam@85
|
196 { printf ("Please be sensible. Run count should be in range (1, 10].\n") ;
|
cannam@85
|
197 exit (1) ;
|
cannam@85
|
198 } ;
|
cannam@85
|
199
|
cannam@85
|
200 multi_run (run_count) ;
|
cannam@85
|
201 }
|
cannam@85
|
202 else
|
cannam@85
|
203 usage_exit (argv [0]) ;
|
cannam@85
|
204
|
cannam@85
|
205 puts (
|
cannam@85
|
206 " Duration is in seconds.\n"
|
cannam@85
|
207 " Throughput is in samples/sec (more is better).\n"
|
cannam@85
|
208 ) ;
|
cannam@85
|
209
|
cannam@85
|
210 return 0 ;
|
cannam@85
|
211 } /* main */
|
cannam@85
|
212
|