1 /*
2 * mpeghdr.c:
3 * Parse MPEG audio headers.
4 *
5 * Copyright (c) 2002 Chris Lightfoot.
6 * Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
7 *
8 */
9
10 #include <stdio.h>
11
12 #include "mpeghdr.h"
13
14 /* bits:
15 * Get bits a through b < a of val. */
16 //#define bits(v, a, b) (((v) & ((4 << ((a) - (b))) - 1)) >> (b))
17
18 #define bits(v, a, b) (((v) & (((2 << ((a) - (b))) - 1) << (b))) >> (b))
19
20 /* bitrate_tbl:
21 * Table of bit rates. Column index: 0 = v1 l1; 1 = v1 l2; 2 = v1 l3;
22 * 3 = v2 l1; 4 = v2 l2, l3. */
23 static int bitrate_tbl[16][5] = {
24 { 0, 0, 0, 0, 0}, /* free */
25 { 32, 32, 32, 32, 8},
26 { 64, 48, 40, 48, 16},
27 { 96, 56, 48, 56, 24},
28 {128, 64, 56, 64, 32},
29 {160, 80, 64, 80, 40},
30 {192, 96, 80, 96, 48},
31 {224, 112, 96, 112, 56},
32 {256, 128, 112, 128, 64},
33 {288, 160, 128, 144, 80},
34 {320, 192, 160, 160, 96},
35 {352, 224, 192, 176, 112},
36 {384, 256, 224, 192, 128},
37 {416, 320, 256, 224, 144},
38 {448, 384, 320, 256, 160},
39 { -1, -1, -1, -1, -1} /* bad */
40 };
41
42 /* samplerate_tbl:
43 * Table of sample rates. Column index: v1 = 0, v2 = 1, v2.5 = 2. */
44 static int samplerate_tbl[4][3] = {
45 {44100, 22050, 11025},
46 {48000, 24000, 12000},
47 {32000, 16000, 8000},
48 { -1, -1, -1} /* reserved */
49 };
50
51 /* mpeg_hdr_parse:
52 * Parse an MPEG header into a struct mpeg_audio_hdr. */
mpeg_hdr_parse(const uint8_t * data,struct mpeg_audio_hdr * h)53 int mpeg_hdr_parse(const uint8_t *data, struct mpeg_audio_hdr *h) {
54 struct mpeg_audio_hdr hz = {0};
55 uint32_t hh;
56 int i;
57
58 *h = hz;
59
60 if (data[0] != 0xff || (data[1] & 0xe0) != 0xe0)
61 return 0;
62
63 hh = (data[1] << 16) | (data[2] << 8) | data[3];
64
65 /*fprintf(stderr, "%08x\n", hh);*/
66
67 /* Version. */
68 switch (bits(hh, 20, 19)) {
69 case 0: h->version = m_vers_2_5; break;
70 case 2: h->version = m_vers_2; break;
71 case 3: h->version = m_vers_1; break;
72
73 default: return 0;
74 }
75
76 /* Layer. */
77 switch (bits(hh, 18, 17)) {
78 case 1: h->layer = m_layer_3; break;
79 case 2: h->layer = m_layer_2; break;
80 case 3: h->layer = m_layer_1; break;
81
82 default: return 0;
83 }
84
85 /* Possible CRC. */
86 h->has_crc = bits(hh, 16, 16);
87 if (h->has_crc)
88 h->crc = (data[5] << 8) | (data[6]);
89
90 /* Bit rate. */
91 i = (h->version == m_vers_1) ? 0 : 3;
92 i += h->layer - 1;
93 if (i == 5) i = 4;
94 h->bitrate = bitrate_tbl[bits(hh, 15, 12)][i];
95 if (h->bitrate == -1)
96 return 0;
97
98 /* Sample rate. */
99 i = h->version - 1;
100 h->samplerate = samplerate_tbl[bits(hh, 11, 10)][i];
101 if (h->samplerate == - 1)
102 return 0;
103
104 /* Is frame padded? */
105 h->padded = bits(hh, 9, 9);
106
107 /* Channel mode. */
108 h->channels = bits(hh, 7, 6);
109
110 /* Mode extension. */
111 h->mode_extn = bits(hh, 5, 4);
112
113 h->copyr = bits(hh, 3, 3);
114 h->original = bits(hh, 2, 2);
115 h->emph = bits(hh, 1, 0);
116
117 return 1;
118 }
119
120 /* mpeg_hdr_nextframe_offset:
121 * Return the offset of the next MPEG header frame.
122 * XXX this doesn't work with (at least) L3 mono frames-- need to fix it. */
mpeg_hdr_nextframe_offset(const struct mpeg_audio_hdr * h)123 int mpeg_hdr_nextframe_offset(const struct mpeg_audio_hdr *h) {
124 int off = 0;
125 /* if (h->has_crc) off += 2; */
126 if (h->layer == m_layer_1)
127 off += ((12 * h->bitrate * 1000) / h->samplerate + h->padded) * 4;
128 else
129 off += (144 * h->bitrate * 1000) / h->samplerate + h->padded;
130 return off;
131 }
132
133 /* mpeg_hdr_print:
134 * Print out useful information about an MPEG audio header. */
135 static char *vers_tbl[] = {"unknown", "1", "2", "2.5"};
136 static char *channel_tbl[] = {"stereo", "joint stereo", "dual stereo", "mono"};
137
mpeg_hdr_print(FILE * fp,const struct mpeg_audio_hdr * h)138 void mpeg_hdr_print(FILE *fp, const struct mpeg_audio_hdr *h) {
139 fprintf(fp, "version %s layer %d\n", vers_tbl[h->version], h->layer);
140 if (h->has_crc)
141 fprintf(fp, " has CRC %04x\n", h->crc);
142 fprintf(fp, "bit rate %d kbps\nsample rate %dHz\n", h->bitrate, h->samplerate);
143 fprintf(fp, "%s padded\n", h->padded ? "is" : "is not");
144 fprintf(fp, "%s\n", channel_tbl[h->channels]);
145 if (h->channels == m_chan_joint)
146 fprintf(fp, "mode extension %d\n", h->mode_extn);
147 fprintf(fp, "%s copyright\n%s original\n", h->copyr ? "is" : "is not", h->original ? "is" : "is not");
148 if (h->emph)
149 fprintf(fp, "emphasis %d\n", h->emph);
150 }
151
152 #if 0
153 int main(int argc, char *argv[]) {
154 char buf[8192], *p;
155 struct mpeg_audio_hdr h;
156 read(0, buf, sizeof buf);
157 for (p = buf; p < buf + sizeof buf; ) {
158 if (!mpeg_hdr_parse(p, &h)) {
159 fprintf(stderr, "no MPEG audio header\n");
160 return -1;
161 }
162 mpeg_hdr_print(stdout, &h);
163 printf("offset to next frame = %d\n", mpeg_hdr_nextframe_offset(&h));
164 p += mpeg_hdr_nextframe_offset(&h);
165 }
166 }
167 #endif
168