Marmalade SDKСтатьи

Проигрываем WAV файл средствами s3eSound

Автор:

Проигрываем WAV файл средствами s3eSound


Android_Icon_170x170_0 | Проигрываем WAV файл средствами s3eSound

чтобы проиграть звуковой семпл функцией  s3eSoundChannelPlay требуется подготовить ей "чистые" RAW данные.
и выставить каналу "правильный" S3E_SOUND_DEFAULT_FREQ.
из минусов - звук должен быть 16 битный и строго МОНО.


все необходимое мы получим из заголовка WAV файла.


нам потребуется две структуры:
typedef struct
{
char rID[4];      // 'RIFF'
long int rLen;
char wID[4];      // 'WAVE'
char fId[4];      // 'fmt'
long int pcmHeaderLength;
short int wFormatTag;
short int numChannels;
long int nSamplesPerSec;
long int nAvgBytesPerSec;
short int numBlockAlingn;
short int numBitsPerSample;
}
WAV_HDR;
typedef struct
{
char dId[4];  // 'data' or 'fact'
long int dLen;
} CHUNK_HDR;


загрузка и парсинг показаны в следукющей функции

int WavFile::openWavFile(char* fileName)
{

    pFile = fopen( fileName, "rb");
    if(pFile == NULL)
    {
        printf("Can't open wav file.");
         return false;
    }

    /* read riff/wav header */ 
    stat = fread((void*) &m_WavHeader, sizeof(WAV_HDR), (size_t)1, pFile);
    if(stat != 1)
    {
        printf("Header missing. May be format is not OK!\n"); // This is tested.
         return false;
    }

    /* check format of header */
    for(i = 0; i < 4; i++)
        outBuffer[i] = m_WavHeader.rID[i];
  
    outBuffer[4] = 0;

    if(strcmp(outBuffer, "RIFF") != 0) // tested.
    {
        printf("\nBad RIFF format. I am not cool enough to support everything");
        printf("\nyou provide us with! Give me a good file.");
         return false;
    }

    for(i = 0; i < 4; i++)
        outBuffer[i] = m_WavHeader.wID[i];

    outBuffer[4] = 0;


    if(strcmp(outBuffer, "WAVE") != 0) // tested.
    {
        printf("\nBad WAVE format");
         return false;
    }

    for(i = 0; i < 4; i++)
        outBuffer[i] = m_WavHeader.fId[i];

    outBuffer[4] = 0;


    if( strcmp(outBuffer, "fmt ") != 0)  // not with "fmt" since 4th pos is blank
    {
        printf("\nBad fmt format");
         return false;
    }

    if( m_WavHeader.wFormatTag != 1 )
    {
        printf("\n Bad wav wFormatTag");
         return false;
    }

    if( ( m_WavHeader.numBitsPerSample != 16 ) && ( m_WavHeader.numBitsPerSample != 8 ))
    {
        printf("\nBad wav bits per sample");
        return false;
    }


    rMore = m_WavHeader.pcmHeaderLength - (sizeof(WAV_HDR) - 20);
    if( 0 != fseek(pFile, rMore, SEEK_CUR))
    {
        printf("Can't seek.");
    }


    sFlag = 1;
    while(sFlag != 0)
    {
        // check attempts.
        if(sFlag > 10) 
        { 
                printf("\nToo manu chunks"); 
                return false;
        }

        // read chunk header
        stat = fread((void*)&m_ChunkHeader, sizeof(CHUNK_HDR), (size_t)1, pFile);
        if( 1 != stat)
        {
            printf("\n I just can't read data. Sorry!");
            return false;
        }

        // check chunk type.
        for(i =0; i < 4; i++)        
            outBuffer[i] = m_ChunkHeader.dId[i];
        
        outBuffer[4] = 0;
        if(strcmp(outBuffer, "data") == 0)  
                break;

        // skip over chunk.
        sFlag++;
        stat = fseek(pFile, m_ChunkHeader.dLen, SEEK_CUR);
        if(stat != 0)
        {
            printf("Can't seek.");
            return false;
        }

    }

    /* find length of `RAW` data. */
    m_FileSize = m_ChunkHeader.dLen;
    m_SoundData = new char[ m_FileSize ] ;
    if( m_SoundData == NULL)
    {
        printf("\nCan't allocate."); 
        return false;
    }

    int succ = fread((void*)m_SoundData, m_FileSize, (size_t)1, pFile);
    if( 1 != succ )
    {
        printf("\nCan't read buffer.");
        return false;
    }

    if( -1 == m_Channel )
    {
        m_Channel = s3eSoundGetFreeChannel();
    
        s3eSoundChannelRegister(m_Channel, S3E_CHANNEL_END_SAMPLE, &onEndOfSample, this );
        s3eSoundSetInt( S3E_SOUND_DEFAULT_FREQ, mWavHeader.nSamplesPerSec );
    }

   if( 8 == m_WavHeader.numBitsPerSample )
    decodeToWav16( m_SoundData, m_FileSize );

    s3eSoundChannelPlay(m_Channel, (int16 *)m_SoundData, m_FileSize/2, true == loop ? 0 : 1, 0);

   return true;
}

ну как то так. как остановить звук и выгрузить хорошо показано в примерах к SDK\nToo manu chunksправильный

decodeToWav16 - функция декодирует в 16 битный wav поскольку мармелад не умеет проигрывать 8 битные звуки.
к тому же звук должен быть строго МОНО - если у вас стерео то требуется отризать вторую дорожку или шаманить с калбеками.

надеюсь я решу эту проблему и будет полноценное стерео.
код выложу тогда позже.

19 июня 2012 (Обновление: 23 июня 2012)

Комментарии [11]