--- a/audiostubs/devsoundextensions_stubs/mmfdevsoundadaptation_stub/src/ToneGenerator.cpp Tue Sep 07 08:19:48 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,993 +0,0 @@
-/*
-* Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description: Audio Stubs - This file contains an implementation of the ToneGenerator interface
-* that converts all tone generation requests in to sampled audio
-* data to be played through the normal local sampled audio interface
-*
-*/
-
-
-
-// INCLUDE FILES
-#include "ToneGenerator.h"
-#include <e32math.h>
-#include <mda/common/resource.h>
-
-// CONSTANTS
-
-/******************************************************************************
-* Tone Generators
-*
-* The following classes are used to generate simple frequency/duration tones,
-* DTMF, and SymbianOS tone sequences in a WINS environment. The below code
-* should only be considered for WINS.
-******************************************************************************/
-
-// this defines the maximum possible amplitude allowed for TSineGen::SetFrequency()
-const TInt KMaxAmplitude = 0x8000;
-
-// default number of samples for trailing silence following a Tone
-const TInt KDefaultTrailingSilenceSamples = 20;
-
-const TInt KRecalculateToneLengths = KMinTInt;
-
-//
-// Sequence constants
-//
-
-#ifdef _DEBUG
-const TInt16 KFixedSequenceSignatureOne='S'+('Q'<<8);
-const TInt16 KFixedSequenceSignatureTwo='N'+('C'<<8);
-#endif // _DEBUG
-
-const TInt KFixedSequenceFunctionReturn=-1;
-const TInt KFixedSequenceFunctionStartLoop=-2;
-const TInt KFixedSequenceFunctionEndLoop=-3;
-
-//
-// Sine tone generator
-//
-
-const TInt16 TSineGen::SineTable[KMaxSineTable] =
- {
- 0, 804, 1607, 2410, 3211, 4011, 4807, 5601,
- 6392, 7179, 7961, 8739, 9511, 10278, 11038, 11792,
- 12539, 13278, 14009, 14732, 15446, 16150, 16845, 17530,
- 18204, 18867, 19519, 20159, 20787, 21402, 22004, 22594,
- 23169, 23731, 24278, 24811, 25329, 25831, 26318, 26789,
- 27244, 27683, 28105, 28510, 28897, 29268, 29621, 29955,
- 30272, 30571, 30851, 31113, 31356, 31580, 31785, 31970,
- 32137, 32284, 32412, 32520, 32609, 32678, 32727, 32757,
- 32767, 32757, 32727, 32678, 32609, 32520, 32412, 32284,
- 32137, 31970, 31785, 31580, 31356, 31113, 30851, 30571,
- 30272, 29955, 29621, 29268, 28897, 28510, 28105, 27683,
- 27244, 26789, 26318, 25831, 25329, 24811, 24278, 23731,
- 23169, 22594, 22004, 21402, 20787, 20159, 19519, 18867,
- 18204, 17530, 16845, 16150, 15446, 14732, 14009, 13278,
- 12539, 11792, 11038, 10278, 9511, 8739, 7961, 7179,
- 6392, 5601, 4807, 4011, 3211, 2410, 1607, 804,
- 0, -804, -1607, -2410, -3211, -4011, -4807, -5601,
- -6392, -7179, -7961, -8739, -9511,-10278,-11038,-11792,
- -12539,-13278,-14009,-14732,-15446,-16150,-16845,-17530,
- -18204,-18867,-19519,-20159,-20787,-21402,-22004,-22594,
- -23169,-23731,-24278,-24811,-25329,-25831,-26318,-26789,
- -27244,-27683,-28105,-28510,-28897,-29268,-29621,-29955,
- -30272,-30571,-30851,-31113,-31356,-31580,-31785,-31970,
- -32137,-32284,-32412,-32520,-32609,-32678,-32727,-32757,
- -32767,-32757,-32727,-32678,-32609,-32520,-32412,-32284,
- -32137,-31970,-31785,-31580,-31356,-31113,-30851,-30571,
- -30272,-29955,-29621,-29268,-28897,-28510,-28105,-27683,
- -27244,-26789,-26318,-25831,-25329,-24811,-24278,-23731,
- -23169,-22594,-22004,-21402,-20787,-20159,-19519,-18867,
- -18204,-17530,-16845,-16150,-15446,-14732,-14009,-13278,
- -12539,-11792,-11038,-10278, -9511, -8739, -7961, -7179,
- -6392, -5601, -4807, -4011, -3211, -2410, -1607, -804,
- };
-
-const TInt16 TSineGen::IncTable[KMaxSineTable] =
- {
- 804, 803, 803, 801, 800, 796, 794,
- 791, 787, 782, 778, 772, 767, 760, 754,
- 747, 739, 731, 723, 714, 704, 695, 685,
- 674, 663, 652, 640, 628, 615, 602, 590,
- 575, 562, 547, 533, 518, 502, 487, 471,
- 455, 439, 422, 405, 387, 371, 353, 334,
- 317, 299, 280, 262, 243, 224, 205, 185,
- 167, 147, 128, 108, 89, 69, 49, 30,
- 10, -10, -30, -49, -69, -89, -108, -128,
- -147, -167, -185, -205, -224, -243, -262, -280,
- -299, -317, -334, -353, -371, -387, -405, -422,
- -439, -455, -471, -487, -502, -518, -533, -547,
- -562, -575, -590, -602, -615, -628, -640, -652,
- -663, -674, -685, -695, -704, -714, -723, -731,
- -739, -747, -754, -760, -767, -772, -778, -782,
- -787, -791, -794, -796, -800, -801, -803, -803,
- -804, -804, -803, -803, -801, -800, -796, -794,
- -791, -787, -782, -778, -772, -767, -760, -754,
- -747, -739, -731, -723, -714, -704, -695, -685,
- -674, -663, -652, -640, -628, -615, -602, -590,
- -575, -562, -547, -533, -518, -502, -487, -471,
- -455, -439, -422, -405, -387, -371, -353, -334,
- -317, -299, -280, -262, -243, -224, -205, -185,
- -167, -147, -128, -108, -89, -69, -49, -30,
- -10, 10, 30, 49, 69, 89, 108, 128,
- 147, 167, 185, 205, 224, 243, 262, 280,
- 299, 317, 334, 353, 371, 387, 405, 422,
- 439, 455, 471, 487, 502, 518, 533, 547,
- 562, 575, 590, 602, 615, 628, 640, 652,
- 663, 674, 685, 695, 704, 714, 723, 731,
- 739, 747, 754, 760, 767, 772, 778, 782,
- 787, 791, 794, 796, 800, 801, 803, 803,
- 804
- };
-
-const TUint8 KDtmfVolumeTable[4][4]=
-//
-// Relative strengths to assign to different DTMF tones
-//
-// This is only important if DTMFs are being played through a speaker
-// and need to be machine-recognisable. This table compensates for frequency
-// drop-off in the speaker and can boost the relative volume of some
-// frequencies so they are still within tolerance.
-//
-// The values normally need to be determined using a frequency analyser on
-// the hardware
-//
-// Each column == same low frequency (697, 770, 852, 941 Hz)
-// Each row == same high frequency (1209, 1336, 1477, 1633 Hz)
-//
-// The value are interpreted as ratios:
-// 0 == 100% low
-// 7f == 50% low, 50% high
-// ff == 100% high
-//
- {
- {38,27,29,37},
- {46,36,36,46},
- {62,47,49,58},
- {70,56,60,68}
- };
-
-const TUint8 KDtmfTone697=0x0;
-const TUint8 KDtmfTone770=0x1;
-const TUint8 KDtmfTone852=0x2;
-const TUint8 KDtmfTone941=0x3;
-
-const TUint8 KDtmfTone1209=0x00;
-const TUint8 KDtmfTone1336=0x10;
-const TUint8 KDtmfTone1477=0x20;
-const TUint8 KDtmfTone1633=0x30;
-
-const TUint8 KDtmfToneTable[16]=
- {
- KDtmfTone941|KDtmfTone1336,//0
- KDtmfTone697|KDtmfTone1209,//1
- KDtmfTone697|KDtmfTone1336,//2
- KDtmfTone697|KDtmfTone1477,//3
- KDtmfTone770|KDtmfTone1209,//4
- KDtmfTone770|KDtmfTone1336,//5
- KDtmfTone770|KDtmfTone1477,//6
- KDtmfTone852|KDtmfTone1209,//7
- KDtmfTone852|KDtmfTone1336,//8
- KDtmfTone852|KDtmfTone1477,//9
-
- KDtmfTone697|KDtmfTone1633,//A
- KDtmfTone770|KDtmfTone1633,//B
- KDtmfTone852|KDtmfTone1633,//C
- KDtmfTone941|KDtmfTone1633,//D
- KDtmfTone941|KDtmfTone1209,//E or *
- KDtmfTone941|KDtmfTone1477,//F or #
- };
-
-
-// -----------------------------------------------------------------------------
-// LOCAL_C void RampVolume
-// Simple function to ramp down the volume of some samples
-// Typically used to prevent "clicking" artifacts at the beginning/end of tones
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-LOCAL_C void RampVolume(
- TInt16* aData,
- TInt aCount,
- TInt aStartVol,
- TInt aEndVol)
- {
- TInt step = (aEndVol - aStartVol)/aCount;
- while (aCount--)
- {
- TInt data = TInt(*aData) * aStartVol;
- *aData++ = TInt16(data>>15);
- aStartVol += step;
- }
- }
-
-// -----------------------------------------------------------------------------
-// GenerateSineTableL
-// Code to generate sine table files used by tone generator
-// Optionally called from InitL()
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-
-// #define GENERATE_SINE_TABLES 1
-#ifdef GENERATE_SINE_TABLES
-LOCAL_C GenerateSineTableL()
- {
- _LIT(KSineFile,"sine.txt");
- _LIT(KSineIncFile,"sineinc.txt");
-
- RFile file;
- file.Replace(MdaManager::Fs(),KSineFile,EFileWrite);
- CleanupClosePushL(file);
-
- RFile file2;
- file2.Replace(MdaManager::Fs(),KSineIncFile,EFileWrite);
- CleanupClosePushL(file2);
-
- const TReal pi=3.141592653589;
- const TReal twopi=pi*2;
- const TReal samples = 256.0;
- const TReal step = twopi/samples;
-
- TBuf8<128> sinebuffer;
- TBuf8<128> incbuffer;
- TReal res;
- TInt first=0;
- TInt last=KMaxTInt;
- TInt current;
- _LIT8(KFormat,"%6d,");
- _LIT8(KNewLine,"\n");
-
- for(TReal angle=0.0;angle<=(twopi-step);) // Copes with rounding errors
- {
- sinebuffer.Zero();
- incbuffer.Zero();
- for (int i=0;i<8;i++)
- {
- User::LeaveIfError(Math::Sin(res,angle));
- current = TInt(KMaxTInt16*res);
- sinebuffer.AppendFormat(KFormat,current);
- if (last != KMaxTInt)
- incbuffer.AppendFormat(KFormat,current-last);
- else
- first = current;
- last = current;
- angle += step;
- }
- sinebuffer.Append(KNewLine);
- incbuffer.Append(KNewLine);
- file.Write(sinebuffer);
- file2.Write(incbuffer);
- }
-
- // Write fine difference to incbuffer - differnece between first and last
- incbuffer.Zero();
- incbuffer.AppendFormat(KFormat,first-last);
- incbuffer.Append(KNewLine);
- file2.Write(incbuffer);
-
- CleanupStack::PopAndDestroy(file2);
- CleanupStack::PopAndDestroy(file);
- }
-#endif
-
-
-// ============================ MEMBER FUNCTIONS ===============================
-
-// -----------------------------------------------------------------------------
-// TSineGen::SetFrequency
-// Given the frequency set iStep.
-// Reset iPosition to the equivalent of 0 degrees.
-// In the special case of aFrequency==4KHz set iPosition to 90 degrees.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void TSineGen::SetFrequency(
- TInt aFrequency,
- TInt aAmplitude)
- {
-
- if (aAmplitude>(1<<15))
- iAmplitude=(1<<15);
- else if (aAmplitude<-(1<<15))
- iAmplitude=-(1<<15);
- else
- iAmplitude=aAmplitude;
-//
-// There are 256 entries in the sine table to traverse 360 degrees.
-// The codec requires samples at a rate of 8000 per second.
-// Thus for a 1Hz tone the step will be 256/8000 or 4/125.
-// Now we need need the integer part of the result to end up in
-// the MSB so we need to multiply by 2^24. This gives the formula
-// step = (f*4*2^24)/125 or (f*2^26)/125.
-// Our highest frequency is 4KHz so that the term (f*2^26) exceeds
-// a 32 bit result by 4000/2^6 (2^6 is the number of significant bits
-// left after a multiply by 2^26). i.e. 6 bits. We overcome this by
-// having 6 bits less in the fraction, so the new formula becomes
-// ((f*2^20)/125)*2^6. This still gives us 20 significant bits in the
-// fraction.
-//
-
- iStep=(((TUint)aFrequency<<20)/125)<<6;
- iPosition=(aFrequency==4000 ? 0x40000000 : 0);
- }
-
-// -----------------------------------------------------------------------------
-// TSineGen::NextSample
-// Generate the next sample using linear interpolation
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TInt TSineGen::NextSample()
- {
- TUint pos=iPosition>>24;
- TInt amp=((IncTable[pos]*((iPosition&0x00ffffff)>>20)));
- amp>>=4;
- amp+=SineTable[pos];
- amp=(amp*iAmplitude)>>15;
- iPosition+=iStep;
- return(amp);
- }
-
-// -----------------------------------------------------------------------------
-// TSineWave::Generate
-// Called when more samples need to be generated.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void TSineWave::Generate(
- TInt16* aDest,
- TInt aCount)
- {
- while (aCount--)
- {
- *aDest++=STATIC_CAST(TInt16,iGen1.NextSample()+iGen2.NextSample());
- }
- }
-
-// -----------------------------------------------------------------------------
-// TSineWave::SetFrequency
-// Set to generate a single frequency
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void TSineWave::SetFrequency(
- TInt aFrequency,
- TInt aAmplitude)
- {
- SetFrequency(aFrequency,aAmplitude,0,0);
- }
-
-// -----------------------------------------------------------------------------
-// TSineWave::SetFrequency
-// Set to generate two frequencies
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void TSineWave::SetFrequency(
- TInt aFrequency1,
- TInt aAmplitude1,
- TInt aFrequency2,
- TInt aAmplitude2)
- {
- iGen1.SetFrequency(aFrequency1,aAmplitude1);
- iGen2.SetFrequency(aFrequency2,aAmplitude2);
- }
-
-
-//
-// TMdaToneGenerator
-//
-
-// -----------------------------------------------------------------------------
-// TMdaToneGenerator::Configure
-// Set up this tone generator to generate data at the desired sample rate
-// and number of channels (typically mono/stereo)
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void TMdaToneGenerator::Configure(
- TInt aRate,
- TInt aChannels,
- TInt aRepeats,
- TInt aSilence,
- TInt aRampUp)
- {
- iRate = aRate;
- iChannels = aChannels;
- iSamplesLeft = 0;
- iRampUp = ETrue; // Default ramping to on as it is normally useful
- iRampDown = ETrue;
- iRepeats = aRepeats;
- iSilenceBetweenRepeats = aSilence;
- iRampUpCount = aRampUp;
- iRampUpLeft = aRampUp;
- iAfterRepeatSilence = EFalse;
- }
-
-// -----------------------------------------------------------------------------
-// TMdaToneGenerator::FillBuffer
-// Fill the supplied buffer with tone data
-// Sets the buffer length to zero if there is no more data to play
-// The buffer must have a max length of at least one sample * channels
-// e.g. 2 bytes mono, 4 bytes stereo
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TInt TMdaToneGenerator::FillBuffer(
- TDes8& aBuffer)
- {
- ASSERT(aBuffer.MaxLength()>= (iChannels<<1));
- aBuffer.SetMax();
-
- TBool silence;
- TInt samples = 0; //
- TInt used = 0; // Data used
- TInt avail = aBuffer.Length(); // Data filled
- TInt count = 0; // Data to be converted
- TBool rampUp = EFalse;
-
- TMdaPtr8 fill;
- fill.Set(aBuffer); // Pointer to data left to be filled
-
- //
- // The rest of this function will loop around continually until the buffer
- // is filled or there is no more data to play
- //
-
-Restart:
- silence = EFalse; // Reset
- if (iSamplesLeft == 0)
- {
- if (iTrailingSilence == 0)
- {
- TInt error = GetNextTone();
- if (error)
- return error;
-
- rampUp = ETrue;
- if ((iSamplesLeft==0)&&(iTrailingSilence==0))
- {
- if ((iSilenceBetweenRepeats)&&(!iAfterRepeatSilence))
- {
- iTrailingSilence = iSilenceBetweenRepeats;
- iAfterRepeatSilence = ETrue;
- goto Restart;
- }
- else
- {
- if ((iRepeats>0)||(iRepeats==KMdaRepeatForever))
- {
- iAfterRepeatSilence = EFalse;
- if (iRepeats>0)
- iRepeats--;
-
- Reset();
- goto Restart;
- }
- }
- // No more to play
- goto Finished;
- }
- goto Restart;
- }
- else
- {
- silence = ETrue;
- samples = iTrailingSilence;
- }
- }
- else
- samples = iSamplesLeft;
-
- count = Min(samples,avail>>1);
- fill.SetLength(count<<1);
-
- if (!silence)
- { // Generate wave
- iSineWave.Generate(REINTERPRET_CAST(TInt16*,&fill[0]),count);
- if (iRampUp)
- { // Ramp up volume at beginning of tone
- const TInt KRampUpSamples = 50;
- if (rampUp)
- { // Fade in first few samples
- TInt fadeInLength = Min(Min(KRampUpSamples,iSamplesLeft),(fill.Length()>>1));
- RampVolume(CONST_CAST(TInt16*,REINTERPRET_CAST(const TInt16*,(&fill[0]))),
- fadeInLength,0,1<<15);
- }
- }
- if (iRampDown)
- { // Ramp down volume at end of tone
- const TInt KRampDownSamples = 50;
- if ((iSamplesLeft-count) < KRampDownSamples)
- { // Fade out last few samples
- TInt fadeOutLength = Min(Min(KRampDownSamples,iSamplesLeft),(fill.Length()>>1));
- RampVolume(CONST_CAST(TInt16*,
- REINTERPRET_CAST(const TInt16*,
- (&(fill.Right(fadeOutLength<<1))[0]))),
- fadeOutLength,1<<15,0);
- }
- }
- iSamplesLeft -= count;
- }
- else
- { // Generate silence
- fill.FillZ(count<<1);
- iTrailingSilence -= count;
- }
-
- used += count<<1;
- avail -= count<<1;
- fill.Shift(count<<1);
-
- if (avail>(iChannels<<1))
- goto Restart;
-
-Finished:
-
- aBuffer.SetLength(used);
-
- // Do any ramp up that is required
- if (iRampUpLeft>0)
- {
- TInt words = iRampUpLeft * iChannels;
- words = Min(words,used>>1);
- if (words>0) // In case buffer has zero length...
- {
- TInt left = iRampUpLeft * iChannels;
- TInt rampup = iRampUpCount * iChannels;
- iRampUpLeft -= words/iChannels;
- TInt16* sample = REINTERPRET_CAST(TInt16*,&aBuffer[0]);
- while (words--)
- {
- *sample++ = STATIC_CAST(TInt16,(TInt32(*sample)*(rampup-(left--)))/rampup);
- }
- }
- }
-
- return KErrNone;
- }
-
-// -----------------------------------------------------------------------------
-// TMdaToneGenerator::DurationToSamples
-// Convert the given duration to a sample count using the current settings
-//
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TInt TMdaToneGenerator::DurationToSamples(
- const TTimeIntervalMicroSeconds& aDuration)
- {
- const TInt64 KTInt64OneMilion = 1000000;
-
- // Calculate duration as samples
- TInt64 microSeconds(aDuration.Int64()); // MSVC doesn't like "aDuration.Int64()" in line below
- TInt64 dur = ((TInt64(iRate) * TInt64(iChannels) * microSeconds) / KTInt64OneMilion);
- if (I64HIGH(dur)>0)
- return KMaxTInt;
- else
- return I64LOW(dur);
- }
-
-//
-// TMdaSimpleToneGenerator
-//
-
-// -----------------------------------------------------------------------------
-// TMdaSimpleToneGenerator::Reset
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void TMdaSimpleToneGenerator::Reset()
- {
- iPlayed = EFalse;
- }
-
-// -----------------------------------------------------------------------------
-// TMdaSimpleToneGenerator::SetFrequencyAndDuration
-// Store the frequency and duration of the specified sine tone
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void TMdaSimpleToneGenerator::SetFrequencyAndDuration(
- TInt aFrequency,
- const TTimeIntervalMicroSeconds& aDuration)
- {
- iFrequency = aFrequency;
- iDuration = aDuration;
- iPlayed = EFalse;
- }
-
-// -----------------------------------------------------------------------------
-// TMdaSimpleToneGenerator::GetNextTone
-// Simple implementation - just sets the supplied frequency and duration
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TInt TMdaSimpleToneGenerator::GetNextTone()
- {
- // This class only plays one tone for the specified duration
- if (!iPlayed)
- {
- iSamplesLeft = I64LOW((iDuration.Int64() * TInt64(iRate))/1000000);
- iSineWave.SetFrequency(iFrequency,1<<14);
- iPlayed = ETrue;
- iTrailingSilence = 20; // Just to stop clicking
- }
- return KErrNone;
- }
-
-//
-// TMdaDualToneGenerator
-//
-
-// -----------------------------------------------------------------------------
-// TMdaDualToneGenerator::Reset
-// ?implementation_description
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void TMdaDualToneGenerator::Reset()
- {
- iPlayed = EFalse;
- }
-
-// -----------------------------------------------------------------------------
-// TMdaDualToneGenerator::SetFrequencyAndDuration
-// Store the frequencies and duration of the specified dual tone
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void TMdaDualToneGenerator::SetFrequencyAndDuration(
- TInt aFrequencyOne,
- TInt aFrequencyTwo,
- const TTimeIntervalMicroSeconds& aDuration)
- {
-
- iFrequencyOne = aFrequencyOne;
- iFrequencyTwo = aFrequencyTwo;
- iDuration = aDuration;
- iPlayed = EFalse;
- }
-
-// -----------------------------------------------------------------------------
-// TMdaDualToneGenerator::GetNextTone
-// This is called by TMdaToneGenerator::FillBuffer()
-// to calculate the number of samples (iSamplesLeft) that will be needed
-// for the tone to be played and to initialize the sine wave generator.
-// If the tone has already been played, then leaves iSamplesLeft
-// unmodified (should be zero) to indicate that it has finished.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TInt TMdaDualToneGenerator::GetNextTone()
- {
- // This class only plays one tone for the specified duration
- if (!iPlayed)
- {
- iSamplesLeft = I64LOW((iDuration.Int64() * TInt64(iRate))/KOneMillionMicroSeconds);
- iSineWave.SetFrequency(iFrequencyOne, KMaxAmplitude/2, iFrequencyTwo, KMaxAmplitude/2);
- iPlayed = ETrue;
- iTrailingSilence = KDefaultTrailingSilenceSamples; // Just to stop clicking
- }
- return KErrNone;
- }
-
-//
-// TMdaDTMFGenerator
-//
-
-// -----------------------------------------------------------------------------
-// TMdaDTMFGenerator::Reset
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void TMdaDTMFGenerator::Reset()
- {
- iChar = 0;
- }
-
-// -----------------------------------------------------------------------------
-// TMdaDTMFGenerator::SetToneDurations
-// Setup the DTMF tone durations
-// aOn can be == -1 indicating should play first tone indefinately
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void TMdaDTMFGenerator::SetToneDurations(
- const TTimeIntervalMicroSeconds32 aOn,
- const TTimeIntervalMicroSeconds32 aOff,
- const TTimeIntervalMicroSeconds32 aPause)
- {
- ASSERT(aOn.Int() >=-1);
- ASSERT(aOff.Int()>=0);
- ASSERT(aPause.Int()>=0);
-
- iOn = aOn;
- iOff = aOff;
- iPause = aPause;
-
- iOnSamples = KRecalculateToneLengths; // Must recalculate these later
- }
-
-// -----------------------------------------------------------------------------
-// TMdaDTMFGenerator::SetString
-// Store the DTMF string to be played
-// No need to validate it as it will already have been checked
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void TMdaDTMFGenerator::SetString(
- const TDesC& aDTMFString)
- {
- iChar = 0;
- iDTMFString = &aDTMFString;
- }
-
-// -----------------------------------------------------------------------------
-// TMdaDTMFGenerator::GetNextTone
-// Setup frequency/duration/silence settings for next DTMF tone
-// Supported characters are 0-9 A-F * # , and any kind of white space
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TInt TMdaDTMFGenerator::GetNextTone()
- {
- TBool onlyPlayFirstTone = EFalse;
-
- if (iOnSamples == KRecalculateToneLengths)
- {
- // Must recalculate tone durations as samples
-
- // Handle special case where tone on duration negative
- // - meaning play first character indefinately
- if (iOn.Int()>=0)
- iOnSamples = DurationToSamples(TInt64(iOn.Int()));
- else
- {
- onlyPlayFirstTone = ETrue;
- iOnSamples = -1;
- }
-
- iOffSamples = DurationToSamples(TInt64(iOff.Int()));
- iPauseSamples = DurationToSamples(TInt64(iPause.Int()));
- }
-
- ASSERT(iDTMFString);
-
- if (iChar==iDTMFString->Length())
- return KErrNone; // Finished. Nothing to do
-
- TInt highFrequency = 0;
- TInt highVolume = 0;
- TInt lowFrequency = 0;
- TInt lowVolume =0;
-
-Retry:
- TChar c((*iDTMFString)[iChar++]);
- if ((TUint)c=='#' || (TUint)c=='*' || c.IsHexDigit())
- {
- TInt tableIndex;
- switch ((TUint)c)
- {
- case '*':
- tableIndex=14;
- break;
- case '#':
- tableIndex=15;
- break;
- default:
- if (c.IsDigit())
- tableIndex=(TUint)c-'0';
- else //letter
- {
- c.UpperCase();
- tableIndex=(TUint)c-'A'+10;
- }
- }
- TInt high=KDtmfToneTable[tableIndex]&0xf0;
- TInt low=KDtmfToneTable[tableIndex]&0x0f;
- switch(high)
- {
- case KDtmfTone1209:
- highFrequency=1209;
- break;
- case KDtmfTone1336:
- highFrequency=1336;
- break;
- case KDtmfTone1477:
- highFrequency=1477;
- break;
- default://KDtmfTone1633:
- highFrequency=1633;
- break;
- }
- switch(low)
- {
- case KDtmfTone697:
- lowFrequency=697;
- break;
- case KDtmfTone770:
- lowFrequency=770;
- break;
- case KDtmfTone852:
- lowFrequency=852;
- break;
- default://KDtmfTone941:
- lowFrequency=941;
- break;
- }
- high>>=4;
- const TUint8* dtmfVolumes=&KDtmfVolumeTable[0][0];
- TInt volume=dtmfVolumes[((low)<<2)+(high)]<<7;
- highVolume = volume;
- lowVolume = (1<<15)-volume;
-
- iTrailingSilence = iOffSamples;
- iSamplesLeft = iOnSamples;
- }
- else if ((TUint)c==',')
- {
- iTrailingSilence = iPauseSamples;
- iSamplesLeft = 0;
- }
- else if (c.IsSpace())
- {
- if (iChar < iDTMFString->Length())
- goto Retry;
- }
- else
- return KErrCorrupt;
-
- if (iOnSamples < 0) // Play only first character for ever
- {
- iTrailingSilence = 0;
- iSamplesLeft = iRate * iChannels; // One second of samples
- iChar = 0; // Reset so this character is played again next time
- iRampDown = EFalse;
- if (!onlyPlayFirstTone)
- {
- iRampUp = EFalse;
- // This is not the first time around so we should not
- // reset the tone generator - it will already have the
- // correct settings and setting them again would cause
- // an audible discontinuity
- return KErrNone;
- }
- }
-
- iSineWave.SetFrequency(highFrequency,highVolume,lowFrequency,lowVolume);
- return KErrNone;
- }
-
-//
-// TMdaSequenceGenerator
-//
-
-
-// -----------------------------------------------------------------------------
-// void TMdaSequenceGenerator::Reset()
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void TMdaSequenceGenerator::Reset()
- {
- iInstructionPtr = REINTERPRET_CAST(const TInt16*,&((*iSequenceData)[0]));
- iInstructionPtr += 2; // Skip signature
- iStackIndex = 0;
- }
-
-// -----------------------------------------------------------------------------
-// TMdaSequenceGenerator::SetSequenceData
-// Store the sequence data to be played
-// No need to validate it as it will already have been checked
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void TMdaSequenceGenerator::SetSequenceData(
- const TDesC8& aSequenceData)
- {
- iSequenceData = &aSequenceData;
- iInstructionPtr = REINTERPRET_CAST(const TInt16*,&aSequenceData[0]);
- iLastInstruction = iInstructionPtr + (iSequenceData->Length()>>1) - 1;
-
- // These are asserts because this should not be called if signature not present
- ASSERT(*iInstructionPtr == KFixedSequenceSignatureOne);
- ASSERT(*(iInstructionPtr+1) == KFixedSequenceSignatureTwo);
-
- iInstructionPtr += 2; // Skip signature
-
- iStackIndex = 0;
- }
-
-// -----------------------------------------------------------------------------
-// TMdaSequenceGenerator::GetNextTone
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TInt TMdaSequenceGenerator::GetNextTone()
- {
- ASSERT(iInstructionPtr); // Sanity check
-
- TInt ret = KRequestPending;
- while (ret == KRequestPending)
- {
- if (iInstructionPtr > iLastInstruction)
- ret = KErrCorrupt;
- else if (*iInstructionPtr<=0)
- {
- switch (*iInstructionPtr)
- {
- case KFixedSequenceFunctionReturn: // End of sequence
- ret = KErrNone;
- break;
-
- case KFixedSequenceFunctionStartLoop:
- if (iStackIndex>2) // Validate - can only nest twice
- ret = KErrCorrupt;
- else if ((iInstructionPtr+2) > iLastInstruction)
- ret = KErrCorrupt; // Don't run off end of sequence
- else
- {
- iStack[iStackIndex++]=(TInt)(iInstructionPtr+2);
- iStack[iStackIndex++]=(TInt)*(iInstructionPtr+1);
- iInstructionPtr+=2;
- }
- break;
-
- case KFixedSequenceFunctionEndLoop:
- if (iStackIndex==0) // Validate - must already be nested
- ret = KErrCorrupt;
- else
- {
- if ((--iStack[iStackIndex-1])!=0)
- iInstructionPtr=(TInt16*)iStack[iStackIndex-2];
- else
- {
- iStackIndex-=2;
- iInstructionPtr++;
- }
- }
- break;
-
- default: // Bad sequence
- ret = KErrCorrupt;
- }
- }
- else
- {
- if ((iInstructionPtr+5) > iLastInstruction)
- ret = KErrCorrupt; // Don't run off end of sequence
- else
- {
- iSamplesLeft = *iInstructionPtr++;
- TInt freqOne = *iInstructionPtr++;
- TInt volOne = *iInstructionPtr++;
- TInt freqTwo = *iInstructionPtr++;
- TInt volTwo = *iInstructionPtr++;
-
- if ((volOne> 1<<15)||(volTwo > 1<<15))
- ret = KErrCorrupt;
- else
- {
- iSineWave.SetFrequency(freqOne,volOne,freqTwo,volTwo);
- ret = KErrNone;
- }
- }
- }
- }
- return ret;
- }
-
-// End of File