如何让单个程序静音,而不影响系统声音

only_youch 2010-09-02 03:23:50
我在程序中遇到一个问题,我的程序是能够播放声音的,我需要让我的程序能够静音,而不影响系统声音,就像音乐播放器一样,能够单调调节本程序的音量而不影响系统音量。另外傲游浏览器里面也有这么个功能,但不知道是如何实现的?

大家能给点意见?
...全文
2641 点赞 收藏 25
写回复
25 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
向立天 2010-10-16
您好
我是本版版主
此帖已多日无人关注
请您及时结帖
如您认为问题没有解决可按无满意结帖处理
另外本版设置了疑难问题汇总帖
并已在版面置顶
相关规定其帖子中有说明
您可以根据规定提交您帖子的链接
如您目前不想结帖只需回帖说明
我们会删除此结帖通知

见此回复三日内无回应
我们将强制结帖
相关规定详见界面界面版关于版主结帖工作的具体办法
回复
WL_river 2010-09-17
最大的问题是xp及以下OS中,程序跟系统用的是一套API,对程序进行的声音调节会影响到系统。
vista及以上的OS中,程序跟系统分别有不同的声音控制API,所以可以单独调节。

个人感觉,类似于The world、搜狗等浏览器中对网页的声音调节,可能用的是DX来实现。
回复
在MCI中,用
setaudio (MCI设备名) volume to (音量大小0-1000)
如:
mciSendString("setaudio MyMCIPlay volume to 500",RetString,128,NULL);
解释:
MCI设备名 是根据你打开MCI设备时所定义的名称
如:

char mcistr[255];
char RetString[128];
//MyMCIPlay 就是自己定义的MCI设备名
sprintf(mcistr,"open %s TYPE MPEGVideo ALIAS MyMCIPlay STYLE child PARENT %d",filename,hWnd);
rd=mciSendString(mcistr, RetString, 128, hwnd);
回复
dengzikun 2010-09-08
[Quote=引用 21 楼 only_youch 的回复:]
我程序中加载的是网页,我是想在程序上加个按钮来开启静音功能,至于网页中的声音如何播放,这个不是我需要去了解的。也不是正途。


引用 20 楼 l_xiangxi 的回复:
引用 14 楼 only_youch 的回复:
你的好像是调节系统的音量,我是要单独调节一个程序的,和系统无关。


引用 12 楼 psbeond 的回复:
以上两种方法, 一种是xp的,一种是vista的……
[/Quote]

两个途径

1. 网页中播放声音的控件提供了独立静音的功能,你去调用.
2. 如果没有提供,只有自己去写播放控件去实现了.
回复
only_youch 2010-09-08
我程序中加载的是网页,我是想在程序上加个按钮来开启静音功能,至于网页中的声音如何播放,这个不是我需要去了解的。也不是正途。

[Quote=引用 20 楼 l_xiangxi 的回复:]
引用 14 楼 only_youch 的回复:
你的好像是调节系统的音量,我是要单独调节一个程序的,和系统无关。


引用 12 楼 psbeond 的回复:
以上两种方法, 一种是xp的,一种是vista的。我几年前总结的。你可以参考一下。


我觉得问题是楼主的程序是如何播放声音的,
把代码贴出来
才能对症下药
[/Quote]
回复
only_youch 2010-09-07
[Quote=引用 16 楼 jackson35296 的回复:]
引用 15 楼 only_youch 的回复:
查了一下这些接口的介绍,好像是可以解决Vista以上版本的这个问题,但XP上有办法如何解决没?


引用 9 楼 jackson35296 的回复:
vista和win7下是可以单独控制每个进程的音量的。可以参考MSDN上的WASAPI,有一些接口
IAudioClient
IAudioSessionControl
ISimpleAu……
[/Quote]

要处理声源,这不太可能吧。我程序中加载的网页要播放什么声音,我就是知道了,也不好去“处理”吧。
回复
jackson35296 2010-09-07
[Quote=引用 15 楼 only_youch 的回复:]
查了一下这些接口的介绍,好像是可以解决Vista以上版本的这个问题,但XP上有办法如何解决没?


引用 9 楼 jackson35296 的回复:
vista和win7下是可以单独控制每个进程的音量的。可以参考MSDN上的WASAPI,有一些接口
IAudioClient
IAudioSessionControl
ISimpleAudioVolume
IAudioStreamVo……
[/Quote]

xp下只能是对声源进行处理了,改变初始波形的振幅,直接控制音量应该是不行的。
回复
l_xiangxi 2010-09-07
[Quote=引用 14 楼 only_youch 的回复:]
你的好像是调节系统的音量,我是要单独调节一个程序的,和系统无关。


引用 12 楼 psbeond 的回复:
以上两种方法, 一种是xp的,一种是vista的。我几年前总结的。你可以参考一下。
[/Quote]

我觉得问题是楼主的程序是如何播放声音的,
把代码贴出来
才能对症下药
回复
用MCI接口做,可以单独控制MCI设备的音量
回复
cdsnpeter 2010-09-07
使用DSound把,DSound的IDirectSoundBuffer有个方法SetVolume就可以来设置音量。

具体可以参考DSound的文档。
回复
only_youch 2010-09-06
查了一下这些接口的介绍,好像是可以解决Vista以上版本的这个问题,但XP上有办法如何解决没?

[Quote=引用 9 楼 jackson35296 的回复:]
vista和win7下是可以单独控制每个进程的音量的。可以参考MSDN上的WASAPI,有一些接口
IAudioClient
IAudioSessionControl
ISimpleAudioVolume
IAudioStreamVolume
IChannelAudioVolume
IAudioEndpointVolume
[/Quote]
回复
only_youch 2010-09-06
你的好像是调节系统的音量,我是要单独调节一个程序的,和系统无关。

[Quote=引用 12 楼 psbeond 的回复:]
以上两种方法, 一种是xp的,一种是vista的。我几年前总结的。你可以参考一下。
[/Quote]
回复
only_youch 2010-09-06
感谢大家,我去研究一下。
回复
psbeond 2010-09-06
以上两种方法, 一种是xp的,一种是vista的。我几年前总结的。你可以参考一下。
回复
psbeond 2010-09-06
调整系统音量和静音For Vista
1.为了编译Endpointvolume.h文件,必须在stdafx.h中定义NTDDI_VERSION,使其值大于或等于NTDDI_WINXPSP1,例如定义成下面的形式:

#define NTDDI_VERSION (NTDDI_WINXPSP1+1)


2. 生成VistaVolume.h和VistaVolume.cpp文件

// VistaVolume.h
#ifndef _VISTAVOLUME_H_
#define _VISTAVOLUME_H_


#include <Mmdeviceapi.h> // for IMMDeviceEnumerator and IMMDevice
#include <Endpointvolume.h> // for IAudioEndpointVolume, must #define NTDDI_VERSION NTDDI_WINXPSP1 in stdafx.h


typedef void (*NotifyCallback)(AUDIO_VOLUME_NOTIFICATION_DATA *);


class CAudioEndpointVolumeCallback;

class CVistaVolume
{
public:
CVistaVolume();
~CVistaVolume();

public:
HRESULT Init();
HRESULT Uninit();
HRESULT SetVolume(float fVolume);
HRESULT GetVolume(float *pfVolume);
HRESULT SetMute(BOOL bMute);
HRESULT GetMute(BOOL *pbMute);
HRESULT SetNotifyCallback(NotifyCallback pfn);

private:
IMMDeviceEnumerator *m_pEnumerator;
IMMDevice *m_pDevice;
IAudioEndpointVolume *m_pAEV;

CAudioEndpointVolumeCallback *m_pCallback;
BOOL m_bInit;
};

#endif //_VISTAVOLUME_H_




// VistaVolume.cpp
#include "stdafx.h"
#include "VistaVolume.h"

template <class T>
inline void SafeRelease(T &p)
{
if (p != NULL)
{
p->Release();
p = NULL;
}
}


class CAudioEndpointVolumeCallback : public IAudioEndpointVolumeCallback
{
public:
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject)
{
return S_OK;
}

virtual ULONG STDMETHODCALLTYPE AddRef(void)
{
m_cRef++;
return m_cRef;
}

virtual ULONG STDMETHODCALLTYPE Release(void)
{
m_cRef--;
if (m_cRef == 0)
{
delete this;
return 0;
}
return m_cRef;
}

virtual HRESULT STDMETHODCALLTYPE OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify)
{
if (m_pfn != NULL)
{
m_pfn(pNotify);
}
return S_OK;
}

public:
CAudioEndpointVolumeCallback()
{
m_cRef = 0;
m_pfn = NULL;
}
virtual ~CAudioEndpointVolumeCallback()
{
m_pfn = NULL;
}

void SetNotifyCallback(NotifyCallback pfn)
{
m_pfn = pfn;
}

private:
LONG m_cRef;
NotifyCallback m_pfn;
};


CVistaVolume::CVistaVolume()
{
m_pEnumerator = NULL;
m_pDevice = NULL;
m_pAEV = NULL;

m_pCallback = NULL;
m_bInit = FALSE;

Init();
}

CVistaVolume::~CVistaVolume()
{
Uninit();
}

HRESULT CVistaVolume::Init()
{
if (m_bInit)
return S_OK;

HRESULT hr = E_FAIL;

hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,
CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&m_pEnumerator);
if (FAILED(hr))
return hr;

hr = m_pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_pDevice);
if (FAILED(hr))
return hr;

hr = m_pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&m_pAEV);
if (FAILED(hr))
return hr;

m_bInit = TRUE;

return hr;
}

HRESULT CVistaVolume::Uninit()
{
if (!m_bInit)
return S_OK;

if (m_pCallback!=NULL && m_pAEV!=NULL)
{
m_pCallback->SetNotifyCallback(NULL);
m_pAEV->UnregisterControlChangeNotify(m_pCallback);
m_pCallback = NULL;
}

SafeRelease(m_pAEV);
SafeRelease(m_pDevice);
SafeRelease(m_pEnumerator);

m_bInit = FALSE;

return S_OK;
}

HRESULT CVistaVolume::SetVolume(float fVolume)
{
HRESULT hr = E_FAIL;

hr = m_pAEV->SetMasterVolumeLevelScalar(fVolume, NULL);

return hr;
}

HRESULT CVistaVolume::GetVolume(float *pfVolume)
{
HRESULT hr = E_FAIL;

hr = m_pAEV->GetMasterVolumeLevelScalar(pfVolume);

return hr;
}

HRESULT CVistaVolume::SetMute(BOOL bMute)
{
HRESULT hr = E_FAIL;

hr = m_pAEV->SetMute(bMute, NULL);

return hr;
}

HRESULT CVistaVolume::GetMute(BOOL *pbMute)
{
HRESULT hr = E_FAIL;

hr = m_pAEV->GetMute(pbMute);

return hr;
}

// 为了响应系统音量或静音状态的改变, 可以使用CVistaVolume::SetNotifyCallback设置一个回调函数, 当有改变时,自动调用用户指定的这个函数.
HRESULT CVistaVolume::SetNotifyCallback(NotifyCallback pfn)
{
if (m_pCallback == NULL)
{
HRESULT hr = E_FAIL;
m_pCallback = new CAudioEndpointVolumeCallback;

int n = 0;
n = 5;

hr = m_pAEV->RegisterControlChangeNotify(m_pCallback);
if (FAILED(hr))
return hr;

m_pCallback->SetNotifyCallback(pfn);
}

return S_OK;
}


使用:定义一个CVistaVolume的类成员m_volume;

// 当音量大小或静音状态改变时, 调用这个函数
void NotifyFun(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify)
{
// 在这里加入处理代码
}

m_volume.SetMute(TRUE);
m_volume.SetNotifyCallback(NotifyFun);
回复
psbeond 2010-09-06
调整系统音量和静音 For 2K,XP.txt
注: 也适用于Vista系统下调整主音量

HWND g_hWnd = NULL; // 指定接收设备改变通知消息MM_MIXM_CONTROL_CHANGE的窗口, 一般在窗口创建的时候初始化g_hWnd. 必须在调用OpenMixer之间初始化g_hWnd
HMIXER g_hMixer = NULL;

UINT OpenMixer()
{
// mixerGetID
UINT mixID;
MMRESULT mmRet = ::mixerGetID(0, &mixID, MIXER_OBJECTF_HMIXER);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// MixerOpen
mmRet = ::mixerOpen(&g_hMixer, mixID, (DWORD)g_hWnd, NULL, MIXER_OBJECTF_HMIXER|CALLBACK_WINDOW);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

return MMSYSERR_NOERROR;
}

UINT CloseMixer()
{
// MixerClose
MMRESULT mmRet;

mmRet = ::mixerClose(g_hMixer);

return mmRet;
}

//
UINT SetVolume(int nValue) // 0-65535
{
MMRESULT mmRet;
// MixerGetLineInfo
MIXERLINE mxl;
mxl.cbStruct = sizeof(MIXERLINE);
mxl.dwDestination = 0;
mmRet = ::mixerGetLineInfo(0, &mxl, MIXER_GETLINEINFOF_DESTINATION);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// --- MixerGetLineInfo
DWORD lr;
lr = mxl.dwLineID;
mxl.cbStruct = sizeof(MIXERLINE);
mxl.dwLineID = lr;
mmRet = ::mixerGetLineInfo(0, &mxl, MIXER_GETLINEINFOF_LINEID);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// --- MixerGetLineControls
MIXERCONTROL *pmxctrl;
pmxctrl = new MIXERCONTROL [mxl.cControls];
MIXERLINECONTROLS mxlc;
mxlc.cbStruct = sizeof(MIXERLINECONTROLS);
mxlc.cControls = mxl.cControls;
mxlc.cbmxctrl = sizeof(MIXERCONTROL);
mxlc.pamxctrl = pmxctrl;
mxlc.dwLineID = lr;
mmRet = ::mixerGetLineControls(0, &mxlc, MIXER_GETLINECONTROLSF_ALL);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// MixerGetControlDetails
UINT i = 0;
for (i=0; i<mxlc.cControls; i++)
{
if (pmxctrl[i].dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
break;
}
MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_UNSIGNED volume;
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = pmxctrl[i].dwControlID;
mxcd.cChannels = 1;
mxcd.hwndOwner = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = &volume;
delete [] pmxctrl;
pmxctrl = NULL;
mmRet = ::mixerGetControlDetails(0, &mxcd, MIXER_OBJECTF_WAVEOUT);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// MixerSetControlDetails
volume.dwValue = nValue;
mmRet = ::mixerSetControlDetails(0, &mxcd, MIXER_OBJECTF_MIXER);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

return MMSYSERR_NOERROR;
}

//
UINT GetVolume(int *pnValue) // 0-65535
{
ASSERT(pnValue != NULL);
MMRESULT mmRet;

// MixerGetLineInfo
MIXERLINE mxl;
mxl.cbStruct = sizeof(MIXERLINE);
mxl.dwDestination = 0;
mmRet = ::mixerGetLineInfo(0, &mxl, MIXER_GETLINEINFOF_DESTINATION);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// --- MixerGetLineInfo
DWORD lr;
lr = mxl.dwLineID;
mxl.cbStruct = sizeof(MIXERLINE);
mxl.dwLineID = lr;
mmRet = ::mixerGetLineInfo(0, &mxl, MIXER_GETLINEINFOF_LINEID);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// --- MixerGetLineControls
MIXERCONTROL *pmxctrl;
pmxctrl = new MIXERCONTROL [mxl.cControls];
MIXERLINECONTROLS mxlc;
mxlc.cbStruct = sizeof(MIXERLINECONTROLS);
mxlc.cControls = mxl.cControls;
mxlc.cbmxctrl = sizeof(MIXERCONTROL);
mxlc.pamxctrl = pmxctrl;
mxlc.dwLineID = lr;
mmRet = ::mixerGetLineControls(0, &mxlc, MIXER_GETLINECONTROLSF_ALL);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// MixerGetControlDetails
UINT i = 0;
for (i=0; i<mxlc.cControls; i++)
{
if (pmxctrl[i].dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
break;
}
MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_UNSIGNED volume;
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = pmxctrl[i].dwControlID;
mxcd.cChannels = 1;
mxcd.hwndOwner = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = &volume;
delete [] pmxctrl;
pmxctrl = NULL;
mmRet = ::mixerGetControlDetails(0, &mxcd, MIXER_OBJECTF_WAVEOUT);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

*pnValue = volume.dwValue;

return MMSYSERR_NOERROR;
}

//
UINT SetMuteState(BOOL bMute)
{
MMRESULT mmRet;

// MixerGetLineInfo
MIXERLINE mxl;
mxl.cbStruct = sizeof(MIXERLINE);
mxl.dwDestination = 0;
mmRet = ::mixerGetLineInfo(0, &mxl, MIXER_GETLINEINFOF_DESTINATION);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// --- MixerGetLineInfo
DWORD lr;
lr = mxl.dwLineID;
mxl.cbStruct = sizeof(MIXERLINE);
mxl.dwLineID = lr;
mmRet = ::mixerGetLineInfo(0, &mxl, MIXER_GETLINEINFOF_LINEID);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// --- MixerGetLineControls
MIXERCONTROL *pmxctrl;
pmxctrl = new MIXERCONTROL [mxl.cControls];
MIXERLINECONTROLS mxlc;
mxlc.cbStruct = sizeof(MIXERLINECONTROLS);
mxlc.cControls = mxl.cControls;
mxlc.cbmxctrl = sizeof(MIXERCONTROL);
mxlc.pamxctrl = pmxctrl;
mxlc.dwLineID = lr;
mmRet = ::mixerGetLineControls(0, &mxlc, MIXER_GETLINECONTROLSF_ALL);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// MixerGetControlDetails
UINT i = 0;
for (i=0; i<mxlc.cControls; i++)
{
if (pmxctrl[i].dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
break;
}
MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_BOOLEAN mute;
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = pmxctrl[i].dwControlID;
mxcd.cChannels = 1;
mxcd.hwndOwner = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = &mute;
delete [] pmxctrl;
pmxctrl = NULL;
mmRet = ::mixerGetControlDetails(0, &mxcd, MIXER_OBJECTF_WAVEOUT);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// MixerSetControlDetails
mute.fValue = bMute;
mmRet = ::mixerSetControlDetails(0, &mxcd, MIXER_OBJECTF_MIXER);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

return MMSYSERR_NOERROR;
}

UINT GetMuteState(BOOL *pbMute)
{
ASSERT(pbMute != NULL);
MMRESULT mmRet;

// MixerGetLineInfo
MIXERLINE mxl;
mxl.cbStruct = sizeof(MIXERLINE);
mxl.dwDestination = 0;
mmRet = ::mixerGetLineInfo(0, &mxl, MIXER_GETLINEINFOF_DESTINATION);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// --- MixerGetLineInfo
DWORD lr;
lr = mxl.dwLineID;
mxl.cbStruct = sizeof(MIXERLINE);
mxl.dwLineID = lr;
mmRet = ::mixerGetLineInfo(0, &mxl, MIXER_GETLINEINFOF_LINEID);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// --- MixerGetLineControls
MIXERCONTROL *pmxctrl;
pmxctrl = new MIXERCONTROL [mxl.cControls];
MIXERLINECONTROLS mxlc;
mxlc.cbStruct = sizeof(MIXERLINECONTROLS);
mxlc.cControls = mxl.cControls;
mxlc.cbmxctrl = sizeof(MIXERCONTROL);
mxlc.pamxctrl = pmxctrl;
mxlc.dwLineID = lr;
mmRet = ::mixerGetLineControls(0, &mxlc, MIXER_GETLINECONTROLSF_ALL);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

// MixerGetControlDetails
UINT i = 0;
for (i=0; i<mxlc.cControls; i++)
{
if (pmxctrl[i].dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
break;
}
MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_BOOLEAN mute;
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = pmxctrl[i].dwControlID;
mxcd.cChannels = 1;
mxcd.hwndOwner = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = &mute;
delete [] pmxctrl;
pmxctrl = NULL;
mmRet = ::mixerGetControlDetails(0, &mxcd, MIXER_OBJECTF_WAVEOUT);
if (mmRet != MMSYSERR_NOERROR)
return mmRet;

*pbMute = mute.fValue;

return MMSYSERR_NOERROR;
}
回复
jackson35296 2010-09-06
vista和win7下是可以单独控制每个进程的音量的。可以参考MSDN上的WASAPI,有一些接口
IAudioClient
IAudioSessionControl
ISimpleAudioVolume
IAudioStreamVolume
IChannelAudioVolume
IAudioEndpointVolume
回复
only_youch 2010-09-06
有人了解这个问题的解决办法没?
回复
oldforest 2010-09-03
播放WAV是没有这样的API,只有自己动手改变波的振幅
用DirectX是有这样的的API可以调用,如楼上所说的SetVolume
回复
dengzikun 2010-09-03
那就用复杂的吧,DSOUND的SetVolume可以独立控制音量,也可控制系统音量.
或者自己往声卡填静音数据.
回复
加载更多回复
相关推荐
发帖
界面
创建于2007-09-28

1.5w+

社区成员

VC/MFC 界面
申请成为版主
帖子事件
创建了帖子
2010-09-02 03:23
社区公告
暂无公告