프로그래밍 관련/사운드

게임사운드 플레이(테스트)

AlrepondTech 2020. 9. 19. 02:26
반응형

 

 

 



 

=======================

=======================

=======================

 

 

 

 

 

CSoundPlayer.cpp
0.02MB
CSoundPlayer.h
0.01MB

 

//---------------------------------------------------------------------CSoundPlayer.h


#pragma once

#include "DXUTsound.h"
#include <list>
#include "CHashMap.h"

#ifdef _DEBUG
#pragma comment(lib, "ogg.d.lib")
#else
#pragma comment(lib, "ogg.r.lib")
#endif


//
// Sound resource
//
#define IDS_LOBBY_WAIT            (1)            //        1    b010.ogg    배경음 1 (접속 후 대기실)
#define IDS_GAME_READY            (2)            //        1    b020.ogg    배경음 2 (게임 룸에서 게임중)
#define IDS_GAME_PLAY            (3)            //        1    b020.ogg    배경음 3 (게임 룸에서 대기상태)
#define IDS_START                  (4)            //        2    Start.ogg   (시작)
#define IDS_M_Start             (5)         //      2   M-Start.ogg (미션시작)
#define IDS_CARDTOUCH           (6)         //      2  CardTouch.ogg (카드터치)
#define IDS_CARDNOTOUCH         (7)         //      2  CardNoTouch.ogg (카드노터치)
#define IDS_CARDMOVE            (8)         //      2  CardMove.ogg (카드무브)
#define IDS_GOSTOP              (9)         //      2  GoStop.ogg (고스톱)


#define SOUNDPLAYER CSoundPlayer::Instance()

using namespace std;

typedef struct 
{
    list<CSound*> lstWaves;

    void Add(CSound *pSound)
    {
        lstWaves.push_back(pSound);
    };

    void Free()
    {
        CSound *pSound;
        list<CSound*>::iterator pos;
        for(pos = lstWaves.begin(); pos != lstWaves.end(); pos++)
        {
            pSound = (*pos);

            pSound->Stop();
            pSound->Reset();

            delete pSound;
        }

        if(lstWaves.size() > 0)
            lstWaves.clear();
    };

    void Play()
    {
        CSound *pSound;
        list<CSound*>::iterator pos;
        for(pos = lstWaves.begin(); pos != lstWaves.end(); pos++)
        {
            pSound = (*pos);
            if(! pSound->IsSoundPlaying() )
            {
                pSound->Play();
                return;
            }
        }
    };
} TWaves;

class CSoundPlayer
{
public:
    CSoundPlayer();
    virtual ~CSoundPlayer();

    static CSoundPlayer* Instance();

private:

    //------------------------------------------------------------------
    -m_pSoundBufferBg   : ogg BackGround Sound
    -m_pSoundBufferEf   : ogg Effect Sound
    
    //------------------------------------------------------------------
    CSoundManager*    m_pSoundManager;

    IDirectSoundBuffer*    m_pSoundBufferBg; 
    IDirectSoundBuffer*    m_pSoundBufferEf; 

    CMapWord2Ptr    m_mapOggs;
    CMapWord2Ptr    m_mapWaves;
    WORD            m_iCurBgm;
    int             m_nSavEffId;

public:

    //------------------------------------------------------------------
    -LoadWave(void* pZf, void* pTzf); : 왼쪽 오른쪽 각각 gzFile,TZFile 스트럭쳐 사용 zlib에서 바로 로드
    -LoadOgg(WORD rid, char *fname)   : 파일로 따로 로드
    -LoadOggMemory(WORD rid, BYTE* pData,int size) : 메모리로 로드
    
    //------------------------------------------------------------------

    bool Init(HWND hWnd);
    void ReleaseAll();
    void LoadAllSound();
    void FreeAllWaves();
    bool Play(WORD rid, int fmt = 0);

    void LoadWave(void* pZf, void* pTzf);
    bool LoadOgg(void* pZf, void* pTzf);
    bool LoadOgg(WORD rid, char *fname);
    bool LoadOggMemory(WORD rid, BYTE* pData,int size, WORD nCnt);

    void FreeAllOggs();
    bool PlayOgg(WORD rid);
    void StopOgg();
    bool ReplayOgg();

private :
    IDirectSoundBuffer * CreateSoundBuffer(int samplerate, int bitn, int channel, int samplenum);

};

//----------------------------------------------------------------------CSoundPlayer.cpp

//--------------------------------------------------------------------------------------
// File: CSoundPlayer.cpp
//
// based CSocket
//--------------------------------------------------------------------------------------

#include "stdbase.h"
#include "CSoundPlayer.h"
#include "vorbisfile.h"
#include "CGameApp.h"
#include "CXzip.h"

//Wav Memory use Struct
struct WAVE_HEADER {

    char riff_id[4];         // "RIFF"
    DWORD riff_size;                  // File size - 8
    char wave_id[4];               // "WAVE"
    char format_id[4];             // "fmt "
    DWORD format_size;               // 16
    PCMWAVEFORMAT WaveRecord;
    char data_id[4];         // "data"
    long data_size;                 // data size
};

//Ogg Memory use Struct
struct SOggFile
{
    char*        dataPtr;            // Pointer to the data in memoru
    int            dataSize;            // Sizeo fo the data
    int            dataRead;            // How much data we have read so far
};

#define    _USER_FILEIO

#ifdef _USER_FILEIO

//OGG Memory Callback
/************************************************************************************************************************
The following function are the vorbis callback functions.  As their names suggest, they are expected to work in exactly the
same way as normal c io functions (fread, fclose etc.).  Its up to us to return the information that the libs need to parse
the file from memory
************************************************************************************************************************/
//---------------------------------------------------------------------------------
// Function    : VorbisRead
// Purpose    : Callback for the Vorbis read function
// Info        : 
//---------------------------------------------------------------------------------
size_t VorbisRead(void *ptr            /* ptr to the data that the vorbis files need*/, 
                  size_t byteSize    /* how big a byte is*/, 
                  size_t sizeToRead /* How much we can read*/, 
                  void *datasource    /* this is a pointer to the data we passed into ov_open_callbacks (our SOggFile struct*/)
{
    size_t                spaceToEOF;            // How much more we can read till we hit the EOF marker
    size_t                actualSizeToRead;    // How much data we are actually going to read from memory
    SOggFile*            vorbisData;            // Our vorbis data, for the typecast

    // Get the data in the right format
    vorbisData = (SOggFile*)datasource;

    // Calculate how much we need to read.  This can be sizeToRead*byteSize or less depending on how near the EOF marker we are
    spaceToEOF = vorbisData->dataSize - vorbisData->dataRead;
    if ((sizeToRead*byteSize) < spaceToEOF)
        actualSizeToRead = (sizeToRead*byteSize);
    else
        actualSizeToRead = spaceToEOF;    

    // A simple copy of the data from memory to the datastruct that the vorbis libs will use
    if (actualSizeToRead)
    {
        // Copy the data from the start of the file PLUS how much we have already read in
        memcpy(ptr, (char*)vorbisData->dataPtr + vorbisData->dataRead, actualSizeToRead);
        // Increase by how much we have read by
        vorbisData->dataRead += int(actualSizeToRead);
    }

    // Return how much we read (in the same way fread would)
    return actualSizeToRead;
}

//---------------------------------------------------------------------------------
// Function    : VorbisSeek
// Purpose    : Callback for the Vorbis seek function
// Info        : 
//---------------------------------------------------------------------------------
int VorbisSeek(void *datasource        /*this is a pointer to the data we passed into ov_open_callbacks (our SOggFile struct*/, 
               ogg_int64_t offset    /*offset from the point we wish to seek to*/, 
               int whence            /*where we want to seek to*/)
{
    size_t                spaceToEOF;        // How much more we can read till we hit the EOF marker
    ogg_int64_t            actualOffset;    // How much we can actually offset it by
    SOggFile*            vorbisData;        // The data we passed in (for the typecast)

    // Get the data in the right format
    vorbisData = (SOggFile*)datasource;

    // Goto where we wish to seek to
    switch (whence)
    {
    case SEEK_SET: // Seek to the start of the data file
        // Make sure we are not going to the end of the file
        if (vorbisData->dataSize >= offset)
            actualOffset = offset;
        else
            actualOffset = vorbisData->dataSize;
        // Set where we now are
        vorbisData->dataRead = (int)actualOffset;
        break;
    case SEEK_CUR: // Seek from where we are
        // Make sure we dont go past the end
        spaceToEOF = vorbisData->dataSize - vorbisData->dataRead;
        if (offset < spaceToEOF)
            actualOffset = (offset);
        else
            actualOffset = spaceToEOF;    
        // Seek from our currrent location
        vorbisData->dataRead += (int)actualOffset;
        break;
    case SEEK_END: // Seek from the end of the file
        vorbisData->dataRead = vorbisData->dataSize+1;
        break;
    default:
        printf("*** ERROR *** Unknown seek command in VorbisSeek\n");
        break;
    };

    return 0;
}

//---------------------------------------------------------------------------------
// Function    : VorbisClose
// Purpose    : Callback for the Vorbis close function
// Info        : 
//---------------------------------------------------------------------------------
int VorbisClose(void *datasource /*this is a pointer to the data we passed into ov_open_callbacks (our SOggFile struct*/)
{
    // This file is called when we call ov_close.  If we wanted, we could free our memory here, but
    // in this case, we will free the memory in the main body of the program, so dont do anything
    return 1;
}

//---------------------------------------------------------------------------------
// Function    : VorbisTell
// Purpose    : Classback for the Vorbis tell function
// Info        : 
//---------------------------------------------------------------------------------
long VorbisTell(void *datasource /*this is a pointer to the data we passed into ov_open_callbacks (our SOggFile struct*/)
{
    SOggFile*    vorbisData;

    // Get the data in the right format
    vorbisData = (SOggFile*)datasource;

    // We just want to tell the vorbis libs how much we have read so far
    return vorbisData->dataRead;
}
ov_callbacks _ogg_memory_callbacks =
{
    VorbisRead, VorbisSeek, VorbisClose, VorbisTell
} ;


//OGG File Callback
//------------------------------------------------------------------
size_t _read_func(void *ptr, size_t size, size_t nmemb, void *datasource)
{
    FILE * fp = (FILE*) datasource;
    return fread(ptr, size, nmemb, fp);
}

int _seek_func(void *datasource, ogg_int64_t offset, int whence)
{
    FILE * fp = (FILE*) datasource;
    return fseek(fp, (int)offset, whence);
}

int _close_func(void *datasource)
{
    return 0;
}

long _tell_func(void *datasource)
{
    FILE * fp = (FILE*) datasource;
    return ftell(fp);
}

ov_callbacks _ogg_callbacks =
{
    _read_func, _seek_func, _close_func, _tell_func
} ;


/************************************************************************************************************************
End of Vorbis callback functions
************************************************************************************************************************/

#endif

#define _ENDIAN    0
#define _SIGN    1

#define MIN_AVAILMEM    (190*1000*1000)
//--------------------------------------------------------------------------------------
// Constructor
//--------------------------------------------------------------------------------------



CSoundPlayer::CSoundPlayer()
{
    m_pSoundManager    = NULL;
    
    m_pSoundBufferBg = NULL; //ogg BackGround Sound
    m_pSoundBufferEf = NULL; //ogg Effect Sound
    m_nSavEffId = -1;

}

CSoundPlayer::~CSoundPlayer()
{
    ReleaseAll();
}

CSoundPlayer* CSoundPlayer::Instance()
{
    static CSoundPlayer instance;
    return &instance;
}



bool CSoundPlayer::Init(HWND  hWnd)
{
    HRESULT hr;
    // Create a static IDirectSound in the CSound class.  
    // Set coop level to DSSCL_PRIORITY, and set primary buffer 
    // format to stereo, 22kHz and 16-bit output.

    m_pSoundManager = new CSoundManager();
    if( NULL == m_pSoundManager )
    {
        return false;
    }

    if( FAILED( hr = m_pSoundManager->Initialize( hWnd, DSSCL_PRIORITY ) ) )
    {
        return false;
    }

    if( FAILED( hr = m_pSoundManager->SetPrimaryBufferFormat( 2, 22050, 16 ) ) )
    {
        return false;
    }

    MEMORYSTATUS ms;
    ms.dwLength = sizeof(ms);
    GlobalMemoryStatus(&ms);

    if(ms.dwAvailPhys >=  MIN_AVAILMEM)
    {
        LoadAllSound();
    }

    return true;
}

void CSoundPlayer::ReleaseAll()
{
    FreeAllOggs();
    FreeAllWaves();
    SAFE_DELETE( m_pSoundManager );
}


void CSoundPlayer::LoadWave(void* pZf, void* pTzf)
{
    if(pZf==NULL || pTzf == NULL)
    {
        printf("CSoundPlayer::LoadWave pointer value error \n");
        return ;
    }

    TGSoundRes *pTDSndRes;
    _MAP_WP *map = CGameData::m_mapSoundRes.GetMap();
    _ITER_WP pos;

    BYTE* pSndData;
    CSound* pSound = NULL;

    gzFile* pZfTmp = (gzFile*)pZf;
    TZFile* pTzfTmp = (TZFile*)pTzf;

    WAVE_HEADER wHeader;
    WAVEFORMATEX sndft;
    ZeroMemory(&sndft,sizeof(LPWAVEFORMATEX));
    ZeroMemory(&wHeader,sizeof(WAVE_HEADER));

    //Find Sound Data List
    for(pos = map->begin(); pos != map->end(); pos++)
    {
        pTDSndRes = (TGSoundRes*)pos->second;
        if(strcmp(pTDSndRes->sound,pTzfTmp->zname)==0) 
        {
            break;
        }
    }

    if(gzread(*pZfTmp, &wHeader, sizeof(WAVE_HEADER)) <0 )
    {
        printf("CSoundPlayer::LoadWave gzread error!!\n");
        gzclose(*pZfTmp);
        return ;
    }

    memcpy( &sndft, &wHeader.WaveRecord, sizeof(wHeader.WaveRecord) );
    sndft.cbSize = 0;

    pSndData = new BYTE[wHeader.data_size];

    if(gzread(*pZfTmp, pSndData,wHeader.data_size) < 0)
    {
        printf("CSoundPlayer::LoadWave gzread error!!\n");
        gzclose(*pZfTmp);
        return ;
    }

    int nPass = pTzfTmp->zsize - sizeof(WAVE_HEADER) - wHeader.data_size;
    if(gzseek(*pZfTmp,nPass,SEEK_CUR) < 0)
    {
        printf("CSoundPlayer::LoadWave gzseek error!!\n");
        gzclose(*pZfTmp);
        return ;
    }
        
    TWaves* pWaves = new TWaves;
    for(int i=0; i<pTDSndRes->count; i++)
    {

        if(! FAILED(m_pSoundManager->CreateFromMemory( &pSound, pSndData, wHeader.data_size , &sndft) ) )
        {
            pWaves->Add(pSound);
        }
    }

    m_mapWaves.Insert(pTDSndRes->sid, pWaves);

    SAFE_DELETE(pSndData);
}


void CSoundPlayer::LoadAllSound()
{

    // Zlib로 압축된 로직이 들어있어 zlib 아닌 파일을 함수로 읽거나 
    // 버퍼스트림으로 읽어들여 따로 로드해도 된다.


    LPAPPINFO lpApp =  _GetApplicationInfo();

    CSound* pSound = NULL;

    char zfile[MAX_PATH];
    //char path[MAX_PATH];

    //WideCharToMultiByte( CP_ACP, 0, lpApp->szAppPath, -1, path, MAX_PATH, NULL, NULL );
    //sprintf_s(zfile, "%s\\sound\\tdsound.tz", path);

    //  [6/30/2010 psj] fix-path
    sprintf_s(zfile,  "..\\..\\..\\res\\sound\\gsound.tz"); 

    gzFile zf;
    zf = gzopen(zfile, "rb");
    if(! zf )
    {
        printf("gzopen error!!\n");
        return ;
    }

    int zread = 0;

    TZHeader zh;
    zread = gzread(zf, &zh, SZ_TZHeader);
    if( zread < 0 )
    {
        printf("gzread error!!\n");
        gzclose(zf);
        return ;
    }

    TZFile tzf;
    while(! gzeof(zf) )
    {
        zread = gzread(zf, &tzf, SZ_TZFile);
        if(zread < 0 || zread != SZ_TZFile)
        {
            printf("gzread error\n");
            gzclose(zf);
            return ;
        }

        if( tzf.zkind != _A_ARCH )
        {
            printf("wrong zkind\n");
            gzclose(zf);
            return ;
        }

        string str = tzf.zname;
        if(str.find(".wav")!=-1)
        {
            LoadWave((void*)&zf,(void*)&tzf);
        }
        else if(str.find(".ogg")!=-1)
        {

            LoadOgg((void*)&zf,(void*)&tzf);
        }
        else
        {
            if(gzseek(zf,tzf.zsize,SEEK_CUR) < 0)
            {
                printf("CSoundPlayer::LoadWave gzseek error!!\n");
                gzclose(zf);
                return ;
            }
        }
    }

    gzclose(zf);
    return ;
}



void CSoundPlayer::FreeAllWaves()
{
    TWaves *pWaves;
    _MAP_WP *map = m_mapWaves.GetMap();
    _ITER_WP pos;

    for(pos = map->begin(); pos != map->end(); pos++)
    {
        pWaves = (TWaves*)pos->second;

        if(pWaves)
        {
            pWaves->Free();
            delete pWaves;
        }
    }
}

bool CSoundPlayer::Play(WORD rid, int fmt)
{
    if(_GetAppOption()->op_off_efs == 1)
        return true;

    TWaves *pWaves;

    if( m_mapWaves.Lookup(rid, (void*&)pWaves) )
    {
        pWaves->Play();
        return true;
    }

    return false;
}

//------------------------------------------------------------------
// OGG format 
//
IDirectSoundBuffer* CSoundPlayer::CreateSoundBuffer(int samplerate, int bitn, int channel, int samplenum)
{
    IDirectSoundBuffer *    sbuf= NULL;
    DSBUFFERDESC            dsbd;
    PCMWAVEFORMAT            wavfmt;

    wavfmt.wBitsPerSample        = (WORD)bitn;
    wavfmt.wf.wFormatTag        = WAVE_FORMAT_PCM;
    wavfmt.wf.nChannels            = (WORD)channel;
    wavfmt.wf.nSamplesPerSec    = samplerate;
    wavfmt.wf.nBlockAlign        = wavfmt.wf.nChannels * wavfmt.wBitsPerSample / 8;
    wavfmt.wf.nAvgBytesPerSec    = wavfmt.wf.nSamplesPerSec * wavfmt.wf.nBlockAlign;

    memset(&dsbd, 0, sizeof(DSBUFFERDESC));

    dsbd.dwSize = sizeof(DSBUFFERDESC);
    dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLVOLUME;
    dsbd.dwBufferBytes = samplenum * bitn / 8 * channel;
    dsbd.lpwfxFormat = (LPWAVEFORMATEX)&wavfmt;

    LPDIRECTSOUND8 lpSound = m_pSoundManager->GetDirectSound();
    if (lpSound->CreateSoundBuffer(&dsbd, &sbuf, NULL) != DS_OK)
        return NULL;

    return sbuf;
}

bool CSoundPlayer::PlayOgg(WORD rid)
{
    m_iCurBgm = rid;

    if(_GetAppOption()->op_off_bgm == 1)
        return true;

    TGSoundRes *pTDSndRes;
    CGameData::m_mapSoundRes.Lookup(rid,(void*&)pTDSndRes);
    vector<IDirectSoundBuffer*>* pVBuffTmp = NULL;

    if(pTDSndRes == NULL)
        return false;

    switch(pTDSndRes->type)
    {
    case 1:
        {
            StopOgg();
            if( m_mapOggs.Lookup(rid, (void*&)pVBuffTmp) )
            {
                m_pSoundBufferBg = (*pVBuffTmp)[0];
                m_pSoundBufferBg->Play(0, 0, DSBPLAY_LOOPING); // DSBPLAY_LOOPING 루핑 사운드 , 0 - 한번재생
                return true;
            }
        }
        break;
    case 2:
        {
            if( m_mapOggs.Lookup(rid, (void*&)pVBuffTmp) )
            {
                DWORD state = 0;
                for(auto it = pVBuffTmp->begin(); it!=pVBuffTmp->end(); it++)
                {

                    (*it)->GetStatus(&state);
                    if(DSBSTATUS_PLAYING == state)
                    {
                        continue;
                    }
                    else
                    {
                        m_pSoundBufferEf = (*it);
                        (*it)->SetCurrentPosition(0);
                        if((*it)->Play(0, NULL, 0) == DSERR_BUFFERLOST)
                        {
                            if(SUCCEEDED((*it)->Restore()))
                                (*it)->Play(0,0,0);
                        }
                        break;
                    }
                }
                return true;
            }
        }
        break;
    default:    
        break;

    };

    return false;
}

void CSoundPlayer::StopOgg()
{
    if( m_pSoundBufferBg )
        m_pSoundBufferBg->Stop();
}

bool CSoundPlayer::ReplayOgg()
{
    StopOgg();

    if( m_mapOggs.Lookup(m_iCurBgm, (void*&)m_pSoundBufferBg) )
    {
        m_pSoundBufferBg->Play(0, 0, DSBPLAY_LOOPING);

        return true;
    }

    return false;
}

bool CSoundPlayer::LoadOgg(void* pZf, void* pTzf)
{
    if(pZf==NULL || pTzf == NULL)
    {
        printf("CSoundPlayer::LoadOgg pointer value error \n");
        return false;
    }

    TGSoundRes *pTDSndRes;
    _MAP_WP *map = CGameData::m_mapSoundRes.GetMap();
    _ITER_WP pos;

    gzFile* pZfTmp = (gzFile*)pZf;
    TZFile* pTzfTmp = (TZFile*)pTzf;

    BYTE* pSndData = new BYTE[pTzfTmp->zsize];

    if(gzread(*pZfTmp, pSndData, pTzfTmp->zsize)<0)
    {
        printf("gzread error!!\n");
        gzclose(*pZfTmp);
        return false;
    }

    for(pos = map->begin(); pos != map->end(); pos++)
    {
        pTDSndRes = (TGSoundRes*)pos->second;
        if(strcmp(pTDSndRes->sound,pTzfTmp->zname)==0) 
        {
            break;
        }
    }

    LoadOggMemory(pTDSndRes->sid, pSndData, pTzfTmp->zsize, pTDSndRes->count);

    SAFE_DELETE(pSndData);

    return true;
}



bool CSoundPlayer::LoadOggMemory(WORD rid, BYTE* pData,int size, WORD nCnt)
{
    LPDIRECTSOUND8 lpSound = m_pSoundManager->GetDirectSound();
    SOggFile    oggMemoryFile;
    OggVorbis_File vf;

    oggMemoryFile.dataPtr = (char*)pData;
    oggMemoryFile.dataRead = 0;
    oggMemoryFile.dataSize = size;

    
#ifdef _USER_FILEIO
    if ( ov_open_callbacks(&oggMemoryFile, &vf, NULL, 0, _ogg_memory_callbacks) < 0)
#else
    if (ov_open(fp, &vf, NULL, 0) < 0)
#endif
    {
        return false;
    }

    vorbis_info *vi = ov_info(&vf, 0);
    int pcm_total = (int)ov_pcm_total(&vf, 0) - 44;
    int len = pcm_total * vi->channels * 16 / 8;


    IDirectSoundBuffer* pSndBuffer;
    LPDIRECTSOUNDBUFFER pSndBufferTmp;

    pSndBuffer = CreateSoundBuffer(vi->rate, 16, vi->channels, pcm_total);

    if(! pSndBuffer)
    {
        return false;
    }

    unsigned long size1, size2;
    void *data1, *data2;

    pSndBuffer->Lock(0, len, &data1, &size1, &data2, &size2, 0);

    for(int i=0; i<len; )
    {
        int bs = 0;
        int readbytes = ov_read(&vf, (char*)data1+i, len-i, _ENDIAN, 16/8, _SIGN, &bs);

        if (bs != 0) // Only one logical bitstream currently supported
            break;

        if (readbytes < 0)
            continue;

        if (readbytes == 0)
            break;

        i += readbytes;
    }

    pSndBuffer->Unlock(0, 0, 0, 0);
    ov_clear(&vf);

    vector<IDirectSoundBuffer*> *pVBuf = new vector<IDirectSoundBuffer*>;
    for(WORD i=0; i<nCnt; i++)
    {
        
        if(pSndBuffer)
        {
            pSndBufferTmp = NULL;
            lpSound->DuplicateSoundBuffer(pSndBuffer,&pSndBufferTmp);

            if(i == 0)
            {
                pVBuf->push_back(pSndBuffer);
            }
            else
            {
                pVBuf->push_back(pSndBufferTmp);

            }
            
        }
    }

    //pSndBuffer->Release();
    
    
    //lpSound->DuplicateSoundBuffer(pSndBuffer,);
    
    return m_mapOggs.Insert(rid, pVBuf);
}

bool CSoundPlayer::LoadOgg(WORD rid, char *fname)
{
    OggVorbis_File vf;
    FILE *fp;

    errno_t err;
    err = fopen_s(&fp, fname, "rb");
    if (err != 0)
        return false;

#ifdef _USER_FILEIO
    if ( ov_open_callbacks((void*)fp, &vf, NULL, 0, _ogg_callbacks) < 0)
#else
    if (ov_open(fp, &vf, NULL, 0) < 0)
#endif
    {
        fclose(fp);
        return false;
    }

    vorbis_info *vi = ov_info(&vf, 0);
    int pcm_total = (int)ov_pcm_total(&vf, 0) - 44;
    int len = pcm_total * vi->channels * 16 / 8;

    IDirectSoundBuffer* pSndBuffer;
    pSndBuffer = CreateSoundBuffer(vi->rate, 16, vi->channels, pcm_total);

    if(! pSndBuffer)
    {
        return false;
    }

    unsigned long size1, size2;
    void *data1, *data2;

    pSndBuffer->Lock(0, len, &data1, &size1, &data2, &size2, 0);

    for(int i=0; i<len; )
    {
        int bs = 0;
        int readbytes = ov_read(&vf, (char*)data1+i, len-i, _ENDIAN, 16/8, _SIGN, &bs);

        if (bs != 0) // Only one logical bitstream currently supported
            break;

        if (readbytes < 0)
            continue;

        if (readbytes == 0)
            break;

        i += readbytes;
    }

    pSndBuffer->Unlock(0, 0, 0, 0);

    ov_clear(&vf);

    fclose(fp);

    return m_mapOggs.Insert(rid, pSndBuffer);

}

void CSoundPlayer::FreeAllOggs()
{
    IDirectSoundBuffer* pSndBuffer;
    vector<IDirectSoundBuffer*>* pVBuffTmp = NULL;
    _MAP_WP *map = m_mapOggs.GetMap();
    _ITER_WP pos;

    for(pos = map->begin(); pos != map->end(); pos++)
    {
        pSndBuffer = (IDirectSoundBuffer*)pos->second;
        pVBuffTmp = (vector<IDirectSoundBuffer*>*)pos->second;

        if(pVBuffTmp)
        {
            for(auto it = pVBuffTmp->begin(); it!=pVBuffTmp->end(); it++)
            {

                pSndBuffer = (*it);
                pSndBuffer->Stop();
                SAFE_RELEASE(pSndBuffer);
            }

        }


        /*if(pSndBuffer)
        {
        pSndBuffer->Stop();
        SAFE_RELEASE(pSndBuffer);
        }*/
    }
}

 



=======================

=======================

=======================

 

 

 

반응형

'프로그래밍 관련 > 사운드' 카테고리의 다른 글

다이렉트 사운드 간단 코드 설명  (0) 2020.09.19
DirectSound C++ Document  (0) 2020.09.19
다이렉트사운드(DirectSound) 관련  (0) 2020.09.17
DirectSound 설명(best) 관련  (0) 2020.09.17
D3Direct Sound 관련  (0) 2020.09.17