Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C++/MFC中停止和启动DirectX声音合成器时的POPs/CHILK 我在Visual Studio 2012中用C++、MFC和DirectX制作了一个软合成器。尽管添加了快速淡出声音的代码,但在停止播放和启动播放时,我仍会遇到弹出/点击的声音_C++_Audio_Mfc_Directx - Fatal编程技术网

在C++/MFC中停止和启动DirectX声音合成器时的POPs/CHILK 我在Visual Studio 2012中用C++、MFC和DirectX制作了一个软合成器。尽管添加了快速淡出声音的代码,但在停止播放和启动播放时,我仍会遇到弹出/点击的声音

在C++/MFC中停止和启动DirectX声音合成器时的POPs/CHILK 我在Visual Studio 2012中用C++、MFC和DirectX制作了一个软合成器。尽管添加了快速淡出声音的代码,但在停止播放和启动播放时,我仍会遇到弹出/点击的声音,c++,audio,mfc,directx,C++,Audio,Mfc,Directx,我从该项目复制了DirectX代码: 我不确定是否允许剪切和粘贴代码项目中的所有代码。基本上,我使用该项目中的Player类,这个类的实例在我的代码中称为m_Player。该类中的停止成员函数调用LPDIRECTSOUNDBUFFER的停止函数: void Player::Stop() { DWORD status; if (m_lpDSBuffer == NULL) return; HRESULT hres = m_lpDSBuffer->GetS

我从该项目复制了DirectX代码:

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

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之间的双精度值,即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停止之前,我没有任何特定的代码来等待声音缓冲区完成播放。除此之外,声音播放工作正常,因此至少我正确初始化了播放机,并且通知代码在这方面工作正常。

尝试将32768替换为32767。无论如何都不确定这是你的问题,但如果你的音频为16位,它可能会溢出正的短整数范围,并导致弹出。

我在停止播放时通过在淡出后用零填充缓冲区来消除弹出/点击。然而,当重新开始播放时,我仍然会听到砰砰声,尽管充满了零,然后又逐渐消失,这是令人沮丧的。

有趣的观察。我试过你的建议,但没有解决问题。由于强制转换为int与floor相同,并且我的rend函数不太可能返回1,因此不太可能溢出。AFAIK是16位音频:format.NbBitsPerSample=16correction。。。对于正分数,至少下限与对整数的转换相同。使用整数转换对负分数进行四舍五入。