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

Детский вопрос по DirectSound (решено)

#0
1:39, 24 сен. 2013

Доброй всем ночи.

В связи с известными событиями внезапно возникла потребность разобраться в DirectSound. До этого работал только с OpenAL. Пример посмотрел, что-то почитал, пропищал в простейшей программе. Но возник вопрос.

В OpenAL я мог создать буфер размером в несколько мегабайт, спокойно загрузить в него трёхминутный саундтрек, поставить на воспроизведение и забыть про него. В DirectSound размер буфера усекается до странных 22664 байтов (при частоте 44100 Гц это меньше одной секунды!). Это что ж получается, мне надо постоянно в этот буфер по мере проигрывания звука докидывать кусочки воспроизводимой звуковой волны? Так оно и работает? Или я что-то недопонял и можно загрузить все звуковые данные целиком?

Подглядел кусок исходного кода OpenAL, отвечающий за реализацию через DSound. Вроде так и есть. Это и правда так?

Решение:
1) не использовать Primary Buffer
2) странные 22664 байта возникают из-за моей ошибки, определил переменную как WORD, соответственно при создании буфера 88200 байт я получал 88200%65536=22664, отсюда и были все проблемы.

#1
2:23, 24 сен. 2013

Правда.  Но что мешает использовать программный буфер? Он может быть очень большим.

#2
2:26, 24 сен. 2013

Alex-y
Что значит "программный буфер"?

У меня вся звуковая волна (к примеру, 5-мегабайтный саундтрек без сжатия) будет храниться в оперативке. Есть способ скормить весь массив ДиректСаунду напрямую из оперативки? Как?

P.S. Флаг DSBCAPS_LOCSOFTWARE не помогает.

#3
2:51, 24 сен. 2013

А с какими флагами создаётся буфер? Главное флаг DSBCAPS_PRIMARYBUFFER  не использовать.

правка:
В первом своем посте я имел ввиду не использовать первичный буфер.

#4
3:02, 24 сен. 2013

Первичный буфер как раз есть (так было в примере). Выкинул его, ситуация не поменялась.

Буфер для аудиоданных - только флаг DSBCAPS_LOCSOFTWARE. В примере был еще STATIC, я его убрал, т.к. на MSDN сказано, что он форсирует размещение буфера в hardware-памяти.

#5
3:12, 24 сен. 2013

Так, ситуация потихоньку проясняется. Размер буфера я выставлял для примера 88200, а получался у меня по 22664. Вычитаем и получаем 65536, то есть в dwBufferBytes вписывались только два младших байта, как будто это short. При попытке создать буфер размером 65537 байт получим 1 байт, 65538 байт - 2 байта и так далее. Втф? dwBufferBytes же, даблворд, 4-байтное целочисленное?

Ну и, разумеется, где-то в дебрях кода переменная была объявлена как WORD вместо DWORD'a. Не уследил, списывая пример.

Проблема вроде как решена:
1) не использовать Primary Buffer
2) флаг DSBCAPS_LOCSOFTWARE.

Заметил еще одну деталь: если звук зациклить, то слышен шов. Причём слышен он только если размер буфена не кратен частоте. Если при частоте дискретизации 22050 Гц делать буферы размером 44100, 66150, 88200 и так далее - зацикливание бесшовное. Это особенность реализации? Зацикливаемые звуки всегда делают кратными частоте дискретизации?

#6
8:40, 24 сен. 2013

Роман Шувалов
> слышен шов. Причём слышен он только если размер буфена не кратен частоте.
А ты уверен, что исходные данные без шва? Сделай буфер 30000 и поставь частоту 30000, разве шов пропадёт?

#7
13:09, 24 сен. 2013

Mikle
> А ты уверен, что исходные данные без шва?
Ой, и правда, период тона не кратен же размеру буфера... короче, надо меньше кодить в 3 часа ночи. Всем спасибо, вопросы решены.

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

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