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