1 #include <windows.h> 2 #include <mmsystem.h> 3 #include "device_mm.h" 4 #include "utility.h" 5 6 7 namespace audiere { 8 9 static const int RATE = 44100; 10 11 12 MMAudioDevice* create(const ParameterList & parameters)13 MMAudioDevice::create(const ParameterList& parameters) { 14 WAVEFORMATEX wfx; 15 memset(&wfx, 0, sizeof(wfx)); 16 wfx.wFormatTag = WAVE_FORMAT_PCM; 17 wfx.nChannels = 2; 18 wfx.nSamplesPerSec = RATE; 19 wfx.nAvgBytesPerSec = RATE * 4; 20 wfx.nBlockAlign = 4; 21 wfx.wBitsPerSample = 16; 22 wfx.cbSize = sizeof(WAVEFORMATEX); 23 24 HWAVEOUT handle; 25 MMRESULT result = waveOutOpen(&handle, WAVE_MAPPER, &wfx, 0, 0, 0); 26 if (result != MMSYSERR_NOERROR) { 27 return 0; 28 } 29 30 return new MMAudioDevice(handle, RATE); 31 } 32 33 MMAudioDevice(HWAVEOUT device,int rate)34 MMAudioDevice::MMAudioDevice(HWAVEOUT device, int rate) 35 : MixerDevice(rate) 36 { 37 ADR_GUARD("MMAudioDevice::MMAudioDevice"); 38 39 m_device = device; 40 m_current_buffer = 0; 41 42 // fill each buffer with samples and prepare it for output 43 for (int i = 0; i < BUFFER_COUNT; ++i) { 44 WAVEHDR& wh = m_buffers[i]; 45 memset(&wh, 0, sizeof(wh)); 46 wh.lpData = (char*)m_samples + i * BUFFER_LENGTH; 47 wh.dwBufferLength = BUFFER_LENGTH; 48 49 read(BUFFER_LENGTH / 4, wh.lpData); 50 51 MMRESULT result = waveOutPrepareHeader(m_device, &wh, sizeof(wh)); 52 if (result != MMSYSERR_NOERROR) { 53 ADR_LOG("waveOutPrepareHeader failed"); 54 } 55 56 result = waveOutWrite(m_device, &wh, sizeof(wh)); 57 if (result != MMSYSERR_NOERROR) { 58 ADR_LOG("waveOutWrite failed"); 59 } 60 } 61 } 62 63 ~MMAudioDevice()64 MMAudioDevice::~MMAudioDevice() { 65 waveOutReset(m_device); 66 67 for (int i = 0; i < BUFFER_COUNT; ++i) { 68 WAVEHDR& wh = m_buffers[i]; 69 if (wh.dwFlags & WHDR_PREPARED || wh.dwFlags & WHDR_DONE) { 70 waveOutUnprepareHeader(m_device, &wh, sizeof(wh)); 71 } 72 } 73 74 waveOutClose(m_device); 75 } 76 77 78 void update()79 MMAudioDevice::update() { 80 ADR_GUARD("MMAudioDevice::update"); 81 82 // if a buffer is done playing, add it to the queue again 83 for (int i = 0; i < BUFFER_COUNT; ++i) { 84 WAVEHDR& wh = m_buffers[i]; 85 if (wh.dwFlags & WHDR_DONE) { 86 87 // unprepare 88 MMRESULT result = waveOutUnprepareHeader(m_device, &wh, sizeof(wh)); 89 if (result != MMSYSERR_NOERROR) { 90 ADR_LOG("waveOutUnprepareHeader failed"); 91 } 92 93 // fill with new samples 94 read(BUFFER_LENGTH / 4, wh.lpData); 95 wh.dwFlags = 0; 96 97 // prepare 98 result = waveOutPrepareHeader(m_device, &wh, sizeof(wh)); 99 if (result != MMSYSERR_NOERROR) { 100 ADR_LOG("waveOutPrepareHeader failed"); 101 } 102 103 // write 104 result = waveOutWrite(m_device, &wh, sizeof(wh)); 105 if (result != MMSYSERR_NOERROR) { 106 ADR_LOG("waveOutWrite failed"); 107 } 108 } 109 } 110 Sleep(10); 111 } 112 113 114 const char* getName()115 MMAudioDevice::getName() { 116 return "winmm"; 117 } 118 119 } 120