haskell - Using Gloss to run a simulation while using SDL to play a sound -


i have simulation that's tied data gleaned sound file. run simulation , play sound file @ same time see how data matches up.

the problem seem unable play sound via sdl.mixer , run gloss simulation @ same time. both of these functions work fine on own.

the window simulation gets created, nothing drawn , wav file plays. data make model simulation (onsets) extremely computationally expensive? doesn't seem evaluated @ all.

{-# language scopedtypevariables #-} module main  import ghc.float import debug.trace import control.concurrent import control.monad.fix import control.monad  import graphics.gloss import graphics.gloss.interface.pure.simulate import graphics.gloss.data.color  import qualified sound.file.sndfile snd import qualified sound.file.sndfile.buffer.vector b import qualified graphics.ui.sdl sdl import qualified graphics.ui.sdl.mixer mix  --my own libraries import sound.analysis.spectrum import sound.analysis.spectralflux import sound.analysis.onset import sound.data.buffers  --(timeelapsed, todraw, tobedrawn) type time = float type drawableonsets = (time, onset, onsetstream)  main =     --bs holds our buffers     (info, (bs :: b.buffer double)) <- snd.readfile "./downtheroad.wav"     --convert unboxed array     let b = sterilize bs      --grab of sound file     let ct = (truncate $ (fromintegral $ snd.frames info)/2048)     let = streaminfo 1024 44100 2      let b' = samplerawpcm 0 ct (i, b)     let s = pcmstream b'      --very expensive computations     let freqs   = freqstream s --get frequency bins     let fluxes  = fluxstream freqs --get spectral flux     let onsets = onset fluxes --get onsets based on spectral flux      let onsetmodel = makemodel onsets      let dispwin = inwindow "onset test" (1440, 300) (0,0)      forkio playsound     simulate dispwin white 45 onsetmodel drawonsets stepworld      print "done"  playsound =     sdl.init [sdl.initaudio]     result <- mix.openaudio 44100 mix.audios16lsb 2 4096     toplay <- mix.loadwav "./downtheroad.wav"     ch1 <- mix.playchannel (-1) toplay 0     fix $ \loop ->         sdl.delay 50         stillplaying <- mix.numchannelsplaying         when (stillplaying /= 0) loop    makemodel :: onsetstream -> drawableonsets makemodel (i, os) = (0.0, onset 0 0.0, (i, os))  drawonsets :: drawableonsets -> picture drawonsets (t, o, os) = translate x 50 $ color red $ circlesolid rad       rad = (double2float $ power o)*0.01             x   = (fromintegral $ frame o)  stepworld :: viewport -> float -> drawableonsets -> drawableonsets stepworld vp t' (t, o, (i, os)) = (elapsed, o', (i, os'))       o'  | elapsed > nexttime = head os                 | otherwise          = o              os' | (elapsed > nexttime) = tail os                 | otherwise          = os              elapsed = t+t'*1000             interval = (fromintegral $ samplerate i)/(fromintegral $ fftwindow i)             nexttime = (fromintegral $ frame o) * 86 

i've tried few things such using evaluate in control.exception package such.

makemodel :: drawableonsets -> io drawableonsets makemodel  (i, os) = evaluate (0.0, onset 0 0.0, os) 

to try , force evaluation of expensive computations, seems have no effect. same goes adding bang pattern makemodel , in let declarations in main.

... let !freqs = freqstream s let !fluxes = fluxstream freqs ...  makemodel (i, !os) = (0.0, onset 0 0.0, os) 

futhermore, if try forkio both playsound , simulate program terminates without playing sound or simulation.

any appreciated!

your code not self-contained, stripped down forkio playsound followed gloss.display of static picture, , experienced same problem: sound playing nothing displayed until stops.

i found out sdl-mixer uses unsafe foreign functions not preemptible. replaced sdl.delay 50 (which blocks current os thread entire duration) threaddelay 50000 give scheduler chance work, , changed forkio forkos make sure ffi calls sdl issued same os thread (generally idea when dealing stateful libraries). picture appears immediately, sound ends abruptly after fraction of second.

then found this answer suggesting audio chunk freed haskell gc while still playing. after inserting touchforeignptr toplay before threaddelay works expected.

playsound =     sdl.init [sdl.initaudio]     result <- mix.openaudio 44100 mix.audios16lsb 2 4096     toplay <- mix.loadwav "./sound.wav"     ch1 <- mix.playchannel (-1) toplay 0     fix $ \loop ->         touchforeignptr toplay         threaddelay 50000         stillplaying <- mix.numchannelsplaying         when (stillplaying /= 0) loop 

of course, make sure compile threaded rts (-threaded ghc option). computationally intensive simulation may introduce additional problems, eager know how works out you.


Comments

Popular posts from this blog

css - Which browser returns the correct result for getBoundingClientRect of an SVG element? -

gcc - Calling fftR4() in c from assembly -

Function that returns a formatted array in VBA -