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

OpenAL 1.1: Проблема с громкостью проигрываемых моно звуков

#0
17:29, 17 ноя. 2008

При программировании звука для движка использую библиотеку OpenAL версии 1.1, инструментальная среда Delphi 7, ОС – XP SP2. Отладил управление сменой моно звуков для любого летящего объекта (ЛО). Пока ЛО летит – один звук, когда его подбили – другой, когда он падает – третий, и когда он разбился – 4-й.
Проблема в следующем. На одной конфигурации компа (где я веду разработку проекта) с материнской платой ASUS P5L-VM 1394 и со встроенной звуковой картой (Realtek) моно звуки слышны через наушники, но как-то тихо, различимо, что они в зависимости от расстояния до слушателя то нарастают, то удаляются. На двух других аналогичных конфигурациях компов при использовании встроенных звуковух и через наушники их практически не слышно.
Исследовал и 2 др. конфигурации. На одном компе стоит Audigy 2 ZS, обеспечивающая объёмное звучание вплоть до 6.1 и акустическая система SVEN IHOO-IR 5.1. На этой машине я также веду разработку этого проекта и монозвуки через акустическую систему слышны слабо, и то только над головой слушателя.
На другом компе продвинутая материнская плата ASUS класса Delux со встроенной звуковой картой, обеспечивающей объёмное звучание вплоть до 7.1. На ней через наушники моно звуки слышны также слабо, как и на предыдущей.
Это при всём при том, что основной регулятор громкости выкручен на полную. А программная настройка с помощью AL_GAIN к существенному усилению звука не приводит.
Причём в Windows Media Player все моно звуки звучат достаточно громко и при установке громкости по середине как в WM Player, так и громкости микшера Realtek.
Может, я какую фишку упустил при программировании, или это какие уже известные проблемы частичной или полной несовместимости библиотеки OpenAL версии 1.1 с какой-либо конфигурацией железа?


#1
18:04, 17 ноя. 2008

Ты используешь позиционирование моно звуков в пространстве? Как у тебя проигрываются стереозвуки?
OpenAL  на ввстроенных картах работает. Конечно в программном режиме, но вполне нормально. Может выложишь код проигрывания звуков? Посмотрим в чем дело.

#2
21:52, 17 ноя. 2008

Да, я использую позиционирование моно звуков в пространстве, и при стрельбе по ЛО с ПЗРК слушателем является стрелок. При этом все звуки ПЗРК это стерео, ракета, вылетающая из ПЗРК тоже со стереозвуками (взрыв порохового заряда и её отлёт от стрелка; отлёт - звук стерео с затуханием для небольшого упрощения).
С ребятами разобрались, что дело не с железом и/или аккустической системой, а что-то в программе недоработано.
Подозреваю, что что-то  с громкостью не доделал или с инициализацией начального положения звуков в пространстве. Перемещение работает, даже на столь тихих моно звуках в программе можно различить их нарастание и затухание.

Для чистоты проверки пробовал даже с одним самолётом работать, для него все звуки точно загружаются в единственном экземпляре и только он их использует. И всё равно тихо.
Слушатель пока не перемещается.
Может надо усложнить процедуру запуска источника на проигрывание файла.
На громкость проигрывания в зависимости от перемещения в пространстве могут повлиять параметры инициализации и сама процедура запуска источника на проигрывание. Процедура перемещения звука от ЛО в принципе справляется со своими обязанностями :)
Управление сменой звуков тоже отлажено надёжно. Да хотя бы, чтобы просто с одним изменяющимся звуком пролетел бы нормально, я уже не говорю про сбитый и взорванный ЛО. Они автоматом также сыграют свою роль.


Привожу краткое содержание юнита

// Запись для буффера, в котором будут храниться атрибуты звуковых файлов
type
  TSndInfo = record
    ID          : TALuint;  // ID звукового файла
    FileName    : string;    // его имя
    SourceID    : TALuint;  // ID источника
    SoundBuffer : TALuint;  // ID буфера
    Position    : array [0..2] of TALfloat; // позиция источника звука в пространстве
  end;

type PSndInfo = ^TSndInfo;


type
  TAudio = class

  private                                         
    MainDevice  : TALCdevice; // переменная отвечает за устройство воспроизведения
    MainContext : TALCcontext; // переменная отвечает за контекст
    FSndList : TList;      // список загруженных звуковых файлов
   
  protected
......................
public
    property SndList : TList read FSndList;

    constructor Create;
    destructor  Destroy; override;

    function LoadWAVFile(vFilePath : string; Pos : TVector; vIsLoop : TALint) : TALint; // загрузка звукового файла в буфер, связывание буфера с источником звука

    procedure Play(IDSnd : TALint); // проигрывание звукового файла
    procedure Stop(IDSnd : TALint);  // остановка проигрывания звукового файла
    procedure MoveSound(Pos : TVector; IDSrc : TALuint); // движение источника звука в пространстве
    procedure UnloadWAVFile; // очистка списка FSndList от источников звуков и буферов
  end;


implementation

var
 
  listenerpos: array [0..2] of TALfloat = (0.0, 0.0, 0.0);  // позиция
  listenervel: array [0..2] of TALfloat = (0.0, 0.0, 0.0);  // движение
  listenerori: array [0..5] of TALfloat = (0.0, 0.0, -1.0, 0.0, 1.0, 0.0); // может тут надо усложнить


constructor TAudio.Create;
begin
  ReadAudioParams;
 
  //инициализируем OpenAL
  if not InitOpenAL then
    begin
      LogMsg(LOG_MSG_ERR1);
      Exit;
    end;
   
  MainDevice := alcOpenDevice(nil); // получаем доступ к устройству, nil - означает, что берётся первое удобное устройство в системе
  if MainDevice = nil then
    begin
      LogMsg(LOG_MSG_ERR2);
      Exit;
    end;

  // получаем контекст для устройства, второй параметр - ссылка
  MainContext := alcCreateContext(MainDevice, nil); // атрибуты устройства, пока что не трогаем, ставим nil
 
  alcMakeContextCurrent(MainContext); // делаем контекст текущим
  FSndList := TList.Create;


end;


// загрузка звукового файла в буфер, связывание буфера с источником звука
function TAudio.LoadWAVFile(vFilePath : string; Pos : TVector; vIsLoop : TALint) : TALint; // procedure TVector
var
  CurrSnd : PSndInfo;  // указатель на структуру хранения атрибутов звукового файла
  // 5 переменных нужны для загрузки звука в буфер
  format : TALenum;
  data  : TALvoid;
  size  : TALsizei;
  freq  : TALsizei;
  loop  : TALint;
begin
  // Проверка наличия файла
  if not FileExists(START_MODEL_PATH + AUDIO_PATH + vFilePath) then
    begin
      LogMsg(LOG_MSG_ERR4 + START_MODEL_PATH + AUDIO_PATH + vFilePath + LOG_MSG_ERR5);
      Result := -1;
      Exit;
    end;

  ///CurrSnd := GetSoundByName(vFilePath); // пока отключил
  if (CurrSnd = nil)  then
    begin
      New(CurrSnd);

      CurrSnd.FileName := vFilePath;
      alutLoadWAVFile(START_MODEL_PATH + AUDIO_PATH + vFilePath, format, data, size, freq, loop); // функция загружает данные из wav-файла в память…
      alGenBuffers(1, @CurrSnd.SoundBuffer);  // выделяем один буфер
      alBufferData(CurrSnd^.SoundBuffer, format, data, size, freq); // переносим загружённые данные в выделенный ранее буфер
      alutUnloadWAV(format, data, size, freq); // выгружаем звук
      alGenSources(1, @CurrSnd.SourceID);      // выделяем один источник

      alSourcei(CurrSnd^.SourceID, AL_BUFFER, CurrSnd^.SoundBuffer); // связываем источник с буфером
      alSourcef(CurrSnd^.SourceID, AL_PITCH, 1.0);
      alSourcef(CurrSnd^.SourceID, AL_GAIN, 1.0); // ставил значения и 32, и 64 и т.д. не помогло
      CurrSnd.Position[0] := Pos.X;
      CurrSnd.Position[1] := Pos.Y;
      CurrSnd.Position[2] := Pos.Z;
      alSourcefv(CurrSnd^.SourceID, AL_POSITION, @CurrSnd.Position);
      alSourcei(CurrSnd^.SourceID, AL_LOOPING, vIsLoop); // источник воспроизводит данные из буфера либо 1 раз, либо по кругу

      listenerpos[0] := GUN_XYZ.X; // присвоение значений глобальных переменных стрелка
      listenerpos[1] := GUN_XYZ.Y;
      listenerpos[2] := GUN_XYZ.Z;
      alListenerfv(AL_POSITION, @listenerpos);
      alListenerfv(AL_ORIENTATION, @listenerori);

      CurrSnd.ID := FSndList.Count;
      FSndList.Add(CurrSnd);
    end;
   
  if (CurrSnd <> nil) then
    Result := CurrSnd.ID
  else Result := -1;
end;

// проигрывание звукового файла
procedure TAudio.Play(IDSnd : TALint);
begin
      // Если файл отсутствует на диске, то уходим
      if IDSnd < 0 then
        Exit;

      alSourcePlay(TSndInfo(FSndList[IDSnd]^).SourceID);
end;

#3
1:00, 18 ноя. 2008

Есть подозрения, что строку
MainDevice := alcOpenDevice(nil);

надо заменить, например, на

MainDevice := alcOpenDevice('Generic Software');

Хотя при этом выскакивает ошибка о переполнении стека

#4
12:07, 18 ноя. 2008

Я вообще то пишу на С++, но насколько понимаю интерфейс у библиотеки особо не отличается.
Сравнивая со своим кодом заметил что у меня вообще не используются

alSourcef(CurrSnd^.SourceID, AL_PITCH, 1.0); 
alSourcef(CurrSnd^.SourceID, AL_GAIN, 1.0);
Положение слушателя в пространстве такое же
Зато для источников задаются направления.
alSource3f( m_SourceInfo.mSource, AL_DIRECTION, X, Y, Z);
Устройство создается с параметром
alcOpenDevice("Generic Software");
Я осознанно решил отказаться от аппаратной поддержки, так как ориентируюсь восновном на интегрированные звуковые карты, а на них количество каналов очень ограничено.
И может еще есть смысл поиграть с масштабами расстояний от источников до слушателя? Может они просто слишком далеко и звук затухает?

#5
12:35, 18 ноя. 2008

Например, самолёт пролетает над головой слушателя на высоте 300 м, я так поставил для большей однозначности при прослушивании. Я бы должен оглохнуть от рёва двигателей, но вместо этого как бы над своей головой слышу только ласковое тихое мурлыканье :) и то ненадолго, около 5 с
До игры с масштабами расстояний ещё дело не дошло, я упускаю из виду что-то элементарное.
То что я раньше писал про ошибку о переполнении в стеке в строке
MainDevice := alcOpenDevice('Generic Software');
Это из-за того, что переименовал dll-ку OpenAL  1.1 и вернул старую (43 кБ). Когда опять вернул новую и проверил, то эта строка ошибку не генерировала.
Я зыком С++ я тоже увлекаюсь :)
Спасибо, попробую задавать направления источников

Жаль, не могу в Инете найти книг по OpenAL в электронном виде, только статьи одни и форумы. Или их и на английском языке ещё не издали авторы этой библиотеки?
По OpenGL ужо сколько книг...

#6
13:32, 18 ноя. 2008

Я только OpenAL Programmer's Guide OpenAL Versions 1.0 and 1.1 читал. Большинство того, что встречается в интерете посвящено старым версиям.

#7
14:57, 18 ноя. 2008

OpenAL Programmer's Guide OpenAL мне очень помогает, но книги от разработчиков этой библиотеки с небольшими примерами применения их детища со спецификой ООП были бы как нельзя кстати. А так нам пока приходится из отвлечённых примеров по крупицам создавать свои классы. Статьи с примерами создания классов на основе этой библиотеки я просматривал. Но конкретная реализация, есть конкретная реализация. И в моём случае, слабая громкость монозвуков является нюансом. Ничего, справимся :)

#8
16:12, 18 ноя. 2008

Ну я надеюсь вы ведь поняли что позиционирование работает только для моно звуков. Поэтому в вашем случае стерео звуки нормально регулируются громкостью, а моно затухают из-за того что далеко находятся.

#9
17:15, 18 ноя. 2008

Про затухание и т.п. моно звуков всё понятно. Непонятно, почему при приближении к слушателю (условно ко мне) за 500 м, а потом при пролетании над головой на высоте 300 м он всё-таки тихий, хотя должен греметь. Только что  в Редакторе воздушной обстановки выставил высоту пролетания самолёта на 30 м (высота рельефа местности в точке стояния стрелка-слушателя), так чтобы он в голову слушателя вообще врезался :) Он пролетел совсем рядом, но звук совсем тихий
При пригрывании этого моно звука в Windows Media Player он гораздо громче и при этом можно считать, что он звучит рядом со мной. Почему он в раз 10 слабее в 3D сцене? Если самолёт в сцене пролетает вообще в нескольких метрах от головы, почему по силе он намного меньше, чем при проигрывании в  Windows Media Player?

#10
9:48, 19 ноя. 2008

Я сделал простенькое приложение и снабдил его регуляторами расстояний по координатным осям. В этом приложении я проигрывал моно звук пролетающего самолёта и получил тот же результат затухания и наростания звука как и в движке. На высоте 1000 усл. ед. (можно считать и в метрах) я получил еле заметный звук, а на 1100 ничего не слышно. Алгоритмист (бывший военный и канд. военн. наук) говорил, что звук от пролетающего самолёта дожен быть ещё отчётливо слышен на расстоянии 1500 м. Следовательно, на вскидку на расстоянии в 2000 м он условно не слышен.
Отсюда вывод, недостаточная мощность аккустической системы, на которой моно звук записывается, и на которой он воспроизводится.
Следовательно, переходим к игре с масштабированием расстояний от источников до слушателя, как вы и посоветовали :)
Но перед этим я попробую ещё задавать направления источников по вашему совету.
Будем на ты?

#11
11:53, 19 ноя. 2008

Там ведь зависимость затухания звука от расстояния тоже настраивается.
Для этого есть параметры
AL_REFERENCE_DISTANCE
AL_MAX_DISTANCE
И т.д. Вот с ними и нужно экспериментировать. И вообще я бы не стал прямолинейно считать что 1500 условных единиц программы - это обязательно реальные метры.

#12
2:09, 20 ноя. 2008

Огроменное спасибо тебе LIVe за такую наводку :) Один только AL_REFERENCE_DISTANCE дал почувствовать силу акустики. Проблема практически решилась. Не пропадай никуда, оставайся на связи. В моих данных на этом форуме есть квиповская аська, стучись и откроется :)

#13
0:06, 21 ноя. 2008

LIVe
А ты какую дистанционную модель расчёта предпочитаешь? Сдаётся мне, чтобы все моно звуки самолёта (напр., подбитого) были слышны и на расстоянии превышающем AL_MAX_DISTANCE, необходимо комбинировать модели. Может для одних звуков инициализировать одну модель, а для других звуков другую?
Ты с этим не игрался?

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

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