📄 sinsound.cpp
字号:
#include "StdAfx.h"
#include "dsound.h"
#include "math.h"
#include "sinsound.h"
CSinSound::CSinSound()
:m_pDs(NULL),
m_pDsb(NULL),
m_pBlankDsb(NULL),
m_rScale(1.0l),
m_bFormatValid(FALSE),
m_bDsbValid(FALSE),
m_bDataValid(FALSE)
{
memset(&m_oPlayedBufferDesc, 0, sizeof(m_oPlayedBufferDesc));
memset(&m_oFormat, 0, sizeof(m_oFormat));
m_oFormat.wFormatTag = WAVE_FORMAT_PCM;
m_oFormat.nChannels = 1;
m_oFormat.nSamplesPerSec = 44100;
m_oFormat.wBitsPerSample = 16;
m_oFormat.nAvgBytesPerSec = m_oFormat.nSamplesPerSec * (m_oFormat.wBitsPerSample / 8) * m_oFormat.nChannels;
m_oFormat.nBlockAlign = 2;
m_oFormat.cbSize = 0;
SetFrequency(1000);
}
CSinSound::~CSinSound(void)
{
if (NULL != m_pDsb)
{
m_pDsb->Release();
m_pDsb = NULL;
}
if (NULL != m_pBlankDsb)
{
m_pBlankDsb->Release();
m_pBlankDsb = NULL;
}
if (NULL != m_pDs)
{
m_pDs->Release();
m_pDs = NULL;
}
}
BOOL CSinSound::Initialize(HWND hWnd)
{
HRESULT hr =
DirectSoundCreate(NULL, &m_pDs, NULL);
if (FAILED(hr))
return FALSE;
hr = m_pDs->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
if (FAILED(hr))
return FALSE;
return InitBufferFormat();
}
BOOL CSinSound::InitBufferFormat()
{
DSBUFFERDESC dsbd;
memset(&dsbd, 0, sizeof(DSBUFFERDESC));
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_STATIC;
dsbd.dwBufferBytes = 8;
dsbd.lpwfxFormat = &m_oFormat;
HRESULT hr = m_pDs->CreateSoundBuffer(&dsbd, &m_pBlankDsb, NULL);
if (m_bFormatValid = SUCCEEDED(hr))
{
PlayBlank();
return InitPlayedBuffer();
}
return FALSE;
}
BOOL CSinSound::InitPlayedBuffer()
{
HRESULT hr;
m_oPlayedBufferDesc.dwSize = sizeof(DSBUFFERDESC);
m_oPlayedBufferDesc.dwFlags = DSBCAPS_STATIC;
m_oPlayedBufferDesc.dwBufferBytes = (DWORD)(m_rBufferLengthMs * m_oFormat.nAvgBytesPerSec / 1000);
m_oPlayedBufferDesc.lpwfxFormat = &m_oFormat;
hr = m_pDs->CreateSoundBuffer(&m_oPlayedBufferDesc, &m_pDsb, NULL);
if (m_bDsbValid = SUCCEEDED(hr))
return WriteBuffer();
return FALSE;
}
BOOL CSinSound::WriteBuffer()
{
LPVOID lpvPtr1;
DWORD dwBytes1;
HRESULT hr = m_pDsb->Lock(0, m_oPlayedBufferDesc.dwBufferBytes, &lpvPtr1, &dwBytes1, NULL, NULL, 0);
// If the buffer was lost, restore and retry lock.
if (DSERR_BUFFERLOST == hr)
{
m_pDsb->Restore();
hr = m_pDsb->Lock(0, m_oPlayedBufferDesc.dwBufferBytes, &lpvPtr1, &dwBytes1, NULL, NULL, DSBLOCK_ENTIREBUFFER);
}
if (FAILED(hr))
return (m_bDataValid = FALSE);
double dt = 1.0l / m_oFormat.nSamplesPerSec;
DWORD nBytesPerSample = m_oFormat.wBitsPerSample / 8;
for (DWORD i = 0; i < dwBytes1 / nBytesPerSample; ++i)
{
double v = sin(2 * PI * dt * i * m_rFrequencyHz) * m_rScale; // -1.0 ~ +1.0
for (DWORD j = 0; j < m_oFormat.nChannels; ++j)
{
if (16 == m_oFormat.wBitsPerSample)
{
*(((short int *)lpvPtr1) + i * m_oFormat.nChannels + j) = (short int)(v * 32767);
}
else if (8 == m_oFormat.wBitsPerSample)
{
*(((char *)lpvPtr1) + i * m_oFormat.nChannels + j) = (char)(v * 255);
}
else
{
return (m_bDataValid = FALSE);
}
}
}
return (m_bDataValid = SUCCEEDED(m_pDsb->Unlock(lpvPtr1, dwBytes1, NULL, NULL)));
}
void CSinSound::Play()
{
m_pDsb->SetCurrentPosition(0);
HRESULT hr = m_pDsb->Play(0, 0, DSBPLAY_LOOPING);
if (DSERR_BUFFERLOST == hr)
{
m_pDsb->Restore();
WriteBuffer();
m_pDsb->Play(0, 0, DSBPLAY_LOOPING);
}
}
void CSinSound::Stop()
{
m_pDsb->Stop();
}
void CSinSound::PlayBlank()
{
HRESULT hr = m_pBlankDsb->Play(0, 0, DSBPLAY_LOOPING);
if (DSERR_BUFFERLOST == hr)
{
m_pBlankDsb->Restore();
m_pBlankDsb->Play(0, 0, DSBPLAY_LOOPING);
}
}
void CSinSound::StopBlank()
{
m_pBlankDsb->Stop();
}
void CSinSound::SetSampleRate(DWORD nSamplesPerSec)
{
if (m_oFormat.nSamplesPerSec != nSamplesPerSec)
{
m_oFormat.nSamplesPerSec = nSamplesPerSec;
m_oFormat.nAvgBytesPerSec = m_oFormat.nSamplesPerSec * (m_oFormat.wBitsPerSample / 8) * m_oFormat.nChannels;
m_bFormatValid = FALSE;
}
}
void CSinSound::SetBitsPerSample(WORD nBits)
{
if (m_oFormat.wBitsPerSample != nBits)
{
m_oFormat.wBitsPerSample = nBits;
m_oFormat.nAvgBytesPerSec = m_oFormat.nSamplesPerSec * (m_oFormat.wBitsPerSample / 8) * m_oFormat.nChannels;
m_bFormatValid = FALSE;
}
}
void CSinSound::SetBufferLength(double rMSec)
{
if (m_rBufferLengthMs != rMSec)
{
m_rBufferLengthMs = rMSec;
m_bDsbValid = FALSE;
}
}
void CSinSound::SetFrequency(double rFrequency)
{
if (m_rFrequencyHz != rFrequency)
{
double w = 1.0l / rFrequency;
double d = 1.0l / m_oFormat.nSamplesPerSec;
int nTimes;
for (nTimes = 100; nTimes <= 1000; ++nTimes)
{
double rRemScale = fmod(w * nTimes, d) / w;
if (rRemScale < 0.001l || rRemScale > 0.998l)
break;
}
m_rFrequencyHz = rFrequency;
m_rBufferLengthMs = nTimes * w * 1000.0l;
m_bDsbValid = FALSE;
}
}
void CSinSound::SetScale(double rScale)
{
if (m_rScale != rScale)
{
m_rScale = rScale;
m_bDataValid = FALSE;
}
}
BOOL CSinSound::Validate()
{
if (!m_bFormatValid)
{
m_pDsb->Release(); m_pDsb = NULL;
m_pBlankDsb->Release(); m_pBlankDsb = NULL;
return InitBufferFormat();
}
else if (!m_bDsbValid)
{
m_pDsb->Release(); m_pDsb = NULL;
return InitPlayedBuffer();
}
else if (!m_bDataValid)
{
return WriteBuffer();
}
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -