00001 #include <windows.h>
00002 #include <mmsystem.h>
00003 #include "device_mm.h"
00004 #include "utility.h"
00005
00006
00007 namespace audiere {
00008
00009 static const int RATE = 44100;
00010
00011
00012 MMAudioDevice*
00013 MMAudioDevice::create(const ParameterList& parameters) {
00014 WAVEFORMATEX wfx;
00015 memset(&wfx, 0, sizeof(wfx));
00016 wfx.wFormatTag = WAVE_FORMAT_PCM;
00017 wfx.nChannels = 2;
00018 wfx.nSamplesPerSec = RATE;
00019 wfx.nAvgBytesPerSec = RATE * 4;
00020 wfx.nBlockAlign = 4;
00021 wfx.wBitsPerSample = 16;
00022 wfx.cbSize = sizeof(WAVEFORMATEX);
00023
00024 HWAVEOUT handle;
00025 MMRESULT result = waveOutOpen(&handle, WAVE_MAPPER, &wfx, 0, 0, 0);
00026 if (result != MMSYSERR_NOERROR) {
00027 return 0;
00028 }
00029
00030 return new MMAudioDevice(handle, RATE);
00031 }
00032
00033
00034 MMAudioDevice::MMAudioDevice(HWAVEOUT device, int rate)
00035 : MixerDevice(rate)
00036 {
00037 ADR_GUARD("MMAudioDevice::MMAudioDevice");
00038
00039 m_device = device;
00040 m_current_buffer = 0;
00041
00042
00043 for (int i = 0; i < BUFFER_COUNT; ++i) {
00044 WAVEHDR& wh = m_buffers[i];
00045 memset(&wh, 0, sizeof(wh));
00046 wh.lpData = (char*)m_samples + i * BUFFER_LENGTH;
00047 wh.dwBufferLength = BUFFER_LENGTH;
00048
00049 read(BUFFER_LENGTH / 4, wh.lpData);
00050
00051 MMRESULT result = waveOutPrepareHeader(m_device, &wh, sizeof(wh));
00052 if (result != MMSYSERR_NOERROR) {
00053 ADR_LOG("waveOutPrepareHeader failed");
00054 }
00055
00056 result = waveOutWrite(m_device, &wh, sizeof(wh));
00057 if (result != MMSYSERR_NOERROR) {
00058 ADR_LOG("waveOutWrite failed");
00059 }
00060 }
00061 }
00062
00063
00064 MMAudioDevice::~MMAudioDevice() {
00065 waveOutReset(m_device);
00066
00067 for (int i = 0; i < BUFFER_COUNT; ++i) {
00068 WAVEHDR& wh = m_buffers[i];
00069 if (wh.dwFlags & WHDR_PREPARED || wh.dwFlags & WHDR_DONE) {
00070 waveOutUnprepareHeader(m_device, &wh, sizeof(wh));
00071 }
00072 }
00073
00074 waveOutClose(m_device);
00075 }
00076
00077
00078 void
00079 MMAudioDevice::update() {
00080 ADR_GUARD("MMAudioDevice::update");
00081
00082
00083 for (int i = 0; i < BUFFER_COUNT; ++i) {
00084 WAVEHDR& wh = m_buffers[i];
00085 if (wh.dwFlags & WHDR_DONE) {
00086
00087
00088 MMRESULT result = waveOutUnprepareHeader(m_device, &wh, sizeof(wh));
00089 if (result != MMSYSERR_NOERROR) {
00090 ADR_LOG("waveOutUnprepareHeader failed");
00091 }
00092
00093
00094 read(BUFFER_LENGTH / 4, wh.lpData);
00095 wh.dwFlags = 0;
00096
00097
00098 result = waveOutPrepareHeader(m_device, &wh, sizeof(wh));
00099 if (result != MMSYSERR_NOERROR) {
00100 ADR_LOG("waveOutPrepareHeader failed");
00101 }
00102
00103
00104 result = waveOutWrite(m_device, &wh, sizeof(wh));
00105 if (result != MMSYSERR_NOERROR) {
00106 ADR_LOG("waveOutWrite failed");
00107 }
00108 }
00109 }
00110 Sleep(10);
00111 }
00112
00113
00114 const char*
00115 MMAudioDevice::getName() {
00116 return "winmm";
00117 }
00118
00119 }