用Delphi实现控制左右声道音量 (100分)

W

wukw

Unregistered / Unconfirmed
GUEST, unregistred user!
用Delphi实现控制左右声道音量
  一、调节全部音量
  1.先在窗体中添加一个trackbar控件,可通过改变它的位置来调节音量,在trackbar1的属性中,我们把Max属性修改成255,改成这个值

是为了便于进行二进制的音量调节操作。
  2.为了调用一个Windows函数,在uses子句里加上Mmsystem。
  3.为trackbar1的Onchange事件编写如下代码:
  procedure Tform1.TrackBar1change(Sender:Tobject);
  var t,v:longint;// t的最大值为8位的二进制:11111111;用v来表示音量的大小,这是个32位的整数,高16位表示右声道的音量,低

16位表示左声道的音量
  begin

  t:=trackbar1.Position;//得到Trackbar的位置,可用这个值来表示音量的大小
  v:=(t shl 8) or (t shl 24);//将t左移8位、24位
  waveoutsetvolume(0,v);//设置音量
  end;
  二、分别控制两个声道的方法
  1.控制左声道
  procedure Tform1.TrackBar1change(Sender:Tobject);
  var t,v:longint;
  begin

  t:=trackbar1.Position;
  waveoutgetvolume(0,@v);//@表示指向变量v的指针(32位),调用此函数的用意就是得到右声道的值,做到在调节左声道的时候,不改

变右声道
  v:=v and $ffff0000 or (t shl 8);//数字前面加$表示是十六进制数字
  waveoutsetvolume(0,v);
  end;
  2.控制右声道
  procedure Tform1.TrackBar2change(Sender:Tobject);
  var t,v:longint;//它的原理同上
  begin

  t:=trackbar2.Position;
  waveoutgetvolume(0,@v);
  v:=v and $0000ffff or (t shl 24);
  waveoutsetvolume(0,v);
  end;
  三、设置滑块的初始位置
  1.程序开始执行时,缺省情况下,Trackbar的位置在0,但我们希望程序开始执行时,这两个滑块能自动得到当前的音量,而处在相应的

位置。
  procedure TForm1.FormCreate(Sender: TObject);
  var v:longint;
  begin

  waveoutgetvolume(0,@v);//得到现在音量
  trackbar1.Position:=hi(v);//设置左滑块的正确位置
  trackbar2.Position:=hi(v shr 16);//设置右声道滑块的正确位置
  end;
  注:函数hi(v)的作用为:返回一个16位无符号整数的高8位值。如果v为32位,则高16位自动被忽略了。
  2.只使用高8位时,可使调节效果更明显。
  3.对波形文件可以用waveoutgetvolume函数,对cd文件可以用auxgetvolume函数。
  注:以上程序均在Delphi 5.0,Windows 98SE下调试通过。}

那个调节左声道,我把它翻译成VC的,为什么不起作用?
void CSoundView::OnReleasedcaptureBalanceSlider(NMHDR* pNMHDR, LRESULT* pResult)
{
int nPos = m_Banlance.GetPos();
DWORD dwVol;
waveOutGetVolume(0, &dwVol);
//
dwVol &amp;= 0xffff0000 | (nPos << 8);
// 执行完这步,居然dwVol数值不变,为什么?
*pResult = 0;
}
 
Beta,你辛苦理解一下:
v:=v and $ffff0000 or (t shl 8);//
我觉得应该是
v:= $ffff0000 or (t shl 8);//

int nPos = m_Banlance.GetPos(); // 得到滑块的当前值(滑块值为1~10,也就是我人为把声音大小分为10个等级)
我现在没考虑右声道,先把左声道做出来(做实验)
(另外,所谓所谓改变左右声道,我觉得应该是一个在减弱,另一个的音量在增强(同时改变)。而上面那篇文章只考虑改变一个声道,好像不对啊。但是我做实验,先不考虑这个)
 
刚才我搞错了,好像滑块值应该设为0~255(上面文章写的)。
我设置0~10的话,nVol的值改变太小了

1936946035 变成
1936916992
可能是我搞错了,我再试试。
 
// 我觉得应该是 v:= $ffff0000 or (t shl 8);
不对,你这样,右声道就到最大了,而原文是不改变右声道。

哦,只考虑左声道啊,我看看,这样吧:

void CSoundView::OnReleasedcaptureBalanceSlider(NMHDR* pNMHDR, LRESULT* pResult)
{
int nPos = m_Banlance.GetPos();
DWORD dwVol;
waveOutGetVolume(0, &amp;dwVol);
// 既然你的 nPos 是 1~10,就应该先把它映射到 0~FF (你只要 8 位)啊:
nPos *= 0xFF / 10;
// 下面这句的错误我刚说了
//dwVol &amp;= 0xffff0000 | (nPos << 8);
dwVol = (dwVol &amp;
0xFFFF0000) | (nPos << 8);
*pResult = 0;
}

你再看看,有问题,再告诉我吧。

 
呵呵 1~10 也可以的,作个映射就可以了,不过 0~10 或许更好些:)

 
呀呀呀,我翻译错了:
v:=v and $ffff0000 or (t shl 8);
应该是:
dwVol = (dwVol &amp;
0xFFFF0000) | (nPos << 8);
而不是
dwVol &amp;= 0xffff0000 | (nPos << 8);
(等价于 dwVol = dwVol &amp;
(0xffff0000 | (nPos << 8));)

左声道有效果了,谢谢Beta。[:)]
不过waveoutsetvolume(0,v);的第一个参数句柄,为什么设为0呢?我要再仔细看看msdn。
 
另外,什么才是真正的改变声道??
我觉得应该是两个同时改变,可是上面的文章确实只改变了一个声道。
 
完整代码如下:看看对不对?
void CSoundView::OnReleasedcaptureBalanceSlider(NMHDR* pNMHDR, LRESULT* pResult)
{
int nPos = m_Banlance.GetPos(); // 0 - 10
nPos *= 0xFF / 10;
DWORD dwVol;
waveOutGetVolume(0, &amp;dwVol);
if (nPos<5)
dwVol = (dwVol &amp;
0xFFFF0000) | (nPos << 8);
else

dwVol = (dwVol &amp;
0x0000FFFF) | (nPos << 24);

waveOutSetVolume(0, dwVol);
*pResult = 0;
}
 
// if (nPos<5)
呵呵,你还拿 nPos 跟 5 比?nPos 都已经映射到 0~FF 了:)

其实要实现均衡不用那么麻烦啦,就用我刚才帖的代码,改两个地方就可以了:
改变左声道时,不保留右声道的值,最后用 FFFF - 左声道的值,就应该是右声道的值,
因为当左声道取最大值的时候,右声道取得最小值。当然,由于你只用到了其中高 8 位,
所以左声道的最大值是 FF00,因此右声道的最小值只能达到 00FF,而不是 0000,不能
达到真正的均衡,不过应该基本上有那个效果,毕竟低 8 位很小;你要改也容易。

void CSoundView::OnReleasedcaptureBalanceSlider(NMHDR* pNMHDR, LRESULT* pResult)
{
int nPos = m_Banlance.GetPos();
DWORD dwVol;
waveOutGetVolume(0, &amp;dwVol);
nPos *= 0xFF / 10;
// 下面这行改一下就可以了(为了方便说明,拆成几行):
// dwVol = (dwVol &amp;
0xFFFF0000) | (nPos << 8);
nPos = nPos << 8;
// 左声道的值
dwVol = 0xFFFF - nPos;
// 右声道的值
dwVol = dwVol << 16 + nPos;
// 混合
waveoutsetvolume(0, dwVol);
*pResult = 0;
}

 
你写的那个不是真正的均衡,你调到左声道的时候,不管它多大,右声道都没有了。
不能这样,看我刚贴的。

 
接受答案了.
 
顶部