Звук SDL-Mixer останавливается при запуске входного цикла Reactive-Banana

Я работал над игрой, в которой используется несколько звуковых дорожек, громкость которых регулируется в реальном времени в зависимости от движения мыши. Я использую SDl-Mixer для звука и Reactive-Banana для игры в целом. Проблема в том, что треки, которые были запущены в самом начале, перестают воспроизводиться при запуске входного цикла. Причина может быть в чем-то другом, но мне интересно, есть ли какое-то странное взаимодействие между SDL и Reactive-Banana, которого я не понимаю. Я пытался разгадать это какое-то время, но это может быть что-то простое, что я упустил из виду. Заранее спасибо. Вот код простого теста:

import Reactive.Banana
import Graphics.UI.SDL
import Graphics.UI.SDL.Mixer
import Control.Monad

musicdir = "/home/silas/code/haskell/river/audio/"

testNet :: AddHandler (Int,Int,[MouseButton]) -> NetworkDescription t ()
testNet mouseHdlr = do
  eMouse <- fromAddHandler mouseHdlr
  reactimate $ (putStrLn . show) <$> eMouse

main = withInit [InitEverything] $ do
         setVideoMode 100 100 32 [SWSurface]
         openAudio defaultFrequency AudioS16Sys 1 1024
         allocateChannels 1
         chunk <- loadWAV $ musicdir ++ "guitar1" ++ ".ogg"
         playChannel 0 chunk (-1)
         (mouseHdlr, mouseAction) <- newAddHandler
         net <- compile $ testNet mouseHdlr
         actuate net
         forever $ getMouseState >>= mouseAction

Редактировать: проблема, похоже, не обязательно связана с реактивным бананом. Любая «вечная» петля приводит к остановке звука.


person user1675049    schedule 16.09.2012    source источник
comment
Что произойдет, если вы удалите реактивный банан с картинки, заменив последнюю строку на forever $ getMouseState >>= print?   -  person Heinrich Apfelmus    schedule 16.09.2012
comment
Тот же результат. Я почти уверен, что реактивный банан не является проблемой на данный момент.   -  person user1675049    schedule 16.09.2012


Ответы (2)


Возможно, это не ваша проблема, но когда у меня была похожая проблема, сборщик мусора не мог сказать, что я все еще использую аудиофрагмент SDL (потому что его использовал только SDL), и освободил ОЗУ из-под SDL. . Чтобы решить эту проблему, вы должны не только убедиться, что элемент находится в области видимости в течение всего времени, пока SDL будет его использовать, но и что ваш код на Haskell действительно каким-то образом использует его (чтобы оптимизатор не менял ничего на ты). Такие вызовы, как touchForeignPtr, очень полезны для этого.

person singpolyma    schedule 16.09.2012
comment
Да! Вывоз мусора был моей проблемой. Спасибо. Многократный вызов touchForeignPtr предотвратил удаление фрагмента сборщиком мусора, и звук продолжался. - person user1675049; 16.09.2012
comment
Похоже, это недостаток в привязках библиотеки SDL. - person Heinrich Apfelmus; 17.09.2012
comment
@HeinrichApfelmus Э-э... может быть? Как бы вы их построили, чтобы сборщик мусора знал, что что-то нужно оставить в рамках? Я думаю, вы могли бы сделать что-то вроде Hipmunk и закрыть карту всего... или что-то в этом роде. Честно говоря, привязки SDL очень тонкие, особенно привязки к -Mixer и -Gfx. - person singpolyma; 17.09.2012
comment
Что ж, на стороне Haskell GC правильно освобождает аудиоданные, поскольку они там больше не используются. Вызов touchForeignPtr работает, но это не правильное решение. Вместо этого сторона SDL должна нести ответственность за сохранение данных и их повторное освобождение. - person Heinrich Apfelmus; 18.09.2012

Это может быть не связано ни с SDL, ни с реактивным бананом. Подобные проблемы часто исправляются путем компиляции с флагом компилятора -threaded. Если это проект Cabal, добавьте

GHC-Options: -W -threaded

в ваш раздел Executable.

person ertes    schedule 16.09.2012
comment
Пробовал, вроде не помогло. На самом деле, звук вообще не запустился. Связано ли это с тем, что FFI порождает свой собственный поток? Мне интересно, нужно ли мне явно разветвлять поток для SDL. У меня действительно нет опыта работы с FFI в haskell, поэтому у меня может быть неправильное представление. - person user1675049; 16.09.2012
comment
Правильно ли я понимаю, что если использовать -threaded, то звук вообще не запустится, а если не использовать -threaded, то хотя бы запустится? Если это так, то это указывает на то, что SDL плохо работает с параллелизмом. (Что, наверное, неудивительно.) - person Heinrich Apfelmus; 16.09.2012
comment
SDL предназначен для работы с параллелизмом (в нем есть библиотека потоков), но, конечно, есть некоторые правила. Большинство вызовов SDL можно сделать только из потока, в котором изначально был вызван SDL.init, но наличие других потоков, безусловно, не вызовет проблем :) - person singpolyma; 16.09.2012
comment
@Apfelmus: на данный момент я не использую параллелизм (насколько мне известно), но да, это то, что произошло. - person user1675049; 16.09.2012