1 /*
2  * mp3plot - Bitrate analysis tool
3  *
4  * Copyright (C) 2007, 2009 Toni Corvera
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 // $Id: console_plotter.cc 1347 2009-06-22 15:53:15Z toni $
22 
23 // References:
24 // [[IMP3C]] Inside the MP3 Codec - Page 13
25 //           <http://www.mp3-converter.com/mp3codec/frames.htm>
26 
27 #include <iostream>
28 #include <string>
29 
30 #include "../mp3_config.h" // PLOT_SYMBOL
31 #include "../utils/str_utils.h"
32 #include "console_plotter.h"
33 
34 using std::cout;
35 using std::endl;
36 using std::string;
37 
38 namespace mp3plot {
39 
40 namespace str = net_outlyer::str;
41 
features() const42 const plotter_features & console_plotter::features() const {
43     static const plotter_features f ( plotter_features::textual() |
44                                         plotter_features::printed() );
45     return f;
46 }
47 
description() const48 const plotter_description & console_plotter::description() const {
49     static const plotter_description D("console", features());
50     return D;
51 }
52 
plot(const mp3file & file,const plot_params & params) const53 void console_plotter::plot(const mp3file & file, const plot_params& params) const
54     throw (e_error)
55 {
56     using str::to_string;
57 
58     const bitrate_distribution & dist = params.br_dist;
59 
60     // Max length of bitrate tags
61     static const size_t LBR = string("invalid").length();
62     // Max length of number of frames, + padding
63     const size_t LOC = str::to_string(dist.max).length() + 1;
64 
65     // Console width
66     // FIXME: detect
67     const uint16_t CONWIDTH = 80;
68     // 4 = "[]: " + 1 => space between number of frames and dots
69     // using float because a cast would be made anyway
70     const float AVAIL = static_cast<float>(CONWIDTH - (LBR + LOC + 5));
71 
72     uint32_t sum=0, fs=0;
73     float sumbrs=.0;
74 
75     // TODO: Adapt to changing mpeg versions/layers
76     const mp3::frame & f = * file.get_frames().begin();
77     const mpeg_version_t ver = f.get_mpeg_version();
78     const mpeg_layer_t layer = f.get_mpeg_layer();
79 
80     for (bitrate_distribution::const_iterator b_it = dist.begin();
81          b_it != dist.end();
82          ++b_it)
83     {
84         const uint8_t bridx = b_it.bitrate_index();
85         const bitrate_t br = mp3::bitrate_translator::get(bridx, ver, layer);
86         const numframes_t nf = b_it.numframes();
87 
88         const string & s_br = (br != 0)
89                                 ? str::pad( to_string(br) + "kbps", LBR, " ", str::PAD_LEFT )
90                                 : str::pad( "free", LBR, " ", str::PAD_LEFT );
91         const string & s_nf = str::pad( str::to_string(nf), LOC );
92 
93         cout << "[" << s_br << "]: " << s_nf;
94 
95         // the scale is relative to the max
96         const int SCALED = int(nf * AVAIL / dist.max);
97         cout << str::pad("", SCALED, PLOT_SYMBOL);
98 
99         cout << "\n";
100 
101         sum += nf; // number of frames of this bitrate
102         sumbrs += (nf * br);
103         // That's the number of bits per seconds at this bitrate
104         const uint32_t secbits = nf * br * 1000;
105         // Each frame is 0.026 seconds (26ms) long, ~38.46fps, see [[IMP3C]]
106         fs+=int( ((double)secbits) * 0.026);
107     }
108     { // Finally print the invalid frames
109         cout << "[invalid]: " << dist.bad_frames();
110         /*
111         const int SCALED = int(br_dist.bad_frames() * AVAIL / br_dist.max);
112         cout << str::pad("", SCALED, PLOT_SYMBOL);
113         */
114         cout << "\n";
115     }
116 
117     string abr = str::to_string(sumbrs/sum);
118     const string::size_type dotidx = abr.find_first_of('.');
119     if (string::npos != dotidx) {
120         if ((dotidx + 3) < abr.length()) {
121             abr.erase(dotidx+3);
122         }
123     }
124 
125     double length_secs = sum * f.get_sample_size() / f.get_sampling_rate();
126 
127     cout << "Average bitrate is " << abr << " kbps\n";
128     cout << "\twith a total of " << sum << " frames" << endl;
129     cout << "\twhich yields a theoretical (raw audio data) size of "
130          << (fs / 8) << " bytes\n"
131          << "\tand a length of " << length_secs << "s" << endl;
132 }
133 
134 } // namespace mp3plot
135 
136 // vim:set ts=4 et ai:
137 
138