2011-04-28 91 views
3

我如何在Windows(32位和64位,直至Windows 7)上播放本機具有給定幅度和給定頻率的聲音(例如,由頻率2 kHz和3 kHz組成)?在Windows上播放任意聲音?

(通過原生我的意思是不使用外部庫)。

我相信這需要waveOutWrite方法,但我不知道它是如何工作的。

回答

2

我得到的東西的工作...

#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; 
} 
+0

+1。但我認爲三角波發生器是錯誤的。根據[Wikipedia](http://en.wikipedia.org/wiki/Triangle_wave#Definitions):'返回(float)asin(sin(angle + 0 * M_PI/2))* 2/M_PI;'。 – JRL 2015-03-01 18:10:28

2

Beep

BOOL WINAPI Beep(
    __in DWORD dwFreq, 
    __in DWORD dwDuration 
); 
0

經由PC揚聲器,或使用的DirectX音動作。 如果需要,我可以提供一些片段。

+0

好蜂鳴功能沒有按不起作用,因爲它不能產生頻率組合。 DirectX的聲音看起來像是過度殺毒,因爲我只是想生成一個簡單的語氣...有沒有辦法用'waveOutWrite'這樣的東西來做?我認爲這是正確的方式,但我不知道要給它什麼數據。 – Mehrdad 2011-04-28 07:35:52

+0

@Mehrdad:wavOutWrite預計WAV格式的聲音塊,iirc。 – 2011-04-29 05:20:35

+0

@亞當:啊,現在*這是一個很好的答案。 =)隨意張貼,所以我可以接受它! (順便說一句,它是*完整*波形數據還是其中的一部分?我是否也需要發送所有RIFF標題?) – Mehrdad 2011-04-29 06:47:35

1

waveOut功能處理聲音波形數據(如果我正確記得,以WAV格式)。

雖然這是針對WPF應用程序,以下鏈接應該證明對任何桌面應用程序有所幫​​助:

Sound Generation in WPF Applications

+0

很酷,感謝您的鏈接! – Mehrdad 2011-04-29 18:00:45