1 /* g++ -o sfrtest sfrtest.cc `pkg-config --cflags --libs sndfile` `pkg-config --cflags --libs glibmm-2.4` */
17 #include <glibmm/miscutils.h>
18 #include <glibmm/fileutils.h>
24 bool with_sync = false;
27 read_one (SNDFILE* sf, uint32_t nframes)
29 if (sf_read_float (sf, (float*) data, nframes) != nframes) {
43 cout << "sfrtest [ -n NFILES ] [ -b BLOCKSIZE ] [ -s ] [ -D ] filename-template" << endl;
47 main (int argc, char* argv[])
49 vector<SNDFILE*> sndfiles;
51 char optstring[] = "n:b:s";
52 uint32_t block_size = 64 * 1024;
53 uint32_t nfiles = 100;
55 const struct option longopts[] = {
56 { "nfiles", 1, 0, 'n' },
57 { "blocksize", 1, 0, 'b' },
58 { "sync", 0, 0, 's' },
59 { "direct", 0, 0, 'D' },
65 char const * name_template = 0;
69 if ((c = getopt_long (argc, argv, optstring, longopts, &option_index)) == -1) {
75 nfiles = atoi (optarg);
78 block_size = atoi (optarg);
93 name_template = argv[optind];
99 for (uint32_t n = 1; n <= nfiles; ++n) {
101 char path[PATH_MAX+1];
103 snprintf (path, sizeof (path), name_template, n);
105 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
109 int flags = O_RDONLY;
110 int fd = open (path, flags, 0644);
113 cerr << "Could not open file #" << n << " @ " << path << " (" << strerror (errno) << ")" << endl;
119 /* Apple man pages say only that it returns "a value other than -1 on success",
120 which probably means zero, but you just can't be too careful with
123 if (fcntl (fd, F_NOCACHE, 1) == -1) {
124 cerr << "Cannot set F_NOCACHE on file # " << n << endl;
129 if ((sf = sf_open_fd (fd, SFM_READ, &format_info, true)) == 0) {
130 cerr << "Could not open SNDFILE #" << n << " @ " << path << " (" << sf_strerror (0) << ")" << endl;
134 samplerate = format_info.samplerate;
136 sndfiles.push_back (sf);
139 cout << "Discovered " << nfiles+1 << " files using " << name_template << endl;
141 data = new float[block_size];
146 before = g_get_monotonic_time();
147 for (vector<SNDFILE*>::iterator s = sndfiles.begin(); s != sndfiles.end(); ++s) {
148 if (read_one (*s, block_size)) {
149 cerr << "Read failed for file #" << distance (sndfiles.begin(), s) << endl;
154 gint64 elapsed = g_get_monotonic_time() - before;
155 double bandwidth = (sndfiles.size() * block_size * sample_size) / (elapsed/1000000.0);
156 double data_minutes = read / (double) (60.0 * 48000.0);
157 const double data_rate = sndfiles.size() * sample_size * samplerate;
159 ds << setprecision (1) << data_minutes;
161 cout << "BW @ " << read << " frames (" << ds.str() << " minutes) = " << (bandwidth/1048576.0) << " MB/sec " << bandwidth / data_rate << " x faster than necessary " << endl;