1 /* g++ -o sftest sftest.cc `pkg-config --cflags --libs sndfile` `pkg-config --cflags --libs glibmm-2.4` */
14 #include <glibmm/miscutils.h>
20 bool with_sync = false;
23 write_one (SNDFILE* sf, uint32_t nframes)
25 if (sf_write_float (sf, (float*) data, nframes) != nframes) {
39 cout << "sftest [ -f HEADER-FORMAT ] [ -F DATA-FORMAT ] [ -r SAMPLERATE ] [ -n NFILES ] [ -b BLOCKSIZE ] [ -s ]" << endl;
40 cout << "\tHEADER-FORMAT is one of:" << endl
44 cout << "\tDATA-FORMAT is one of:" << endl
45 << "\t\tFLOAT" << endl
52 main (int argc, char* argv[])
54 vector<SNDFILE*> sndfiles;
56 char optstring[] = "f:r:F:n:c:b:s";
57 int channels, samplerate;
58 char const *suffix = ".wav";
59 char const *header_format = "wav";
60 char const *data_format = "float";
61 uint32_t block_size = 64 * 1024;
62 uint32_t nfiles = 100;
63 const struct option longopts[] = {
64 { "header-format", 1, 0, 'f' },
65 { "data-format", 1, 0, 'F' },
66 { "rate", 1, 0, 'r' },
67 { "nfiles", 1, 0, 'n' },
68 { "blocksize", 1, 0, 'b' },
69 { "channels", 1, 0, 'c' },
70 { "sync", 0, 0, 's' },
78 if ((c = getopt_long (argc, argv, optstring, longopts, &option_index)) == -1) {
84 header_format = optarg;
92 samplerate = atoi (optarg);
96 nfiles = atoi (optarg);
100 channels = atoi (optarg);
103 block_size = atoi (optarg);
115 /* setup file format */
116 memset (&format_info, 0, sizeof (format_info));
118 if (samplerate == 0 || nfiles == 0 || block_size == 0 || channels == 0) {
123 format_info.samplerate = samplerate;
124 format_info.channels = channels;
126 if (strcasecmp (header_format, "wav") == 0) {
127 format_info.format |= SF_FORMAT_WAV;
129 } else if (strcasecmp (header_format, "caf") == 0) {
130 format_info.format |= SF_FORMAT_CAF;
132 } else if (strcasecmp (header_format, "w64") == 0) {
133 format_info.format |= SF_FORMAT_W64;
140 if (strcasecmp (data_format, "float") == 0) {
141 format_info.format |= SF_FORMAT_FLOAT;
142 sample_size = sizeof (float);
143 } else if (strcasecmp (data_format, "32") == 0) {
144 format_info.format |= SF_FORMAT_PCM_32;
146 } else if (strcasecmp (data_format, "24") == 0) {
147 format_info.format |= SF_FORMAT_PCM_24;
149 } else if (strcasecmp (data_format, "16") == 0) {
150 format_info.format |= SF_FORMAT_PCM_16;
157 char tmpdirname[] = "sftest-XXXXXX";
158 g_mkdtemp (tmpdirname);
160 for (uint32_t n = 0; n < nfiles; ++n) {
169 path = Glib::build_filename (tmpdirname, ss.str());
171 if ((sf = sf_open (path.c_str(), SFM_RDWR, &format_info)) == 0) {
172 cerr << "Could not open file #" << n << " @ " << path << endl;
176 sndfiles.push_back (sf);
179 cout << nfiles << " files are in " << tmpdirname << endl;
180 cout << "Format is " << suffix << ' ' << channels << " channel" << (channels > 1 ? "s" : "") << " written in chunks of " << block_size << " frames, synced ? " << (with_sync ? "yes" : "no") << endl;
182 data = new float[block_size*channels];
183 uint64_t written = 0;
187 before = g_get_monotonic_time();
188 for (vector<SNDFILE*>::iterator s = sndfiles.begin(); s != sndfiles.end(); ++s) {
189 if (write_one (*s, block_size)) {
190 cerr << "Write failed for file #" << distance (sndfiles.begin(), s) << endl;
194 written += block_size;
195 gint64 elapsed = g_get_monotonic_time() - before;
196 double bandwidth = (sndfiles.size() * block_size * channels * sample_size) / (elapsed/1000000.0);
197 double data_minutes = written / (double) (60.0 * 48000.0);
198 const double data_rate = sndfiles.size() * channels * sample_size * samplerate;
200 ds << setprecision (1) << data_minutes;
202 cout << "BW @ " << written << " frames (" << ds.str() << " minutes) = " << (bandwidth/1048576.0) << " MB/sec " << bandwidth / data_rate << " x faster than necessary " << endl;