1 7 8 package org.jboss.media.format.audio.mpeg; 9 10 import java.io.IOException ; 11 import java.io.InputStream ; 12 import java.io.PushbackInputStream ; 13 import java.util.HashMap ; 14 import java.util.Map ; 15 16 import javax.emb.FormatSyntaxException; 17 import javax.emb.MediaException; 18 import javax.emb.MediaHeader; 19 20 26 public class MpegAudioHeader implements MediaHeader 27 { 28 31 private final static int[] v1L1BitRates = 33 { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }; 34 35 private final static int[] v1L2BitRates = 37 { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }; 38 39 private final static int[] v1L3BitRates = 41 { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 }; 42 43 private final static int[] v2L1BitRates = 45 { 0, 32, 48, 56, 64, 80, 96, 112, 128, 411, 460, 476, 192, 224, 256 }; 46 47 private final static int[] v2L23BitRates = 49 { 0, 8, 16, 24, 32, 40, 28, 56, 64, 80, 96, 112, 128, 144, 160 }; 50 51 54 private final static int[] v1SampleRates = { 44100, 48000, 32000 }; 55 private final static int[] v2SampleRates = { 22050, 24000, 16000 }; 56 private final static int[] v25SampleRates = { 11025, 12000, 8000 }; 57 58 61 private final static String VERSION_KEY = "version"; 62 private final static String LAYER_KEY = "layer"; 63 private final static String BITRATE_KEY = "bitRate"; 64 private final static String SAMPLERATE_KEY = "samplingRate"; 65 private final static String CHANNELMODE_KEY = "channelMode"; 66 private final static String COPYRIGHT_KEY = "copyright"; 67 private final static String ORGINAL_KEY = "original"; 68 69 private final Map fieldMap = new HashMap (7); 71 72 private final PushbackInputStream content; 73 74 85 public MpegAudioHeader(InputStream data) 86 throws MediaException, FormatSyntaxException 87 { 88 try 89 { 90 content = new PushbackInputStream (data, 4); 91 int headerPos = findHeaderStart(content, 0); 92 93 if (headerPos != -1) 94 { 95 byte[] header = new byte[4]; 96 content.read(header); 97 readHeader(header); 98 } 99 else 100 { 101 throw new FormatSyntaxException("MPEG Audio header could not be found; this is not valid MPEG Audio data"); 102 } 103 } 104 catch (IOException ex) 105 { 106 throw new MediaException(ex.getMessage()); 107 } 108 } 109 110 115 public int getBitrate() 116 { 117 return ((Integer ) fieldMap.get(BITRATE_KEY)).intValue(); 118 } 119 120 126 public MpegAudioFormat.ChannelMode getChannelMode() 127 { 128 return (MpegAudioFormat.ChannelMode) fieldMap.get(CHANNELMODE_KEY); 129 } 130 131 136 public boolean isCopyright() 137 { 138 return ((Boolean ) fieldMap.get(COPYRIGHT_KEY)).booleanValue(); 139 } 140 141 148 public MpegAudioFormat.Layer getLayer() 149 { 150 return (MpegAudioFormat.Layer) fieldMap.get(LAYER_KEY); 151 } 152 153 158 public boolean isOriginal() 159 { 160 return ((Boolean ) fieldMap.get(ORGINAL_KEY)).booleanValue(); 161 } 162 163 168 public int getSamplerate() 169 { 170 return ((Integer ) fieldMap.get(SAMPLERATE_KEY)).intValue(); 171 } 172 173 179 public MpegAudioFormat.Version getVersion() 180 { 181 return (MpegAudioFormat.Version) fieldMap.get(VERSION_KEY); 182 } 183 184 190 public String [] getFieldNames() 191 { 192 return (String []) fieldMap.keySet().toArray(new String [0]); 193 } 194 195 204 public Object getField(String fieldname) 205 { 206 return fieldMap.get(fieldname); 207 } 208 209 218 private int findHeaderStart(PushbackInputStream content, int offset) 219 throws MediaException 220 { 221 try 222 { 223 if (offset == 0) 224 { 225 byte[] id3 = new byte[4]; 226 content.read(id3); 227 String id3Test = new String (id3); 228 content.unread(id3); 229 if (id3Test.equals("ID3")) 231 { 232 ID3Tag id3Tag = new ID3Tag(content); 233 offset += id3Tag.getSize(); 234 } 235 } 236 237 byte[] headerTest = new byte[2]; 238 239 while ((content.read(headerTest)) != -1) 240 { 241 if (((headerTest[0] & 0xFF) == 0xFF) 243 && ((headerTest[1] & 0xE0) == 0xE0)) 244 { 245 content.unread(headerTest); 246 return offset; 247 } 248 content.unread(headerTest[1]); 249 offset++; 250 } 251 } 252 catch (IOException e) 253 { 254 throw new MediaException(e); 255 } 256 257 return -1; 258 } 259 260 268 private void readHeader(byte[] header) throws FormatSyntaxException 269 { 270 if (header.length < 4) 271 { 272 throw new IllegalArgumentException ("Not enough header data"); 273 } 274 275 fieldMap.put(VERSION_KEY, getVersion(header[1])); 276 fieldMap.put(LAYER_KEY, getLayer(header[1])); 277 fieldMap.put(BITRATE_KEY, new Integer (getBitrate(header[2]))); 278 fieldMap.put(SAMPLERATE_KEY, new Integer (getSampleRate(header[2]))); 279 fieldMap.put(CHANNELMODE_KEY, getChannelMode(header[3])); 280 fieldMap.put(COPYRIGHT_KEY, new Boolean (getCopyright(header[3]))); 281 fieldMap.put(ORGINAL_KEY, new Boolean (getOriginal(header[3]))); 282 } 283 284 293 private MpegAudioFormat.Version getVersion(byte versionByte) 294 throws FormatSyntaxException 295 { 296 switch (versionByte & 0x18) { 298 case 0x00 : 299 return MpegAudioFormat.Version.MPEG25; 300 case 0x10 : 301 return MpegAudioFormat.Version.MPEG2; 302 case 0x18 : 303 return MpegAudioFormat.Version.MPEG1; 304 default : 305 throw new FormatSyntaxException("Could not determine MPEG Audio version"); 306 } 307 } 308 309 317 private MpegAudioFormat.Layer getLayer(byte layerByte) 318 throws FormatSyntaxException 319 { 320 switch (layerByte & 0x06) { 322 case 0x02 : 323 return MpegAudioFormat.Layer.LAYERIII; 324 case 0x04 : 325 return MpegAudioFormat.Layer.LAYERII; 326 case 0x06 : 327 return MpegAudioFormat.Layer.LAYERI; 328 default : 329 throw new FormatSyntaxException("Could not determine MPEG Audio version"); 330 } 331 } 332 333 339 private boolean getCRC(byte crcByte) 340 { 341 return (crcByte & 0x1) == 0; 342 } 343 344 352 private int getBitrate(byte bitrateByte) throws FormatSyntaxException 353 { 354 int bitrateKey = (bitrateByte & 0xF0) >>> 4; 355 356 if (0xF == bitrateKey) 357 { 358 throw new FormatSyntaxException("Illegal bitrate specified"); 359 } 360 361 if (MpegAudioFormat.Version.MPEG1 == getVersion()) 362 { 363 if (MpegAudioFormat.Layer.LAYERI == getLayer()) 364 { 365 return v1L1BitRates[bitrateKey]; 366 } 367 368 if (MpegAudioFormat.Layer.LAYERII == getLayer()) 369 { 370 return v1L2BitRates[bitrateKey]; 371 } 372 373 if (MpegAudioFormat.Layer.LAYERIII == getLayer()) 374 { 375 return v1L3BitRates[bitrateKey]; 376 } 377 } 378 379 if ((MpegAudioFormat.Version.MPEG2 == getVersion()) 380 || (MpegAudioFormat.Version.MPEG25 == getVersion())) 381 { 382 if (MpegAudioFormat.Layer.LAYERI == getLayer()) 383 { 384 return v2L1BitRates[bitrateKey]; 385 } 386 387 if ((MpegAudioFormat.Layer.LAYERII == getLayer()) 388 || (MpegAudioFormat.Layer.LAYERIII == getLayer())) 389 { 390 return v2L23BitRates[bitrateKey]; 391 } 392 } 393 394 throw new IllegalStateException ("Version and layer must be determined before extracting bitrate"); 395 } 396 397 406 private int getSampleRate(byte samplerateByte) throws FormatSyntaxException 407 { 408 int samplerateKey = (samplerateByte & 0xC) >>> 2; 409 410 if (samplerateKey > 2) 411 { 412 throw new FormatSyntaxException("Illegal sampling rate specified"); 413 } 414 415 if (MpegAudioFormat.Version.MPEG1 == getVersion()) 416 { 417 return v1SampleRates[samplerateKey]; 418 } 419 420 if (MpegAudioFormat.Version.MPEG2 == getVersion()) 421 { 422 return v2SampleRates[samplerateKey]; 423 } 424 425 if (MpegAudioFormat.Version.MPEG25 == getVersion()) 426 { 427 return v25SampleRates[samplerateKey]; 428 } 429 430 throw new IllegalStateException ("Version must be determined before extracting sample rate"); 431 } 432 433 440 private MpegAudioFormat.ChannelMode getChannelMode(byte channelModeByte) 441 throws FormatSyntaxException 442 { 443 switch (channelModeByte & 0xC0) 444 { 445 case 0x00 : 446 return MpegAudioFormat.ChannelMode.STEREO; 447 case 0x40 : 448 return MpegAudioFormat.ChannelMode.JOINT_STEREO; 449 case 0x80 : 450 return MpegAudioFormat.ChannelMode.DUAL_CHANNEL; 451 case 0xC0 : 452 return MpegAudioFormat.ChannelMode.SINGLE_CHANNEL; 453 default : 454 throw new FormatSyntaxException("Illegal Channel Mode encountered"); 455 } 456 } 457 458 461 private boolean getCopyright(byte copyrightByte) 462 { 463 return (copyrightByte & 8) != 0; 464 } 465 466 private boolean getOriginal(byte originalByte) 467 { 468 return (originalByte & 4) != 0; 469 } 470 } | Popular Tags |