2014-09-02 19 views
1

소프트웨어 자동 변환없이 winmm (waveOutXxxx())을 사용하여 44100hz 8 비트 모노 PCM 스트림을 열려고합니다. (이러한 변환으로 인해 발생할 수있는 필터링없이 출력 파형을 완벽하게 제어하려고합니다.)waveOutGetDevCaps()가 할 수있을 때 Windows Vista/latera의 waveOutOpen()이 기본 출력 장치가 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: %s\n", errmsg); 
     return 1; 
    } 
    fprintf(stderr, "open successful\n"); 
    return 0; 
} 

Windows XP와 와인에서 잘 작동합니다.

// 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 %x\n", 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: %d\n", 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 

이다 : 그러나 Windows 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. 

을 얻을 그럼 그렇게하자 ... 대기하지만 WAVE_FORMAT_4M08은 지원 목록에 있습니다!

무엇을 제공합니까? 감사.

답변

3

오류는 nBlockAlign 값이 잘못 되었기 때문에 waveOutOpen()WAVEFORMATEX 구조체를 거부 함을 나타냅니다. documentation 상태 :

wFormatTag가 WAVE_FORMAT_PCM 인 경우, nBlockAlign는 동일해야합니다 (nChannels × wBitsPerSample)/8

당신은 / 8 부분 누락 :

fmt.nBlockAlign = (fmt.nChannels * fmt.wBitsPerSample)/8; 
+0

아차, 내 나쁜 . 감사! – andlabs