DWORD DSound51_Driver::WorkerThread() { while( dsound_running ) { u32 rv = WaitForMultipleObjects(numBuffers,buffer_events,FALSE,200); s16* p1, *oldp1; LPVOID p2; DWORD s1,s2; u32 poffset = DSound51::BufferSizeBytes * rv; #ifdef _DEBUG verifyc(buffer->Lock(poffset,DSound51::BufferSizeBytes,(LPVOID*)&p1,&s1,&p2,&s2,0)); #else if( FAILED(buffer->Lock(poffset,DSound51::BufferSizeBytes,(LPVOID*)&p1,&s1,&p2,&s2,0) ) ) { fputs( " * SPU2 : Directsound Warning > Buffer lock failure. You may need to increase the DSound buffer count.\n", stderr ); continue; } #endif oldp1 = p1; for(int p=0; p<DSound51::PacketsPerBuffer; p++, p1+=SndOutPacketSize ) { s32 temp[SndOutPacketSize]; s32* s = temp; s16* t = p1; buff->ReadSamples( temp ); for(int j=0;j<SndOutPacketSize/2;j++) { // DPL2 code here: inputs s[0] and s[1]. outputs t[0] to t[5] dpl2.Convert( t, s[0], s[1] ); t+=6; s+=2; } } #ifndef PUBLIC verifyc(buffer->Unlock(oldp1,s1,p2,s2)); #else buffer->Unlock(oldp1,s1,p2,s2); #endif // Set the write pointer to the beginning of the next block. myLastWrite = (poffset + DSound51::BufferSizeBytes) % (DSound51::BufferSizeBytes*numBuffers); } return 0; }
u32 THREADCALL SoundThread1(void* param) { for(;;) { u32 rv = WaitForMultipleObjects(sound_buffer_count,buffer_events,FALSE,400); if (!soundthread_running) break; LPVOID p1,p2; DWORD s1,s2; rv-=WAIT_OBJECT_0; if(SUCCEEDED(buffer->Lock(WritePositions[rv],wait_buffer_size,&p1,&s1,&p2,&s2,0))) { UpdateBuff((u8*)p1); verifyc(buffer->Unlock(p1,s1,p2,s2)); } } return 0; }
DSound51_Driver::DSound51_Driver( SndBuffer *sb ) : buff( sb ), numBuffers( Config_DSound51.NumBuffers ), dpl2( Config_DSound51.LowpassLFE, SampleRate ) { // // Initialize DSound // GUID cGuid; bool success = false; if( (strlen(Config_DSound51.Device)>0)&&(!FAILED(GUIDFromString(Config_DSound51.Device,&cGuid)))) { if( !FAILED( DirectSoundCreate8(&cGuid,&dsound,NULL) ) ) success = true; } // if the GUID failed, just open up the default dsound driver: if( !success ) { verifyc(DirectSoundCreate8(NULL,&dsound,NULL)); } verifyc(dsound->SetCooperativeLevel(GetDesktopWindow(),DSSCL_PRIORITY)); IDirectSoundBuffer* buffer_; DSBUFFERDESC desc; // Set up WAV format structure. memset(&wfx, 0, sizeof(WAVEFORMATEX)); wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfx.Format.nSamplesPerSec = SampleRate; wfx.Format.nChannels=6; wfx.Format.wBitsPerSample = 16; wfx.Format.nBlockAlign = wfx.Format.nChannels*wfx.Format.wBitsPerSample/8; wfx.Format.nAvgBytesPerSec = SampleRate * wfx.Format.nBlockAlign; wfx.Format.cbSize=22; wfx.Samples.wValidBitsPerSample=0; wfx.dwChannelMask=SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT; wfx.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; verifyc(dsound->SetSpeakerConfig(DSSPEAKER_5POINT1)); // Set up DSBUFFERDESC structure. memset(&desc, 0, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;// _CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; desc.dwBufferBytes = DSound51::BufferSizeBytes * numBuffers; desc.lpwfxFormat = &wfx.Format; desc.dwFlags |=DSBCAPS_LOCSOFTWARE; desc.dwFlags|=DSBCAPS_GLOBALFOCUS; verifyc(dsound->CreateSoundBuffer(&desc,&buffer_,0)); verifyc(buffer_->QueryInterface(IID_IDirectSoundBuffer8,(void**)&buffer)); buffer_->Release(); verifyc(buffer->QueryInterface(IID_IDirectSoundNotify8,(void**)&buffer_notify)); DSBPOSITIONNOTIFY not[DSound51::MAX_BUFFER_COUNT]; for(u32 i=0;i<numBuffers;i++) { buffer_events[i]=CreateEvent(NULL,FALSE,FALSE,NULL); not[i].dwOffset=(wfx.Format.nBlockAlign*2 + DSound51::BufferSizeBytes*(i+1))%desc.dwBufferBytes; not[i].hEventNotify=buffer_events[i]; } buffer_notify->SetNotificationPositions(numBuffers,not); LPVOID p1=0,p2=0; DWORD s1=0,s2=0; verifyc(buffer->Lock(0,desc.dwBufferBytes,&p1,&s1,&p2,&s2,0)); assert(p2==0); memset(p1,0,s1); verifyc(buffer->Unlock(p1,s1,p2,s2)); //Play the buffer ! verifyc(buffer->Play(0,0,DSBPLAY_LOOPING)); // Start Thread myLastWrite = 0; dsound_running=true; thread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RThread,this,0,&tid); SetThreadPriority(thread,THREAD_PRIORITY_TIME_CRITICAL); }
void ds_InitAudio() { if (settings.BufferSize<2048) { StreamV2=true; } verifyc(DirectSoundCreate8(NULL,&dsound,NULL)); verifyc(dsound->SetCooperativeLevel((HWND)eminf.GetRenderTarget(),DSSCL_PRIORITY)); IDirectSoundBuffer* buffer_; WAVEFORMATEX wfx; DSBUFFERDESC desc; // Set up WAV format structure. memset(&wfx, 0, sizeof(WAVEFORMATEX)); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = 44100; wfx.nBlockAlign = 4; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; wfx.wBitsPerSample = 16; // Set up DSBUFFERDESC structure. memset(&desc, 0, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;// _CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; if (!StreamV2) desc.dwBufferBytes = settings.BufferSize*(2)* wfx.nBlockAlign; else desc.dwBufferBytes = V2_BUFFERSZ* wfx.nBlockAlign; //fixed at 8k samples :) desc.lpwfxFormat = &wfx; wait_buffer_size=settings.BufferSize*wfx.nBlockAlign; if (settings.HW_mixing==0) { desc.dwFlags |=DSBCAPS_LOCSOFTWARE; } else if (settings.HW_mixing==1) { desc.dwFlags |=DSBCAPS_LOCHARDWARE; } else if (settings.HW_mixing==2) { //auto } else { die("settings.HW_mixing: Invalid value"); } if (settings.GlobalFocus) desc.dwFlags|=DSBCAPS_GLOBALFOCUS; verifyc(dsound->CreateSoundBuffer(&desc,&buffer_,0)); verifyc(buffer_->QueryInterface(IID_IDirectSoundBuffer8,(void**)&buffer)); buffer_->Release(); verifyc(buffer->QueryInterface(IID_IDirectSoundNotify8,(void**)&buffer_notify)); DWORD chunk_count; if (StreamV2) { chunk_count=V2_BUFFERSZ/settings.BufferSize; printf("DSOUND V2 : Using %d chunks of %d size\n",chunk_count,wait_buffer_size); } else { chunk_count=2; printf("DSOUND V1 : Using 2 chunks of %d size\n",wait_buffer_size); } sound_buffer_count=chunk_count; for (u32 bei=0;bei<chunk_count;bei++) { buffer_events[bei]=not[bei].hEventNotify=CreateEvent(NULL,FALSE,FALSE,NULL); not[bei].dwOffset=bei*wait_buffer_size; WritePositions[(bei+chunk_count-1)%chunk_count]=not[bei].dwOffset; } buffer_notify->SetNotificationPositions(chunk_count,not); //Clear the buffer with silence LPVOID p1=0,p2=0; DWORD s1=0,s2=0; verifyc(buffer->Lock(0,desc.dwBufferBytes,&p1,&s1,&p2,&s2,0)); verify(p2==0); memset(p1,0,s1); verifyc(buffer->Unlock(p1,s1,p2,s2)); //Start the thread soundthread_running=true; verify(SetThreadPriority((HANDLE)sound_th.hThread,THREAD_PRIORITY_TIME_CRITICAL)); sound_th.Start(); //Make sure its run before the buffer releases the event Sleep(0); //Play the buffer ! verifyc(buffer->Play(0,0,DSBPLAY_LOOPING)); }
s32 Init() { numBuffers = Config_DSoundOut.NumBuffers; // // Initialize DSound // GUID cGuid; try { if( Config_DSoundOut.Device.empty() ) throw std::runtime_error( "screw it" ); // Convert from unicode to ANSI: char guid[256]; sprintf_s( guid, "%S", Config_DSoundOut.Device.c_str() ); if( (FAILED(GUIDFromString( guid, &cGuid ))) || FAILED( DirectSoundCreate8(&cGuid,&dsound,NULL) ) ) throw std::runtime_error( "try again?" ); } catch( std::runtime_error& ) { // if the GUID failed, just open up the default dsound driver: if( FAILED(DirectSoundCreate8(NULL,&dsound,NULL) ) ) throw std::runtime_error( "DirectSound failed to initialize!" ); } if( FAILED(dsound->SetCooperativeLevel(GetDesktopWindow(),DSSCL_PRIORITY)) ) throw std::runtime_error( "DirectSound Error: Cooperative level could not be set." ); // Determine the user's speaker configuration, and select an expansion option as needed. // FAIL : Directsound doesn't appear to support audio expansion >_< DWORD speakerConfig = 2; //dsound->GetSpeakerConfig( &speakerConfig ); IDirectSoundBuffer* buffer_; DSBUFFERDESC desc; // Set up WAV format structure. memset(&wfx, 0, sizeof(WAVEFORMATEX)); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nSamplesPerSec = SampleRate; wfx.nChannels = (WORD)speakerConfig; wfx.wBitsPerSample = 16; wfx.nBlockAlign = 2*(WORD)speakerConfig; wfx.nAvgBytesPerSec = SampleRate * wfx.nBlockAlign; wfx.cbSize = 0; uint BufferSizeBytes = BufferSize * wfx.nBlockAlign; // Set up DSBUFFERDESC structure. memset(&desc, 0, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;// _CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; desc.dwBufferBytes = BufferSizeBytes * numBuffers; desc.lpwfxFormat = &wfx; desc.dwFlags |= DSBCAPS_LOCSOFTWARE; desc.dwFlags |= DSBCAPS_GLOBALFOCUS; if( FAILED(dsound->CreateSoundBuffer(&desc,&buffer_,0) ) ) throw std::runtime_error( "DirectSound Error: Interface could not be queried." ); if( FAILED(buffer_->QueryInterface(IID_IDirectSoundBuffer8,(void**)&buffer)) ) throw std::runtime_error( "DirectSound Error: Interface could not be queried." ); buffer_->Release(); verifyc( buffer->QueryInterface(IID_IDirectSoundNotify8,(void**)&buffer_notify) ); DSBPOSITIONNOTIFY not[MAX_BUFFER_COUNT]; for(u32 i=0;i<numBuffers;i++) { // [Air] note: wfx.nBlockAlign modifier was *10 -- seems excessive to me but maybe // it was needed for some quirky driver? Theoretically we want the notification as soon // as possible after the buffer has finished playing. buffer_events[i] = CreateEvent(NULL,FALSE,FALSE,NULL); not[i].dwOffset = (wfx.nBlockAlign + BufferSizeBytes*(i+1)) % desc.dwBufferBytes; not[i].hEventNotify = buffer_events[i]; } buffer_notify->SetNotificationPositions(numBuffers,not); LPVOID p1=0,p2=0; DWORD s1=0,s2=0; verifyc(buffer->Lock(0,desc.dwBufferBytes,&p1,&s1,&p2,&s2,0)); assert(p2==0); memset(p1,0,s1); verifyc(buffer->Unlock(p1,s1,p2,s2)); //Play the buffer ! verifyc(buffer->Play(0,0,DSBPLAY_LOOPING)); // Start Thread myLastWrite = 0; dsound_running = true; thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RThread<StereoOut16>,this,0,&tid); SetThreadPriority(thread,THREAD_PRIORITY_ABOVE_NORMAL); return 0; }
s32 Init() { CoInitializeEx( NULL, COINIT_MULTITHREADED ); // // Initialize DSound // GUID cGuid; try { if( m_Device.empty() ) throw std::runtime_error( "screw it" ); // Convert from unicode to ANSI: char guid[256]; sprintf_s( guid, "%S", m_Device.c_str() ); if( (FAILED(GUIDFromString( guid, &cGuid ))) || FAILED( DirectSoundCreate8(&cGuid,&dsound,NULL) ) ) throw std::runtime_error( "try again?" ); } catch( std::runtime_error& ) { // if the GUID failed, just open up the default dsound driver: if( FAILED(DirectSoundCreate8(NULL,&dsound,NULL) ) ) throw std::runtime_error( "DirectSound failed to initialize!" ); } if( FAILED(dsound->SetCooperativeLevel(GetDesktopWindow(),DSSCL_PRIORITY)) ) throw std::runtime_error( "DirectSound Error: Cooperative level could not be set." ); // Determine the user's speaker configuration, and select an expansion option as needed. // FAIL : Directsound doesn't appear to support audio expansion >_< DWORD speakerConfig = 2; //dsound->GetSpeakerConfig( &speakerConfig ); IDirectSoundBuffer* buffer_; DSBUFFERDESC desc; // Set up WAV format structure. memset(&wfx, 0, sizeof(WAVEFORMATEX)); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nSamplesPerSec = SampleRate; wfx.nChannels = (WORD)speakerConfig; wfx.wBitsPerSample = 16; wfx.nBlockAlign = 2*(WORD)speakerConfig; wfx.nAvgBytesPerSec = SampleRate * wfx.nBlockAlign; wfx.cbSize = 0; uint BufferSizeBytes = BufferSize * wfx.nBlockAlign; // Set up DSBUFFERDESC structure. memset(&desc, 0, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY; desc.dwBufferBytes = BufferSizeBytes * m_NumBuffers; desc.lpwfxFormat = &wfx; // Try a hardware buffer first, and then fall back on a software buffer if // that one fails. desc.dwFlags |= m_UseHardware ? DSBCAPS_LOCHARDWARE : DSBCAPS_LOCSOFTWARE; desc.dwFlags |= m_DisableGlobalFocus ? DSBCAPS_STICKYFOCUS : DSBCAPS_GLOBALFOCUS; if( FAILED(dsound->CreateSoundBuffer(&desc, &buffer_, 0) ) ) { if( m_UseHardware ) { desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE; desc.dwFlags |= m_DisableGlobalFocus ? DSBCAPS_STICKYFOCUS : DSBCAPS_GLOBALFOCUS; if( FAILED(dsound->CreateSoundBuffer(&desc, &buffer_, 0) ) ) throw std::runtime_error( "DirectSound Error: Buffer could not be created." ); } throw std::runtime_error( "DirectSound Error: Buffer could not be created." ); } if( FAILED(buffer_->QueryInterface(IID_IDirectSoundBuffer8,(void**)&buffer)) || buffer == NULL ) throw std::runtime_error( "DirectSound Error: Interface could not be queried." ); buffer_->Release(); verifyc( buffer->QueryInterface(IID_IDirectSoundNotify8,(void**)&buffer_notify) ); DSBPOSITIONNOTIFY not[MAX_BUFFER_COUNT]; for(uint i=0;i<m_NumBuffers;i++) { buffer_events[i] = CreateEvent(NULL,FALSE,FALSE,NULL); not[i].dwOffset = (wfx.nBlockAlign + BufferSizeBytes*(i+1)) % desc.dwBufferBytes; not[i].hEventNotify = buffer_events[i]; } buffer_notify->SetNotificationPositions(m_NumBuffers,not); LPVOID p1=0,p2=0; DWORD s1=0,s2=0; verifyc(buffer->Lock(0,desc.dwBufferBytes,&p1,&s1,&p2,&s2,0)); assert(p2==0); memset(p1,0,s1); verifyc(buffer->Unlock(p1,s1,p2,s2)); //Play the buffer ! verifyc(buffer->Play(0,0,DSBPLAY_LOOPING)); // Start Thread myLastWrite = 0; dsound_running = true; thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RThread<StereoOut16>,this,0,&tid); SetThreadPriority(thread,THREAD_PRIORITY_ABOVE_NORMAL); return 0; }
void os_InitAudio() { verifyc(DirectSoundCreate8(NULL,&dsound,NULL)); verifyc(dsound->SetCooperativeLevel((HWND)libPvr_GetRenderTarget(),DSSCL_PRIORITY)); IDirectSoundBuffer* buffer_; WAVEFORMATEX wfx; DSBUFFERDESC desc; // Set up WAV format structure. memset(&wfx, 0, sizeof(WAVEFORMATEX)); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = 44100; wfx.nBlockAlign = 4; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; wfx.wBitsPerSample = 16; // Set up DSBUFFERDESC structure. ds_ring_size=8192*wfx.nBlockAlign; memset(&desc, 0, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;// _CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; desc.dwBufferBytes = ds_ring_size; desc.lpwfxFormat = &wfx; if (settings.aica.HW_mixing==0) { desc.dwFlags |=DSBCAPS_LOCSOFTWARE; } else if (settings.aica.HW_mixing==1) { desc.dwFlags |=DSBCAPS_LOCHARDWARE; } else if (settings.aica.HW_mixing==2) { //auto } else { die("settings.HW_mixing: Invalid value"); } if (settings.aica.GlobalFocus) desc.dwFlags|=DSBCAPS_GLOBALFOCUS; verifyc(dsound->CreateSoundBuffer(&desc,&buffer_,0)); verifyc(buffer_->QueryInterface(IID_IDirectSoundBuffer8,(void**)&buffer)); buffer_->Release(); //Play the buffer ! verifyc(buffer->Play(0,0,DSBPLAY_LOOPING)); }