为什么 Windows Vista/更新版上的 waveOutOpen() 说默认输出设备不能播放 44100hz 单声道 8 位 PCM,而 waveOutGetDevCaps() 说它可以?



我正试图在没有软件自动转换的情况下使用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;

相关内容

  • 没有找到相关文章

最新更新