mmlibs/mmfw/Recogniser/src/mp3parser.cpp
changeset 0 40261b775718
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 #include "parsers.h"
       
    18 
       
    19 //
       
    20 // Masks used for reading bits.
       
    21 //
       
    22 static const TInt KMP3Sync1Mask = 0xff;			// 11111111
       
    23 static const TInt KMP3Sync2Mask = 0xe0;			// 11100000
       
    24 static const TInt KMP3VersionMask = 0x18;		// 00011000
       
    25 static const TInt KMP3LayerMask = 0x06;			// 00000110
       
    26 static const TInt KMP3BitrateMask = 0xf0;		// 11110000
       
    27 static const TInt KMP3SampleRateMask = 0x0c;	// 00001100
       
    28 static const TInt KMP3PaddingMask = 0x02;		// 00000010
       
    29 
       
    30 static const TInt KBitsPerByte = 8;
       
    31 
       
    32 //
       
    33 // Macros for retrieving the values.
       
    34 //
       
    35 #define MP3_GET_SYNC1(d)				(d & KMP3Sync1Mask)
       
    36 #define MP3_GET_SYNC2(d)				((d & KMP3Sync2Mask) >> 5)
       
    37 #define MP3_GET_VERSION(d)				((d & KMP3VersionMask) >> 3)
       
    38 #define MP3_GET_LAYER(d)				((d & KMP3LayerMask) >> 1)
       
    39 #define MP3_GET_BITRATE(d)				((d & KMP3BitrateMask) >> 4)
       
    40 #define MP3_GET_SAMPLE_RATE(d)			((d & KMP3SampleRateMask) >> 2)
       
    41 #define MP3_GET_PADDING(d)				((d & KMP3PaddingMask) >> 1)
       
    42 
       
    43 
       
    44 //
       
    45 // Macros used for checking various bitfields.
       
    46 //
       
    47 #define IS_BAD_MP3_FRAME_SYNC1(s)		((s) != 0xff)
       
    48 #define IS_BAD_MP3_FRAME_SYNC2(s)		((s) != 0x07)	
       
    49 #define IS_BAD_MP3_VERSION(v)			((v) <  0x02)
       
    50 #define IS_BAD_MP3_LAYER(l)				((l) == 0x00) 
       
    51 #define IS_BAD_MP3_BITRATE(b)			((b) == 0x0f)	
       
    52 #define IS_BAD_MP3_SAMPLE_RATE(s)		((s) == 0x03)
       
    53 
       
    54 
       
    55 // 
       
    56 // Meanings of the 'Version' field.
       
    57 // --------------------------------
       
    58 // 00 - MPEG Version 2.5 (Unofficial standard. We don't support it.)
       
    59 // 01 - Reserved
       
    60 // 10 - MPEG Version 2
       
    61 // 11 - MPEG Version 1
       
    62 //
       
    63 static const TInt8 KMP3Version2 = 2;
       
    64 static const TInt8 KMP3Version1 = 3;
       
    65 
       
    66 
       
    67 // 
       
    68 // Meanings of the 'Layer' field.
       
    69 // ------------------------------
       
    70 // 00 - Reserved
       
    71 // 01 - Layer III
       
    72 // 10 - Layer II
       
    73 // 11 - Layer I
       
    74 //
       
    75 
       
    76 static const TUint16 KBad = 0;
       
    77 static const TUint16 KFree = 0;
       
    78 
       
    79 //
       
    80 // MPEG Version 1 bitrates. Measured in kilobits per second.
       
    81 //
       
    82 static const TUint16 KBitrateVersion1[4][16] =
       
    83 	{
       
    84 	{ KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad}, // Reserved layer
       
    85 	{KFree,   32,   40,   48,   56,   64,   80,   96,  112,  128,  160,  192,  224,  256,  320, KBad}, // Layer III
       
    86 	{KFree,   32,   48,   56,   64,   80,   96,  112,  128,  160,  192,  224,  256,  320,  384, KBad}, // Layer II
       
    87 	{KFree,   32,   64,   96,  128,  160,  192,  224,  256,  288,  320,  352,  384,  416,  448, KBad}  // Layer I
       
    88 	};
       
    89 
       
    90 //
       
    91 // MPEG Version 2 bitrates. Measured in kilobits per second.
       
    92 //
       
    93 static const TUint16 KBitrateVersion2[4][16] =
       
    94 	{
       
    95 	{ KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad}, // Reserved layer
       
    96 	{KFree,    8,   16,   24,   32,   40,   48,   56,   64,   80,   96,  112,  128,  144,  160, KBad}, // Layer III 
       
    97 	{KFree,    8,   16,   24,   32,   40,   48,   56,   64,   80,   96,  112,  128,  144,  160, KBad}, // Layer II
       
    98 	{KFree,   32,   48,   56,   64,   80,   96,  112,  128,  144,  160,  176,  192,  224,  256, KBad}  // Layer I
       
    99 	};
       
   100 
       
   101 //
       
   102 // Sample rates for the MPEG versions.
       
   103 //
       
   104 static const TUint16 KSampleRate[4][4] = 
       
   105 	{
       
   106 		{11025, 12000,  8000, KBad}, // Version 2.5
       
   107 		{ KBad,  KBad,  KBad, KBad}, // Reserved
       
   108 		{22050, 24000, 16000, KBad}, // Version 2
       
   109 		{44100, 48000, 32000, KBad}  // Version 1
       
   110 	};
       
   111 
       
   112 //
       
   113 // Sample rates per frame for the MPEG layers.
       
   114 //
       
   115 static const TUint16 KSamplesPerFrame[4][4] = 
       
   116 	{
       
   117 		{KBad, KBad, KBad, KBad}, // Reserved layer
       
   118 		{ 576, KBad,  576, 1152}, // Layer III
       
   119 		{1152, KBad, 1152, 1152}, // Layer II
       
   120 		{ 384, KBad,  384,  384}  // Layer I
       
   121 	};
       
   122 
       
   123 //
       
   124 // The various states the recognition process goes through.
       
   125 //
       
   126 typedef enum
       
   127 	{
       
   128 	ESearchFrame1,
       
   129 	ESearchFrame2
       
   130 	}
       
   131 TMP3State;
       
   132 
       
   133 //
       
   134 // This truth table maps the following flags to a confidence level.
       
   135 // -----------------------------------------------------------------
       
   136 // A: Frame2 found.
       
   137 // B: Frame1 found.
       
   138 // C: Extension recognised.
       
   139 //
       
   140 // A B C -> Confidence
       
   141 // ===================
       
   142 // 0 0 0 -> ENotRecognized
       
   143 // 0 0 1 -> EPossible
       
   144 // 0 1 0 -> ENotRecognized
       
   145 // 0 1 1 -> ECertain
       
   146 // 1 0 0 -> EPossible
       
   147 // 1 0 1 -> EProbable
       
   148 // 1 1 0 -> EProbable
       
   149 // 1 1 1 -> ECertain
       
   150 //
       
   151 // In the case where two consecutive mp3 frames
       
   152 // are found, ECertain is automatically returned.
       
   153 //
       
   154 static const TInt KMP3FlagsToConfidence[8] = 
       
   155 	{
       
   156 	KConfNotRecognised,
       
   157 	KConfPossible,
       
   158 	KConfNotRecognised,
       
   159 	KConfCertain,
       
   160 	KConfPossible,
       
   161 	KConfProbable,
       
   162 	KConfProbable,
       
   163 	KConfCertain
       
   164 	};
       
   165 
       
   166 #define KMP3ConfidenceMask	0x07	// 00000111
       
   167 #define KMP3Frame1Bit		KBit1
       
   168 #define KMP3Frame2Bit		KBit2
       
   169 
       
   170 //
       
   171 //
       
   172 //
       
   173 TMP3Parser::TMP3Parser(CReader& aReader, TFlags& aFlags)
       
   174  : 	iReader(aReader),
       
   175  	iFlags(aFlags)
       
   176 	{
       
   177 	}
       
   178 
       
   179 
       
   180 //
       
   181 // MP3 recogition function.
       
   182 //
       
   183 void TMP3Parser::DoRecognise(const TDesC& aExt, CReader& aReader, TMatch& aMatch)
       
   184 	{
       
   185 	TFlags flags;
       
   186 	
       
   187 	// Try to match the extension.
       
   188 	if (aExt.MatchF(TPtrC(KExtMP3)) != KErrNotFound)
       
   189 		{
       
   190 		flags.SetExtensionFlag();
       
   191 		}
       
   192 
       
   193 	// Parse the data.
       
   194 	TMP3Parser parser(aReader, flags);
       
   195 	TRAP_IGNORE(parser.ParseL());
       
   196 	
       
   197 	TInt confIndex = flags.GetBitField(KMP3ConfidenceMask);
       
   198 	aMatch.iConfidence = KMP3FlagsToConfidence[confIndex];
       
   199 	if (aMatch.iConfidence != KConfNotRecognised)
       
   200 		{
       
   201 		aMatch.iMime = KMimeMP3;
       
   202 		}
       
   203 	}
       
   204 
       
   205 
       
   206 //
       
   207 // Attempts to parse an mp3 file.
       
   208 // First of all it checks if there is an ID3 metadata header
       
   209 // present at the current reader position. Then it checks for up to
       
   210 // two consecutive mp3 audio frames.
       
   211 //
       
   212 void TMP3Parser::ParseL()
       
   213 	{
       
   214 	TInt length;
       
   215 	TMP3State state = ESearchFrame1;
       
   216 
       
   217 	FOREVER
       
   218 		{
       
   219 		TID3Parser::ReadAndSkipID3L(iReader);
       
   220 		
       
   221 		TInt err = CheckForFrameHeaderL(length);
       
   222 		if (err == KErrNotFound)
       
   223 			{
       
   224 			return;
       
   225 			}
       
   226 			
       
   227 		switch (state)
       
   228 			{
       
   229 			case ESearchFrame1:
       
   230 				iFlags.SetBit(KMP3Frame1Bit);
       
   231 				state = ESearchFrame2;
       
   232 				break;
       
   233 					
       
   234 			case ESearchFrame2:
       
   235 				iFlags.SetBit(KMP3Frame2Bit);
       
   236 				return;
       
   237 			}
       
   238 				
       
   239 		// Skip over the audio frame.
       
   240 		// This should be done after flags have been set.
       
   241 		iReader.SeekL(length - KMP3FrameHeaderSize);
       
   242 		}
       
   243 	}
       
   244 	
       
   245 
       
   246 //
       
   247 // Checks for an MP3 frame header at the current reader position.
       
   248 // If one is not found KErrNotFound is returned and aFrameLength
       
   249 // remains unchanged. If one is found KErrNone is retured and
       
   250 // aFrameLength is set to the length of the frame.
       
   251 //
       
   252 TInt TMP3Parser::CheckForFrameHeaderL(TInt& aFrameLength)
       
   253 	{
       
   254 	TBuf8<KMP3FrameHeaderSize> data;
       
   255 	TUint8 versionIndex;
       
   256 	TUint8 layerIndex;
       
   257 	TUint8 bitrateIndex;
       
   258 	TUint8 sampleRateIndex;
       
   259 	TUint8 padding;
       
   260 	TUint8 sync;
       
   261 	
       
   262 	data.SetLength(KMP3FrameHeaderSize);
       
   263 	iReader.ReadBytesL(data);
       
   264 	
       
   265 	do
       
   266 		{
       
   267 		sync = MP3_GET_SYNC1(data[0]);
       
   268 		if (IS_BAD_MP3_FRAME_SYNC1(sync))
       
   269 			{
       
   270 			break;
       
   271 			}
       
   272 			
       
   273 		sync = MP3_GET_SYNC2(data[1]);
       
   274 		if (IS_BAD_MP3_FRAME_SYNC2(sync))
       
   275 			{
       
   276 			break;
       
   277 			}
       
   278 		
       
   279 		versionIndex = MP3_GET_VERSION(data[1]);
       
   280 		if (IS_BAD_MP3_VERSION(versionIndex))
       
   281 			{
       
   282 			break;
       
   283 			}
       
   284 			
       
   285 		layerIndex = MP3_GET_LAYER(data[1]);
       
   286 		if (IS_BAD_MP3_LAYER(layerIndex))
       
   287 			{
       
   288 			break;
       
   289 			}
       
   290 			
       
   291 		bitrateIndex = MP3_GET_BITRATE(data[2]);
       
   292 		if (IS_BAD_MP3_BITRATE(bitrateIndex))
       
   293 			{
       
   294 			break;
       
   295 			}
       
   296 			
       
   297 		sampleRateIndex = MP3_GET_SAMPLE_RATE(data[2]);
       
   298 		if (IS_BAD_MP3_SAMPLE_RATE(sampleRateIndex))
       
   299 			{
       
   300 			break;
       
   301 			}
       
   302 			
       
   303 		padding = MP3_GET_PADDING(data[2]);
       
   304 		
       
   305 		// All the data is valid.
       
   306 		// Compute the audio data length.
       
   307 		TUint32 bitRate = KBad;
       
   308 		TUint16 sampleRate = KBad;
       
   309 		TUint16 samplesPerFrame = KBad;
       
   310 		
       
   311 		if (versionIndex == KMP3Version1)
       
   312 			{
       
   313 			bitRate = KBitrateVersion1[layerIndex][bitrateIndex];
       
   314 			}
       
   315 		else if (versionIndex == KMP3Version2)
       
   316 			{
       
   317 			bitRate = KBitrateVersion2[layerIndex][bitrateIndex];
       
   318 			}
       
   319 		else 
       
   320 			{
       
   321 			// Version 2.5 is not supported.
       
   322 			break;
       
   323 			}
       
   324 
       
   325 		sampleRate = KSampleRate[versionIndex][sampleRateIndex];
       
   326 		samplesPerFrame = KSamplesPerFrame[layerIndex][versionIndex];
       
   327 		
       
   328 		// Check we have valid values.
       
   329 		if ((bitRate == KBad) || (sampleRate == KBad) || (samplesPerFrame == KBad))
       
   330 			{
       
   331 			break;
       
   332 			}
       
   333 
       
   334 		bitRate *= 1000; // Convert to kilobits.
       
   335 		aFrameLength = (((samplesPerFrame / KBitsPerByte) * bitRate) / sampleRate) + padding;
       
   336 		return KErrNone;
       
   337 		}
       
   338 	while (EFalse);
       
   339 	
       
   340 	// No valid frame header was found.
       
   341 	aFrameLength = 0;
       
   342 	iReader.SeekL(-KMP3FrameHeaderSize);
       
   343 	return KErrNotFound;
       
   344 	}
       
   345 	
       
   346 
       
   347 
       
   348