1 /**
2  * KFR (http://kfrlib.com)
3  * Copyright (C) 2016  D Levin
4  * See LICENSE.txt for details
5  */
6 
7 #include <kfr/base.hpp>
8 #include <kfr/dsp.hpp>
9 #include <kfr/io.hpp>
10 
11 using namespace kfr;
12 
main(int argc,char ** argv)13 int main(int argc, char** argv)
14 {
15     if (argc < 3)
16     {
17         println("Usage: ebu_test INPUT_IN_F32_RAW_FORMAT CHANNEL_NUMBER");
18         return 1;
19     }
20 
21     // Prepare
22     FILE* f                  = fopen(argv[1], "rb");
23     const int channel_number = atoi(argv[2]);
24     if (channel_number < 1 || channel_number > 6)
25     {
26         println("Incorrect number of channels");
27         return 1;
28     }
29     fseek(f, 0, SEEK_END);
30     uintmax_t size = ftell(f);
31     fseek(f, 0, SEEK_SET);
32     if (size % (sizeof(float) * channel_number))
33     {
34         println("Incorrect file size");
35         return 1;
36     }
37 
38     // Read file
39     const size_t length = size / (sizeof(float) * channel_number);
40     univector<float> interleaved(size / sizeof(float));
41     size_t read_len = fread(interleaved.data(), 1, size, f);
42     if (read_len != size)
43     {
44         println("Can't read file");
45         return 1;
46     }
47 
48     // Deinterleave
49     univector<univector<float>> data(channel_number, univector<float>(length));
50     for (size_t ch = 0; ch < channel_number; ++ch)
51     {
52         for (size_t i = 0; i < length; ++i)
53         {
54             data[ch][i] = interleaved[i * channel_number + ch];
55         }
56     }
57 
58     std::vector<Speaker> speakers;
59     switch (channel_number)
60     {
61     case 1:
62         speakers = { Speaker::Mono };
63         break;
64     case 2:
65         speakers = { Speaker::Left, Speaker::Right };
66         break;
67     case 3:
68         speakers = { Speaker::Left, Speaker::Right, Speaker::Center };
69         break;
70     case 4:
71         speakers = { Speaker::Left, Speaker::Right, Speaker::LeftSurround, Speaker::RightSurround };
72         break;
73     case 5:
74         speakers = { Speaker::Left, Speaker::Right, Speaker::Center, Speaker::LeftSurround,
75                      Speaker::RightSurround };
76         break;
77     case 6:
78         speakers = { Speaker::Left,         Speaker::Right,         Speaker::Center,
79                      Speaker::LeftSurround, Speaker::RightSurround, Speaker::Lfe };
80         break;
81     }
82 
83     ebu_r128<float> loudness(48000, speakers);
84 
85     float M, S, I, RL, RH;
86     float maxM = -HUGE_VALF, maxS = -HUGE_VALF;
87     for (size_t i = 0; i < length / loudness.packet_size(); i++)
88     {
89         std::vector<univector_ref<float>> channels;
90         for (size_t ch = 0; ch < channel_number; ++ch)
91         {
92             channels.push_back(data[ch].slice(i * loudness.packet_size(), loudness.packet_size()));
93         }
94         loudness.process_packet(channels);
95         loudness.get_values(M, S, I, RL, RH);
96         maxM = std::max(maxM, M);
97         maxS = std::max(maxS, S);
98     }
99 
100     {
101         // For file-based measurements, the signal should be followed by at least 1.5 s of silence
102         std::vector<univector_dyn<float>> channels(channel_number,
103                                                    univector_dyn<float>(loudness.packet_size()));
104         for (size_t i = 0; i < 15; ++i)
105             loudness.process_packet(channels);
106         float dummyM, dummyS, dummyI;
107         loudness.get_values(dummyM, dummyS, dummyI, RL, RH);
108     }
109 
110     println(argv[1]);
111     println("M = ", M);
112     println("S = ", S);
113     println("I = ", I);
114     println("LRA = ", RH - RL);
115     println("maxM = ", maxM);
116     println("maxS = ", maxS);
117     println();
118 
119     return 0;
120 }
121