1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
#ifndef __C_WAVEIN_H__
#define __C_WAVEIN_H__
#include <windows.h>
#include <mmsystem.h>
#define EXIT_ON_ERROR(hr) \
if (FAILED(hr)) { goto Exit; }
#define SAFE_RELEASE(what) \
if ((what) != NULL) \
{ (what)->Release(); (what) = NULL; }
template<int numbuffers, int buffersize> class C_WAVEIN {
private:
short Samples[numbuffers][buffersize];
WAVEFORMATEX wfx;
WAVEHDR wvhdr[numbuffers];
HWAVEIN hwi;
WAVEINCAPS wic;
unsigned long iNumDevs, iy;
HRESULT hr;
IMMDeviceEnumerator *pEnumerate;
IMMDevice *pDevice;
IMMDeviceCollection *ppDevices;
IPropertyStore *pProps;
BOOL useXpSound;
PROPVARIANT varName;
char buf[1024];
public:
C_WAVEIN() {
hwi = NULL;
memset(Samples, 0, sizeof(Samples));
memset(wvhdr, 0, sizeof(wvhdr));
iNumDevs = iy = 0;
hr = S_OK;
pEnumerate = NULL;
pDevice = NULL;
ppDevices = NULL;
pProps = NULL;
useXpSound = false;
memset(buf, 0, sizeof(buf));
}
virtual ~C_WAVEIN() {
Close();
}
char * getDeviceName(unsigned int devid=-1) {
hr = S_OK;
pEnumerate = NULL;
pDevice = NULL;
ppDevices = NULL;
pProps = NULL;
useXpSound = false;
PROPVARIANT varName;
PropVariantInit(&varName);
// Get enumerator for audio endpoint devices.
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
NULL, CLSCTX_INPROC_SERVER,
__uuidof(IMMDeviceEnumerator),
(void**)&pEnumerate);
EXIT_ON_ERROR(hr)
hr = pEnumerate->GetDefaultAudioEndpoint(eCapture,eConsole,&pDevice);
EXIT_ON_ERROR(hr)
Exit:
if (FAILED(hr)) {
useXpSound = true;
} else
useXpSound = false;
memset(buf, 0, sizeof(buf));
if (useXpSound) {
if (!waveInGetDevCaps(devid, &wic, sizeof(WAVEINCAPS))) {
lstrcpyn(buf, wic.szPname, ARRAYSIZE(buf));
goto Fin;
}
} else {
pDevice->OpenPropertyStore(STGM_READ, &pProps);
pProps->GetValue(PKEY_Device_FriendlyName, &varName);
WideCharToMultiByte(CP_ACP, 0, (LPWSTR)varName.pwszVal, -1, buf, ARRAYSIZE(buf), NULL, NULL);
goto Fin;
}
Fin:
PropVariantClear(&varName);
SAFE_RELEASE(pProps)
SAFE_RELEASE(pEnumerate)
SAFE_RELEASE(pDevice)
SAFE_RELEASE(ppDevices)
CoUninitialize();
return buf;
}
void Create(int sRate, int nCh,int devid=-1) {
if (hwi == NULL) {
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.wBitsPerSample = 16;
wfx.nSamplesPerSec = sRate;
wfx.nChannels = (WORD)nCh;
wfx.nBlockAlign = (wfx.nChannels * wfx.wBitsPerSample) / 8;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
wfx.cbSize = 0;
waveInOpen(&hwi,devid,&wfx,0,0,CALLBACK_NULL);
waveInStop(hwi);
waveInReset(hwi);
for(int i = 0; i < numbuffers; i++) {
memset(&wvhdr[i],0,sizeof(wvhdr[i]));
wvhdr[i].lpData = (char *)&Samples[i];
wvhdr[i].dwBufferLength = buffersize * sizeof(short);
waveInPrepareHeader(hwi,&wvhdr[i],sizeof(WAVEHDR));
waveInAddBuffer(hwi,&wvhdr[i],sizeof(WAVEHDR));
}
waveInStart(hwi);
}
}
void Close() {
if (hwi != NULL) {
waveInStop(hwi);
waveInReset(hwi);
for(int i = 0; i < numbuffers; i++) {
if (wvhdr[i].dwFlags & WHDR_PREPARED) {
waveInUnprepareHeader(hwi,&wvhdr[i],sizeof(WAVEHDR));
}
}
waveInClose(hwi);
hwi = NULL;
}
}
short *operator[](int buffernum) {
return (short *)&Samples[buffernum];
}
int getNumSamples(int buffernum) {
return wvhdr[buffernum].dwBytesRecorded / (wfx.nChannels * sizeof(short));
}
int isOpen() {
return hwi != NULL;
}
int isFilled(int buffernum) {
return wvhdr[buffernum].dwFlags & WHDR_DONE && wvhdr[buffernum].dwBytesRecorded <= buffersize * sizeof(short);
}
void cycleBuffer(int buffernum) {
if (hwi != NULL) {
wvhdr[buffernum].dwFlags = WHDR_PREPARED;
wvhdr[buffernum].dwBytesRecorded = 0;
waveInAddBuffer(hwi,&wvhdr[buffernum],sizeof(WAVEHDR));
}
}
};
#endif // !__C_WAVEIN_H__
|