audiostubs/devsoundextensions_stubs/mmfdevsoundadaptation_stub/src/ToneGenerator.cpp
branchRCL_3
changeset 44 b5894bb67e73
parent 35 37b610eb7fe3
equal deleted inserted replaced
35:37b610eb7fe3 44:b5894bb67e73
     1 /*
       
     2 * Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Audio Stubs -  This file contains an implementation of the ToneGenerator interface
       
    15 *  				 that converts all tone generation requests in to sampled audio
       
    16 *  				 data to be played through the normal local sampled audio interface
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 
       
    22 // INCLUDE FILES
       
    23 #include "ToneGenerator.h"
       
    24 #include <e32math.h>
       
    25 #include <mda/common/resource.h>
       
    26 
       
    27 // CONSTANTS
       
    28 
       
    29 /******************************************************************************
       
    30 *	Tone Generators
       
    31 *
       
    32 *	The following classes are used to generate simple frequency/duration tones,
       
    33 *	DTMF, and SymbianOS tone sequences in a WINS environment.  The below code
       
    34 *	should only be considered for WINS.
       
    35 ******************************************************************************/
       
    36 
       
    37 // this defines the maximum possible amplitude allowed for TSineGen::SetFrequency()
       
    38 const TInt KMaxAmplitude = 0x8000;
       
    39 
       
    40 // default number of samples for trailing silence following a Tone
       
    41 const TInt KDefaultTrailingSilenceSamples = 20;
       
    42 
       
    43 const TInt KRecalculateToneLengths = KMinTInt;
       
    44 
       
    45 //
       
    46 // Sequence constants
       
    47 //
       
    48 
       
    49 #ifdef _DEBUG
       
    50 const TInt16 KFixedSequenceSignatureOne='S'+('Q'<<8);
       
    51 const TInt16 KFixedSequenceSignatureTwo='N'+('C'<<8);
       
    52 #endif // _DEBUG
       
    53 
       
    54 const TInt KFixedSequenceFunctionReturn=-1;
       
    55 const TInt KFixedSequenceFunctionStartLoop=-2;
       
    56 const TInt KFixedSequenceFunctionEndLoop=-3;
       
    57 
       
    58 //
       
    59 // Sine tone generator
       
    60 //
       
    61 
       
    62 const TInt16 TSineGen::SineTable[KMaxSineTable] =
       
    63 	{
       
    64 		 0,   804,  1607,  2410,  3211,  4011,  4807,  5601,
       
    65 	  6392,  7179,  7961,  8739,  9511, 10278, 11038, 11792,
       
    66 	 12539, 13278, 14009, 14732, 15446, 16150, 16845, 17530,
       
    67 	 18204, 18867, 19519, 20159, 20787, 21402, 22004, 22594,
       
    68 	 23169, 23731, 24278, 24811, 25329, 25831, 26318, 26789,
       
    69 	 27244, 27683, 28105, 28510, 28897, 29268, 29621, 29955,
       
    70 	 30272, 30571, 30851, 31113, 31356, 31580, 31785, 31970,
       
    71 	 32137, 32284, 32412, 32520, 32609, 32678, 32727, 32757,
       
    72 	 32767, 32757, 32727, 32678, 32609, 32520, 32412, 32284,
       
    73 	 32137, 31970, 31785, 31580, 31356, 31113, 30851, 30571,
       
    74 	 30272, 29955, 29621, 29268, 28897, 28510, 28105, 27683,
       
    75 	 27244, 26789, 26318, 25831, 25329, 24811, 24278, 23731,
       
    76 	 23169, 22594, 22004, 21402, 20787, 20159, 19519, 18867,
       
    77 	 18204, 17530, 16845, 16150, 15446, 14732, 14009, 13278,
       
    78 	 12539, 11792, 11038, 10278,  9511,  8739,  7961,  7179,
       
    79 	  6392,  5601,  4807,  4011,  3211,  2410,  1607,   804,
       
    80 		 0,  -804, -1607, -2410, -3211, -4011, -4807, -5601,
       
    81 	 -6392, -7179, -7961, -8739, -9511,-10278,-11038,-11792,
       
    82 	-12539,-13278,-14009,-14732,-15446,-16150,-16845,-17530,
       
    83 	-18204,-18867,-19519,-20159,-20787,-21402,-22004,-22594,
       
    84 	-23169,-23731,-24278,-24811,-25329,-25831,-26318,-26789,
       
    85 	-27244,-27683,-28105,-28510,-28897,-29268,-29621,-29955,
       
    86 	-30272,-30571,-30851,-31113,-31356,-31580,-31785,-31970,
       
    87 	-32137,-32284,-32412,-32520,-32609,-32678,-32727,-32757,
       
    88 	-32767,-32757,-32727,-32678,-32609,-32520,-32412,-32284,
       
    89 	-32137,-31970,-31785,-31580,-31356,-31113,-30851,-30571,
       
    90 	-30272,-29955,-29621,-29268,-28897,-28510,-28105,-27683,
       
    91 	-27244,-26789,-26318,-25831,-25329,-24811,-24278,-23731,
       
    92 	-23169,-22594,-22004,-21402,-20787,-20159,-19519,-18867,
       
    93 	-18204,-17530,-16845,-16150,-15446,-14732,-14009,-13278,
       
    94 	-12539,-11792,-11038,-10278, -9511, -8739, -7961, -7179,
       
    95 	 -6392, -5601, -4807, -4011, -3211, -2410, -1607,  -804,
       
    96 	};
       
    97 
       
    98 const TInt16 TSineGen::IncTable[KMaxSineTable] =
       
    99 	{
       
   100 			804,  803,  803,  801,  800,  796,  794,
       
   101 	  791,  787,  782,  778,  772,  767,  760,  754,
       
   102 	  747,  739,  731,  723,  714,  704,  695,  685,
       
   103 	  674,  663,  652,  640,  628,  615,  602,  590,
       
   104 	  575,  562,  547,  533,  518,  502,  487,  471,
       
   105 	  455,  439,  422,  405,  387,  371,  353,  334,
       
   106 	  317,  299,  280,  262,  243,  224,  205,  185,
       
   107 	  167,  147,  128,  108,   89,   69,   49,   30,
       
   108 	   10,  -10,  -30,  -49,  -69,  -89, -108, -128,
       
   109 	 -147, -167, -185, -205, -224, -243, -262, -280,
       
   110 	 -299, -317, -334, -353, -371, -387, -405, -422,
       
   111 	 -439, -455, -471, -487, -502, -518, -533, -547,
       
   112 	 -562, -575, -590, -602, -615, -628, -640, -652,
       
   113 	 -663, -674, -685, -695, -704, -714, -723, -731,
       
   114 	 -739, -747, -754, -760, -767, -772, -778, -782,
       
   115 	 -787, -791, -794, -796, -800, -801, -803, -803,
       
   116 	 -804, -804, -803, -803, -801, -800, -796, -794,
       
   117 	 -791, -787, -782, -778, -772, -767, -760, -754,
       
   118 	 -747, -739, -731, -723, -714, -704, -695, -685,
       
   119 	 -674, -663, -652, -640, -628, -615, -602, -590,
       
   120 	 -575, -562, -547, -533, -518, -502, -487, -471,
       
   121 	 -455, -439, -422, -405, -387, -371, -353, -334,
       
   122 	 -317, -299, -280, -262, -243, -224, -205, -185,
       
   123 	 -167, -147, -128, -108,  -89,  -69,  -49,  -30,
       
   124 	  -10,   10,   30,   49,   69,   89,  108,  128,
       
   125 	  147,  167,  185,  205,  224,  243,  262,  280,
       
   126 	  299,  317,  334,  353,  371,  387,  405,  422,
       
   127 	  439,  455,  471,  487,  502,  518,  533,  547,
       
   128 	  562,  575,  590,  602,  615,  628,  640,  652,
       
   129 	  663,  674,  685,  695,  704,  714,  723,  731,
       
   130 	  739,  747,  754,  760,  767,  772,  778,  782,
       
   131 	  787,  791,  794,  796,  800,  801,  803,  803,
       
   132 	  804
       
   133 	};
       
   134 
       
   135 const TUint8 KDtmfVolumeTable[4][4]=
       
   136 //
       
   137 // Relative strengths to assign to different DTMF tones
       
   138 //
       
   139 // This is only important if DTMFs are being played through a speaker
       
   140 // and need to be machine-recognisable. This table compensates for frequency
       
   141 // drop-off in the speaker and can boost the relative volume of some
       
   142 // frequencies so they are still within tolerance.
       
   143 //
       
   144 // The values normally need to be determined using a frequency analyser on
       
   145 // the hardware
       
   146 //
       
   147 // Each column == same low frequency (697, 770, 852, 941 Hz)
       
   148 // Each row == same high frequency (1209, 1336, 1477, 1633 Hz)
       
   149 //
       
   150 // The value are interpreted as ratios:
       
   151 //		0  == 100% low
       
   152 //		7f == 50% low, 50% high
       
   153 //		ff == 100% high
       
   154 //
       
   155 	{
       
   156 	{38,27,29,37},
       
   157 	{46,36,36,46},
       
   158 	{62,47,49,58},
       
   159 	{70,56,60,68}
       
   160 	};
       
   161 
       
   162 const TUint8 KDtmfTone697=0x0;
       
   163 const TUint8 KDtmfTone770=0x1;
       
   164 const TUint8 KDtmfTone852=0x2;
       
   165 const TUint8 KDtmfTone941=0x3;
       
   166 
       
   167 const TUint8 KDtmfTone1209=0x00;
       
   168 const TUint8 KDtmfTone1336=0x10;
       
   169 const TUint8 KDtmfTone1477=0x20;
       
   170 const TUint8 KDtmfTone1633=0x30;
       
   171 
       
   172 const TUint8 KDtmfToneTable[16]=
       
   173 	{
       
   174 	KDtmfTone941|KDtmfTone1336,//0
       
   175 	KDtmfTone697|KDtmfTone1209,//1
       
   176 	KDtmfTone697|KDtmfTone1336,//2
       
   177 	KDtmfTone697|KDtmfTone1477,//3
       
   178 	KDtmfTone770|KDtmfTone1209,//4
       
   179 	KDtmfTone770|KDtmfTone1336,//5
       
   180 	KDtmfTone770|KDtmfTone1477,//6
       
   181 	KDtmfTone852|KDtmfTone1209,//7
       
   182 	KDtmfTone852|KDtmfTone1336,//8
       
   183 	KDtmfTone852|KDtmfTone1477,//9
       
   184 
       
   185 	KDtmfTone697|KDtmfTone1633,//A
       
   186 	KDtmfTone770|KDtmfTone1633,//B
       
   187 	KDtmfTone852|KDtmfTone1633,//C
       
   188 	KDtmfTone941|KDtmfTone1633,//D
       
   189 	KDtmfTone941|KDtmfTone1209,//E or *
       
   190 	KDtmfTone941|KDtmfTone1477,//F or #
       
   191 	};
       
   192 
       
   193 
       
   194 // -----------------------------------------------------------------------------
       
   195 // LOCAL_C void RampVolume
       
   196 // Simple function to ramp down the volume of some samples
       
   197 // Typically used to prevent "clicking" artifacts at the beginning/end of tones
       
   198 // (other items were commented in a header).
       
   199 // -----------------------------------------------------------------------------
       
   200 //
       
   201 LOCAL_C void RampVolume(
       
   202 	TInt16* aData,
       
   203 	TInt aCount,
       
   204 	TInt aStartVol,
       
   205 	TInt aEndVol)
       
   206 	{
       
   207 	TInt step = (aEndVol - aStartVol)/aCount;
       
   208 	while (aCount--)
       
   209 		{
       
   210 		TInt data = TInt(*aData) * aStartVol;
       
   211 		*aData++ = TInt16(data>>15);
       
   212 		aStartVol += step;
       
   213 		}
       
   214 	}
       
   215 
       
   216 // -----------------------------------------------------------------------------
       
   217 // GenerateSineTableL
       
   218 // Code to generate sine table files used by tone generator
       
   219 // Optionally called from InitL()
       
   220 // (other items were commented in a header).
       
   221 // -----------------------------------------------------------------------------
       
   222 
       
   223 // #define GENERATE_SINE_TABLES 1
       
   224 #ifdef GENERATE_SINE_TABLES
       
   225 LOCAL_C GenerateSineTableL()
       
   226 	{
       
   227 	_LIT(KSineFile,"sine.txt");
       
   228 	_LIT(KSineIncFile,"sineinc.txt");
       
   229 
       
   230 	RFile file;
       
   231 	file.Replace(MdaManager::Fs(),KSineFile,EFileWrite);
       
   232 	CleanupClosePushL(file);
       
   233 
       
   234 	RFile file2;
       
   235 	file2.Replace(MdaManager::Fs(),KSineIncFile,EFileWrite);
       
   236 	CleanupClosePushL(file2);
       
   237 
       
   238 	const TReal pi=3.141592653589;
       
   239 	const TReal twopi=pi*2;
       
   240 	const TReal samples = 256.0;
       
   241 	const TReal step = twopi/samples;
       
   242 
       
   243 	TBuf8<128> sinebuffer;
       
   244 	TBuf8<128> incbuffer;
       
   245 	TReal res;
       
   246 	TInt first=0;
       
   247 	TInt last=KMaxTInt;
       
   248 	TInt current;
       
   249 	_LIT8(KFormat,"%6d,");
       
   250 	_LIT8(KNewLine,"\n");
       
   251 
       
   252 	for(TReal angle=0.0;angle<=(twopi-step);) // Copes with rounding errors
       
   253 		{
       
   254 		sinebuffer.Zero();
       
   255 		incbuffer.Zero();
       
   256 		for (int i=0;i<8;i++)
       
   257 			{
       
   258 			User::LeaveIfError(Math::Sin(res,angle));
       
   259 			current = TInt(KMaxTInt16*res);
       
   260 			sinebuffer.AppendFormat(KFormat,current);
       
   261 			if (last != KMaxTInt)
       
   262 				incbuffer.AppendFormat(KFormat,current-last);
       
   263 			else
       
   264 				first = current;
       
   265 			last = current;
       
   266 			angle += step;
       
   267 			}
       
   268 		sinebuffer.Append(KNewLine);
       
   269 		incbuffer.Append(KNewLine);
       
   270 		file.Write(sinebuffer);
       
   271 		file2.Write(incbuffer);
       
   272 		}
       
   273 
       
   274 	// Write fine difference to incbuffer - differnece between first and last
       
   275 	incbuffer.Zero();
       
   276 	incbuffer.AppendFormat(KFormat,first-last);
       
   277 	incbuffer.Append(KNewLine);
       
   278 	file2.Write(incbuffer);
       
   279 
       
   280 	CleanupStack::PopAndDestroy(file2);
       
   281 	CleanupStack::PopAndDestroy(file);
       
   282 	}
       
   283 #endif
       
   284 
       
   285 
       
   286 // ============================ MEMBER FUNCTIONS ===============================
       
   287 
       
   288 // -----------------------------------------------------------------------------
       
   289 // TSineGen::SetFrequency
       
   290 // Given the frequency set iStep.
       
   291 // Reset iPosition to the equivalent of 0 degrees.
       
   292 // In the special case of aFrequency==4KHz set iPosition to 90 degrees.
       
   293 // (other items were commented in a header).
       
   294 // -----------------------------------------------------------------------------
       
   295 //
       
   296 void TSineGen::SetFrequency(
       
   297 	TInt aFrequency,
       
   298 	TInt aAmplitude)
       
   299 	{
       
   300 
       
   301 	if (aAmplitude>(1<<15))
       
   302 		iAmplitude=(1<<15);
       
   303 	else if (aAmplitude<-(1<<15))
       
   304 		iAmplitude=-(1<<15);
       
   305 	else
       
   306 		iAmplitude=aAmplitude;
       
   307 //
       
   308 // There are 256 entries in the sine table to traverse 360 degrees.
       
   309 // The codec requires samples at a rate of 8000 per second.
       
   310 // Thus for a 1Hz tone the step will be 256/8000 or 4/125.
       
   311 // Now we need need the integer part of the result to end up in
       
   312 // the MSB so we need to multiply by 2^24. This gives the formula
       
   313 // step = (f*4*2^24)/125 or (f*2^26)/125.
       
   314 // Our highest frequency is 4KHz so that the term (f*2^26) exceeds
       
   315 // a 32 bit result by 4000/2^6 (2^6 is the number of significant bits
       
   316 // left after a multiply by 2^26). i.e. 6 bits. We overcome this by
       
   317 // having 6 bits less in the fraction, so the new formula becomes
       
   318 // ((f*2^20)/125)*2^6. This still gives us 20 significant bits in the
       
   319 // fraction.
       
   320 //
       
   321 
       
   322 	iStep=(((TUint)aFrequency<<20)/125)<<6;
       
   323 	iPosition=(aFrequency==4000 ? 0x40000000 : 0);
       
   324 	}
       
   325 
       
   326 // -----------------------------------------------------------------------------
       
   327 // TSineGen::NextSample
       
   328 // Generate the next sample using linear interpolation
       
   329 // (other items were commented in a header).
       
   330 // -----------------------------------------------------------------------------
       
   331 //
       
   332 TInt TSineGen::NextSample()
       
   333 	{
       
   334 	TUint pos=iPosition>>24;
       
   335 	TInt amp=((IncTable[pos]*((iPosition&0x00ffffff)>>20)));
       
   336 	amp>>=4;
       
   337 	amp+=SineTable[pos];
       
   338 	amp=(amp*iAmplitude)>>15;
       
   339 	iPosition+=iStep;
       
   340 	return(amp);
       
   341 	}
       
   342 
       
   343 // -----------------------------------------------------------------------------
       
   344 // TSineWave::Generate
       
   345 // Called when more samples need to be generated.
       
   346 // (other items were commented in a header).
       
   347 // -----------------------------------------------------------------------------
       
   348 //
       
   349 void TSineWave::Generate(
       
   350 	TInt16* aDest,
       
   351 	TInt aCount)
       
   352 	{
       
   353 	while (aCount--)
       
   354 		{
       
   355 		*aDest++=STATIC_CAST(TInt16,iGen1.NextSample()+iGen2.NextSample());
       
   356 		}
       
   357 	}
       
   358 
       
   359 // -----------------------------------------------------------------------------
       
   360 // TSineWave::SetFrequency
       
   361 // Set to generate a single frequency
       
   362 // (other items were commented in a header).
       
   363 // -----------------------------------------------------------------------------
       
   364 //
       
   365 void TSineWave::SetFrequency(
       
   366 	TInt aFrequency,
       
   367 	TInt aAmplitude)
       
   368 	{
       
   369 	SetFrequency(aFrequency,aAmplitude,0,0);
       
   370 	}
       
   371 
       
   372 // -----------------------------------------------------------------------------
       
   373 // TSineWave::SetFrequency
       
   374 // Set to generate two frequencies
       
   375 // (other items were commented in a header).
       
   376 // -----------------------------------------------------------------------------
       
   377 //
       
   378 void TSineWave::SetFrequency(
       
   379 	TInt aFrequency1,
       
   380 	TInt aAmplitude1,
       
   381 	TInt aFrequency2,
       
   382 	TInt aAmplitude2)
       
   383 	{
       
   384 	iGen1.SetFrequency(aFrequency1,aAmplitude1);
       
   385 	iGen2.SetFrequency(aFrequency2,aAmplitude2);
       
   386 	}
       
   387 
       
   388 
       
   389 //
       
   390 // TMdaToneGenerator
       
   391 //
       
   392 
       
   393 // -----------------------------------------------------------------------------
       
   394 // TMdaToneGenerator::Configure
       
   395 // Set up this tone generator to generate data at the desired sample rate
       
   396 // and number of channels (typically mono/stereo)
       
   397 // (other items were commented in a header).
       
   398 // -----------------------------------------------------------------------------
       
   399 //
       
   400 void TMdaToneGenerator::Configure(
       
   401 	TInt aRate,
       
   402 	TInt aChannels,
       
   403 	TInt aRepeats,
       
   404 	TInt aSilence,
       
   405 	TInt aRampUp)
       
   406 	{
       
   407 	iRate = aRate;
       
   408 	iChannels = aChannels;
       
   409 	iSamplesLeft = 0;
       
   410 	iRampUp = ETrue; // Default ramping to on as it is normally useful
       
   411 	iRampDown = ETrue;
       
   412 	iRepeats = aRepeats;
       
   413 	iSilenceBetweenRepeats = aSilence;
       
   414 	iRampUpCount = aRampUp;
       
   415 	iRampUpLeft = aRampUp;
       
   416 	iAfterRepeatSilence = EFalse;
       
   417 	}
       
   418 
       
   419 // -----------------------------------------------------------------------------
       
   420 // TMdaToneGenerator::FillBuffer
       
   421 // Fill the supplied buffer with tone data
       
   422 // Sets the buffer length to zero if there is no more data to play
       
   423 // The buffer must have a max length of at least one sample * channels
       
   424 // e.g. 2 bytes mono, 4 bytes stereo
       
   425 // (other items were commented in a header).
       
   426 // -----------------------------------------------------------------------------
       
   427 //
       
   428 TInt TMdaToneGenerator::FillBuffer(
       
   429 	TDes8& aBuffer)
       
   430 	{
       
   431 	ASSERT(aBuffer.MaxLength()>= (iChannels<<1));
       
   432 	aBuffer.SetMax();
       
   433 
       
   434 	TBool silence;
       
   435 	TInt samples = 0; //
       
   436 	TInt used = 0; // Data used
       
   437 	TInt avail = aBuffer.Length(); // Data filled
       
   438 	TInt count = 0; // Data to be converted
       
   439 	TBool rampUp = EFalse;
       
   440 
       
   441 	TMdaPtr8 fill;
       
   442 	fill.Set(aBuffer); // Pointer to data left to be filled
       
   443 
       
   444 	//
       
   445 	// The rest of this function will loop around continually until the buffer
       
   446 	// is filled or there is no more data to play
       
   447 	//
       
   448 
       
   449 Restart:
       
   450 	silence = EFalse; // Reset
       
   451 	if (iSamplesLeft == 0)
       
   452 		{
       
   453 		if (iTrailingSilence == 0)
       
   454 			{
       
   455 			TInt error = GetNextTone();
       
   456 			if (error)
       
   457 				return error;
       
   458 
       
   459 			rampUp = ETrue;
       
   460 			if ((iSamplesLeft==0)&&(iTrailingSilence==0))
       
   461 				{
       
   462 				if ((iSilenceBetweenRepeats)&&(!iAfterRepeatSilence))
       
   463 					{
       
   464 					iTrailingSilence = iSilenceBetweenRepeats;
       
   465 					iAfterRepeatSilence = ETrue;
       
   466 					goto Restart;
       
   467 					}
       
   468 				else
       
   469 					{
       
   470 					if ((iRepeats>0)||(iRepeats==KMdaRepeatForever))
       
   471 						{
       
   472 						iAfterRepeatSilence = EFalse;
       
   473 						if (iRepeats>0)
       
   474 							iRepeats--;
       
   475 
       
   476 						Reset();
       
   477 						goto Restart;
       
   478 						}
       
   479 					}
       
   480 				// No more to play
       
   481 				goto Finished;
       
   482 				}
       
   483 			goto Restart;
       
   484 			}
       
   485 		else
       
   486 			{
       
   487 			silence = ETrue;
       
   488 			samples = iTrailingSilence;
       
   489 			}
       
   490 		}
       
   491 	else
       
   492 		samples = iSamplesLeft;
       
   493 
       
   494 	count = Min(samples,avail>>1);
       
   495 	fill.SetLength(count<<1);
       
   496 
       
   497 	if (!silence)
       
   498 		{ // Generate wave
       
   499 		iSineWave.Generate(REINTERPRET_CAST(TInt16*,&fill[0]),count);
       
   500 		if (iRampUp)
       
   501 			{ // Ramp up volume at beginning of tone
       
   502 			const TInt KRampUpSamples = 50;
       
   503 			if (rampUp)
       
   504 				{ // Fade in first few samples
       
   505 				TInt fadeInLength = Min(Min(KRampUpSamples,iSamplesLeft),(fill.Length()>>1));
       
   506 				RampVolume(CONST_CAST(TInt16*,REINTERPRET_CAST(const TInt16*,(&fill[0]))),
       
   507 				            fadeInLength,0,1<<15);
       
   508 				}
       
   509 			}
       
   510 		if (iRampDown)
       
   511 			{ // Ramp down volume at end of tone
       
   512 			const TInt KRampDownSamples = 50;
       
   513 			if ((iSamplesLeft-count) < KRampDownSamples)
       
   514 				{ // Fade out last few samples
       
   515 				TInt fadeOutLength = Min(Min(KRampDownSamples,iSamplesLeft),(fill.Length()>>1));
       
   516 				RampVolume(CONST_CAST(TInt16*,
       
   517 				                      REINTERPRET_CAST(const TInt16*,
       
   518 				                        (&(fill.Right(fadeOutLength<<1))[0]))),
       
   519 				            fadeOutLength,1<<15,0);
       
   520 				}
       
   521 			}
       
   522 		iSamplesLeft -= count;
       
   523 		}
       
   524 	else
       
   525 		{ // Generate silence
       
   526 		fill.FillZ(count<<1);
       
   527 		iTrailingSilence -= count;
       
   528 		}
       
   529 
       
   530 	used += count<<1;
       
   531 	avail -= count<<1;
       
   532 	fill.Shift(count<<1);
       
   533 
       
   534 	if (avail>(iChannels<<1))
       
   535 		goto Restart;
       
   536 
       
   537 Finished:
       
   538 
       
   539 	aBuffer.SetLength(used);
       
   540 
       
   541 	// Do any ramp up that is required
       
   542 	if (iRampUpLeft>0)
       
   543 		{
       
   544 		TInt words = iRampUpLeft * iChannels;
       
   545 		words = Min(words,used>>1);
       
   546 		if (words>0) // In case buffer has zero length...
       
   547 			{
       
   548 			TInt left = iRampUpLeft * iChannels;
       
   549 			TInt rampup = iRampUpCount * iChannels;
       
   550 			iRampUpLeft -= words/iChannels;
       
   551 			TInt16* sample = REINTERPRET_CAST(TInt16*,&aBuffer[0]);
       
   552 			while (words--)
       
   553 				{
       
   554 				*sample++ = STATIC_CAST(TInt16,(TInt32(*sample)*(rampup-(left--)))/rampup);
       
   555 				}
       
   556 			}
       
   557 		}
       
   558 
       
   559 	return KErrNone;
       
   560 	}
       
   561 
       
   562 // -----------------------------------------------------------------------------
       
   563 // TMdaToneGenerator::DurationToSamples
       
   564 // Convert the given duration to a sample count using the current settings
       
   565 //
       
   566 // (other items were commented in a header).
       
   567 // -----------------------------------------------------------------------------
       
   568 //
       
   569 TInt TMdaToneGenerator::DurationToSamples(
       
   570 	const TTimeIntervalMicroSeconds& aDuration)
       
   571 	{
       
   572 	const TInt64 KTInt64OneMilion = 1000000;
       
   573 
       
   574 	// Calculate duration as samples
       
   575 	TInt64 microSeconds(aDuration.Int64());  // MSVC doesn't like "aDuration.Int64()" in line below
       
   576 	TInt64 dur = ((TInt64(iRate) * TInt64(iChannels) * microSeconds) / KTInt64OneMilion);
       
   577 	if (I64HIGH(dur)>0)
       
   578 		return KMaxTInt;
       
   579 	else
       
   580 		return I64LOW(dur);
       
   581 	}
       
   582 
       
   583 //
       
   584 // TMdaSimpleToneGenerator
       
   585 //
       
   586 
       
   587 // -----------------------------------------------------------------------------
       
   588 // TMdaSimpleToneGenerator::Reset
       
   589 // (other items were commented in a header).
       
   590 // -----------------------------------------------------------------------------
       
   591 //
       
   592 void TMdaSimpleToneGenerator::Reset()
       
   593 	{
       
   594 	iPlayed = EFalse;
       
   595 	}
       
   596 
       
   597 // -----------------------------------------------------------------------------
       
   598 // TMdaSimpleToneGenerator::SetFrequencyAndDuration
       
   599 // Store the frequency and duration of the specified sine tone
       
   600 // (other items were commented in a header).
       
   601 // -----------------------------------------------------------------------------
       
   602 //
       
   603 void TMdaSimpleToneGenerator::SetFrequencyAndDuration(
       
   604 	TInt aFrequency,
       
   605 	const TTimeIntervalMicroSeconds& aDuration)
       
   606 	{
       
   607 	iFrequency = aFrequency;
       
   608 	iDuration = aDuration;
       
   609 	iPlayed = EFalse;
       
   610 	}
       
   611 
       
   612 // -----------------------------------------------------------------------------
       
   613 // TMdaSimpleToneGenerator::GetNextTone
       
   614 // Simple implementation - just sets the supplied frequency and duration
       
   615 // (other items were commented in a header).
       
   616 // -----------------------------------------------------------------------------
       
   617 //
       
   618 TInt TMdaSimpleToneGenerator::GetNextTone()
       
   619 	{
       
   620 	// This class only plays one tone for the specified duration
       
   621 	if (!iPlayed)
       
   622 		{
       
   623 		iSamplesLeft = I64LOW((iDuration.Int64() * TInt64(iRate))/1000000);
       
   624 		iSineWave.SetFrequency(iFrequency,1<<14);
       
   625 		iPlayed = ETrue;
       
   626 		iTrailingSilence = 20; // Just to stop clicking
       
   627 		}
       
   628 	return KErrNone;
       
   629 	}
       
   630 
       
   631 //
       
   632 // TMdaDualToneGenerator
       
   633 //
       
   634 
       
   635 // -----------------------------------------------------------------------------
       
   636 // TMdaDualToneGenerator::Reset
       
   637 // ?implementation_description
       
   638 // (other items were commented in a header).
       
   639 // -----------------------------------------------------------------------------
       
   640 //
       
   641 void TMdaDualToneGenerator::Reset()
       
   642 	{
       
   643 	iPlayed = EFalse;
       
   644 	}
       
   645 
       
   646 // -----------------------------------------------------------------------------
       
   647 // TMdaDualToneGenerator::SetFrequencyAndDuration
       
   648 // Store the frequencies and duration of the specified dual tone
       
   649 // (other items were commented in a header).
       
   650 // -----------------------------------------------------------------------------
       
   651 //
       
   652 void TMdaDualToneGenerator::SetFrequencyAndDuration(
       
   653 	TInt aFrequencyOne,
       
   654 	TInt aFrequencyTwo,
       
   655 	const TTimeIntervalMicroSeconds& aDuration)
       
   656 	{
       
   657 
       
   658 	iFrequencyOne = aFrequencyOne;
       
   659 	iFrequencyTwo = aFrequencyTwo;
       
   660 	iDuration = aDuration;
       
   661 	iPlayed = EFalse;
       
   662 	}
       
   663 
       
   664 // -----------------------------------------------------------------------------
       
   665 // TMdaDualToneGenerator::GetNextTone
       
   666 // This is called by TMdaToneGenerator::FillBuffer()
       
   667 // to calculate the number of samples (iSamplesLeft) that will be needed
       
   668 // for the tone to be played and to initialize the sine wave generator.
       
   669 // If the tone has already been played, then leaves iSamplesLeft
       
   670 // unmodified (should be zero) to indicate that it has finished.
       
   671 // (other items were commented in a header).
       
   672 // -----------------------------------------------------------------------------
       
   673 //
       
   674 TInt TMdaDualToneGenerator::GetNextTone()
       
   675 	{
       
   676 	// This class only plays one tone for the specified duration
       
   677 	if (!iPlayed)
       
   678 		{
       
   679 		iSamplesLeft = I64LOW((iDuration.Int64() * TInt64(iRate))/KOneMillionMicroSeconds);
       
   680 		iSineWave.SetFrequency(iFrequencyOne, KMaxAmplitude/2, iFrequencyTwo, KMaxAmplitude/2);
       
   681 		iPlayed = ETrue;
       
   682 		iTrailingSilence = KDefaultTrailingSilenceSamples; // Just to stop clicking
       
   683 		}
       
   684 	return KErrNone;
       
   685 	}
       
   686 
       
   687 //
       
   688 // TMdaDTMFGenerator
       
   689 //
       
   690 
       
   691 // -----------------------------------------------------------------------------
       
   692 // TMdaDTMFGenerator::Reset
       
   693 // (other items were commented in a header).
       
   694 // -----------------------------------------------------------------------------
       
   695 //
       
   696 void TMdaDTMFGenerator::Reset()
       
   697 	{
       
   698 	iChar = 0;
       
   699 	}
       
   700 
       
   701 // -----------------------------------------------------------------------------
       
   702 // TMdaDTMFGenerator::SetToneDurations
       
   703 // Setup the DTMF tone durations
       
   704 // aOn can be == -1 indicating should play first tone indefinately
       
   705 // (other items were commented in a header).
       
   706 // -----------------------------------------------------------------------------
       
   707 //
       
   708 void TMdaDTMFGenerator::SetToneDurations(
       
   709 	const TTimeIntervalMicroSeconds32 aOn,
       
   710 	const TTimeIntervalMicroSeconds32 aOff,
       
   711 	const TTimeIntervalMicroSeconds32 aPause)
       
   712 	{
       
   713 	ASSERT(aOn.Int() >=-1);
       
   714 	ASSERT(aOff.Int()>=0);
       
   715 	ASSERT(aPause.Int()>=0);
       
   716 
       
   717 	iOn = aOn;
       
   718 	iOff = aOff;
       
   719 	iPause = aPause;
       
   720 
       
   721 	iOnSamples = KRecalculateToneLengths; // Must recalculate these later
       
   722 	}
       
   723 
       
   724 // -----------------------------------------------------------------------------
       
   725 // TMdaDTMFGenerator::SetString
       
   726 // Store the DTMF string to be played
       
   727 // No need to validate it as it will already have been checked
       
   728 // (other items were commented in a header).
       
   729 // -----------------------------------------------------------------------------
       
   730 //
       
   731 void TMdaDTMFGenerator::SetString(
       
   732 	const TDesC& aDTMFString)
       
   733 	{
       
   734 	iChar = 0;
       
   735 	iDTMFString = &aDTMFString;
       
   736 	}
       
   737 
       
   738 // -----------------------------------------------------------------------------
       
   739 // TMdaDTMFGenerator::GetNextTone
       
   740 // Setup frequency/duration/silence settings for next DTMF tone
       
   741 // Supported characters are 0-9 A-F * # , and any kind of white space
       
   742 // (other items were commented in a header).
       
   743 // -----------------------------------------------------------------------------
       
   744 //
       
   745 TInt TMdaDTMFGenerator::GetNextTone()
       
   746 	{
       
   747 	TBool onlyPlayFirstTone = EFalse;
       
   748 
       
   749 	if (iOnSamples == KRecalculateToneLengths)
       
   750 		{
       
   751 		// Must recalculate tone durations as samples
       
   752 
       
   753 		// Handle special case where tone on duration negative
       
   754 		// - meaning play first character indefinately
       
   755 		if (iOn.Int()>=0)
       
   756 			iOnSamples = DurationToSamples(TInt64(iOn.Int()));
       
   757 		else
       
   758 			{
       
   759 			onlyPlayFirstTone = ETrue;
       
   760 			iOnSamples = -1;
       
   761 			}
       
   762 
       
   763 		iOffSamples = DurationToSamples(TInt64(iOff.Int()));
       
   764 		iPauseSamples = DurationToSamples(TInt64(iPause.Int()));
       
   765 		}
       
   766 
       
   767 	ASSERT(iDTMFString);
       
   768 
       
   769 	if (iChar==iDTMFString->Length())
       
   770 		return KErrNone; // Finished. Nothing to do
       
   771 
       
   772 	TInt highFrequency = 0;
       
   773 	TInt highVolume = 0;
       
   774 	TInt lowFrequency = 0;
       
   775 	TInt lowVolume =0;
       
   776 
       
   777 Retry:
       
   778    	TChar c((*iDTMFString)[iChar++]);
       
   779    	if ((TUint)c=='#' || (TUint)c=='*' || c.IsHexDigit())
       
   780    		{
       
   781     	TInt tableIndex;
       
   782 		switch ((TUint)c)
       
   783 			{
       
   784 		case '*':
       
   785 			tableIndex=14;
       
   786 			break;
       
   787 		case '#':
       
   788 			tableIndex=15;
       
   789 			break;
       
   790 		default:
       
   791 			if (c.IsDigit())
       
   792     			tableIndex=(TUint)c-'0';
       
   793 			else //letter
       
   794 		   		{
       
   795 				c.UpperCase();
       
   796     			tableIndex=(TUint)c-'A'+10;
       
   797 				}
       
   798 			}
       
   799 		TInt high=KDtmfToneTable[tableIndex]&0xf0;
       
   800 		TInt low=KDtmfToneTable[tableIndex]&0x0f;
       
   801 		switch(high)
       
   802 			{
       
   803 		case KDtmfTone1209:
       
   804 			highFrequency=1209;
       
   805 			break;
       
   806 		case KDtmfTone1336:
       
   807 			highFrequency=1336;
       
   808 			break;
       
   809 		case KDtmfTone1477:
       
   810 			highFrequency=1477;
       
   811 			break;
       
   812 		default://KDtmfTone1633:
       
   813 			highFrequency=1633;
       
   814 			break;
       
   815 			}
       
   816 		switch(low)
       
   817 			{
       
   818 		case KDtmfTone697:
       
   819 			lowFrequency=697;
       
   820 			break;
       
   821 		case KDtmfTone770:
       
   822 			lowFrequency=770;
       
   823 			break;
       
   824 		case KDtmfTone852:
       
   825 			lowFrequency=852;
       
   826 			break;
       
   827 		default://KDtmfTone941:
       
   828 			lowFrequency=941;
       
   829 			break;
       
   830 			}
       
   831 		high>>=4;
       
   832 		const TUint8* dtmfVolumes=&KDtmfVolumeTable[0][0];
       
   833 		TInt volume=dtmfVolumes[((low)<<2)+(high)]<<7;
       
   834 		highVolume = volume;
       
   835 		lowVolume = (1<<15)-volume;
       
   836 
       
   837 		iTrailingSilence = iOffSamples;
       
   838 		iSamplesLeft = iOnSamples;
       
   839 		}
       
   840    	else if ((TUint)c==',')
       
   841 		{
       
   842   		iTrailingSilence = iPauseSamples;
       
   843  		iSamplesLeft = 0;
       
   844     	}
       
   845 	else if (c.IsSpace())
       
   846 		{
       
   847 		if (iChar < iDTMFString->Length())
       
   848 			goto Retry;
       
   849 		}
       
   850 	else
       
   851 		return KErrCorrupt;
       
   852 
       
   853 	if (iOnSamples < 0) // Play only first character for ever
       
   854 		{
       
   855 		iTrailingSilence = 0;
       
   856 		iSamplesLeft = iRate * iChannels; // One second of samples
       
   857 		iChar = 0; // Reset so this character is played again next time
       
   858 		iRampDown = EFalse;
       
   859 		if (!onlyPlayFirstTone)
       
   860 			{
       
   861 			iRampUp = EFalse;
       
   862 			// This is not the first time around so we should not
       
   863 			// reset the tone generator - it will already have the
       
   864 			// correct settings and setting them again would cause
       
   865 			// an audible discontinuity
       
   866 			return KErrNone;
       
   867 			}
       
   868 		}
       
   869 
       
   870 	iSineWave.SetFrequency(highFrequency,highVolume,lowFrequency,lowVolume);
       
   871 	return KErrNone;
       
   872 	}
       
   873 
       
   874 //
       
   875 // TMdaSequenceGenerator
       
   876 //
       
   877 
       
   878 
       
   879 // -----------------------------------------------------------------------------
       
   880 // void TMdaSequenceGenerator::Reset()
       
   881 // (other items were commented in a header).
       
   882 // -----------------------------------------------------------------------------
       
   883 //
       
   884 void TMdaSequenceGenerator::Reset()
       
   885 	{
       
   886 	iInstructionPtr = REINTERPRET_CAST(const TInt16*,&((*iSequenceData)[0]));
       
   887 	iInstructionPtr += 2; // Skip signature
       
   888 	iStackIndex = 0;
       
   889 	}
       
   890 
       
   891 // -----------------------------------------------------------------------------
       
   892 // TMdaSequenceGenerator::SetSequenceData
       
   893 // Store the sequence data to be played
       
   894 // No need to validate it as it will already have been checked
       
   895 // (other items were commented in a header).
       
   896 // -----------------------------------------------------------------------------
       
   897 //
       
   898 void TMdaSequenceGenerator::SetSequenceData(
       
   899 	const TDesC8& aSequenceData)
       
   900 	{
       
   901 	iSequenceData = &aSequenceData;
       
   902 	iInstructionPtr = REINTERPRET_CAST(const TInt16*,&aSequenceData[0]);
       
   903 	iLastInstruction = iInstructionPtr + (iSequenceData->Length()>>1) - 1;
       
   904 
       
   905 	// These are asserts because this should not be called if signature not present
       
   906 	ASSERT(*iInstructionPtr == KFixedSequenceSignatureOne);
       
   907 	ASSERT(*(iInstructionPtr+1) == KFixedSequenceSignatureTwo);
       
   908 
       
   909 	iInstructionPtr += 2; // Skip signature
       
   910 
       
   911 	iStackIndex = 0;
       
   912 	}
       
   913 
       
   914 // -----------------------------------------------------------------------------
       
   915 // TMdaSequenceGenerator::GetNextTone
       
   916 // (other items were commented in a header).
       
   917 // -----------------------------------------------------------------------------
       
   918 //
       
   919 TInt TMdaSequenceGenerator::GetNextTone()
       
   920 	{
       
   921 	ASSERT(iInstructionPtr); // Sanity check
       
   922 
       
   923 	TInt ret = KRequestPending;
       
   924 	while (ret == KRequestPending)
       
   925 		{
       
   926 		if (iInstructionPtr > iLastInstruction)
       
   927 			ret = KErrCorrupt;
       
   928 		else if (*iInstructionPtr<=0)
       
   929 	   		{
       
   930 	   		switch (*iInstructionPtr)
       
   931 	   			{
       
   932 	   		case KFixedSequenceFunctionReturn: // End of sequence
       
   933 				ret = KErrNone;
       
   934 				break;
       
   935 
       
   936 	   		case KFixedSequenceFunctionStartLoop:
       
   937 				if (iStackIndex>2) // Validate - can only nest twice
       
   938 					ret = KErrCorrupt;
       
   939 				else if ((iInstructionPtr+2) > iLastInstruction)
       
   940 					ret = KErrCorrupt; // Don't run off end of sequence
       
   941 				else
       
   942 					{
       
   943 		   			iStack[iStackIndex++]=(TInt)(iInstructionPtr+2);
       
   944 		   			iStack[iStackIndex++]=(TInt)*(iInstructionPtr+1);
       
   945 	   				iInstructionPtr+=2;
       
   946 					}
       
   947 	   			break;
       
   948 
       
   949 	   		case KFixedSequenceFunctionEndLoop:
       
   950 				if (iStackIndex==0) // Validate - must already be nested
       
   951 					ret = KErrCorrupt;
       
   952 				else
       
   953 					{
       
   954 		   			if ((--iStack[iStackIndex-1])!=0)
       
   955 		   				iInstructionPtr=(TInt16*)iStack[iStackIndex-2];
       
   956 		   			else
       
   957 		   				{
       
   958 		   				iStackIndex-=2;
       
   959 		   				iInstructionPtr++;
       
   960 		   				}
       
   961 					}
       
   962 	   			break;
       
   963 
       
   964 	   		default: // Bad sequence
       
   965 				ret = KErrCorrupt;
       
   966 	   			}
       
   967 			}
       
   968 		else
       
   969 			{
       
   970 			if ((iInstructionPtr+5) > iLastInstruction)
       
   971 				ret = KErrCorrupt; // Don't run off end of sequence
       
   972 			else
       
   973 				{
       
   974 				iSamplesLeft = *iInstructionPtr++;
       
   975 				TInt freqOne = *iInstructionPtr++;
       
   976 				TInt volOne  = *iInstructionPtr++;
       
   977 				TInt freqTwo = *iInstructionPtr++;
       
   978 				TInt volTwo  = *iInstructionPtr++;
       
   979 
       
   980 				if ((volOne> 1<<15)||(volTwo > 1<<15))
       
   981 					ret = KErrCorrupt;
       
   982 				else
       
   983 					{
       
   984 					iSineWave.SetFrequency(freqOne,volOne,freqTwo,volTwo);
       
   985 					ret = KErrNone;
       
   986 					}
       
   987 				}
       
   988 			}
       
   989 		}
       
   990 	return ret;
       
   991 	}
       
   992 
       
   993 //  End of File