Войти
ПрограммированиеФорумЗвук

Линеаризация громкости для DirectSound

#0
0:38, 8 окт. 2009

Вот функция установки громкости для аудио-плеера:

void player::set_volume(double vol)
{
    volume = std::min(1.0, std::max(0.0, vol)); // Клампим в [0; 1]
    sound_buffer->SetVolume(DSBVOLUME_MIN + volume * (DSBVOLUME_MAX - DSBVOLUME_MIN));
}

Громкость задается float-point значением, 0.0 - минимальная, 1.0 - максимальная. Есть проблема - т.к. в DirectSound громкость задается в децибелах, то линейная интерполяция в децибелах дает нелинейную зависимость в амплитуде. Подскажите пожалуйста формулу, которая позволит преобразовать входной параметр таким образом, чтобы громкость с помощью него регулировалась линейно.


#1
0:48, 8 окт. 2009

DEN
log

double vol это жесть :)

#2
0:50, 8 окт. 2009

outcast

> log
Что log?

> double vol это жесть :)
Что жесть?

#3
2:07, 8 окт. 2009

DEN
Тебе нужна эта формула?
[дБ] = 20 log ([% изменения]/100)

#4
8:05, 8 окт. 2009

DEN
Подумай сперва, надо ли оно тебе.
Громкость задается в децибеллах не просто так. Именно такое изменение громкости НА СЛУХ воспринимается как линейное.

#5
9:32, 8 окт. 2009

andriano
> Громкость задается в децибеллах не просто так. Именно такое изменение громкости
> НА СЛУХ воспринимается как линейное.

не воспринимается.
Задается оно так, потомучто громкость затухает в обратной логорифмической зависимости от расстояния до источника звука. А расстояние является определяющим фактором для определения уровня гомкости в игровых движках.

DEN
вот эта функция преобразовывает 0.0f...1.0f  в линейную DS громкость 0...10000

int ToDirectVolume(float volume)
{
    int vol = round(volume*10000.0f);
    vol++;
    return round(1085.73f * logf(vol)) - 10000;
}

#6
9:42, 8 окт. 2009

http://www.gamedev.net/community/forums/topic.asp?topic_id=309489

#7
10:36, 8 окт. 2009

>> return round(1085.73f * logf(vol)) - 10000;
откуда такое магическое число 1085.73? 8) Я юзаю вот такую функцию:

function dsu_CalcVolume( const Volume : Single ) : Integer;
begin
  if volume = 0 Then
    Result := -10000
  else
    Result := - Round( 1000 * ln( 1 / volume ) );
end;

#8
21:13, 8 окт. 2009

> Задается оно так, потомучто громкость затухает в обратной логорифмической зависимости от расстояния до источника звука.
Учите физику.
Звук от точечного источника затухает обратно пропорционально квадрату расстояния.
От бипольного - быстрее. От плоского - медленнее. Но логарифм нигде не входит.

#9
22:07, 8 окт. 2009

andriano
ни квадрату, ни логарифму затухание звука не пропорционально, все куда сложнее.

Физика тут нипричем, речь о DirectSound, где многие законы распространения звука сильно упрощены, как и должно быть.

#10
22:50, 8 окт. 2009

void CDirSound::SetSoundVolume(int _nVolume)
{
  _nVolume=min(_nVolume,100);
  _nVolume=max(_nVolume,0);

  int realvolume=(int)floorf(-expf((-5*_nVolume/100.0f+4)*logf(10)))+1;
  realvolume=min(realvolume,DSBVOLUME_MAX);
  realvolume=max(realvolume,DSBVOLUME_MIN);

  for (UINT i=1; i<=m_currentBufferNum; i++)
  {
    if (i!=m_nMusicBuffer)
    {
      SetVolume(i,realvolume);
    }
  }
}

Выбирай на вкус.

#11
0:29, 9 окт. 2009

Тэкс... Спасибо за тучу формул, буду пробовать...

#12
4:55, 17 окт. 2009

Нет ты всё-таки отпишись какая формула оказалась лучше.

#13
8:39, 17 окт. 2009

И пусть на твое решение не влияет тот факт, что я 3 года ходил в музыкальную школу.

ПрограммированиеФорумЗвук

Тема в архиве.