//--------------------------------------------------------------------------- #include "system.hpp" #include "classes.hpp" #pragma hdrstop #define STRICT #include "Sound.h" #include "Usefull.h" #include "Globals.h" //#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } char Directory[]= "sounds\\"; LPDIRECTSOUND TSoundsManager::pDS; LPDIRECTSOUNDNOTIFY TSoundsManager::pDSNotify; int TSoundsManager::Count= 0; TSoundContainer *TSoundsManager::First=NULL; __fastcall TSoundContainer::TSoundContainer( LPDIRECTSOUND pDS, char *Directory, char *strFileName, int NConcurrent) {//wczytanie pliku dźwiękowego int hr= 111; DSBuffer=NULL; //na początek, gdyby uruchomić dźwięków się nie udało Concurrent= NConcurrent; Oldest= 0; // strcpy(Name, strFileName); strcpy(Name,Directory); strcat(Name,strFileName); CWaveSoundRead* pWaveSoundRead; // Create a new wave file class pWaveSoundRead = new CWaveSoundRead(); // Load the wave file if (FAILED(pWaveSoundRead->Open(Name))) if(FAILED(pWaveSoundRead->Open(strFileName))) { // SetFileUI( hDlg, TEXT("Bad wave file.") ); return; ErrorLog("Missed sound: "+AnsiString(strFileName)); } strcpy(Name,AnsiString(strFileName).LowerCase().c_str()); // Set up the direct sound buffer, and only request the flags needed // since each requires some overhead and limits if the buffer can // be hardware accelerated DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; if (!Global::bInactivePause) //jeśli przełączony w tło ma nadal działać dsbd.dwFlags|=DSBCAPS_GLOBALFOCUS; //to dźwięki mają być również słyszalne dsbd.dwBufferBytes = pWaveSoundRead->m_ckIn.cksize; dsbd.lpwfxFormat = pWaveSoundRead->m_pwfx; fSamplingRate=pWaveSoundRead->m_pwfx->nSamplesPerSec; iBitsPerSample=pWaveSoundRead->m_pwfx->wBitsPerSample; // pDSBuffer= (LPDIRECTSOUNDBUFFER*) malloc(Concurrent*sizeof(LPDIRECTSOUNDBUFFER)); // for (int i=0; iCreateSoundBuffer( &dsbd, &(DSBuffer), NULL ) ) ) //if (FAILED(pDS->CreateSoundBuffer(&dsbd,&(DSBuffer),NULL))) return; // Remember how big the buffer is DWORD dwBufferBytes; dwBufferBytes = dsbd.dwBufferBytes; //---------------------------------------------------------- BYTE* pbWavData; // Pointer to actual wav data UINT cbWavSize; // Size of data VOID* pbData = NULL; VOID* pbData2 = NULL; DWORD dwLength; DWORD dwLength2; // The size of wave data is in pWaveFileSound->m_ckIn INT nWaveFileSize = pWaveSoundRead->m_ckIn.cksize; // Allocate that buffer. pbWavData = new BYTE[ nWaveFileSize ]; if( NULL == pbWavData ) return ;//E_OUTOFMEMORY; //if (FAILED(hr=pWaveSoundRead->Read( nWaveFileSize,pbWavData,&cbWavSize))) if( FAILED( hr = pWaveSoundRead->Read( nWaveFileSize, pbWavData, &cbWavSize ) ) ) return ; // Reset the file to the beginning pWaveSoundRead->Reset(); // Lock the buffer down //if (FAILED(hr=DSBuffer->Lock(0,dwBufferBytes,&pbData,&dwLength,&pbData2,&dwLength2,0))) if( FAILED( hr = DSBuffer->Lock( 0, dwBufferBytes, &pbData, &dwLength, &pbData2, &dwLength2, 0L ) ) ) return ; // Copy the memory to it. memcpy( pbData, pbWavData, dwBufferBytes ); // Unlock the buffer, we don't need it anymore. DSBuffer->Unlock( pbData, dwBufferBytes, NULL, 0 ); pbData = NULL; // We dont need the wav file data buffer anymore, so delete it delete[] pbWavData; delete pWaveSoundRead; DSBuffers.push(DSBuffer); /* for (int i=1; iDuplicateSoundBuffer(pDSBuffer[0],&(pDSBuffer[i])))) { Concurrent= i; break; }; };*/ }; __fastcall TSoundContainer::~TSoundContainer() { // for (int i=Concurrent-1; i>=0; i--) // SAFE_RELEASE( pDSBuffer[i] ); // free(pDSBuffer); while (!DSBuffers.empty()) { SAFE_RELEASE(DSBuffers.top()); DSBuffers.pop(); } SafeDelete( Next ); }; LPDIRECTSOUNDBUFFER __fastcall TSoundContainer::GetUnique(LPDIRECTSOUND pDS) { if (!DSBuffer) return NULL; //jeśli się dobrze zainicjowało LPDIRECTSOUNDBUFFER buff; pDS->DuplicateSoundBuffer(DSBuffer,&buff); if (buff) DSBuffers.push(buff); return DSBuffers.top(); }; __fastcall TSoundsManager::~TSoundsManager() { Free(); }; void __fastcall TSoundsManager::Free() { SafeDelete( First ); SAFE_RELEASE( pDS ); }; TSoundContainer* __fastcall TSoundsManager::LoadFromFile(char *Dir,char *Name,int Concurrent) { TSoundContainer *Tmp=First; First=new TSoundContainer(pDS,Dir,Name,Concurrent); First->Next=Tmp; Count++; return First; //albo NULL, jak nie wyjdzie (na razie zawsze wychodzi) }; void __fastcall TSoundsManager::LoadSounds(char *Directory) {//wczytanie wszystkich plików z katalogu - mało elastyczne WIN32_FIND_DATA FindFileData; HANDLE handle=FindFirstFile("sounds\\*.wav",&FindFileData); if (handle!=INVALID_HANDLE_VALUE) do { LoadFromFile(Directory,FindFileData.cFileName,1); } while (FindNextFile(handle,&FindFileData)); FindClose(handle); }; LPDIRECTSOUNDBUFFER __fastcall TSoundsManager::GetFromName(char *Name,bool Dynamic,float *fSamplingRate) {//wyszukanie dźwięku w pamięci albo wczytanie z pliku AnsiString file; if (Dynamic) {//próba wczytania z katalogu pojazdu file=Global::asCurrentDynamicPath+AnsiString(Name); if (FileExists(file)) Name=file.c_str(); //nowa nazwa else Dynamic=false; //wczytanie z "sounds/" } TSoundContainer *Next=First; DWORD dwStatus; for (int i=0;iName)==0) { if (fSamplingRate) *fSamplingRate=Next->fSamplingRate; //częstotliwość return (Next->GetUnique(pDS)); // DSBuffers. /* Next->pDSBuffer[Next->Oldest]->Stop(); Next->pDSBuffer[Next->Oldest]->SetCurrentPosition(0); if (Next->OldestConcurrent-1) { Next->Oldest++; return (Next->pDSBuffer[Next->Oldest-1]); } else { Next->Oldest= 0; return (Next->pDSBuffer[Next->Concurrent-1]); }; /* for (int j=0; jConcurrent; j++) { Next->pDSBuffer[j]->GetStatus(&dwStatus); if ((dwStatus & DSBSTATUS_PLAYING) != DSBSTATUS_PLAYING) return (Next->pDSBuffer[j]); } */ } else Next=Next->Next; }; if (Dynamic) //wczytanie z katalogu pojazdu Next=LoadFromFile("",Name,1); else Next=LoadFromFile(Directory,Name,1); if (Next) {// if (fSamplingRate) *fSamplingRate=Next->fSamplingRate; //częstotliwość return Next->GetUnique(pDS); } ErrorLog("Missed sound: "+AnsiString(Name)); return (NULL); }; void __fastcall TSoundsManager::RestoreAll() { TSoundContainer *Next= First; HRESULT hr; DWORD dwStatus; for (int i=0; iDSBuffer->GetStatus( &dwStatus ) ) ); // return hr; if( dwStatus & DSBSTATUS_BUFFERLOST ) { // Since the app could have just been activated, then // DirectSound may not be giving us control yet, so // the restoring the buffer may fail. // If it does, sleep until DirectSound gives us control. do { hr = Next->DSBuffer->Restore(); if( hr == DSERR_BUFFERLOST ) Sleep( 10 ); } while ((hr=Next->DSBuffer->Restore())!=NULL); // char *Name= Next->Name; // int cc= Next->Concurrent; // delete Next; // Next= new TSoundContainer(pDS, Directory, Name, cc); // if( FAILED( hr = FillBuffer() ) ); // return hr; }; Next= Next->Next; }; }; //void __fastcall TSoundsManager::Init(char *Name, int Concurrent) //__fastcall TSoundsManager::TSoundsManager(HWND hWnd) //void __fastcall TSoundsManager::Init(HWND hWnd, char *NDirectory) void __fastcall TSoundsManager::Init(HWND hWnd) { First= NULL; Count= 0; pDS= NULL; pDSNotify= NULL; HRESULT hr; //=222; LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; // strcpy(Directory, NDirectory); // Create IDirectSound using the primary sound device hr = DirectSoundCreate( NULL, &pDS, NULL ); if( hr!=DS_OK ) { if (hr==DSERR_ALLOCATED) return; if (hr==DSERR_INVALIDPARAM) return; if (hr==DSERR_NOAGGREGATION) return; if (hr==DSERR_NODRIVER) return; if (hr==DSERR_OUTOFMEMORY) return; // hr=0; }; // return ; // Set coop level to DSSCL_PRIORITY // if( FAILED( hr = pDS->SetCooperativeLevel( hWnd, DSSCL_PRIORITY ) ) ); // return ; pDS->SetCooperativeLevel( hWnd, DSSCL_PRIORITY ); // Get the primary buffer DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; if (!Global::bInactivePause) //jeśli przełączony w tło ma nadal działać dsbd.dwFlags|=DSBCAPS_GLOBALFOCUS; //to dźwięki mają być również słyszalne dsbd.dwBufferBytes = 0; dsbd.lpwfxFormat = NULL; if( FAILED( hr = pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) return ; // Set primary buffer format to 22kHz and 16-bit output. WAVEFORMATEX wfx; ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = 44100; wfx.wBitsPerSample = 16; wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) return ; SAFE_RELEASE( pDSBPrimary ); }; //--------------------------------------------------------------------------- #pragma package(smart_init)