📄 sound_directsound.cxx
字号:
else
PTRACE (4, "dsound\tWriteToDXBuffer Failed : " << DXGetErrorString9 (hr));
return written;
}
/*
* DESC: Reads (len) bytes from the buffer (*buf) from DirectX sound capture device buffer
* BEHAVIOUR : Locks the buffer on the requested size; In case buffer was lost, tries to restore it.
* Copies the data into the buffer
* Unlock the buffer
* RETURN : Returns the size actually read
*/
PINDEX
PSoundChannelDirectSound::ReadFromDXBuffer (const void * buf,
PINDEX len)
{
HRESULT hr;
LPVOID lpvRead1, lpvRead2;
DWORD dwLength1, dwLength2;
PINDEX read = 0;
/*** Lock the buffer ***/
hr = mAudioCaptureBuffer->Lock (mDXOffset,
len,
&lpvRead1,
&dwLength1,
&lpvRead2,
&dwLength2,
0L);
if (!FAILED(hr))
{
/*** Copy memory into buffer ***/
memcpy ((BYTE *)buf + lastReadCount, lpvRead1, dwLength1);
if (lpvRead2 != NULL)
memcpy ((BYTE *) buf + dwLength1 + lastReadCount, lpvRead2, dwLength2);
read = dwLength1 + dwLength2;
mDXOffset += read;
mDXOffset %= mDXBufferSize;
/*** Unlock the buffer ***/
mAudioCaptureBuffer->Unlock (lpvRead1,
dwLength1,
lpvRead2,
dwLength2);
}
else
PTRACE (4, "dsound\tReadFromDXBuffer Lock failed: " << DXGetErrorString9 (hr));
return read;
}
/*
* DESC : Suspend the treatment in order to let the buffer flush itself
* BEHAVIOUR : Compute the time needed to play the remaining data in buffer.
* In case it exceed 600 ms, sleeps for 500 ms.
* RETURN : /
*/
void
PSoundChannelDirectSound::FlushBuffer ()
{
DWORD sleep_time = (mDXBufferSize - GetDXBufferFreeSpace ()) * 8000 / ( mWFX.wBitsPerSample * mWFX.nSamplesPerSec);
if (sleep_time > 600)
Sleep((DWORD)(sleep_time-500));
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::SetFormat (unsigned numChannels,
unsigned sampleRate,
unsigned bitsPerSample)
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " SetFormat\n"
<< " --> nChannels :" << mWFX.nChannels << '\n'
<< " --> nSamplesPerSec :" << mWFX.nSamplesPerSec << '\n'
<< " --> wBitsPerSample :" << mWFX.wBitsPerSample << '\n'
<< " --> nBlockAlign :" << mWFX.nBlockAlign << '\n'
<< " --> nAvgBytesPerSec :" << mWFX.nAvgBytesPerSec << '\n'
<< " --> mOutburst :" << mOutburst);
memset (&mWFX, 0, sizeof (mWFX));
mWFX.wFormatTag = WAVE_FORMAT_PCM;
mWFX.nChannels = (WORD)numChannels;
mWFX.nSamplesPerSec = sampleRate;
mWFX.wBitsPerSample = (WORD)bitsPerSample;
mWFX.nBlockAlign = mWFX.nChannels * (mWFX.wBitsPerSample / 8);
mWFX.nAvgBytesPerSec = mWFX.nSamplesPerSec * mWFX.nBlockAlign;
mWFX.cbSize = 0; //ignored
mOutburst = mWFX.nBlockAlign*8;
return PTrue;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
unsigned
PSoundChannelDirectSound::GetChannels() const
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " GetChannels");
return mNumChannels;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
unsigned
PSoundChannelDirectSound::GetSampleRate() const
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " GetSampleRate");
return mSampleRate;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
unsigned
PSoundChannelDirectSound::GetSampleSize() const
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " GetSampleSize");
return mBitsPerSample;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::SetBuffers (PINDEX size, PINDEX count)
{
//kept for records
mBufferCount = count;
mBufferSize = size;
mDXBufferSize = mWFX.nAvgBytesPerSec;
PTRACE (4, "dsound\tSetBuffers ==> size = " << size << " | count = " << count << " | DXBufferSize = " << mDXBufferSize);
if (mDirection == Player)
InitPlaybackBuffer ();
else
InitCaptureBuffer ();
return PTrue;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::GetBuffers(PINDEX & size, PINDEX & count)
{
count = mBufferCount;
size = mBufferSize;
return PTrue;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::InitCaptureBuffer()
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " InitCaptureBuffer");
if (isInitialised)
return false;
HRESULT hr;
DSCBUFFERDESC dscbdesc;
LPDIRECTSOUNDCAPTUREBUFFER pDscb = NULL;
memset(&dscbdesc, 0, sizeof(DSCBUFFERDESC));
dscbdesc.dwSize = sizeof(DSCBUFFERDESC);
dscbdesc.dwFlags = DSCBCAPS_WAVEMAPPED;
dscbdesc.dwBufferBytes = mDXBufferSize;
dscbdesc.lpwfxFormat = &mWFX;
hr = sAudioCaptureDevice->CreateCaptureBuffer(&dscbdesc,
&pDscb,
NULL);
if (SUCCEEDED(hr))
{
hr = pDscb->QueryInterface(IID_IDirectSoundCaptureBuffer8, (LPVOID*) &mAudioCaptureBuffer);
pDscb->Release();
mDXOffset = 0;
mAudioCaptureBuffer->Start (DSCBSTART_LOOPING);
isInitialised = true;
}
else
PTRACE (4, "dsound\tInitCaptureBuffer : Create Sound Buffer Failed " << DXGetErrorString9 (hr));
return isInitialised;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::InitPlaybackBuffer()
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " InitPlaybackBuffer");
if (isInitialised)
return false;
DSBUFFERDESC dsbdesc;
HRESULT hr;
LPDIRECTSOUNDBUFFER pDsb = NULL;
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
dsbdesc.dwBufferBytes = mDXBufferSize;
dsbdesc.lpwfxFormat = &mWFX;
hr = sAudioPlaybackDevice->CreateSoundBuffer(&dsbdesc,
&pDsb,
NULL);
if (SUCCEEDED(hr))
{
hr = pDsb->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID*) &mAudioPlaybackBuffer);
pDsb->Release();
mDXOffset = 0;
//fill buffer with silence
PBYTEArray silence(mDXBufferSize);
memset (silence.GetPointer(), (mWFX.wBitsPerSample == 8) ? 128 : 0, mDXBufferSize);
WriteToDXBuffer (silence, mDXBufferSize);
mAudioPlaybackBuffer->SetCurrentPosition (0);
isInitialised = true;
}
else
PTRACE (4, "dsound\tInitPlaybackBuffer : Create Sound Buffer Failed " << DXGetErrorString9 (hr));
return isInitialised;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::PlaySound(const PSound & sound, PBoolean wait)
{
mStreaming = false;
if (!Write((const void *)sound, sound.GetSize()))
return PFalse;
if (wait)
return WaitForPlayCompletion();
return PTrue;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::PlayFile(const PFilePath & filename, PBoolean wait)
{
BYTE buffer [512];
mStreaming = false;
PFile file (filename, PFile::ReadOnly);
if (!file.IsOpen())
return PFalse;
for (;;)
{
if (!file.Read (buffer, 512))
break;
PINDEX len = file.GetLastReadCount();
if (len == 0)
break;
if (!Write(buffer, len))
break;
}
file.Close();
if (wait)
return WaitForPlayCompletion();
return PTrue;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::HasPlayCompleted()
{
DWORD dwStatus;
if (mAudioPlaybackBuffer != NULL)
{
mAudioPlaybackBuffer->GetStatus (&dwStatus);
if (dwStatus & DSBSTATUS_PLAYING)
return PFalse;
}
return PTrue;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::WaitForPlayCompletion()
{
while (!HasPlayCompleted())
Sleep (50);
return PTrue;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::RecordSound(PSound & /*sound*/)
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " RecordSound");
return PFalse;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::RecordFile(const PFilePath & /*filename*/)
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " RecordFile");
return PFalse;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::StartRecording()
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " StartRecording");
return PFalse;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean PSoundChannelDirectSound::IsRecordBufferFull()
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " IsRecordBufferFull");
return PTrue;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean PSoundChannelDirectSound::AreAllRecordBuffersFull()
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " AreAllRecordBuffersFull");
return PTrue;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean PSoundChannelDirectSound::WaitForRecordBufferFull()
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " WaitForRecordBufferFull");
return PTrue;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean PSoundChannelDirectSound::WaitForAllRecordBuffersFull()
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " WaitForAllRecordBuffersFull");
return PFalse;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::Abort()
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " Abort");
return PTrue;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::SetVolume (unsigned newVal)
{
PBoolean no_error=PTrue;
HRESULT hr;
long volume = (long) (log10((double)newVal) * 5000.0) - 10000;
switch (mDirection) {
case Player:
if (mAudioPrimaryPlaybackBuffer)
{
if (FAILED (hr = mAudioPlaybackBuffer->SetVolume( volume )))
{
PTRACE (4, "PSoundChannelDirectSound::SetVolume Failed " << DXGetErrorString9 (hr));
no_error = PFalse;
}
}
else
PTRACE (4, "PSoundChannelDirectSound::SetVolume Failed mAudioPlaybackBuffer is NULLL (huh?)");
break;
case Recorder:
// DirectX does not let you change the capture buffer volume
mVolume = newVal;
break;
}
return no_error;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::GetVolume(unsigned &devVol)
{
PBoolean no_error=PTrue;
HRESULT hr;
long volume = 100;
switch (mDirection)
{
case Player:
if (mAudioPlaybackBuffer)
{
if (FAILED (hr = mAudioPlaybackBuffer->GetVolume( &volume )))
{
PTRACE (4, "PSoundChannelDirectSound::GetVolume Failed " << DXGetErrorString9 (hr));
no_error = PFalse;
}
devVol = (unsigned int) pow(10.0, (float)(volume+10000) / 5000.0);
}
break;
case Recorder:
// DirectX does not let you change the capture buffer volume
devVol = mVolume;
break;
}
return no_error;
}
/*
* DESC :
* BEHAVIOUR :
* RETURN :
*/
PBoolean
PSoundChannelDirectSound::IsOpen () const
{
PTRACE (4, "dsound\t" << ((mDirection == Player) ? "Playback" : "Recording") << " IsOpen");
return isOpen;
}
#endif // P_DIRECTSOUND
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -