Do not use a BiMap.
[sonitus.git] / src / main / java / net / pterodactylus / sonitus / io / mp3 / Frame.java
1 /*
2  * Sonitus - Frame.java - Copyright © 2013 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sonitus.io.mp3;
19
20 import java.util.Map;
21
22 import com.google.common.base.Optional;
23 import com.google.common.base.Supplier;
24 import com.google.common.base.Suppliers;
25 import com.google.common.collect.ImmutableMap;
26
27 /**
28  * A single MPEG audio frame.
29  * <p/>
30  * This uses information from <a href="http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm">mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm</a>.
31  *
32  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
33  */
34 public class Frame {
35
36         /** The MPEG audio version. */
37         public enum MpegAudioVersion {
38
39                 /** Verstion 2.5. */
40                 VERSION_2_5,
41
42                 /** Reserved. */
43                 RESERVED,
44
45                 /** Version 2. */
46                 VERSION_2,
47
48                 /** Version 1. */
49                 VERSION_1
50
51         }
52
53         /** The MPEG layer description. */
54         public enum LayerDescription {
55
56                 /** Reserved. */
57                 RESERVED,
58
59                 /** Layer III. */
60                 LAYER_3,
61
62                 /** Layer II. */
63                 LAYER_2,
64
65                 /** Layer I. */
66                 LAYER_1
67
68         }
69
70         /** The channel mode. */
71         public enum ChannelMode {
72
73                 /* Stereo. */
74                 STEREO,
75
76                 /** Joint stereo. */
77                 JOINT_STEREO,
78
79                 /** Dual-channel stereo. */
80                 DUAL_CHANNEL,
81
82                 /** Single channel, aka mono. */
83                 SINGLE_CHANNEL
84
85         }
86
87         /** Mode of emphasis. */
88         public enum Emphasis {
89
90                 /** No emphasis. */
91                 NONE,
92
93                 /** 50/15 ms. */
94                 _50_15_MS,
95
96                 /** Reserved. */
97                 RESERVED,
98
99                 /** CCIT J.17. */
100                 CCIT_J_17
101
102         }
103
104         /** Bitrate table. */
105         private static final Supplier<Map<MpegAudioVersion, Map<LayerDescription, Map<Integer, Integer>>>> bitrateSupplier = Suppliers.memoize(new Supplier<Map<MpegAudioVersion, Map<LayerDescription, Map<Integer, Integer>>>>() {
106
107                 @Override
108                 public Map<MpegAudioVersion, Map<LayerDescription, Map<Integer, Integer>>> get() {
109                         ImmutableMap.Builder<MpegAudioVersion, Map<LayerDescription, Map<Integer, Integer>>> mpegAudioVersionMapBuilder = ImmutableMap.builder();
110
111                         /* MPEG 1. */
112                         ImmutableMap.Builder<LayerDescription, Map<Integer, Integer>> mpeg1Builder = ImmutableMap.builder();
113
114                         /* Layer 1. */
115                         ImmutableMap.Builder<Integer, Integer> bitrates = ImmutableMap.builder();
116                         bitrates.put(0, 0).put(1, 32).put(2, 64).put(3, 96).put(4, 128).put(5, 160).put(6, 192).put(7, 224);
117                         bitrates.put(8, 256).put(9, 288).put(10, 320).put(11, 352).put(12, 384).put(13, 416).put(14, 448).put(15, -1);
118                         mpeg1Builder.put(LayerDescription.LAYER_1, bitrates.build());
119
120                         /* MPEG 1, Layer 2 bitrates. */
121                         bitrates = ImmutableMap.builder();
122                         bitrates.put(0, 0).put(1, 32).put(2, 48).put(3, 56).put(4, 64).put(5, 80).put(6, 96).put(7, 112);
123                         bitrates.put(8, 128).put(9, 160).put(10, 192).put(11, 224).put(12, 256).put(13, 320).put(14, 384).put(15, -1);
124                         mpeg1Builder.put(LayerDescription.LAYER_2, bitrates.build());
125
126                         /* MPEG 1, Layer 3 bitrates. */
127                         bitrates = ImmutableMap.builder();
128                         bitrates.put(0, 0).put(1, 32).put(2, 40).put(3, 48).put(4, 56).put(5, 64).put(6, 80).put(7, 96);
129                         bitrates.put(8, 112).put(9, 128).put(10, 160).put(11, 192).put(12, 224).put(13, 256).put(14, 320).put(15, -1);
130                         mpeg1Builder.put(LayerDescription.LAYER_3, bitrates.build());
131                         mpegAudioVersionMapBuilder.put(MpegAudioVersion.VERSION_1, mpeg1Builder.build());
132
133                         /* MPEG 2 & 2.5. */
134                         ImmutableMap.Builder<LayerDescription, Map<Integer, Integer>> mpeg2Builder = ImmutableMap.builder();
135
136                         /* Layer 1. */
137                         bitrates = ImmutableMap.builder();
138                         bitrates.put(0, 0).put(1, 32).put(2, 48).put(3, 56).put(4, 64).put(5, 80).put(6, 96).put(7, 112);
139                         bitrates.put(8, 128).put(9, 144).put(10, 160).put(11, 176).put(12, 192).put(13, 224).put(14, 256).put(15, -1);
140                         mpeg2Builder.put(LayerDescription.LAYER_1, bitrates.build());
141
142                         /* Layer 2 & 3. */
143                         bitrates = ImmutableMap.builder();
144                         bitrates.put(0, 0).put(1, 8).put(2, 16).put(3, 24).put(4, 32).put(5, 40).put(6, 48).put(7, 56);
145                         bitrates.put(8, 64).put(9, 80).put(10, 96).put(11, 112).put(12, 128).put(13, 144).put(14, 160).put(15, -1);
146                         mpeg2Builder.put(LayerDescription.LAYER_2, bitrates.build());
147                         mpeg2Builder.put(LayerDescription.LAYER_3, bitrates.build());
148
149                         mpegAudioVersionMapBuilder.put(MpegAudioVersion.VERSION_2, mpeg2Builder.build());
150                         mpegAudioVersionMapBuilder.put(MpegAudioVersion.VERSION_2_5, mpeg2Builder.build());
151
152                         return mpegAudioVersionMapBuilder.build();
153                 }
154         });
155
156         /** Sampling rate table. */
157         private static final Supplier<Map<MpegAudioVersion, Map<Integer, Integer>>> samplingRateSupplier = Suppliers.memoize(new Supplier<Map<MpegAudioVersion, Map<Integer, Integer>>>() {
158
159                 @Override
160                 public Map<MpegAudioVersion, Map<Integer, Integer>> get() {
161                         ImmutableMap.Builder<MpegAudioVersion, Map<Integer, Integer>> mpegAudioVersions = ImmutableMap.builder();
162
163                         /* MPEG 1. */
164                         ImmutableMap.Builder<Integer, Integer> samplingRates = ImmutableMap.builder();
165                         samplingRates.put(0, 44100).put(1, 48000).put(2, 32000).put(3, 0);
166                         mpegAudioVersions.put(MpegAudioVersion.VERSION_1, samplingRates.build());
167
168                         /* MPEG 2. */
169                         samplingRates = ImmutableMap.builder();
170                         samplingRates.put(0, 22050).put(1, 24000).put(2, 16000).put(3, 0);
171                         mpegAudioVersions.put(MpegAudioVersion.VERSION_2, samplingRates.build());
172
173                         /* MPEG 2.5. */
174                         samplingRates = ImmutableMap.builder();
175                         samplingRates.put(0, 11025).put(1, 12000).put(2, 8000).put(3, 0);
176                         mpegAudioVersions.put(MpegAudioVersion.VERSION_2_5, samplingRates.build());
177
178                         return mpegAudioVersions.build();
179                 }
180         });
181
182         /** The decoded MPEG audio version ID. */
183         private final int mpegAudioVersionId;
184
185         /** The decoded layer description. */
186         private final int layerDescription;
187
188         /** The decoded protection bit. */
189         private final int protectionBit;
190
191         /** The decoded bitrate index. */
192         private final int bitrateIndex;
193
194         /** The deocded sampling rate frequency index. */
195         private final int samplingRateFrequencyIndex;
196
197         /** The decoded padding bit. */
198         private final int paddingBit;
199
200         /** The decoded private bit. */
201         private final int privateBit;
202
203         /** The decoded channel mode. */
204         private final int channelMode;
205
206         /** The deocded mode extension. */
207         private final int modeExtension;
208
209         /** The decoded copyright bit. */
210         private final int copyrightBit;
211
212         /** The deocded original bit. */
213         private final int originalBit;
214
215         /** The decoded emphasis mode. */
216         private final int emphasis;
217
218         /**
219          * Creates a new frame from the given values.
220          *
221          * @param mpegAudioVersionId
222          *              The MPEG audio version ID
223          * @param layerDescription
224          *              The layer description
225          * @param protectionBit
226          *              The protection bit
227          * @param bitrateIndex
228          *              The bitrate index
229          * @param samplingRateFrequencyIndex
230          *              The sampling rate frequency index
231          * @param paddingBit
232          *              The padding bit
233          * @param privateBit
234          *              The private bit
235          * @param channelMode
236          *              The channel mode
237          * @param modeExtension
238          *              The mode extension
239          * @param copyrightBit
240          *              The copyright bit
241          * @param originalBit
242          *              The original bit
243          * @param emphasis
244          *              The emphasis
245          */
246         private Frame(int mpegAudioVersionId, int layerDescription, int protectionBit, int bitrateIndex, int samplingRateFrequencyIndex, int paddingBit, int privateBit, int channelMode, int modeExtension, int copyrightBit, int originalBit, int emphasis) {
247                 this.mpegAudioVersionId = mpegAudioVersionId;
248                 this.layerDescription = layerDescription;
249                 this.protectionBit = protectionBit;
250                 this.bitrateIndex = bitrateIndex;
251                 this.samplingRateFrequencyIndex = samplingRateFrequencyIndex;
252                 this.paddingBit = paddingBit;
253                 this.privateBit = privateBit;
254                 this.channelMode = channelMode;
255                 this.modeExtension = modeExtension;
256                 this.copyrightBit = copyrightBit;
257                 this.originalBit = originalBit;
258                 this.emphasis = emphasis;
259         }
260
261         //
262         // ACCESSORS
263         //
264
265         /**
266          * Returns the MPEG audio version.
267          *
268          * @return The MPEG audio version
269          */
270         public MpegAudioVersion mpegAudioVersion() {
271                 return MpegAudioVersion.values()[mpegAudioVersionId];
272         }
273
274         /**
275          * Returns the layer description.
276          *
277          * @return The layer description
278          */
279         public LayerDescription layerDescription() {
280                 return LayerDescription.values()[layerDescription];
281         }
282
283         /**
284          * Returns the protection bit.
285          *
286          * @return {@code true} if the protection bit is set, {@code false} otherwise
287          */
288         public boolean protectionBit() {
289                 return protectionBit != 0;
290         }
291
292         /**
293          * Returns the bitrate of this frame.
294          *
295          * @return The bitrate of this frame (in kbps)
296          */
297         public int bitrate() {
298                 return bitrateSupplier.get().get(mpegAudioVersion()).get(layerDescription()).get(bitrateIndex);
299         }
300
301         /**
302          * Returns the sampling rate of the audio data in this frame.
303          *
304          * @return The sample rate (in Hertz)
305          */
306         public int samplingRate() {
307                 return samplingRateSupplier.get().get(mpegAudioVersion()).get(samplingRateFrequencyIndex);
308         }
309
310         /**
311          * Returns the padding bit.
312          *
313          * @return {@code true} if the padding bit is set, {@code false} otherwise
314          */
315         public boolean paddingBit() {
316                 return paddingBit != 0;
317         }
318
319         /**
320          * Returns the private bit.
321          *
322          * @return {@code true} if the private bit is set, {@code false} otherwise
323          */
324         public boolean privateBit() {
325                 return privateBit != 0;
326         }
327
328         /**
329          * Returns the channel mode.
330          *
331          * @return The channel mode
332          */
333         public ChannelMode channelMode() {
334                 return ChannelMode.values()[channelMode];
335         }
336
337         /* TODO - mode extension. */
338
339         /**
340          * Returns the copyright bit.
341          *
342          * @return {@code true} if the copyright bit is set, {@code false} otherwise
343          */
344         public boolean copyrightBit() {
345                 return copyrightBit != 0;
346         }
347
348         /**
349          * Returns the original bit.
350          *
351          * @return {@code true} if the original bit is set, {@code false} otherwise
352          */
353         public boolean originalBit() {
354                 return originalBit != 0;
355         }
356
357         /**
358          * Returns the emphasis.
359          *
360          * @return The emphasis
361          */
362         public Emphasis emphasis() {
363                 return Emphasis.values()[emphasis];
364         }
365
366         //
367         // STATIC METHODS
368         //
369
370         /**
371          * Returns whether the data beginning at the given offset is an MPEG audio
372          * frame.
373          *
374          * @param buffer
375          *              The buffer in which the data is stored
376          * @param offset
377          *              The beginning of the data to parse
378          * @param length
379          *              The length of the data to parse
380          * @return {@code true} if the data at the given offset is an MPEG audio frame
381          */
382         public static boolean isFrame(byte[] buffer, int offset, int length) {
383                 return (length > 3) && (((buffer[offset] & 0xff) == 0xff) && ((buffer[offset + 1] & 0xe0) == 0xe0));
384         }
385
386         /**
387          * Tries to create an MPEG audio from the given data.
388          *
389          * @param buffer
390          *              The buffer in which the data is stored
391          * @param offset
392          *              The offset at which to look for a frame
393          * @param length
394          *              The length of the data in the buffer
395          * @return The frame if it could be parsed, or {@link Optional#absent()} if no
396          *         frame could be found
397          */
398         public static Optional<Frame> create(byte[] buffer, int offset, int length) {
399                 if (isFrame(buffer, offset, length)) {
400                         int mpegAudioVersionId = (buffer[offset + 1] & 0x18) >>> 3;
401                         int layerDescription = (buffer[offset + 1] & 0x06) >>> 1;
402                         int protectionBit = buffer[offset + 1] & 0x01;
403                         int bitrateIndex = (buffer[offset + 2] & 0xf0) >>> 4;
404                         int samplingRateFrequencyIndex = (buffer[offset + 2] & 0x0c) >>> 2;
405                         int paddingBit = (buffer[offset + 2] & 0x02) >>> 1;
406                         int privateBit = buffer[offset + 2] & 0x01;
407                         int channelMode = (buffer[offset + 3] & 0xc0) >> 6;
408                         int modeExtension = (buffer[offset + 3] & 0x60) >> 4;
409                         int copyright = (buffer[offset + 3] & 0x08) >> 3;
410                         int original = (buffer[offset + 3] & 0x04) >> 2;
411                         int emphasis = buffer[offset + 3] & 0x03;
412                         return Optional.of(new Frame(mpegAudioVersionId, layerDescription, protectionBit, bitrateIndex, samplingRateFrequencyIndex, paddingBit, privateBit, channelMode, modeExtension, copyright, original, emphasis));
413                 }
414                 return Optional.absent();
415         }
416
417 }