鱼C论坛

 找回密码
 立即注册
查看: 264|回复: 3

波形图不连续

[复制链接]
发表于 2023-8-16 13:40:56 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x


  1. // ************定义全局变量*************
  2. #define NUM_SAMPLES 1024
  3. HWAVEIN hWaveIn;
  4. WAVEFORMATEX waveform;
  5. short g_samples[NUM_SAMPLES];
  6. //位深=16,每个采样点两个字节
  7. WAVEHDR waveHeader;
  8. int zong = 0;
  9. CWnd* pWnd;  //picture控件句柄
  10. HWND hWnd;
  11. HDC hdc;
  12. HPEN hpen;
  13. HPEN oldhpen;
  14. RECT rect;
  15. HBRUSH hbr;
  16. HBRUSH oldhbr;
  17. HANDLE mutex;//互斥锁句柄
  18. int beisu ;//纵向缩小倍数
  19. int beisu1;//横向放大倍数倍数

  20. int nReturn;
  21. WAVEINCAPS* pwic;
  22. int suoyin = 0;//麦克风ID




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

  25.         // 设置音频格式
  26.         waveform.wFormatTag = WAVE_FORMAT_PCM;
  27.         waveform.nChannels = 1;   // 声道数
  28.         waveform.nSamplesPerSec = 44100;   // 采样频率
  29.         waveform.wBitsPerSample = 16;   // 位深
  30.        
  31.         waveform.nBlockAlign = waveform.nChannels * (waveform.wBitsPerSample / 8);
  32.         waveform.nAvgBytesPerSec = waveform.nSamplesPerSec * waveform.nBlockAlign;
  33.         waveform.cbSize = 0;

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

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

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

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

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


  69.        

  70.        
  71.        
  72.         //代码
  73.        

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

  85. }


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

  92. }




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

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

  101.                 for (int i = 0; i < zong / sizeof(short); i++) {
  102.                         if (t == 1) {
  103.                                 //移到起始点
  104.                                 ::MoveToEx(hdc, i, *(g + i), NULL);
  105.                                 t = 0;
  106.                         }
  107.                         else {
  108.                                 LineTo(hdc, i* beisu1, *(g + i)/beisu+150);//绘制直线
  109.                         }
  110.                 }

  111.        
  112.         return 0;
  113. }


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


  125. afx_msg LRESULT CMFCyinpinDlg::OnMM_WIM_CLOSE(WPARAM wParam, LPARAM lParam)
  126. {
  127.        
  128.        
  129.         return 0;
  130. }


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

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


  139.         *pResult = 0;
  140. }

复制代码




我的问题:我采集麦克风音频,画出波形图,可是 波形图 不连续  ??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-8-16 13:41:29 | 显示全部楼层
问题出在绘制波形图的代码上。在 func1 函数中,每次绘制直线时,使用的是缩小后的坐标和采样值,这导致波形图不连续。解决方法是在绘制直线之前,先将坐标和采样值进行缩放,使其保持连续性。

以下是修改后的代码:

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

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

  7.     for (int i = 0; i < zong / sizeof(short); i++) {
  8.         if (t == 1) {
  9.             // 移到起始点
  10.             ::MoveToEx(hdc, i, *(g + i), NULL);
  11.             t = 0;
  12.         }
  13.         else {
  14.             // 缩放坐标和采样值
  15.             int x = i * beisu1;
  16.             int y = *(g + i) / beisu + 150;
  17.             LineTo(hdc, x, y); // 绘制直线
  18.         }
  19.     }

  20.     return 0;
  21. }
复制代码


在绘制直线之前,将 i 乘以 beisu1 ,将 *(g + i) 除以 beisu ,这样就保持了坐标和采样值的连续性。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-16 16:45:00 | 显示全部楼层
波形图不连续可能有以下几个原因:

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

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

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

我建议你先检查以上几个方面,查找问题所在,并进行相应的调整。如果问题仍然存在,可以提供更多关于问题的详细信息,我会尽力提供帮助。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

你的代码  跟我的没什么区别啊   ??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-27 14:03

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表