2008. október 5., vasárnap

How to control the volume of an audio card without disturbing the balance


Problem/Question/Abstract:

I can easily adjust the left and right channels independently on an audio card using the mixer API. My question is: How do I have one trackbar set the overall volume without disturbing the current balance between channels? Or how do I use two trackbars, but "lock" them together? Basically I need to directly manipulate one channel, but have the other one follow while keeping the relative relationship between the two channels the same.

Answer:

Here is the method I use. It uses a mixer component though, but I believe the code should make sense.


procedure setVolume(percent: real);
var
  value: integer;
  balance: real;
  highChannel, lowChannel: byte;
begin
  if percent > 1 then
    percent := 1;
  if percent < 0 then
    percent := 0;
  value := high(word) - round(percent * high(word));
  if value > high(word) then
    value := high(word);
  if value < 0 then
    value := 0;
  aMixer.outputs[0].inputs[0].volume.beginUpdate;
  if (aMixer.outputs[0].inputs[0].Volume.position[0] = 0) and
    (aMixer.outputs[0].inputs[0].Volume.position[1] = 0) then
  begin
    {Both are muted, get old balance}
    if oldBalance = 10 then
      {oldBalance is set to 10 on program start (dummy value)}
    begin
      balance := 1;
      highChannel := 0;
      lowChannel := 1
    end
    else
    begin
      if oldBalance < 0 then
      begin
        highChannel := 0;
        lowChannel := 1;
        balance := oldBalance * -1
      end
      else
      begin
        highChannel := 1;
        lowChannel := 0;
        balance := oldBalance
      end
    end
  end
  else
  begin
    if aMixer.outputs[0].inputs[0].Volume.position[0] >
      aMixer.outputs[0].inputs[0].Volume.position[1] then
    begin
      highChannel := 0;
      lowChannel := 1
    end
    else
    begin
      highChannel := 1;
      lowChannel := 0
    end;
    balance := aMixer.outputs[0].inputs[0].Volume.position[lowChannel] /
      aMixer.outputs[0].inputs[0].Volume.position[highChannel]
  end;
  aMixer.outputs[0].inputs[0].Volume.position[highChannel] := value;
  aMixer.outputs[0].inputs[0].Volume.position[lowChannel] := round(value * balance);
  if value > 0 then
  begin
    oldBalance := balance;
    if highChannel = 0 then
      oldBalance := oldBalance * -1
  end;
  aMixer.outputs[0].inputs[0].volume.endUpdate
end;

Nincsenek megjegyzések:

Megjegyzés küldése