/*
* Wave file structure: Riff header + Wave format chunk + Wave data chunk
* 
* Riff header:
* ==================================================
* Offset Size Description      Value
* 0x00      4 Chunk ID         "RIFF"
* 0x04      4 Chunk Data Size  ( file size ) - 8
* 0x08      4 RIFF Type        "WAVE"
* 0x0c      *  Wave chunks *
*
* Wave Format Chunk:
* ==================================================
* Offset Size Description      Value
* 0x00      4 Chunk ID         "fmt "
* 0x04      4 Chunk Data Size  16 + extra format bytes ( 0 for normal wav files)
* 0x08      2 Compression code 1...65535               ( 1 for PCM uncompressed)
* 0x0a      2 Nbr of channels  1...65535
* 0x0c      4 Sample rate      1...0xFFFFFFFF
* 0x10      4 Average bytes per sec
* 0x14      2 block align
* 0x16      2 siginificant bits per sample
* 0x18      2 extra format bytes 0...65535
* 0x1a        * extra format bytes, if any *
*
* Wave Data Chunk:
* ==================================================
* Offset Size Description      Value
* 0x00      4 Chunk ID         "data"
* 0x04      4 Chunk data size  
* 0x08        * sample data *
*
*/
void CTactileAudioPlayer::ReadSampleL( RFile& aFile, 
                                       HBufC8*& aDes, 
                                       TUint& aChannels, 
                                       TUint& aSampleRate )
    {
    TRACE("CTactileAudioPlayer::ReadSampleL - Start");
    const TInt fmtOffset  = 0x0c;
    const TInt dataOffset = fmtOffset + 0x18;
    
    TBuf8<KRiffHeaderSize> header;
    TInt err = aFile.Read( header, KRiffHeaderSize );
    if ( err )
        {
        TRACE("CTactileAudioPlayer::ReadSampleL: reading from file failed, aborting");
        User::Leave( err );
        }

    TPtr8 p = header.LeftTPtr( 4 );
    
    if ( p.Compare( KRiff ) )
        {
        TRACE("CTactileAudioPlayer::ReadSampleL: no RIFF header found, aborting" );
        User::Leave( KErrCorrupt );
        }

    p = header.MidTPtr( 0x08, 4 );
    if ( p.Compare( KWave ) )
        {
        TRACE("CTactileAudioPlayer::ReadSampleL:  not a WAVE file, aborting" );
        User::Leave( KErrCorrupt );
        }

    p = header.MidTPtr( fmtOffset + 0x00, 4 );
    if ( p.Compare( KFmt ) )
        {
        TRACE("CTactileAudioPlayer::ReadSampleL:  no 'fmt ' chunk found, aborting" );
        User::Leave( KErrCorrupt );
        }

    p = header.MidTPtr( dataOffset, 4 );
    if ( p.Compare( KData ) )
        {
        TRACE("CTactileAudioPlayer::ReadSampleL:  no 'data' chunk found, aborting" );
        User::Leave( KErrCorrupt );
        }

    TUint8 lo = header[ fmtOffset + 0x08 ];
    TUint8 hi = header[ fmtOffset + 0x08 + 1 ];
    if ( !( lo == 1 && hi == 0) )
        {
        TRACE("CTactileAudioPlayer::ReadSampleL: non PCM wav not supported, aborting" );
        User::Leave( KErrNotSupported );
        }

    lo = header[ fmtOffset + 0x0a ];
    hi = header[ fmtOffset + 0x0a + 1 ];
    aChannels = lo;
    if ( !(aChannels == 1 || aChannels == 2 && hi == 0) )
        {
        TRACE2("CTactileAudioPlayer::ReadSampleL: unsupported number of channels ( %d ), aborting", aChannels );
        User::Leave( KErrNotSupported );
        }

    aSampleRate = 0;
    for ( TInt i = 0; i < 4; i++ )
        {
        lo = header[ fmtOffset + 0x0c + i ];
        TUint32 tmp = lo;
        tmp = tmp << i * 8;

        aSampleRate = aSampleRate | tmp;
        }

    lo = header[ fmtOffset + 0x16 ];
    hi = header[ fmtOffset + 0x16 + 1 ];
    TUint16 bitsPerSample = hi;
    bitsPerSample = bitsPerSample << 8;
    bitsPerSample = bitsPerSample | lo;

    if ( bitsPerSample != 16 )
        {
        TRACE2("CTactileAudioPlayer::ReadSampleL:  %d bits per sample not supported", bitsPerSample );
        User::Leave( KErrNotSupported );
        }

    TUint32 bytesPerSample = bitsPerSample / 8;
    
    // how many bytes for 6 ms
    TUint bytesNeeded = ( aSampleRate * aChannels * bytesPerSample * 6 ) / 1000;

    TInt fsize( 0 );
    if ( aFile.Size( fsize ) == KErrNone && fsize >= bytesNeeded + KRiffHeaderSize )
        {
        aDes = HBufC8::NewL( bytesNeeded );
        TPtr8 des = aDes->Des();
        aFile.Read( des, bytesNeeded );
        }
    else
        {
        TRACE("CTactileAudioPlayer::ReadSampleL: Less than 6ms content in file, aborting" );
        User::Leave( KErrNotSupported );
        }

    TRACE3("CTactileAudioPlayer::ReadSampleL %dHz %dchannel sample read successfully - End", 
        iSampleRate, iChannels);
    }