gpt4 book ai didi

c++ - 在C++/MFC中停止和启动DirectX声音合成器时弹出/单击

转载 作者:行者123 更新时间:2023-12-03 02:03:45 25 4
gpt4 key购买 nike

我在Visual Studio 2012中使用C++,MFC和DirectX制作了一个软合成器。尽管添加了代码以快速淡出声音,但在停止播放时(以及在开始播放时),我还是会突然弹出/单击。

我从以下项目复制了DirectX代码:http://www.codeproject.com/Articles/7474/Sound-Generator-How-to-create-alien-sounds-using-m

我不确定是否允许剪切和粘贴代码项目中的所有代码。基本上,我按原样使用该项目中的Player类,该类的实例在我的代码中称为m_player。该类中的Stop成员函数调用LPDIRECTSOUNDBUFFER的Stop函数:

void Player::Stop()
{
DWORD status;
if (m_lpDSBuffer == NULL)
return;
HRESULT hres = m_lpDSBuffer->GetStatus(&status);
if (FAILED(hres))
EXCEP(DirectSoundErr::GetErrDesc(hres), "Player::Stop GetStatus");
if ((status & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
{
hres = m_lpDSBuffer->Stop();
if (FAILED(hres))
EXCEP(DirectSoundErr::GetErrDesc(hres), "Player::Stop Stop");
}
}

这是我的项目中填充声音缓冲区的通知代码(带有一些支持代码)。请注意,rend函数始终返回-1到1之间的 double 数,m_ev_smps = 441,m_n_evs = 3,m_ev_sz =882。从OnInitDialog中调用subInit:
#define FD_STEP 0.0005
#define SC_NOT_PLYD 0
#define SC_PLYNG 1
#define SC_FD_OUT 2
#define SC_FD_IN 3
#define SC_STPNG 4
#define SC_STPD 5

bool CMainDlg::subInit()
// initialises various variables and the sound player
{
Player *pPlayer;
SOUNDFORMAT format;
std::vector<DWORD> events;
int t, buf_sz;
try
{
pPlayer = new Player();
pPlayer->SetHWnd(m_hWnd);
m_player = pPlayer;
m_player->Init();
format.NbBitsPerSample = 16;
format.NbChannels = 1;
format.SamplingRate = 44100;
m_ev_smps = 441;
m_n_evs = 3;
m_smps = new short[m_ev_smps];
m_smp_scale = (int)pow(2, format.NbBitsPerSample - 1);
m_max_tm = (int)((double)m_ev_smps / (double)(format.SamplingRate * 1000));
m_ev_sz = m_ev_smps * format.NbBitsPerSample/8;
buf_sz = m_ev_sz * m_n_evs;
m_player->CreateSoundBuffer(format, buf_sz, 0);
m_player->SetSoundEventListener(this);
for(t = 0; t < m_n_evs; t++)
events.push_back((int)((t + 1)*m_ev_sz - m_ev_sz * 0.95));
m_player->CreateEventReadNotification(events);
m_status = SC_NOT_PLYD;
}
catch(MATExceptions &e)
{
MessageBox(e.getAllExceptionStr().c_str(), "Error initializing the sound player");
EndDialog(IDCANCEL);
return FALSE;
}
return TRUE;
}

void CMainDlg::Stop()
// stop playing
{
m_player->Stop();
m_status = SC_STPD;
}

void CMainDlg::OnBnClickedStop()
// causes fade out
{
m_status = SC_FD_OUT;
}

void CMainDlg::OnSoundPlayerNotify(int ev_num)
// render some sound samples and check for errors
{
ScopeGuardMutex guard(&m_mutex);
int s, end, begin, elapsed;
if (m_status != SC_STPNG)
{
begin = GetTickCount();
try
{
for(s = 0; s < m_ev_smps; s++)
{
m_smps[s] = (int)(m_synth->rend() * 32768 * m_fade);
if (m_status == SC_FD_IN)
{
m_fade += FD_STEP;
if (m_fade > 1)
{
m_fade = 1;
m_status = SC_PLYNG;
}
}
else if (m_status == SC_FD_OUT)
{
m_fade -= FD_STEP;
if (m_fade < 0)
{
m_fade = 0;
m_status = SC_STPNG;
}
}
}
}
catch(MATExceptions &e)
{
OutputDebugString(e.getAllExceptionStr().c_str());
}
try
{
m_player->Write(((ev_num + 1) % m_n_evs)*m_ev_sz, (unsigned char*)m_smps, m_ev_sz);
}
catch(MATExceptions &e)
{
OutputDebugString(e.getAllExceptionStr().c_str());
}
end = GetTickCount();
elapsed = end - begin;
if(elapsed > m_max_tm)
m_warn_msg.Format(_T("Warning! compute time: %dms"), elapsed);
else
m_warn_msg.Format(_T("compute time: %dms"), elapsed);
}
if (m_status == SC_STPNG)
Stop();
}

当单击停止按钮时,似乎缓冲区并不总是响起。在DirectX Stop调用之前,我没有任何特定的代码来等待声音缓冲区播放完毕。除此之外,声音播放还可以,所以至少我可以正确初始化播放器,并且通知代码在这方面也可以正常工作。

最佳答案

尝试将32768替换为32767。绝对不能确定这是您的问题,但是它可能会溢出正的int短范围(假设您的音频为16位)并引起“爆裂”。

关于c++ - 在C++/MFC中停止和启动DirectX声音合成器时弹出/单击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29264125/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com