Created
July 27, 2017 00:14
-
-
Save bit-hack/5a51cf731c50d95723f86f2aa61ab022 to your computer and use it in GitHub Desktop.
polling winmm playback
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <array> | |
#include <cassert> | |
#include <cmath> | |
#include <cstdint> | |
#include <Windows.h> | |
#define WAVE_RATE 44100 | |
#define WAVE_SAMPLES 1024 | |
#define WAVE_CHANNELS 2 | |
#define WAVE_DEPTH 16 | |
#define MMOK(EXP) ((EXP) == MMSYSERR_NOERROR) | |
struct WaveData { | |
std::array<WAVEHDR, 4> wavehdr; | |
}; | |
float rate = ((2.f * 3.14f) / float(WAVE_RATE)) * 1000.f; | |
float wval = 0.f; | |
void fillBuffer(WAVEHDR* wavehdr, void* user) | |
{ | |
int16_t* ptr = (int16_t*)wavehdr->lpData; | |
const int16_t* end = (int16_t*)((uint8_t*)ptr + wavehdr->dwBufferLength); | |
for (; ptr < end; ptr += 2) { | |
const int16_t v = int16_t(sinf(wval) * float(0x1fff)); | |
ptr[0] = v; | |
ptr[1] = v; | |
wval += rate; | |
} | |
} | |
bool prepareWaveData(WaveData& data, HWAVEOUT& waveout) | |
{ | |
const size_t numSamples = WAVE_SAMPLES * WAVE_CHANNELS; | |
const size_t numBytes = numSamples * WAVE_DEPTH / 8; | |
for (WAVEHDR& hdr : data.wavehdr) { | |
// allocate the wave header object | |
memset(&hdr, 0, sizeof(hdr)); | |
hdr.lpData = (LPSTR) new int16_t[numBytes]; | |
hdr.dwBufferLength = numBytes; | |
memset(hdr.lpData, 0, numBytes); | |
// prepare the header for the device | |
if (!MMOK(waveOutPrepareHeader(waveout, &hdr, sizeof(hdr)))) { | |
return false; | |
} | |
// write the buffer to the device | |
if (!MMOK(waveOutWrite(waveout, &hdr, sizeof(hdr)))) { | |
return false; | |
} | |
} | |
return true; | |
} | |
bool pollBuffers(WaveData& data, HWAVEOUT& waveout) | |
{ | |
for (WAVEHDR& hdr : data.wavehdr) { | |
// if this buffer is used | |
if ((hdr.dwFlags & WHDR_DONE) == 0) { | |
continue; | |
} | |
if (!MMOK(waveOutUnprepareHeader(waveout, &hdr, sizeof(hdr)))) { | |
return false; | |
} | |
// fill with new data | |
fillBuffer(&hdr, 0); | |
if (!MMOK(waveOutPrepareHeader(waveout, &hdr, sizeof(hdr)))) { | |
return false; | |
} | |
if (!MMOK(waveOutWrite(waveout, &hdr, sizeof(WAVEHDR)))) { | |
return false; | |
} | |
} | |
return true; | |
} | |
int main() | |
{ | |
// prepare output wave format | |
WAVEFORMATEX waveformat; | |
memset(&waveformat, 0, sizeof(waveformat)); | |
waveformat.cbSize = 0; | |
waveformat.wFormatTag = WAVE_FORMAT_PCM; | |
waveformat.nChannels = WAVE_CHANNELS; | |
waveformat.nSamplesPerSec = WAVE_RATE; | |
waveformat.wBitsPerSample = WAVE_DEPTH; | |
waveformat.nBlockAlign = (WAVE_CHANNELS * waveformat.wBitsPerSample) / 8; | |
waveformat.nAvgBytesPerSec = WAVE_RATE * waveformat.nBlockAlign; | |
// create wave output | |
HWAVEOUT waveout; | |
memset(&waveout, 0, sizeof(waveout)); | |
if (!MMOK(waveOutOpen( | |
&waveout, | |
WAVE_MAPPER, | |
&waveformat, | |
NULL, | |
NULL, | |
CALLBACK_NULL))) { | |
return 1; | |
} | |
// prepare waveout data | |
WaveData wavedata; | |
if (!prepareWaveData(wavedata, waveout)) { | |
return 1; | |
} | |
// buffer poll and refill loop | |
for (;;) { | |
if (!pollBuffers(wavedata, waveout)) { | |
break; | |
} | |
Sleep(10); | |
} | |
// teardown | |
waveOutClose(waveout); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment