os/mm/mmlibs/mmfw/Recogniser/src/mp3parser.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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