File: Header.cs

package info (click to toggle)
banshee 0.11.2%2Bdfsg-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 11,976 kB
  • ctags: 9,958
  • sloc: cs: 54,529; xml: 21,240; sh: 8,835; ansic: 2,040; makefile: 1,248
file content (217 lines) | stat: -rw-r--r-- 8,604 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/***************************************************************************
    copyright            : (C) 2005 by Brian Nickel
    email                : brian.nickel@gmail.com
    based on             : mpegheader.cpp from TagLib
 ***************************************************************************/

/***************************************************************************
 *   This library is free software; you can redistribute it and/or modify  *
 *   it  under the terms of the GNU Lesser General Public License version  *
 *   2.1 as published by the Free Software Foundation.                     *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful, but   *
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
 *   USA                                                                   *
 ***************************************************************************/

using System.Collections;
using System;

namespace TagLib.Mpeg
{
   public enum Version
   {
      Version1   = 0, // MPEG Version 1
      Version2   = 1, // MPEG Version 2
      Version2_5 = 2  // MPEG Version 2.5
   }

   public enum ChannelMode
   {
      Stereo        = 0, // Stereo
      JointStereo   = 1, // Stereo
      DualChannel   = 2, // Dual Mono
      SingleChannel = 3  // Mono
   };

   public class Header
   {
      //////////////////////////////////////////////////////////////////////////
      // private properties
      //////////////////////////////////////////////////////////////////////////
      private bool        is_valid;
      private Version     version;
      private int         layer;
      private bool        protection_enabled;
      private int         bitrate;
      private int         sample_rate;
      private bool        is_padded;
      private ChannelMode channel_mode;
      private bool        is_copyrighted;
      private bool        is_original;
      private int         frame_length;
      
      
      //////////////////////////////////////////////////////////////////////////
      // public methods
      //////////////////////////////////////////////////////////////////////////
      public Header (ByteVector data)
      {
          is_valid           = false;
          version            = Version.Version1;
          layer              = 0;
          protection_enabled = false;
          bitrate            = 0;
          sample_rate        = 0;
          is_padded          = false;
          channel_mode       = ChannelMode.Stereo;
          is_copyrighted     = false;
          is_original        = false;
          frame_length       = 0;
          
          Parse (data);
      }
      
      public Header (Header header)
      {
          is_valid           = header.IsValid;
          version            = header.Version;
          layer              = header.Layer;
          protection_enabled = header.ProtectionEnabled;
          bitrate            = header.Bitrate;
          sample_rate        = header.SampleRate;
          is_padded          = header.IsPadded;
          channel_mode       = header.ChannelMode;
          is_copyrighted     = header.IsCopyrighted;
          is_original        = header.IsOriginal;
          frame_length       = header.FrameLength;
      }
      
      
      //////////////////////////////////////////////////////////////////////////
      // public properties
      //////////////////////////////////////////////////////////////////////////
      public bool        IsValid           {get {return is_valid;}}
      public Version     Version           {get {return version;}}
      public int         Layer             {get {return layer;}}
      public bool        ProtectionEnabled {get {return protection_enabled;}}
      public int         Bitrate           {get {return bitrate;}}
      public int         SampleRate        {get {return sample_rate;}}
      public bool        IsPadded          {get {return is_padded;}}
      public ChannelMode ChannelMode       {get {return channel_mode;}}
      public bool        IsCopyrighted     {get {return is_copyrighted;}}
      public bool        IsOriginal        {get {return is_original;}}
      public int         FrameLength       {get {return frame_length;}}
      
      
      //////////////////////////////////////////////////////////////////////////
      // private methods
      //////////////////////////////////////////////////////////////////////////
      private void Parse (ByteVector data)
      {
         if(data.Count < 4 || data [0] != 0xff)
         {
            Debugger.Debug ("Mpeg.Header.Parse () -- First byte did not mactch MPEG synch.");
            return;
         }

         uint flags = data.ToUInt();

         // Check for the second byte's part of the MPEG synch

         if ((flags & 0xFFE00000) != 0xFFE00000)
         {
            Debugger.Debug ("Mpeg.Header.Parse () -- Second byte did not mactch MPEG synch.");
            return;
         }

         // Set the MPEG version
         switch ((flags >> 19) & 0x03)
         {
            case 0: version = Version.Version2_5; break;
            case 2: version = Version.Version2; break;
            case 3: version = Version.Version1; break;
         }

         // Set the MPEG layer
         switch ((flags >> 17) & 0x03)
         {
            case 1: layer = 3; break;
            case 2: layer = 2; break;
            case 3: layer = 1; break;
         }

         protection_enabled = ((flags >>16) & 1) == 0;

         // Set the bitrate
         int [,,] bitrates = new int [2,3,16] {
            { // Version 1
               { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 }, // layer 1
               { 0, 32, 48, 56, 64,  80,  96,  112, 128, 160, 192, 224, 256, 320, 384, 0 }, // layer 2
               { 0, 32, 40, 48, 56,  64,  80,  96,  112, 128, 160, 192, 224, 256, 320, 0 }  // layer 3
            },
            { // Version 2 or 2.5
               { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0 }, // layer 1
               { 0, 8,  16, 24, 32, 40, 48, 56,  64,  80,  96,  112, 128, 144, 160, 0 }, // layer 2
               { 0, 8,  16, 24, 32, 40, 48, 56,  64,  80,  96,  112, 128, 144, 160, 0 }  // layer 3
            }
         };

         int version_index = version == Version.Version1 ? 0 : 1;
         int layer_index = layer > 0 ? layer - 1 : 0;

         // The bitrate index is encoded as the first 4 bits of the 3rd byte,
         // i.e. 1111xxxx

         int i = (int) (flags >> 12) & 0x0F;

         bitrate = bitrates [version_index,layer_index,i];

         // Set the sample rate

         int [,] sample_rates = new int [3,4] {
            { 44100, 48000, 32000, 0 }, // Version 1
            { 22050, 24000, 16000, 0 }, // Version 2
            { 11025, 12000, 8000,  0 }  // Version 2.5
         };

         // The sample rate index is encoded as two bits in the 3nd byte,
         // i.e. xxxx11xx
         i = (int) (flags >> 10) & 0x03;

         sample_rate = sample_rates [(int) version,i];

         if(sample_rate == 0)
         {
            Debugger.Debug ("Mpeg.Header.Parse () -- Invalid sample rate.");
            return;
         }

         // The channel mode is encoded as a 2 bit value at the end of the 3nd
         // byte, i.e. xxxxxx11
         channel_mode = (ChannelMode)((flags >> 16) & 0x3);

         // TODO: Add mode extension for completeness

         is_copyrighted = (flags & 1) == 1;
         is_original = ((flags >> 1) & 1) == 1;

         // Calculate the frame length
         if(layer == 1)
            frame_length = 24000 * 2 * bitrate / sample_rate + (IsPadded ? 1 : 0);
         else if (layer == 3)
            frame_length = 144000 * bitrate / sample_rate + (IsPadded ? 1 : 0);
         else
            frame_length = 144000 * bitrate / sample_rate / (version == Version.Version1 ? 1 : 2) + (IsPadded ? 1 : 0);

         // Now that we're done parsing, set this to be a valid frame.
         is_valid = true;
      }
   }
}