Winapi 在Windows上播放任意声音?
比如说,我如何在Windows(32位和64位,直至Windows 7)上本机播放具有给定振幅和给定频率组成(例如,由2 kHz和3 kHz频率组成)的声音 (我所说的本机是指不使用外部库。) 我相信这需要这种方法,但我不知道它是如何工作的。Winapi 在Windows上播放任意声音?,winapi,audio,wave,Winapi,Audio,Wave,比如说,我如何在Windows(32位和64位,直至Windows 7)上本机播放具有给定振幅和给定频率组成(例如,由2 kHz和3 kHz频率组成)的声音 (我所说的本机是指不使用外部库。) 我相信这需要这种方法,但我不知道它是如何工作的。 通过pc扬声器或使用Directx声音发出嘟嘟声。 如果您需要,我可以提供一些片段。waveOut函数处理声音波形数据(如果我没有记错的话,以WAV格式) 虽然这是针对WPF应用程序的,但以下链接对任何桌面应用程序都会有帮助: 我有些东西在工作 #defi
通过pc扬声器或使用Directx声音发出嘟嘟声。
如果您需要,我可以提供一些片段。waveOut函数处理声音波形数据(如果我没有记错的话,以WAV格式) 虽然这是针对WPF应用程序的,但以下链接对任何桌面应用程序都会有帮助:
我有些东西在工作
#define _USE_MATH_DEFINES 1
#include <math.h>
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <mmreg.h>
#include <complex>
#pragma comment(lib, "Winmm.lib")
MMRESULT play(float nSeconds,
float signal(float timeInSeconds, unsigned short channel, void *context),
void *context = NULL, unsigned long samplesPerSecond = 48000)
{
UINT timePeriod = 1;
MMRESULT mmresult = MMSYSERR_NOERROR;
WAVEFORMATEX waveFormat = {0};
waveFormat.cbSize = 0;
waveFormat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
waveFormat.nChannels = 2;
waveFormat.nSamplesPerSec = samplesPerSecond;
const size_t nBuffer =
(size_t)(nSeconds * waveFormat.nChannels * waveFormat.nSamplesPerSec);
float *buffer;
waveFormat.wBitsPerSample = CHAR_BIT * sizeof(buffer[0]);
waveFormat.nBlockAlign =
waveFormat.nChannels * waveFormat.wBitsPerSample / CHAR_BIT;
waveFormat.nAvgBytesPerSec =
waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
buffer = (float *)calloc(nBuffer, sizeof(*buffer));
__try
{
for (size_t i = 0; i < nBuffer; i += waveFormat.nChannels)
for (unsigned short j = 0; j < waveFormat.nChannels; j++)
buffer[i+j] = signal((i+j) * nSeconds / nBuffer, j, context);
HWAVEOUT hWavOut = NULL;
mmresult = waveOutOpen(&hWavOut, WAVE_MAPPER,
&waveFormat, NULL, NULL, CALLBACK_NULL);
if (mmresult == MMSYSERR_NOERROR)
{
__try
{
timeBeginPeriod(timePeriod);
__try
{
WAVEHDR hdr = {0};
hdr.dwBufferLength =
(ULONG)(nBuffer * sizeof(buffer[0]));
hdr.lpData = (LPSTR)&buffer[0];
mmresult = waveOutPrepareHeader(hWavOut,
&hdr, sizeof(hdr));
if (mmresult == MMSYSERR_NOERROR)
{
__try
{
ULONG start = GetTickCount();
mmresult =
waveOutWrite(hWavOut, &hdr, sizeof(hdr));
Sleep((ULONG)(1000 * nSeconds
- (GetTickCount() - start)));
}
__finally
{ waveOutUnprepareHeader(hWavOut, &hdr, sizeof(hdr)); }
}
}
__finally { timeEndPeriod(timePeriod); }
}
__finally { waveOutClose(hWavOut); }
}
}
__finally { free(buffer); }
return mmresult;
}
// Triangle wave generator
float triangle(float timeInSeconds, unsigned short channel, void *context)
{
const float frequency = *(const float *)context;
const float angle = (float)(frequency * 2 * M_PI * timeInSeconds);
switch (channel)
{
case 0: return (float)asin(sin(angle + 0 * M_PI / 2));
default: return (float)asin(sin(angle + 1 * M_PI / 2));
}
}
// Pure tone generator
float pure(float timeInSeconds, unsigned short channel, void *context)
{
const float frequency = *(const float *)context;
const float angle = (float)(frequency * 2 * M_PI * timeInSeconds);
switch (channel)
{
case 0: return (float)sin(angle + 0 * M_PI / 2);
default: return (float)sin(angle + 1 * M_PI / 2);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
float frequency = 2 * 261.626F;
play(1, pure, &frequency);
return 0;
}
定义使用数学定义1
#包括
#包括
#包括
#包括
#包括
#包括
#pragma注释(lib,“Winmm.lib”)
MM结果播放(浮点N秒,
浮点信号(浮点时间顺序、无符号短通道、void*上下文),
void*context=NULL,无符号长样本persecond=48000)
{
UINT时间段=1;
MMRESULT MMRESULT=MMSYSERR\u NOERROR;
WAVEFORMATEX waveFormat={0};
waveFormat.cbSize=0;
waveFormat.wFormatTag=WAVE\u FORMAT\u IEEE\u FLOAT;
波形通道=2;
waveFormat.nSamplesPerSec=采样每秒;
常数大小=
(大小)(N秒*waveFormat.nChannels*waveFormat.nSamplesPerSec);
浮点*缓冲器;
waveFormat.wBitsPerSample=CHAR_BIT*sizeof(缓冲器[0]);
波形格式nBlockAlign=
waveFormat.nchannes*waveFormat.wBitsPerSample/CHAR\u位;
波形格式nAvgBytesPerSec=
waveFormat.nSamplesPerSec*waveFormat.nBlockAlign;
buffer=(float*)calloc(nBuffer,sizeof(*buffer));
__试一试
{
对于(大小i=0;i
蜂鸣器功能无法工作,因为它无法生成频率组合。DirectX的声音似乎有些过分,因为我只想生成一个简单的音调。。。有没有办法用像waveOutWrite这样的东西来实现这一点?我认为这是正确的方法,但我不知道应该提供什么数据。@Mehrdad:WavowWrite需要WAV格式的声音块,iirc。@Adam:啊,这是一个很好的答案。=)请随意张贴,这样我就可以接受了!(顺便说一句,它是完整的波浪数据还是它的一部分?我是否也需要发送所有的RIFF头?+1。但我认为三角波发生器是错误的。根据:return(float)asin(sin(角度+0*M_-PI/2))*2/M_-PI代码>。
#define _USE_MATH_DEFINES 1
#include <math.h>
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <mmreg.h>
#include <complex>
#pragma comment(lib, "Winmm.lib")
MMRESULT play(float nSeconds,
float signal(float timeInSeconds, unsigned short channel, void *context),
void *context = NULL, unsigned long samplesPerSecond = 48000)
{
UINT timePeriod = 1;
MMRESULT mmresult = MMSYSERR_NOERROR;
WAVEFORMATEX waveFormat = {0};
waveFormat.cbSize = 0;
waveFormat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
waveFormat.nChannels = 2;
waveFormat.nSamplesPerSec = samplesPerSecond;
const size_t nBuffer =
(size_t)(nSeconds * waveFormat.nChannels * waveFormat.nSamplesPerSec);
float *buffer;
waveFormat.wBitsPerSample = CHAR_BIT * sizeof(buffer[0]);
waveFormat.nBlockAlign =
waveFormat.nChannels * waveFormat.wBitsPerSample / CHAR_BIT;
waveFormat.nAvgBytesPerSec =
waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
buffer = (float *)calloc(nBuffer, sizeof(*buffer));
__try
{
for (size_t i = 0; i < nBuffer; i += waveFormat.nChannels)
for (unsigned short j = 0; j < waveFormat.nChannels; j++)
buffer[i+j] = signal((i+j) * nSeconds / nBuffer, j, context);
HWAVEOUT hWavOut = NULL;
mmresult = waveOutOpen(&hWavOut, WAVE_MAPPER,
&waveFormat, NULL, NULL, CALLBACK_NULL);
if (mmresult == MMSYSERR_NOERROR)
{
__try
{
timeBeginPeriod(timePeriod);
__try
{
WAVEHDR hdr = {0};
hdr.dwBufferLength =
(ULONG)(nBuffer * sizeof(buffer[0]));
hdr.lpData = (LPSTR)&buffer[0];
mmresult = waveOutPrepareHeader(hWavOut,
&hdr, sizeof(hdr));
if (mmresult == MMSYSERR_NOERROR)
{
__try
{
ULONG start = GetTickCount();
mmresult =
waveOutWrite(hWavOut, &hdr, sizeof(hdr));
Sleep((ULONG)(1000 * nSeconds
- (GetTickCount() - start)));
}
__finally
{ waveOutUnprepareHeader(hWavOut, &hdr, sizeof(hdr)); }
}
}
__finally { timeEndPeriod(timePeriod); }
}
__finally { waveOutClose(hWavOut); }
}
}
__finally { free(buffer); }
return mmresult;
}
// Triangle wave generator
float triangle(float timeInSeconds, unsigned short channel, void *context)
{
const float frequency = *(const float *)context;
const float angle = (float)(frequency * 2 * M_PI * timeInSeconds);
switch (channel)
{
case 0: return (float)asin(sin(angle + 0 * M_PI / 2));
default: return (float)asin(sin(angle + 1 * M_PI / 2));
}
}
// Pure tone generator
float pure(float timeInSeconds, unsigned short channel, void *context)
{
const float frequency = *(const float *)context;
const float angle = (float)(frequency * 2 * M_PI * timeInSeconds);
switch (channel)
{
case 0: return (float)sin(angle + 0 * M_PI / 2);
default: return (float)sin(angle + 1 * M_PI / 2);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
float frequency = 2 * 261.626F;
play(1, pure, &frequency);
return 0;
}