annotate foosdk/sdk/foobar2000/helpers/mp3_utils.cpp @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #include "StdAfx.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #include "mp3_utils.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4 #include "bitreader_helper.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 using namespace bitreader_helper;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 static unsigned extract_header_bits(const t_uint8 p_header[4],unsigned p_base,unsigned p_bits)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10 PFC_ASSERT(p_base+p_bits<=32);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 return (unsigned) extract_bits(p_header,p_base,p_bits);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 namespace {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 class header_parser
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 header_parser(const t_uint8 p_header[4]) : m_bitptr(0)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21 memcpy(m_header,p_header,4);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 unsigned read(unsigned p_bits)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 unsigned ret = extract_header_bits(m_header,m_bitptr,p_bits);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 m_bitptr += p_bits;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 t_uint8 m_header[4];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 unsigned m_bitptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 typedef t_uint16 uint16;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 static const uint16 bitrate_table_l1v1[16] = { 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448, 0};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 static const uint16 bitrate_table_l2v1[16] = { 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384, 0};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 static const uint16 bitrate_table_l3v1[16] = { 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320, 0};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40 static const uint16 bitrate_table_l1v2[16] = { 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256, 0};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41 static const uint16 bitrate_table_l23v2[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160, 0};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 static const uint16 sample_rate_table[] = {11025,12000,8000};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 unsigned mp3_utils::QueryMPEGFrameSize(const t_uint8 p_header[4])
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 TMPEGFrameInfo info;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 if (!ParseMPEGFrameHeader(info,p_header)) return 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 return info.m_bytes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51 bool mp3_utils::ParseMPEGFrameHeader(TMPEGFrameInfo & p_info,const t_uint8 p_header[4])
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53 enum {MPEG_LAYER_1 = 3, MPEG_LAYER_2 = 2, MPEG_LAYER_3 = 1};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 enum {_MPEG_1 = 3, _MPEG_2 = 2, _MPEG_25 = 0};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56 header_parser parser(p_header);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57 if (parser.read(11) != 0x7FF) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 unsigned mpeg_version = parser.read(2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 unsigned layer = parser.read(2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60 unsigned protection = parser.read(1);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 unsigned bitrate_index = parser.read(4);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 unsigned sample_rate_index = parser.read(2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 if (sample_rate_index == 3) return false;//reserved
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 unsigned paddingbit = parser.read(1);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 int paddingdelta = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 parser.read(1);//private
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 unsigned channel_mode = parser.read(2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 unsigned channel_mode_ext = parser.read(2);//channel_mode_extension
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69 parser.read(1);//copyright
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 parser.read(1);//original
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 parser.read(2);//emphasis
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 unsigned bitrate = 0,sample_rate = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75 switch(layer)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 default:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79 case MPEG_LAYER_3:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 paddingdelta = paddingbit ? 1 : 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 p_info.m_layer = 3;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 switch(mpeg_version)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 case _MPEG_1:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86 p_info.m_duration = 1152;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 bitrate = bitrate_table_l3v1[bitrate_index];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 case _MPEG_2:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 case _MPEG_25:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 p_info.m_duration = 576;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 bitrate = bitrate_table_l23v2[bitrate_index];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 default:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 case MPEG_LAYER_2:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 paddingdelta = paddingbit ? 1 : 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 p_info.m_duration = 1152;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 p_info.m_layer = 2;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 switch(mpeg_version)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 case _MPEG_1:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 bitrate = bitrate_table_l2v1[bitrate_index];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108 case _MPEG_2:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109 case _MPEG_25:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110 bitrate = bitrate_table_l23v2[bitrate_index];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112 default:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 case MPEG_LAYER_1:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 paddingdelta = paddingbit ? 4 : 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118 p_info.m_duration = 384;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119 p_info.m_layer = 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120 switch(mpeg_version)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 case _MPEG_1:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123 bitrate = bitrate_table_l1v1[bitrate_index];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 case _MPEG_2:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126 case _MPEG_25:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 bitrate = bitrate_table_l1v2[bitrate_index];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 default:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 if (bitrate == 0) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136 sample_rate = sample_rate_table[sample_rate_index];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 if (sample_rate == 0) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138 switch(mpeg_version)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 case _MPEG_1:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141 sample_rate *= 4;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142 p_info.m_mpegversion = MPEG_1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144 case _MPEG_2:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 sample_rate *= 2;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146 p_info.m_mpegversion = MPEG_2;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 case _MPEG_25:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149 p_info.m_mpegversion = MPEG_25;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 switch(channel_mode)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
155 case 0:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156 case 1:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
157 case 2:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
158 p_info.m_channels = 2;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
159 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
160 case 3:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
161 p_info.m_channels = 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
162 break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
163 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
164
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
165
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
166 p_info.m_channel_mode = channel_mode;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
167 p_info.m_channel_mode_ext = channel_mode_ext;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
168
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
169 p_info.m_sample_rate = sample_rate;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
170 p_info.m_sample_rate_idx = sample_rate_index;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
171
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
172 p_info.m_bitrate = bitrate;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
173 p_info.m_bitrate_idx = bitrate_index;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
174
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
175 p_info.m_bytes = ( bitrate /*kbps*/ * (1000/8) /* kbps-to-bytes*/ * p_info.m_duration /*samples-per-frame*/ ) / sample_rate + paddingdelta;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
176
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
177 if (p_info.m_layer == 1) p_info.m_bytes &= ~3;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
178
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
179 p_info.m_crc = protection == 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
180
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
181 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
182 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
183
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
184 unsigned mp3header::get_samples_per_frame()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
185 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
186 mp3_utils::TMPEGFrameInfo fr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
187 if (!decode(fr)) return 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
188 return fr.m_duration;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
189 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
190
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
191 bool mp3_utils::IsSameStream(TMPEGFrameInfo const & p_frame1,TMPEGFrameInfo const & p_frame2) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
192 return
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
193 // FFmpeg writes VBR headers with null channel mode...
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
194 /* p_frame1.m_channel_mode == p_frame2.m_channel_mode && */
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
195 p_frame1.m_sample_rate == p_frame2.m_sample_rate &&
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
196 p_frame1.m_layer == p_frame2.m_layer &&
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
197 p_frame1.m_mpegversion == p_frame2.m_mpegversion;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
198 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
199
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
200
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
201
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
202 bool mp3_utils::ValidateFrameCRC(const t_uint8 * frameData, t_size frameSize, TMPEGFrameInfo const & info) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
203 if (frameSize < info.m_bytes) return false; //FAIL, incomplete data
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
204 if (!info.m_crc) return true; //nothing to check, frame appears valid
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
205 return ExtractFrameCRC(frameData, frameSize, info) == CalculateFrameCRC(frameData, frameSize, info);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
206 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
207
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
208 static t_uint32 CRC_update(unsigned value, t_uint32 crc)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
209 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
210 enum { CRC16_POLYNOMIAL = 0x8005 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
211 unsigned i;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
212 value <<= 8;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
213 for (i = 0; i < 8; i++) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
214 value <<= 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
215 crc <<= 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
216 if (((crc ^ value) & 0x10000)) crc ^= CRC16_POLYNOMIAL;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
217 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
218 return crc;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
219 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
220
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
221
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
222 void mp3_utils::RecalculateFrameCRC(t_uint8 * frameData, t_size frameSize, TMPEGFrameInfo const & info) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
223 PFC_ASSERT( frameSize >= info.m_bytes && info.m_crc );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
224
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
225 const t_uint16 crc = CalculateFrameCRC(frameData, frameSize, info);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
226 frameData[4] = (t_uint8)(crc >> 8);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
227 frameData[5] = (t_uint8)(crc & 0xFF);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
228 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
229
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
230 static t_uint16 grabFrameCRC(const t_uint8 * frameData, t_size sideInfoLen) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
231 t_uint32 crc = 0xffff;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
232 crc = CRC_update(frameData[2], crc);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
233 crc = CRC_update(frameData[3], crc);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
234 for (t_size i = 6; i < sideInfoLen; i++) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
235 crc = CRC_update(frameData[i], crc);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
236 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
237
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
238 return (t_uint32) (crc & 0xFFFF);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
239 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
240
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
241 t_uint16 mp3_utils::ExtractFrameCRC(const t_uint8 * frameData, t_size frameSize, TMPEGFrameInfo const & info) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
242 PFC_ASSERT(frameSize >= info.m_bytes && info.m_crc); (void)info; (void)frameSize;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
243
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
244 return ((t_uint16)frameData[4] << 8) | (t_uint16)frameData[5];
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
245
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
246 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
247 t_uint16 mp3_utils::CalculateFrameCRC(const t_uint8 * frameData, t_size frameSize, TMPEGFrameInfo const & info) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
248 PFC_ASSERT(frameSize >= info.m_bytes && info.m_crc); (void)frameSize;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
249
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
250 t_size sideInfoLen = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
251 if (info.m_mpegversion == MPEG_1)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
252 sideInfoLen = (info.m_channels == 1) ? 4 + 17 : 4 + 32;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
253 else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
254 sideInfoLen = (info.m_channels == 1) ? 4 + 9 : 4 + 17;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
255
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
256 //CRC
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
257 sideInfoLen += 2;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
258
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
259 PFC_ASSERT( sideInfoLen <= frameSize );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
260
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
261 return grabFrameCRC(frameData, sideInfoLen);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
262 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
263
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
264
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
265 bool mp3_utils::ValidateFrameCRC(const t_uint8 * frameData, t_size frameSize) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
266 if (frameSize < 4) return false; //FAIL, not a valid frame
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
267 TMPEGFrameInfo info;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
268 if (!ParseMPEGFrameHeader(info, frameData)) return false; //FAIL, not a valid frame
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
269 return ValidateFrameCRC(frameData, frameSize, info);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
270 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
271
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
272
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
273 bool mp3_utils::ParseMPEGFrameHeader(TMPEGFrameInfo & p_info, const void * bytes, size_t bytesAvail) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
274 if (bytesAvail < 4) return false; //FAIL, not a valid frame
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
275 return ParseMPEGFrameHeader(p_info, reinterpret_cast<const t_uint8*>(bytes));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
276 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
277
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
278 bool mp3_utils::IsValidMPEGFrameHeader(const void* fourbytes) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
279 TMPEGFrameInfo info = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
280 return ParseMPEGFrameHeader(info, fourbytes, 4);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
281 }