lm68140318 发表于 2023-8-16 13:40:56

波形图不连续



// ************定义全局变量*************
#define NUM_SAMPLES 1024
HWAVEIN hWaveIn;
WAVEFORMATEX waveform;
short g_samples;
//位深=16,每个采样点两个字节
WAVEHDR waveHeader;
int zong = 0;
CWnd* pWnd;//picture控件句柄
HWND hWnd;
HDC hdc;
HPEN hpen;
HPEN oldhpen;
RECT rect;
HBRUSH hbr;
HBRUSH oldhbr;
HANDLE mutex;//互斥锁句柄
int beisu ;//纵向缩小倍数
int beisu1;//横向放大倍数倍数

int nReturn;
WAVEINCAPS* pwic;
int suoyin = 0;//麦克风ID




//**********初始化**************
        // TODO: 在此添加额外的初始化代码

        // 设置音频格式
        waveform.wFormatTag = WAVE_FORMAT_PCM;
        waveform.nChannels = 1;   // 声道数
        waveform.nSamplesPerSec = 44100;   // 采样频率
        waveform.wBitsPerSample = 16;   // 位深
       
        waveform.nBlockAlign = waveform.nChannels * (waveform.wBitsPerSample / 8);
        waveform.nAvgBytesPerSec = waveform.nSamplesPerSec * waveform.nBlockAlign;
        waveform.cbSize = 0;

        //创建并准备缓冲区
        waveHeader.lpData = (LPSTR)g_samples;
        waveHeader.dwBufferLength = NUM_SAMPLES * sizeof(short);
        waveHeader.dwBytesRecorded = 0;
        waveHeader.dwUser = 0;
        waveHeader.dwFlags = 0;
        waveHeader.dwLoops = 0;
        pWnd = GetDlgItem(IDC_SOUND);//获取picture控件句柄
        hWnd = ::GetDlgItem(GetSafeHwnd(), IDC_SOUND);
        hdc = ::GetDC(hWnd);
        hpen = CreatePen(PS_SOLID, 2, RGB(0, 0, 255));//创建画笔
        oldhpen= (HPEN)SelectObject(hdc, hpen);
        ::GetClientRect(hWnd, &rect);//获取picture控件客户区的坐标
        hbr = CreateSolidBrush(RGB(255, 255, 255));
        oldhbr =(HBRUSH)SelectObject(hdc, hbr);
        FillRect(hdc, &rect, hbr);//绘制并填充矩形

        myspin.SetRange32(0, 1000);    //调节的范围
        myspin.SetBase(10); //十进制
        myspin.SetBuddy(GetDlgItem(IDC_EDIT1));    //设置关联的编辑框
        myspin.SetPos(200);//设置当前值
        beisu = 200;
        beisu1 = 6;

        int nReturn = waveInGetNumDevs();//获取系统中存在的波形音频输入设备数
        if (nReturn==0) {
                AfxMessageBox(_T("请插入麦克风!"));
                return 0;
        }

        pwic = new WAVEINCAPS;
        for (int i = 0; i < nReturn; i++) {
                MMRESULT mmresult = waveInGetDevCaps(i, (pwic+i), sizeof(WAVEINCAPS)); //获取给定的波形音频输入设备的信息
                m_cmbRec.AddString(pwic->szPname);
                //m_cmbRec下拉列表框变量名
        }

        m_cmbRec.SetCurSel(0);
        suoyin= m_cmbRec.GetCurSel();//获取选中项的索引号


       

       
       
        //代码
       

void CMFCyinpinDlg::OnBnClickedBtnStart()
{
        //MMRESULT mm=waveInOpen(&hWaveIn, WAVE_MAPPER, &waveform, (DWORD)this->m_hWnd, NULL, CALLBACK_WINDOW);//打开录音设备
        MMRESULT mm = waveInOpen(&hWaveIn, suoyin, &waveform, (DWORD)this->m_hWnd, NULL, CALLBACK_WINDOW);//打开录音设备
        if (mm != MMSYSERR_NOERROR) {
                AfxMessageBox(_T("打开失败"));
                return;
        }
        waveInPrepareHeader(hWaveIn, &waveHeader, sizeof(WAVEHDR));//准备缓冲区
        waveInAddBuffer(hWaveIn, &waveHeader, sizeof(WAVEHDR));// 添加缓冲区到音频输入设备
        waveInStart(hWaveIn);//启动输入设备

}


void CMFCyinpinDlg::OnBnClickedBtnStop()
{
       
        waveInReset(hWaveIn);//停止录音设备
        waveInUnprepareHeader(hWaveIn, &waveHeader, sizeof(WAVEHDR));//去除缓冲区的准备
        ReleaseMutex(mutex);//释放线程控制权

}




UINT func1(LPVOID pParam)   //线程函数
{
                       
        FillRect(hdc, &rect, hbr);//绘制并填充矩形

        int t = 1;//第一个点不能画直线
        short* g = (short*)pParam;
        DWORD d = WaitForSingleObject(mutex, INFINITE);
               

                for (int i = 0; i < zong / sizeof(short); i++) {
                        if (t == 1) {
                                //移到起始点
                                ::MoveToEx(hdc, i, *(g + i), NULL);
                                t = 0;
                        }
                        else {
                                LineTo(hdc, i* beisu1, *(g + i)/beisu+150);//绘制直线
                        }
                }

       
        return 0;
}


afx_msg LRESULT CMFCyinpinDlg::OnMM_WIM_DATA(WPARAM wParam, LPARAM lParam)
{
        WAVEHDR* pWaveHdr = (WAVEHDR*)lParam;
        memcpy(g_samples, pWaveHdr->lpData, pWaveHdr->dwBytesRecorded);//复制音频数据
        zong = pWaveHdr->dwBytesRecorded;
        CWinThread* pp = AfxBeginThread(func1, (short*)(g_samples), 0, 0, 0, NULL);//创建工作线程
               
        waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR));// 继续录制下一段音频数据
               
        return 0;
}


afx_msg LRESULT CMFCyinpinDlg::OnMM_WIM_CLOSE(WPARAM wParam, LPARAM lParam)
{
       
       
        return 0;
}


void CMFCyinpinDlg::OnDeltaposSpin1(NMHDR* pNMHDR, LRESULT* pResult)
{
        LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
        // TODO: 在此添加控件通知处理程序代码

        beisu = myspin.GetPos();//获取当前值
        CString str;
        str.Format(_T("倍数=%d"),beisu );
        ::OutputDebugString(str);


        *pResult = 0;
}





我的问题:我采集麦克风音频,画出波形图,可是 波形图 不连续??

isdkz 发表于 2023-8-16 13:41:29

问题出在绘制波形图的代码上。在 func1 函数中,每次绘制直线时,使用的是缩小后的坐标和采样值,这导致波形图不连续。解决方法是在绘制直线之前,先将坐标和采样值进行缩放,使其保持连续性。

以下是修改后的代码:

UINT func1(LPVOID pParam)
{
    FillRect(hdc, &rect, hbr); // 绘制并填充矩形

    int t = 1; // 第一个点不能画直线
    short* g = (short*)pParam;
    DWORD d = WaitForSingleObject(mutex, INFINITE);

    for (int i = 0; i < zong / sizeof(short); i++) {
      if (t == 1) {
            // 移到起始点
            ::MoveToEx(hdc, i, *(g + i), NULL);
            t = 0;
      }
      else {
            // 缩放坐标和采样值
            int x = i * beisu1;
            int y = *(g + i) / beisu + 150;
            LineTo(hdc, x, y); // 绘制直线
      }
    }

    return 0;
}


在绘制直线之前,将 i 乘以 beisu1 ,将 *(g + i) 除以 beisu ,这样就保持了坐标和采样值的连续性。

琅琊王朝 发表于 2023-8-16 16:45:00

波形图不连续可能有以下几个原因:

缓冲区设置不正确:在代码中,你使用了固定大小的缓冲区(short g_samples),但是你在处理音频数据时,并没有考虑到缓冲区的填充与清空。你可以尝试增加缓冲区的大小或者优化缓冲区的操作,确保连续的音频数据能够被正确处理。

绘制速度过快:在绘制波形图时,你使用了MoveToEx和LineTo函数来绘制直线。如果绘制速度过快,可能会导致直线之间的间隔过大,从而看起来波形不连续。你可以尝试调整绘制速度或者使用其他绘图方法来实现连续的波形。

数据传输问题:在录制音频数据时,可能存在数据传输的问题,导致采集到的音频数据有丢失或不完整的情况。你可以检查录音设备的设置、音频数据的传输方式等,确保数据能够正确传输。

我建议你先检查以上几个方面,查找问题所在,并进行相应的调整。如果问题仍然存在,可以提供更多关于问题的详细信息,我会尽力提供帮助。

lm68140318 发表于 2023-8-17 11:40:54

isdkz 发表于 2023-8-16 13:41
问题出在绘制波形图的代码上。在 func1 函数中,每次绘制直线时,使用的是缩小后的坐标和采样值,这导致波 ...

你的代码跟我的没什么区别啊   ??
页: [1]
查看完整版本: 波形图不连续