View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.tika.parser.mp3;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  
22  import org.apache.tika.exception.TikaException;
23  import org.xml.sax.ContentHandler;
24  import org.xml.sax.SAXException;
25  
26  /**
27   * An Audio Frame in an MP3 file. These come after the ID3v2 tags in the file.
28   * Currently, only the header is processed, not the raw audio data.
29   */
30  public class AudioFrame implements MP3Frame {
31      private String version;
32      private int sampleRate;
33      private int channels;
34  
35      public String getVersion() {
36          return version;
37      }
38  
39      /**
40       * Get the sampling rate, in Hz
41       */
42      public int getSampleRate() {
43          return sampleRate;
44      }
45  
46      /**
47       * Get the number of channels (1=mono, 2=stereo)
48       */
49      public int getChannels() {
50          return channels;
51      }
52  
53      /**
54       * Does this appear to be a 4 byte audio frame header?
55       */
56      public static boolean isAudioHeader(int h1, int h2, int h3, int h4) {
57          if (h1 == -1 || h2 == -1 || h3 == -1 || h4 == -1) {
58              return false;
59          }
60          // Check for the magic 11 bits set at the start
61          // Note - doesn't do a CRC check
62          if (h1 == 0xff && (h2 & 0x60) == 0x60) {
63              return true;
64          }
65          return false;
66      }
67  
68  
69      public AudioFrame(InputStream stream, ContentHandler handler)
70              throws IOException, SAXException, TikaException {
71          this(-2, -2, -2, -2, stream);
72      }
73  
74      public AudioFrame(int h1, int h2, int h3, int h4, InputStream in)
75              throws IOException {
76          if (h1 == -2 && h2 == -2 && h3 == -2 && h4 == -2) {
77              h1 = in.read();
78              h2 = in.read();
79              h3 = in.read();
80              h4 = in.read();
81          }
82  
83          if (isAudioHeader(h1, h2, h3, h4)) {
84              version = "MPEG 3 Layer ";
85              int layer = (h2 >> 1) & 0x03;
86              if (layer == 1) {
87                  version += "III";
88              } else if (layer == 2) {
89                  version += "II";
90              } else if (layer == 3) {
91                  version += "I";
92              } else {
93                  version += "(reserved)";
94              }
95  
96              version += " Version ";
97              int ver = (h2 >> 3) & 0x03;
98              if (ver == 0) {
99                  version += "2.5";
100             } else if(ver == 2) {
101                 version += "2";
102             } else if(ver == 3) {
103                 version += "1";
104             } else {
105                 version += "(reseved)";
106             }
107 
108             int rate = (h3 >> 2) & 0x03;
109             switch (rate) {
110             case 0:
111                 sampleRate = 11025;
112                 break;
113             case 1:
114                 sampleRate = 12000;
115                 break;
116             default:
117                 sampleRate = 8000;
118             }
119             if (ver == 2) {
120                 sampleRate *= 2;
121             } else if(ver == 3) {
122                 sampleRate *= 4;
123             }
124 
125             int chans = h4 & 0x03;
126             if (chans < 3) {
127                 // Stereo, joint stereo, dual channel
128                 channels = 2;
129             } else {
130                 channels = 1;
131             }
132         } else {
133             throw new IllegalArgumentException("Magic Audio Frame Header not found");
134         }
135     }
136 
137 }