微信电脑版,pc上运行。工作聊天利器。但是用下来发现,播放语音音量很小,如果把系统音量调大最大,凑合能听到,但是其他app的音量又太大,闲来无事,就写了音量放大器。
背景分析:
经过od分析,微信电脑版,播放声音调用的waveout打头的一系列api,播放用的是waveOutWrite,该函数原型如下:
MMRESULT mywaveOutWrite(
HWAVEOUT hwo,
LPWAVEHDR pwh,
UINT cbwh
)
/* wave data block header */
typedef struct wavehdr_tag {
LPSTR lpData; /* pointer to locked data buffer */
DWORD dwBufferLength; /* length of data buffer */
DWORD dwBytesRecorded; /* used for input only */
DWORD_PTR dwUser; /* for client's use */
DWORD dwFlags; /* assorted flags (see defines) */
DWORD dwLoops; /* loop control counter */
struct wavehdr_tag FAR *lpNext; /* reserved for driver */
DWORD_PTR reserved; /* reserved for driver */
} WAVEHDR, *PWAVEHDR, NEAR *NPWAVEHDR, FAR *LPWAVEHDR;
其中pwh即为音频相关数据,其中dwBufferLength为音频长度,lpData为音频数据,pcm原始数据,一般为16位的立体声数据
遂写一个apihook,hook该api的调用,然后在hook函数中,将lpData乘以放大倍数即可实现音量放大。核心代码如下:
MMRESULT mywaveOutWrite(
HWAVEOUT hwo,
LPWAVEHDR pwh,
UINT cbwh
)
{
_hooks.End(_hwaveOutWrite);
int v = GetVolumnFromMain();
if (v != -1)
{
double vol = (double)v;
short* lpData = (short*)pwh->lpData;
for (int i = 0; i < pwh->dwBufferLength / 2; i++)
{
int nd = lpData[i] * vol;
if (nd > 32767)
nd = 32767;
else if (nd < -32768)
nd = -32768;
lpData[i] = nd;
}
}
MMRESULT res = waveOutWrite(hwo, pwh, cbwh);
_hooks.Begin(_hwaveOutWrite);
return res;
}
apihook相关代码请参考附件代码,欢迎指正。