修正後 修正前オリジナル
   
// //
//      MMMAN : Multimedia manager source //      MMMAN : Multimedia manager source
//              for OpenSL/ES enviroment //              for OpenSL/ES enviroment
//              onion software/onitama 2012/6 //              onion software/onitama 2012/6
// //
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
.#include <unistd.h>  
#include "../../hsp3/hsp3config.h" #include "../../hsp3/hsp3config.h"
#include "../../hsp3/dpmread.h" #include "../../hsp3/dpmread.h"
#include "../../hsp3/strbuf.h" #include "../../hsp3/strbuf.h"
#include "../supio.h" #include "../supio.h"
#include "../../javafunc.h" #include "../../javafunc.h"
   
#include <android/asset_manager.h> #include <android/asset_manager.h>
#include <android/asset_manager_jni.h> #include <android/asset_manager_jni.h>
   
#include "mmman.h" #include "mmman.h"
   
#define sndbank(a) (char *)(mem_snd[a].mempt) #define sndbank(a) (char *)(mem_snd[a].mempt)
   
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
   
//  MMDATA structure //  MMDATA structure
// //
typedef struct MMM typedef struct MMM
{ {
    //  Multimedia Data structure     //  Multimedia Data structure
    //     //
    int        flag;           //  bank mode (0=none/1=wav/2=mid/3=cd/4=avi)     int        flag;           //  bank mode (0=none/1=wav/2=mid/3=cd/4=avi)
    int        opt;           //  option (0=none/1=loop/2=wait/16=fullscr)     int        opt;           //  option (0=none/1=loop/2=wait/16=fullscr)
    int        num;           //  request number     int        num;           //  request number
    short    track;           //  CD track No.     short    track;           //  CD track No.
    short    lasttrk;       //  CD last track No.     short    lasttrk;       //  CD last track No.
    void    *mempt;           //  pointer to sound data     void    *mempt;           //  pointer to sound data
    char    *fname;           //  sound filename (sbstr)     char    *fname;           //  sound filename (sbstr)
    int        vol;     int        vol;
    int        pan;     int        pan;
   
    //  OpenSL/ES Objects     //  OpenSL/ES Objects
    //     //
    SLObjectItf   playerObject;     SLObjectItf   playerObject;
    SLPlayItf     playerPlay;     SLPlayItf     playerPlay;
    SLSeekItf     playerSeek;     SLSeekItf     playerSeek;
    SLVolumeItf   playerVolume;     SLVolumeItf   playerVolume;
.    SLPrefetchStatusItf    prefetchItf;  
   
    //  FileDescriptor  
    //  
    int fd;  
   
    //  
    //  
    int pause_flag;     int pause_flag;
   
} MMM; } MMM;
   
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
.class FileDescriptor {  
public:  
    explicit FileDescriptor(int fd) : m_fd(fd) {}  
    ~FileDescriptor() {  
        if (m_fd >= 0) close(m_fd);  
    }  
   
    // Prohibition of copying and moving  
    FileDescriptor(const FileDescriptor&) = delete;  
    FileDescriptor& operator=(const FileDescriptor&) = delete;  
   
    // Relinquish ownership of file descriptors  
    int release() {  
        int fd = m_fd;  
        m_fd = -1;  // renunciation of ownership  
        return fd;  
    }  
   
    // Get file descriptor  
    int get() const { return m_fd; }  
   
private:  
    int m_fd;  
};  
//---------------------------------------------------------------------------  
   
MMMan::MMMan() MMMan::MMMan()
{ {
    //      initalize MM manager     //      initalize MM manager
    //     //
    mem_snd = NULL;     mem_snd = NULL;
    mm_cur = 0;     mm_cur = 0;
    engine_flag = 0;     engine_flag = 0;
   
    SLresult result;     SLresult result;
   
    // create engine     // create engine
    const SLInterfaceID engine_ids[] = {SL_IID_ENGINE};     const SLInterfaceID engine_ids[] = {SL_IID_ENGINE};
    const SLboolean engine_req[] = {SL_BOOLEAN_TRUE};     const SLboolean engine_req[] = {SL_BOOLEAN_TRUE};
    result = slCreateEngine(&engineObject, 0, NULL, 1, engine_ids, engine_req);     result = slCreateEngine(&engineObject, 0, NULL, 1, engine_ids, engine_req);
    if (SL_RESULT_SUCCESS != result) {     if (SL_RESULT_SUCCESS != result) {
        return;         return;
    }     }
    // realize the engine     // realize the engine
    result = (*this->engineObject)->Realize(this->engineObject, SL_BOOLEAN_FALSE);     result = (*this->engineObject)->Realize(this->engineObject, SL_BOOLEAN_FALSE);
    if (SL_RESULT_SUCCESS != result) {     if (SL_RESULT_SUCCESS != result) {
        return;         return;
    }     }
    // get the engine interface, which is needed in order to create other objects     // get the engine interface, which is needed in order to create other objects
    result = (*this->engineObject)->GetInterface(this->engineObject, SL_IID_ENGINE, &this->engineEngine);     result = (*this->engineObject)->GetInterface(this->engineObject, SL_IID_ENGINE, &this->engineEngine);
    if (SL_RESULT_SUCCESS != result) {     if (SL_RESULT_SUCCESS != result) {
        return;         return;
    }     }
    // create output mix     // create output mix
    const SLInterfaceID mix_ids[1] = {SL_IID_VOLUME};     const SLInterfaceID mix_ids[1] = {SL_IID_VOLUME};
    const SLboolean mix_req[1] = {SL_BOOLEAN_TRUE};     const SLboolean mix_req[1] = {SL_BOOLEAN_TRUE};
    result = (*this->engineEngine)->CreateOutputMix(this->engineEngine, &this->outputMixObject, 0, mix_ids, mix_req);     result = (*this->engineEngine)->CreateOutputMix(this->engineEngine, &this->outputMixObject, 0, mix_ids, mix_req);
    if (SL_RESULT_SUCCESS != result) {     if (SL_RESULT_SUCCESS != result) {
        return;         return;
    }     }
    // realize the output mix     // realize the output mix
    result = (*this->outputMixObject)->Realize(this->outputMixObject, SL_BOOLEAN_FALSE);     result = (*this->outputMixObject)->Realize(this->outputMixObject, SL_BOOLEAN_FALSE);
    if (SL_RESULT_SUCCESS != result) {     if (SL_RESULT_SUCCESS != result) {
        return;         return;
    }     }
   
    engine_flag = 1;     engine_flag = 1;
    //Alertf( "[MMMan Ready]" );     //Alertf( "[MMMan Ready]" );
} }
   
   
MMMan::~MMMan() MMMan::~MMMan()
{ {
    //      terminate MM manager     //      terminate MM manager
    //     //
    ClearAllBank();     ClearAllBank();
   
    if ( engine_flag ) {     if ( engine_flag ) {
        (*this->outputMixObject)->Destroy(this->outputMixObject);         (*this->outputMixObject)->Destroy(this->outputMixObject);
        (*this->engineObject)->Destroy(this->engineObject);         (*this->engineObject)->Destroy(this->engineObject);
    }     }
} }
   
void MMMan::DeleteBank( int bank ) void MMMan::DeleteBank( int bank )
{ {
    MMM *m;     MMM *m;
    char *lpSnd;     char *lpSnd;
   
    m = &(mem_snd[bank]);     m = &(mem_snd[bank]);
    if ( m->flag == MMDATA_INTWAVE ) {     if ( m->flag == MMDATA_INTWAVE ) {
            StopBank( m );             StopBank( m );
            (*m->playerObject)->Destroy(m->playerObject);             (*m->playerObject)->Destroy(m->playerObject);
.   
            // Close file descriptor  
            if ( m->fd >= 0) {  
                close(m->fd);  
                m->fd = -1;  
            }  
    }     }
    lpSnd = sndbank( bank );     lpSnd = sndbank( bank );
    if ( lpSnd != NULL ) {     if ( lpSnd != NULL ) {
        free( lpSnd );         free( lpSnd );
    }     }
    mem_snd[bank].mempt=NULL;     mem_snd[bank].mempt=NULL;
} }
   
   
SLuint32 MMMan::GetState( MMM *mmm ) SLuint32 MMMan::GetState( MMM *mmm )
{ {
    SLuint32 state;     SLuint32 state;
    (*mmm->playerPlay)->GetPlayState(mmm->playerPlay, &state);     (*mmm->playerPlay)->GetPlayState(mmm->playerPlay, &state);
    return state;     return state;
} }
   
   
void MMMan::SetState( MMM *mmm, SLuint32 state ) void MMMan::SetState( MMM *mmm, SLuint32 state )
{ {
    (*mmm->playerPlay)->SetPlayState(mmm->playerPlay, state);     (*mmm->playerPlay)->SetPlayState(mmm->playerPlay, state);
.   
    SLresult result;  
    SLuint32 playState;  
   
    do  
    {  
        // get current status  
        result = (*mmm->playerPlay)->GetPlayState(mmm->playerPlay, &playState);  
        if (result != SL_RESULT_SUCCESS)  
        {  
            break;  
        }  
   
        // wait  
        usleep(100 * 10);  // 10ms  
    } while (playState != state);  
   
} }
   
   
int MMMan::AllocBank( void ) int MMMan::AllocBank( void )
{ {
    int ids,sz;     int ids,sz;
   
    if ( engine_flag == 0 ) return -1;     if ( engine_flag == 0 ) return -1;
   
    ids = mm_cur++;     ids = mm_cur++;
    sz = mm_cur * sizeof(MMM);     sz = mm_cur * sizeof(MMM);
    if ( mem_snd == NULL ) {     if ( mem_snd == NULL ) {
        mem_snd = (MMM *)sbAlloc( sz );         mem_snd = (MMM *)sbAlloc( sz );
    } else {     } else {
        mem_snd = (MMM *)sbExpand( (char *)mem_snd, sz );         mem_snd = (MMM *)sbExpand( (char *)mem_snd, sz );
    }     }
    mem_snd[ids].flag = MMDATA_NONE;     mem_snd[ids].flag = MMDATA_NONE;
    mem_snd[ids].num = -1;     mem_snd[ids].num = -1;
    return ids;     return ids;
} }
   
   
int MMMan::SearchBank( int num ) int MMMan::SearchBank( int num )
{ {
    int a;     int a;
    for(a=0;a<mm_cur;a++) {     for(a=0;a<mm_cur;a++) {
        if ( mem_snd[a].num == num ) return a;         if ( mem_snd[a].num == num ) return a;
    }     }
    return -1;     return -1;
} }
   
   
MMM *MMMan::SetBank( int num, int flag, int opt, void *mempt, char *fname ) MMM *MMMan::SetBank( int num, int flag, int opt, void *mempt, char *fname )
{ {
    int bank;     int bank;
    MMM *m;     MMM *m;
   
    bank = SearchBank( num );     bank = SearchBank( num );
    if ( bank < 0 ) {     if ( bank < 0 ) {
        bank = AllocBank();         bank = AllocBank();
    } else {     } else {
        DeleteBank( bank );         DeleteBank( bank );
    }     }
   
    if ( bank < 0 ) return NULL;     if ( bank < 0 ) return NULL;
   
    m = &(mem_snd[bank]);     m = &(mem_snd[bank]);
    m->flag = flag;     m->flag = flag;
    m->opt = opt;     m->opt = opt;
    m->num = num;     m->num = num;
    m->mempt = mempt;     m->mempt = mempt;
    m->fname = NULL;     m->fname = NULL;
    m->pause_flag = 0;     m->pause_flag = 0;
    m->vol = 0;     m->vol = 0;
    m->pan = 0;     m->pan = 0;
.    m->fd = -1;  
    return m;     return m;
} }
   
   
void MMMan::ClearAllBank( void ) void MMMan::ClearAllBank( void )
{ {
    int a;     int a;
    if ( mem_snd != NULL ) {     if ( mem_snd != NULL ) {
        Stop();         Stop();
        for(a=0;a<mm_cur;a++) {         for(a=0;a<mm_cur;a++) {
            DeleteBank( a );             DeleteBank( a );
        }         }
        sbFree( mem_snd );         sbFree( mem_snd );
        mem_snd = NULL;         mem_snd = NULL;
        mm_cur = 0;         mm_cur = 0;
    }     }
} }
   
   
void MMMan::Reset( void *hwnd ) void MMMan::Reset( void *hwnd )
{ {
    ClearAllBank();     ClearAllBank();
    //hwm = hwnd;     //hwm = hwnd;
    //avi_wnd = hwnd;     //avi_wnd = hwnd;
    //curmus=-1;     //curmus=-1;
} }
   
   
void MMMan::SetWindow( void *hwnd, int x, int y, int sx, int sy ) void MMMan::SetWindow( void *hwnd, int x, int y, int sx, int sy )
{ {
} }
   
   
void MMMan::Pause( void ) void MMMan::Pause( void )
{ {
    //      pause all playing sounds     //      pause all playing sounds
    //     //
    MMM *m;     MMM *m;
    int a;     int a;
    m = &(mem_snd[0]);     m = &(mem_snd[0]);
    for(a=0;a<mm_cur;a++) {     for(a=0;a<mm_cur;a++) {
        PauseBank( m );         PauseBank( m );
        m++;         m++;
    }     }
} }
   
   
void MMMan::Resume( void ) void MMMan::Resume( void )
{ {
    //      resume all playing sounds     //      resume all playing sounds
    //     //
    MMM *m;     MMM *m;
    int a;     int a;
    m = &(mem_snd[0]);     m = &(mem_snd[0]);
    for(a=0;a<mm_cur;a++) {     for(a=0;a<mm_cur;a++) {
        ResumeBank( m );         ResumeBank( m );
        m++;         m++;
    }     }
} }
   
   
void MMMan::Stop( void ) void MMMan::Stop( void )
{ {
    //      stop all playing sounds     //      stop all playing sounds
    //     //
    MMM *m;     MMM *m;
    int a;     int a;
    m = &(mem_snd[0]);     m = &(mem_snd[0]);
    for(a=0;a<mm_cur;a++) {     for(a=0;a<mm_cur;a++) {
        StopBank( m );         StopBank( m );
        m++;         m++;
    }     }
} }
   
   
void MMMan::StopBank( MMM *mmm ) void MMMan::StopBank( MMM *mmm )
{ {
    if ( mmm == NULL ) return;     if ( mmm == NULL ) return;
    SetState( mmm, SL_PLAYSTATE_STOPPED );     SetState( mmm, SL_PLAYSTATE_STOPPED );
    mmm->pause_flag = 0;     mmm->pause_flag = 0;
} }
   
   
void MMMan::PauseBank( MMM *mmm ) void MMMan::PauseBank( MMM *mmm )
{ {
    if ( mmm == NULL ) return;     if ( mmm == NULL ) return;
    if ( GetState(mmm) == SL_PLAYSTATE_PLAYING ) {     if ( GetState(mmm) == SL_PLAYSTATE_PLAYING ) {
        SetState( mmm, SL_PLAYSTATE_PAUSED );         SetState( mmm, SL_PLAYSTATE_PAUSED );
        mmm->pause_flag = 1;         mmm->pause_flag = 1;
    }     }
} }
   
   
void MMMan::ResumeBank( MMM *mmm ) void MMMan::ResumeBank( MMM *mmm )
{ {
    if ( mmm == NULL ) return;     if ( mmm == NULL ) return;
    if ( mmm->pause_flag ) {     if ( mmm->pause_flag ) {
        SetState( mmm, SL_PLAYSTATE_PLAYING );         SetState( mmm, SL_PLAYSTATE_PLAYING );
        mmm->pause_flag = 0;         mmm->pause_flag = 0;
    }     }
} }
   
   
void MMMan::PlayBank( MMM *mmm ) void MMMan::PlayBank( MMM *mmm )
{ {
    if ( mmm == NULL ) return;     if ( mmm == NULL ) return;
    SetState( mmm, SL_PLAYSTATE_STOPPED );     SetState( mmm, SL_PLAYSTATE_STOPPED );
    SeekBank( mmm,  0, SL_SEEKMODE_FAST );     SeekBank( mmm,  0, SL_SEEKMODE_FAST );
    SetState( mmm, SL_PLAYSTATE_PLAYING );     SetState( mmm, SL_PLAYSTATE_PLAYING );
    mmm->pause_flag = 0;     mmm->pause_flag = 0;
} }
   
   
void MMMan::SetLoopBank( MMM *mmm, int flag ) void MMMan::SetLoopBank( MMM *mmm, int flag )
{ {
    if ( mmm == NULL ) return;     if ( mmm == NULL ) return;
    if (flag) {     if (flag) {
        (*mmm->playerSeek)->SetLoop(mmm->playerSeek, SL_BOOLEAN_TRUE, 0, SL_TIME_UNKNOWN);         (*mmm->playerSeek)->SetLoop(mmm->playerSeek, SL_BOOLEAN_TRUE, 0, SL_TIME_UNKNOWN);
    } else {     } else {
        (*mmm->playerSeek)->SetLoop(mmm->playerSeek, SL_BOOLEAN_FALSE, 0, SL_TIME_UNKNOWN);         (*mmm->playerSeek)->SetLoop(mmm->playerSeek, SL_BOOLEAN_FALSE, 0, SL_TIME_UNKNOWN);
    }     }
} }
   
   
void MMMan::SeekBank( MMM *mmm, int pos, SLuint32 seekMode ) void MMMan::SeekBank( MMM *mmm, int pos, SLuint32 seekMode )
{ {
    if ( mmm == NULL ) return;     if ( mmm == NULL ) return;
    (*mmm->playerSeek)->SetPosition(mmm->playerSeek, pos, seekMode);     (*mmm->playerSeek)->SetPosition(mmm->playerSeek, pos, seekMode);
} }
   
   
int MMMan::BankLoad( MMM *mmm, char *fname ) int MMMan::BankLoad( MMM *mmm, char *fname )
{ {
    SLresult result;     SLresult result;
    struct engine *en;     struct engine *en;
   
    if ( mmm == NULL ) return -9;     if ( mmm == NULL ) return -9;
   
    en = javafunc_engine();     en = javafunc_engine();
    //Alertf( "[MMMan] Start Loading %s [%x]",fname, en );     //Alertf( "[MMMan] Start Loading %s [%x]",fname, en );
   
    AAssetManager* mgr = en->app->activity->assetManager;     AAssetManager* mgr = en->app->activity->assetManager;
    if (mgr == NULL) return -1;     if (mgr == NULL) return -1;
   
    AAsset* asset = AAssetManager_open(mgr, fname, AASSET_MODE_UNKNOWN);     AAsset* asset = AAssetManager_open(mgr, fname, AASSET_MODE_UNKNOWN);
    if (asset == NULL) return -2;     if (asset == NULL) return -2;
   
    // open asset as file descriptor     // open asset as file descriptor
    off_t start, length;     off_t start, length;
    int fd = AAsset_openFileDescriptor(asset, &start, &length);     int fd = AAsset_openFileDescriptor(asset, &start, &length);
.    AAsset_close(asset);  
    if (fd < 0) return -3;     if (fd < 0) return -3;
.      AAsset_close(asset);
    FileDescriptor fdWrapper(fd);  
   
    // configure audio source     // configure audio source
    SLDataLocator_AndroidFD loc_fd = {SL_DATALOCATOR_ANDROIDFD, fd, start, length};     SLDataLocator_AndroidFD loc_fd = {SL_DATALOCATOR_ANDROIDFD, fd, start, length};
    SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};     SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
    SLDataSource audioSrc = {&loc_fd, &format_mime};     SLDataSource audioSrc = {&loc_fd, &format_mime};
   
    // configure audio sink     // configure audio sink
    SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, this->outputMixObject};     SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, this->outputMixObject};
    SLDataSink audioSnk = {&loc_outmix, NULL};     SLDataSink audioSnk = {&loc_outmix, NULL};
   
    // create audio player     // create audio player
.    const SLInterfaceID player_ids[4] = {SL_IID_PLAY, SL_IID_VOLUME, SL_IID_SEEK, SL_IID_PREFETCHSTATUS};     const SLInterfaceID player_ids[3] = {SL_IID_PLAY, SL_IID_VOLUME, SL_IID_SEEK};
    const SLboolean player_req[4] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};     const SLboolean player_req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    result = (*engineEngine)->CreateAudioPlayer(this->engineEngine, &mmm->playerObject, &audioSrc, &audioSnk,     result = (*engineEngine)->CreateAudioPlayer(this->engineEngine, &mmm->playerObject, &audioSrc, &audioSnk,
.            4, player_ids, player_req);             3, player_ids, player_req);
    if (SL_RESULT_SUCCESS != result) return -4;     if (SL_RESULT_SUCCESS != result) return -4;
   
    // realize the player     // realize the player
    result = (*mmm->playerObject)->Realize(mmm->playerObject, SL_BOOLEAN_FALSE);     result = (*mmm->playerObject)->Realize(mmm->playerObject, SL_BOOLEAN_FALSE);
    if (SL_RESULT_SUCCESS != result) return -5;     if (SL_RESULT_SUCCESS != result) return -5;
   
    // get the play interface     // get the play interface
    result = (*mmm->playerObject)->GetInterface(mmm->playerObject, SL_IID_PLAY, &mmm->playerPlay);     result = (*mmm->playerObject)->GetInterface(mmm->playerObject, SL_IID_PLAY, &mmm->playerPlay);
    if (SL_RESULT_SUCCESS != result) return -6;     if (SL_RESULT_SUCCESS != result) return -6;
    // get the seek interface     // get the seek interface
    result = (*mmm->playerObject)->GetInterface(mmm->playerObject, SL_IID_SEEK, &mmm->playerSeek);     result = (*mmm->playerObject)->GetInterface(mmm->playerObject, SL_IID_SEEK, &mmm->playerSeek);
    if (SL_RESULT_SUCCESS != result) return -7;     if (SL_RESULT_SUCCESS != result) return -7;
    // the volume interface     // the volume interface
    result = (*mmm->playerObject)->GetInterface(mmm->playerObject, SL_IID_VOLUME, &mmm->playerVolume);     result = (*mmm->playerObject)->GetInterface(mmm->playerObject, SL_IID_VOLUME, &mmm->playerVolume);
    if (SL_RESULT_SUCCESS != result) return -8;     if (SL_RESULT_SUCCESS != result) return -8;
   
.    result = (*mmm->playerObject)->GetInterface(mmm->playerObject, SL_IID_PREFETCHSTATUS, &mmm->prefetchItf);  
    if (SL_RESULT_SUCCESS != result) return -9;  
   
    (*mmm->playerSeek)->SetPosition(mmm->playerSeek, 0, SL_SEEKMODE_FAST);     (*mmm->playerSeek)->SetPosition(mmm->playerSeek, 0, SL_SEEKMODE_FAST);
    (*mmm->playerPlay)->SetPlayState(mmm->playerPlay, SL_PLAYSTATE_PAUSED);     (*mmm->playerPlay)->SetPlayState(mmm->playerPlay, SL_PLAYSTATE_PAUSED);
.   
    SLuint32 prefetchStatus = SL_PREFETCHSTATUS_UNDERFLOW;  
    while (prefetchStatus != SL_PREFETCHSTATUS_SUFFICIENTDATA)  
    {  
        usleep(100 * 10);  // wait 10ms  
        result = (*mmm->prefetchItf)->GetPrefetchStatus(mmm->prefetchItf, &prefetchStatus);  
        if (SL_RESULT_SUCCESS != result) return -10;  
    }  
   
    (*mmm->playerPlay)->SetPlayState(mmm->playerPlay, SL_PLAYSTATE_STOPPED);     (*mmm->playerPlay)->SetPlayState(mmm->playerPlay, SL_PLAYSTATE_STOPPED);
   
.    mmm->fd = fdWrapper.release();  
    return 0;     return 0;
} }
   
   
int MMMan::Load( char *fname, int num, int opt ) int MMMan::Load( char *fname, int num, int opt )
{ {
    //      Load sound to bank     //      Load sound to bank
    //          opt : 0=normal/1=loop/2=wait/3=continuous     //          opt : 0=normal/1=loop/2=wait/3=continuous
    //     //
    int flag,res;     int flag,res;
    MMM *mmm;     MMM *mmm;
   
    flag = MMDATA_INTWAVE;     flag = MMDATA_INTWAVE;
    mmm = SetBank( num, flag, opt, NULL, fname );     mmm = SetBank( num, flag, opt, NULL, fname );
   
    if ( mmm != NULL ) {     if ( mmm != NULL ) {
        res = BankLoad( mmm, fname );         res = BankLoad( mmm, fname );
        if ( res ) {         if ( res ) {
            mmm->flag = MMDATA_NONE;             mmm->flag = MMDATA_NONE;
            Alertf( "[MMMan] Failed %s on bank #%d (%d)",fname,num,res );             Alertf( "[MMMan] Failed %s on bank #%d (%d)",fname,num,res );
            return -1;             return -1;
        }         }
        if ( opt == 1 ) SetLoopBank( mmm, opt );         if ( opt == 1 ) SetLoopBank( mmm, opt );
    }     }
    Alertf( "[MMMan] Loaded %s on bank #%d",fname,num );     Alertf( "[MMMan] Loaded %s on bank #%d",fname,num );
    return 0;     return 0;
} }
   
   
int MMMan::Play( int num ) int MMMan::Play( int num )
{ {
    //      Play sound     //      Play sound
    //     //
    int bank;     int bank;
    MMM *m;     MMM *m;
    bank = SearchBank(num);     bank = SearchBank(num);
    if ( bank < 0 ) return 1;     if ( bank < 0 ) return 1;
    m = &(mem_snd[bank]);     m = &(mem_snd[bank]);
    if ( m->flag == MMDATA_INTWAVE ) PlayBank( m );     if ( m->flag == MMDATA_INTWAVE ) PlayBank( m );
    return 0;     return 0;
} }
   
   
void MMMan::Notify( void ) void MMMan::Notify( void )
{ {
    //      callback from windows message     //      callback from windows message
    //          "MM_MCINOTIFY"     //          "MM_MCINOTIFY"
    //     //
} }
   
   
void MMMan::GetInfo( int bank, char **fname, int *num, int *flag, int *opt ) void MMMan::GetInfo( int bank, char **fname, int *num, int *flag, int *opt )
{ {
    //      Get MMM info     //      Get MMM info
    //     //
    MMM *mmm;     MMM *mmm;
    mmm=&mem_snd[bank];     mmm=&mem_snd[bank];
    *fname = mmm->fname;     *fname = mmm->fname;
    *opt=mmm->opt;     *opt=mmm->opt;
    *flag=mmm->flag;     *flag=mmm->flag;
    *num=mmm->num;     *num=mmm->num;
} }
   
   
/*--------------------------------------------------------------------------------*/  /*--------------------------------------------------------------------------------*/ 
   
float gain_to_attenuation( float gain ) float gain_to_attenuation( float gain )
{ {
    return gain < 0.01F ? -96.0F : 20 * log10( gain );     return gain < 0.01F ? -96.0F : 20 * log10( gain );
} }
   
void MMMan::SetVol( int num, int vol ) void MMMan::SetVol( int num, int vol )
{ {
    MMM *mmm;     MMM *mmm;
    int bank,flg;     int bank,flg;
    char ss[1024];     char ss[1024];
    bank = SearchBank( num );     bank = SearchBank( num );
    if ( bank < 0 ) return;     if ( bank < 0 ) return;
   
    mmm=&mem_snd[bank];     mmm=&mem_snd[bank];
    mmm->vol = vol;     mmm->vol = vol;
    if ( mmm->vol > 0 ) mmm->vol = 0;     if ( mmm->vol > 0 ) mmm->vol = 0;
    if ( mmm->vol < -1000 ) mmm->vol = -1000;     if ( mmm->vol < -1000 ) mmm->vol = -1000;
   
    flg=mmm->flag;     flg=mmm->flag;
    switch(flg) {     switch(flg) {
    case MMDATA_INTWAVE:                           // when "WAV"     case MMDATA_INTWAVE:                           // when "WAV"
   
        float myvol;         float myvol;
        float maxvol;         float maxvol;
        maxvol = 1000.0;         maxvol = 1000.0;
        myvol = (float)(mmm->vol + 1000);         myvol = (float)(mmm->vol + 1000);
        myvol = myvol / 1000.0f;         myvol = myvol / 1000.0f;
        (*mmm->playerVolume)->SetVolumeLevel( mmm->playerVolume, (SLmillibel)(gain_to_attenuation( myvol ) * 100) );         (*mmm->playerVolume)->SetVolumeLevel( mmm->playerVolume, (SLmillibel)(gain_to_attenuation( myvol ) * 100) );
   
        break;         break;
    }     }
} }
   
   
void MMMan::SetPan( int num, int pan ) void MMMan::SetPan( int num, int pan )
{ {
    MMM *mmm;     MMM *mmm;
    int bank,flg;     int bank,flg;
    int fixpan;     int fixpan;
    bank = SearchBank( num );     bank = SearchBank( num );
    if ( bank < 0 ) return;     if ( bank < 0 ) return;
   
    mmm=&mem_snd[bank];     mmm=&mem_snd[bank];
    flg=mmm->flag;     flg=mmm->flag;
    switch(flg) {     switch(flg) {
    case MMDATA_INTWAVE:                           // when "WAV"     case MMDATA_INTWAVE:                           // when "WAV"
   
        fixpan = pan;         fixpan = pan;
        if ( fixpan < -1000 ) fixpan = -1000;         if ( fixpan < -1000 ) fixpan = -1000;
        if ( fixpan > 1000 ) fixpan = 1000;         if ( fixpan > 1000 ) fixpan = 1000;
        mmm->pan = fixpan;         mmm->pan = fixpan;
   
        (*mmm->playerVolume)->EnableStereoPosition( mmm->playerVolume, SL_BOOLEAN_TRUE );         (*mmm->playerVolume)->EnableStereoPosition( mmm->playerVolume, SL_BOOLEAN_TRUE );
        (*mmm->playerVolume)->SetStereoPosition( mmm->playerVolume, fixpan );         (*mmm->playerVolume)->SetStereoPosition( mmm->playerVolume, fixpan );
   
        break;         break;
    }     }
} }
   
   
int MMMan::GetStatus( int num, int infoid ) int MMMan::GetStatus( int num, int infoid )
{ {
    MMM *mmm;     MMM *mmm;
    int bank,flg;     int bank,flg;
    int res;     int res;
    bank = SearchBank( num );     bank = SearchBank( num );
    if ( bank < 0 ) return 0;     if ( bank < 0 ) return 0;
   
    mmm = &(mem_snd[bank]);     mmm = &(mem_snd[bank]);
    if ( mmm->flag != MMDATA_INTWAVE ) return 0;     if ( mmm->flag != MMDATA_INTWAVE ) return 0;
    flg=mmm->flag;     flg=mmm->flag;
    res = 0;     res = 0;
    switch( infoid ) {     switch( infoid ) {
    case 0:     case 0:
        res = mmm->opt;         res = mmm->opt;
        break;         break;
    case 1:     case 1:
        res = mmm->vol;         res = mmm->vol;
        break;         break;
    case 2:     case 2:
        res = mmm->pan;         res = mmm->pan;
        break;         break;
    case 16:     case 16:
        if ( GetState(mmm) == SL_PLAYSTATE_PLAYING ) { res = 1; }         if ( GetState(mmm) == SL_PLAYSTATE_PLAYING ) { res = 1; }
        break;         break;
    }     }
    return res;     return res;
} }
   
   
void MMMan::StopBank( int num ) void MMMan::StopBank( int num )
{ {
    //      stop playing sound     //      stop playing sound
    //     //
    int bank;     int bank;
    MMM *m;     MMM *m;
    if ( num < 0 ) {     if ( num < 0 ) {
        Stop();         Stop();
        return;         return;
    }     }
    bank = SearchBank(num);     bank = SearchBank(num);
    if ( bank < 0 ) return;     if ( bank < 0 ) return;
    m = &(mem_snd[bank]);     m = &(mem_snd[bank]);
    StopBank( m );     StopBank( m );
} }