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