Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/anotherbigidea/flash/sound/MP3Frame.java


1   /****************************************************************
2    * Copyright (c) 2001, David N. Main, All rights reserved.
3    * 
4    * Redistribution and use in source and binary forms, with or
5    * without modification, are permitted provided that the 
6    * following conditions are met:
7    *
8    * 1. Redistributions of source code must retain the above 
9    * copyright notice, this list of conditions and the following 
10   * disclaimer. 
11   * 
12   * 2. Redistributions in binary form must reproduce the above 
13   * copyright notice, this list of conditions and the following 
14   * disclaimer in the documentation and/or other materials 
15   * provided with the distribution.
16   * 
17   * 3. The name of the author may not be used to endorse or 
18   * promote products derived from this software without specific 
19   * prior written permission. 
20   * 
21   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY 
22   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
23   * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
24   * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
25   * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
26   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
27   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
28   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
29   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
30   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
31   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
32   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   ****************************************************************/
34  package com.anotherbigidea.flash.sound;
35  
36  import java.io.*;
37  import java.util.*;
38  import com.anotherbigidea.io.*;
39  import com.anotherbigidea.flash.*;
40  import com.anotherbigidea.flash.structs.*;
41  import com.anotherbigidea.flash.interfaces.*;
42  
43  /**
44   * An MP3 sound data frame.
45   */
46  public class MP3Frame
47  {
48      public static final int MPEG_Version_2_5 = 0;
49      public static final int MPEG_Version_2   = 2;
50      public static final int MPEG_Version_1   = 3;
51      
52      public static final int MPEG_Layer_3 = 1;
53      public static final int MPEG_Layer_2 = 2;
54      public static final int MPEG_Layer_1 = 3;
55  
56      public static final int CHANNEL_MODE_STEREO       = 0;
57      public static final int CHANNEL_MODE_JOINT_STEREO = 1;
58      public static final int CHANNEL_MODE_DUAL_CHANNEL = 2;
59      public static final int CHANNEL_MODE_MONO         = 3;
60      
61      public static final int EMPHASIS_NONE     = 0;
62      public static final int EMPHASIS_50_15_MS = 1;
63      public static final int EMPHASIS_RESERVED = 2;
64      public static final int EMPHASIS_CCIT_J17 = 3;
65      
66      protected static final int[] MPEG1BitRates = { 0, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 0 }; 
67      protected static final int[] MPEG2BitRates = { 0,  8000, 16000, 24000, 32000, 40000, 48000, 56000,  64000,  80000,  96000, 112000, 128000, 144000, 160000, 0 };
68          
69      protected static final int[] MPEG10SampleRates = { 44100, 48000, 32000, 0 };
70      protected static final int[] MPEG20SampleRates = { 22050, 24000, 16000, 0 };
71      protected static final int[] MPEG25SampleRates = { 11025, 12000,  8000, 0 };
72      
73      private static int FRAME_SAMPLES_MPEG_1 = 1152;
74      private static int FRAME_SAMPLES_MPEG_2 = 576;    
75      
76      protected int     mpegVersion;
77      protected int     mpegLayer;
78      protected boolean isProtected;
79      protected int     bitRate;
80      protected int     sampleRate;
81      protected boolean padded;
82      protected int     channelMode;
83      protected int     modeExtension;
84      protected boolean copyrighted;
85      protected boolean original;
86      protected int     emphasis;
87      protected byte[]  data;
88      
89      protected int bit_rate;
90      protected int sample_rate;
91      
92      public int getBitRate()    { return bitRate; }
93      public int getSampleRate() { return sampleRate; }
94      public boolean isStereo()  { return channelMode != this.CHANNEL_MODE_MONO; }
95      public int getDataLength() { return data.length; }
96      
97      public int getSamplesPerFrame() 
98      { 
99          if( mpegVersion == this.MPEG_Version_1 ) return this.FRAME_SAMPLES_MPEG_1;
100         else return this.FRAME_SAMPLES_MPEG_2;
101     }
102     
103     /**
104      * Read the next MP3 frame from the stream - return null if no more
105      */
106     public static MP3Frame readFrame( InputStream in ) throws IOException
107     {
108         MP3Frame frame = new MP3Frame();
109         
110         while( true )
111         {
112             int b = in.read();
113             
114             if( b < 0 ) return null;
115             if( b == 0xFF )
116             {
117                 b = in.read();
118  
119                 if( b < 0 ) return null;
120                 if( (b & 0xE0) != 0xE0 ) continue;
121 
122                 frame.mpegVersion = ( b & 0x18 ) >> 3;
123                 frame.mpegLayer   = ( b & 0x06 ) >> 1;        
124                 frame.isProtected = ( b & 1 ) == 0;
125  
126                 if( frame.mpegLayer != MPEG_Layer_3 ) continue;
127                 break;
128             }
129         }
130  
131         //skip the CRC
132         if( frame.isProtected )
133         {
134             in.read();
135             in.read();
136         }
137         
138         int b = in.read();
139         if( b < 0 ) return null;
140         
141         frame.bit_rate = ( b & 0xF0 ) >> 4;
142          
143         if( frame.mpegVersion == MPEG_Version_1 ) frame.bitRate = MPEG1BitRates[frame.bit_rate];
144         else                                      frame.bitRate = MPEG2BitRates[frame.bit_rate];
145         
146         frame.sample_rate = ( b & 0x0C ) >> 2;
147         if     ( frame.mpegVersion == MPEG_Version_1 ) frame.sampleRate = MPEG10SampleRates[frame.sample_rate];
148         else if( frame.mpegVersion == MPEG_Version_2 ) frame.sampleRate = MPEG20SampleRates[frame.sample_rate];
149         else                                           frame.sampleRate = MPEG25SampleRates[frame.sample_rate];
150         
151         frame.padded = ( b & 2 ) != 0;
152         
153         b = in.read();
154         if( b < 0 ) return null;
155 
156         frame.channelMode   = ( b & 0xC0 ) >> 6;
157         frame.modeExtension = ( b & 0x30 ) >> 4;
158         
159         frame.copyrighted = (( b & 0x80 ) >> 3) != 0;
160         frame.original    = (( b & 0x40 ) >> 2) != 0;
161         
162         frame.emphasis = b & 0x02;
163         
164         int size = (((frame.mpegVersion == MPEG_Version_1 ? 144 : 72) 
165                      * frame.bitRate ) / frame.sampleRate ) + 
166                        (frame.padded ? 1 : 0) - 4;
167         
168         byte[] data = new byte[size];
169         int read = 0;
170         int r;
171         
172         while( (r = in.read( data, read, size - read )) >= 0 && read < size )
173         {
174             read += r;
175         }
176         
177         if( read != size ) throw new IOException( "Unexpected end of MP3 data" );
178         
179         frame.data = data;   
180        
181         //System.out.print( "." );
182         return frame;
183     }
184     
185     public MP3Frame( ) {}
186     
187     public void write( OutputStream out ) throws IOException
188     {
189         out.write( 0xff );
190                 
191         int b = 0xE1;
192         b |= this.mpegVersion << 3;
193         b |= this.mpegLayer   << 1;
194         out.write( b );
195         
196         b  = bit_rate << 4;
197         b |= sample_rate << 2;
198         if( padded ) b |= 2;
199         out.write( b );
200         
201         b  = channelMode   << 6;
202         b |= modeExtension << 4;
203         b |= emphasis;
204         out.write( b );
205         
206         out.write( data );
207     }
208     
209     public String toString()
210     {
211         String version = null;
212         if     ( mpegVersion == this.MPEG_Version_1   ) version = "1";
213         else if( mpegVersion == this.MPEG_Version_2   ) version = "2";
214         else if( mpegVersion == this.MPEG_Version_2_5 ) version = "2.5";
215         
216         return "MP3 Frame: " +                
217                " version=" + version +
218                " bit-rate=" + bitRate +   
219                " sample-rate=" + sampleRate +
220                " stereo=" +  (channelMode != this.CHANNEL_MODE_MONO);
221     }
222 }