我正试图在没有软件自动转换的情况下使用winmm(waveOutXxxx()
)打开44100hz 8位单声道PCM流(我希望完全控制输出波形,而不进行此类转换可能导致的滤波)。
// 2 september 2014
#define UNICODE
#define _UNICODE
#define STRICT
#define STRICT_TYPED_ITEMIDS
// get Windows version right; right now Windows XP
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#define _WIN32_WINDOWS 0x0501 /* according to Microsoft's winperf.h */
#define _WIN32_IE 0x0600 /* according to Microsoft's sdkddkver.h */
#define NTDDI_VERSION 0x05010000 /* according to Microsoft's sdkddkver.h */
#include <windows.h>
#include <stdio.h>
int main(void)
{
HWAVEOUT wo;
HANDLE event;
WAVEFORMATEX fmt;
MMRESULT err;
event = CreateEvent(NULL, TRUE, TRUE, NULL); // start off signaled just in case
if (event == NULL) {
fprintf(stderr, "CreateEvent() failed (last error %d)n", GetLastError());
return 3;
}
ZeroMemory(&fmt, sizeof (WAVEFORMATEX));
fmt.wFormatTag = WAVE_FORMAT_PCM;
fmt.nChannels = 1;
fmt.nSamplesPerSec = 44100;
fmt.wBitsPerSample = 8;
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample;
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
fmt.cbSize = 0;
err = waveOutOpen(&wo, WAVE_MAPPER, &fmt,
(DWORD_PTR) event, 0,
CALLBACK_EVENT | WAVE_FORMAT_DIRECT);
if (err != MMSYSERR_NOERROR) {
WCHAR errmsg[MAXERRORLENGTH + 1];
MMRESULT converr;
converr = waveOutGetErrorTextW(err, errmsg, MAXERRORLENGTH + 1);
if (converr != MMSYSERR_NOERROR) {
fprintf(stderr, "open error %x (message conversion error %x)n", err, converr);
return 2;
}
fwprintf(stderr, L"open error: %sn", errmsg);
return 1;
}
fprintf(stderr, "open successfuln");
return 0;
}
这在Windows XP和葡萄酒中运行良好。但在Windows Vista和更新版本(已经尝试过Vista、7和8.1)上,我得到了
open error: The specified format is not supported or cannot be translated. Use the Capabilities function to determine the supported formats.
让我们这样做:
// 1 september 2014
#define UNICODE
#define _UNICODE
#define STRICT
#define STRICT_TYPED_ITEMIDS
// get Windows version right; right now Windows XP
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#define _WIN32_WINDOWS 0x0501 /* according to Microsoft's winperf.h */
#define _WIN32_IE 0x0600 /* according to Microsoft's sdkddkver.h */
#define NTDDI_VERSION 0x05010000 /* according to Microsoft's sdkddkver.h */
#include <windows.h>
#include <stdio.h>
int main(void)
{
MMRESULT err;
WAVEOUTCAPS caps;
ZeroMemory(&caps, sizeof (WAVEOUTCAPS));
err = waveOutGetDevCaps((DWORD_PTR) WAVE_MAPPER, &caps, sizeof (WAVEOUTCAPS));
if (err != MMSYSERR_NOERROR) {
fprintf(stderr, "mmsys err %xn", err);
return 1;
}
printf("formats: ");
#define FORMATS(x) if((caps.dwFormats & x) != 0) printf("%s ", #x);
FORMATS(WAVE_FORMAT_1M08);
FORMATS(WAVE_FORMAT_1M16);
FORMATS(WAVE_FORMAT_1S08);
FORMATS(WAVE_FORMAT_1S16);
FORMATS(WAVE_FORMAT_2M08);
FORMATS(WAVE_FORMAT_2M16);
FORMATS(WAVE_FORMAT_2S08);
FORMATS(WAVE_FORMAT_2S16);
FORMATS(WAVE_FORMAT_4M08);
FORMATS(WAVE_FORMAT_4M16);
FORMATS(WAVE_FORMAT_4S08);
FORMATS(WAVE_FORMAT_4S16);
FORMATS(WAVE_FORMAT_96M08);
FORMATS(WAVE_FORMAT_96M16);
FORMATS(WAVE_FORMAT_96S08);
FORMATS(WAVE_FORMAT_96S16);
printf("n");
printf("channels: %dn", caps.wChannels);
printf("supports: ");
#define SUPPORTS(x) if((caps.dwSupport & x) != 0) printf("%s ", #x);
SUPPORTS(WAVECAPS_LRVOLUME);
SUPPORTS(WAVECAPS_PITCH);
SUPPORTS(WAVECAPS_PLAYBACKRATE);
SUPPORTS(WAVECAPS_SYNC);
SUPPORTS(WAVECAPS_VOLUME);
SUPPORTS(WAVECAPS_SAMPLEACCURATE);
printf("n");
return 0;
}
现在的输出是
formats: WAVE_FORMAT_1M08 WAVE_FORMAT_1M16 WAVE_FORMAT_1S08 WAVE_FORMAT_1S16 WAVE_FORMAT_2M08 WAVE_FORMAT_2M16 WAVE_FORMAT_2S08 WAVE_FORMAT_2S16 WAVE_FORMAT_4M08 WAVE_FORMAT_4M16 WAVE_FORMAT_4S08 WAVE_FORMAT_4S16 WAVE_FORMAT_96M08 WAVE_FORMAT_96M16 WAVE_FORMAT_96S08 WAVE_FORMAT_96S16
channels: 2
supports: WAVECAPS_LRVOLUME WAVECAPS_VOLUME WAVECAPS_SAMPLEACCURATE
但是等待,WAVE_FORMAT_4M08
被列为支持!
什么东西?谢谢
此错误表示waveOutOpen()
拒绝您的WAVEFORMATEX
结构,可能是因为nBlockAlign
值错误。文件说明:
如果wFormatTag为WAVE_FORMAT_PCM,nBlockAlign必须等于(nChannels×wBitsPerSample)/8
您缺少/ 8
部分:
fmt.nBlockAlign = (fmt.nChannels * fmt.wBitsPerSample) / 8;