This doesn’t make any sense. I have a class that uses Apples Audio Queue Services framework and it works fine. But I’m refactoring it and this refactor sometimes doesn’t work for the oddest reason.
Like this line…
dim t As Ptr = theAQ
theAQ is a Ptr property of the class, it’s the main Ptr that’s passed to every Audio Queue declare. Simply assigning it to a dummy variable that’s never used can change whether my code produces sound or not.
I first pinned down the problem with a test for “theAQ = nil” at the beginning of a method. My code didn’t work but if I commented out that test I got sound. Here’s a sketch…
[code]Class Qsynth //original
Property theAQ As Ptr
Sub begin()
//initialize theAQ
//start running AQ
End Sub
End Class
Class QMonoFloat32Synth //refactor
Property theAQ As Ptr
Sub createAQ()
//initialize theAQ
End Sub
Sub start()
if theAQ = nil then return //<<<<---- this prevents sound
//start running AQ
End Sub
End Class[/code]
I need to perform this test and found if I do it like this then sound comes out…
[code]if Integer(theAQ) = 0 then return
or
dim null As Ptr
if theAQ = null then return[/code]
I never noticed such squirrelly behavior while working on the original. The difference between the two is theAQ is setup and run all in a single method in the original but there’s method boundaries splitting the 2 parts in the refactor. Maybe something happens in the boundary, I don’t know, I can’t imagine what.
And it gets wierder. I work in Xojo 13r4.1 and there having no test produces sound, but in 14r3.2 there’s no sound. Then adding that line “dim t As Ptr = theAQ” makes sound in 14r3.2, but prevents sound in 13r4.1.
To clarify, when it doesn’t work it’s just that my callback is never called. Every Audio Queue declare takes theAQ as a parameter and returns an error code. It gets setup with my Xojo method for callback, buffers allocated and primed, all without errors. It’s just that if I don’t ‘touch’ theAQ the right way then when I call the AudioQueueStart function it doesn’t start calling the callback.
Actually I do have a guess what’s wrong, something I planned to ask about once this was built up more: the voodoo of CFRunLoops. When creating the AQ you have to tell it which RunLoop to run on. I use CFRunLoopGetMain because that’s the only one I could make work, but I’m not very clear on the implications, like reentrancy. Maybe RunLoops have impact in method boundaries and that’s why the refactored version is susceptible. Still I don’t see how “if theAQ = nil then” or “dim t As Ptr = theAQ” could change anything.
Here’s a trimmed down project. Go to QMonoFloat32Synth.start() and try uncommenting the marked sections then run and click start. If it plays it’s a harsh sine wave, throttle your volume.
http://home.comcast.net/~trochoid/AQ.zip