【问题标题】:Analysing audio with Windows API in C++在 C++ 中使用 Windows API 分析音频
【发布时间】:2013-07-25 07:38:20
【问题描述】:

(我在这里的第一个问题,所以我希望我没有踩到任何脚趾 - 我尝试搜索我的问题,但我没有看到任何似乎适用的东西;但它可能有而且我根本没有明白我在看什么。)

我以前从来不需要处理音频,所以我有点失落。我需要做的很简单;监控来自麦克风的实时馈送,并在音量超过一定水平时做一些事情。我已经完成了做的事情,但是我所有试图理解音频的谷歌搜索让我比开始时更加困惑。

如果它有所作为;我正在使用 Visual Studio Express 2012。

这是我目前的代码:

#include <windows.h>
#include <queue>
//I figured I could put the sound info
//in a queue and push it through checking
//the volume as I went.

using namespace std;

//For this code, the below is just for debug messages
//It plays a more important role in the full code.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        LPSTR lpCmdLine, int nCmdShow);

//This seemed to be a decent way to make sure I could read in
//from the audio.
MMRESULT IsFormatSupported(LPWAVEFORMATEX pwfx, UINT uDeviceID) 
{ 
    return (waveOutOpen( 
        NULL,                 // ptr can be NULL for query 
        uDeviceID,            // the device identifier 
        pwfx,                 // defines requested format 
        NULL,                 // no callback 
        NULL,                 // no instance data 
        WAVE_FORMAT_QUERY));  // query only, do not open device 
} 

int main()
{
    UINT wReturn; 
    const int NUMPTS = 11025 * 10;   // 10 seconds
    short int waveIn[NUMPTS];
    queue<short int*> my_queue;
    WAVEFORMATEX pcmWaveFormat; 

    // Set up WAVEFORMATEX for 11 kHz 8-bit mono. 

    pcmWaveFormat.wFormatTag = WAVE_FORMAT_PCM; 
    pcmWaveFormat.nChannels = 1; 
    pcmWaveFormat.nSamplesPerSec = 11025L; 
    pcmWaveFormat.nAvgBytesPerSec = 11025L; 
    pcmWaveFormat.nBlockAlign = 1; 
    pcmWaveFormat.wBitsPerSample = 8; 
    pcmWaveFormat.cbSize = 0;
    MMRESULT result = 0;
    HWAVEIN microHandle;
    WAVEHDR waveHeader;
    // See if format is supported by any device in system. 

    wReturn = IsFormatSupported(&pcmWaveFormat, WAVE_MAPPER); 
    // Report results. 
    if (wReturn == 0) 
    {
        //To make sure I can actually get the audio:
        //MessageBox(NULL, "11 kHz 8-bit mono IS supported.",
        //"", MB_ICONINFORMATION); 
    }
    else if (wReturn == WAVERR_BADFORMAT) 
    {
    MessageBox(NULL, "11 kHz 8-bit mono NOT supported.",
        "", MB_ICONINFORMATION); 
    return -2;
    }
    else 
    {
    MessageBox(NULL, "Error opening waveform device.",
        "Error", MB_ICONEXCLAMATION); 
    return -3;
    }

result = waveInOpen(&microHandle, WAVE_MAPPER,
         &pcmWaveFormat, 0L, 0L, WAVE_FORMAT_DIRECT); 
    // Set up and prepare header for input
    waveHeader.lpData = (LPSTR)waveIn;
    waveHeader.dwBufferLength = NUMPTS*2;
    waveHeader.dwBytesRecorded=0;
    waveHeader.dwUser = 0L;
    waveHeader.dwFlags = 0L;
    waveHeader.dwLoops = 0L;
    waveInPrepareHeader(microHandle, &waveHeader, sizeof(WAVEHDR));

    // Insert a wave input buffer
    result = waveInAddBuffer(microHandle, &waveHeader, sizeof(WAVEHDR));

    waveInStart(microHandle);
    //In theory, this should stop after ten seconds,
    //as set by NUMPTS - but doesn't.
do {} while (waveInUnprepareHeader(microHandle,
    &waveHeader, sizeof(WAVEHDR))==WAVERR_STILLPLAYING);
MessageBox(NULL, "Done Recording", "", MB_ICONINFORMATION); 

    waveInClose(microHandle);

    cout << "Press ENTER to continue...";
    cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
    return 0;
}

我还必须手动进入项目属性并在 Linker->Input->Additional Dependencies 下添加 Winmm.lib

我不确定从这里去哪里。我知道我需要检查音频流的音量,但我不需要存储它以供以后使用,这就是我放置#include 队列的原因。但我什至不知道在队列中存储什么或如何阅读它,所以我不完全确定这是否合适。

如果有人对音频初学者有建议、答案或好的资源,我将不胜感激。

【问题讨论】:

  • 你需要在waveInUnprepareHeader之前调用waveInStart
  • 那...可能会有所帮助。谢谢。
  • 如果只有 SDL 可以同时进行音频输入和音频输出,我当然会推荐它,因为它比任何 Windows API 都更易于使用。

标签: winapi visual-c++ audio


【解决方案1】:

如果您使用 16 位/样本,则值将接近 0 以表示静音。响亮的音调会产生具有正负峰值的正弦波 (+32K ... - 32K)。

短体积 = abs(sample);

音高不是那么容易。从技术上讲,它是正弦波过零之间时间的补充。有一种数学算法 (FFT) 可以计算音调频谱。

要更熟悉这些概念,请获取音频编辑器并使用它。它们显示来自 waveIn 或 WAV 文件的数据。其中有无数可用作共享软件。

【讨论】:

  • 好的,这比我最初想象的要复杂一些:但是你给了我足够的东西来开始弄清楚,所以非常感谢。
【解决方案2】:

音频样本将在您的 waveIn 缓冲区中。不需要队列,只需检查 waveIn 中的值。

您使用了 8 位/样本。如果这真的是你想要的 waveIn 缓冲区是错误的类型。它应该是字节,而不是短裤。但是 16 位/样本是更好的选择:8 位数据是一种有趣的格式,需要额外的转换。如果每个样本使用 16 位,则普通有符号算术将用于比较样本值。

【讨论】:

  • 谢谢。看来我还需要设置pcmWaveFormat.nChannels = 2;,否则会出现“不支持”错误。这有助于查看数据,而且我知道它正在工作,因为每次打印出来时我都会得到不同的值。我把for (int x = 0; x&lt;=15; x++){cout &lt;&lt; waveIn[x] &lt;&lt; endl;} 放在waveInClose(microHandle); 之后,每次运行它都不同。但是这些值是什么意思?例如,我如何提取音量或音高?这有参考吗?最后,我假设每个声音样本一次只需要查看一个waveIn;对吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-06
  • 2014-01-19
  • 1970-01-01
  • 2014-05-07
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多