4

我正在用原生 vc++(不是 .Net)制作游戏

我正在寻找一种通过真正的扬声器(不是内部)播放噪音(可能是 8 位或其他东西)的方法。我知道 PlaySound,但我不想让我的 EXE 变大。我想对声音进行编程。

是否有一种 api 方式(有点像 Beep() )但通过真正的扬声器播放?

谢谢

4

4 回答 4

11

你提到你知道PlaySound。它的标志之一 ( SND_MEMORY) 将允许您播放已加载到内存中的 WAVE,即您自己创建的缓冲区。只要缓冲区具有适当的 WAVE 标头,您放入其中的任何内容都应该通过扬声器播放。

标头是一个 44 字节的块,非常简单

struct WaveHeader
{
    DWORD chunkID;       // 0x46464952 "RIFF" in little endian
    DWORD chunkSize;     // 4 + (8 + subChunk1Size) + (8 + subChunk2Size)
    DWORD format;        // 0x45564157 "WAVE" in little endian

    DWORD subChunk1ID;   // 0x20746d66 "fmt " in little endian
    DWORD subChunk1Size; // 16 for PCM
    WORD  audioFormat;   // 1 for PCM, 3 fot EEE floating point , 7 for μ-law
    WORD  numChannels;   // 1 for mono, 2 for stereo
    DWORD sampleRate;    // 8000, 22050, 44100, etc...
    DWORD byteRate;      // sampleRate * numChannels * bitsPerSample/8
    WORD  blockAlign;    // numChannels * bitsPerSample/8
    WORD  bitsPerSample; // number of bits (8 for 8 bits, etc...)

    DWORD subChunk2ID;   // 0x61746164 "data" in little endian
    DWORD subChunk2Size; // numSamples * numChannels * bitsPerSample/8 (this is the actual data size in bytes)
};

您将使用类似于以下内容的方式设置缓冲区:

char *myBuffer = new char[sizeof(WaveHeader) + myDataSize];

WaveHeader *header = (WaveHeader*)myBuffer;
// fill out the header...

char *data = myBuffer + sizeof(WaveHeader); //jumps to beginning of data
// fill out waveform data...

所以你使用它是这样的:

PlaySound(myBuffer, NULL, SND_MEMORY | SND_ASYNC);

我假设您将在您的应用程序的整个生命周期中使用您生成的声音。如果不是,请小心使用该SND_ASYNC标志。也就是说,不要在调用 PlaySound 后直接释放缓冲区(当它仍在使用时)。

MSDN PlaySound Docs
有关 WAV 标头的更多详细信息的页面- 现在不工作)

DirectX 还支持从内存缓冲区播放音频,并且是一个功能更强大的 API,但对于您需要做的事情来说,它可能有点矫枉过正 :)

于 2009-09-20T19:28:05.043 回答
1

虽然 Windows 上有多种可能性,但最简单的一种是 sndPlaySound():

  • 包括mmsystem.h
  • 链接到winmm.lib
  • ::sndPlaySound("sound.wav", SND_ASYNC|SND_NODEFAULT);
  • 停止播放:::sndPlaySound(NULL, NULL);

当然,如果您更清楚地看到自己的需求,还有其他方法,例如 mci 和直达声,可能会更好地满足您的需求。

于 2009-09-20T18:30:11.803 回答
0

我发现了这个: http ://www.xtremevbtalk.com/showthread.php?p=829281 它可能对你有用

于 2009-09-20T18:07:45.140 回答
0

我对另一个问题的回答可能会有所帮助,请在此处查看

我谈论了一个易于使用的开源 api(综合工具包),它具有读取/写入 wav 文件的类,并且具有易于使用的包装类来实时输出到不同的驱动程序(wdm、asio、jack...)

恕我直言,它比 winapi 函数更容易使用

于 2009-09-20T19:54:28.700 回答