Adding multiple channels, each with a filter, causes scratchy output !
This has been a vexing problem for several days. I have an app where the input audio is replicated to multiple channels each with one filter. All of those channels feed one output group. The user controls the relative volume of each and can add and remove them, essentially a mixer. I add the channel/filters one by one, but after about 3 of them, the output has a scratchy sound. The scratchy sound follows the input (that is, no input no scratchy sound). The number of channels/filters needed to cause the problem changes on different models of iPhone, but I consistently get the problem on a iPod Touch at three. Adding the first two filters is flawless.
My basic structure is simple. i have one output group (theOutputGroup). Each time I add a channel/filter, I approximately do this:
_playthrough = [[AEPlaythroughChannel alloc] init];
[_playthrough setVolume:0.0];
[_audioController addInputReceiver:_playthrough];
[_audioController addChannels:@[_playthrough] toChannelGroup:theOutputGroup];
_filter = [[AEAudioUnitFilter alloc] initWithComponentDescription:somedescription];
[_audioController addFilter:_filter toChannel:_playthrough];
I then wait for filter to start, then let the user set the relative volume of this filter (which is setting _playthrough volume). The last two lines of code that create the filter and add it to the channel are done on a background thread (not the main thread) as that operation will can block for several seconds.
If i remove a channel/filter, the scratchy sound disappears.
the actual code has an array of playthroughs and an array of filters, but i simplified it here. I tried a version where I created all the channels in advance, then added filters one at a time and the same problem occurs.
Some other information:
Odd #1 - I suspected some kind of endian-issue in the data, so I recorded the output (with AERecorder) and found that even when I hear scratchy, the recording seems to be fine
Odd #2 - originally I just put a loop of NSLog statements with the audio data to peek at it. When the NSLog's were looping, the scratchy sound went away! of course the app's UI was frozen during this time. I don't know what to make of this, but if it means something to someone..
I SUSPECT THIS: as i add filters, there is a change in the audio format that doesn't quite get reflected everywhere in the complete graph of the audio where converters may be necessary that weren't necessary prior to filter added. (for example, from mono to stereo or from little to big-endian). seems like this should be handled though without any of code on my part.
Any help would be greatly appreciated!
-dave
Comments
Hi @davethewave - it sounds to me like a processor overload. Have you seen any warnings in the console about the render taking too long?
Thanks for the help! Yes, I suspected cpu overload, thought Xcode never shows more than 25% CPU usage, but I do test this on the least powerful device I have (an older iPod Touch) to find such issues. More powerful devices, like iPhone6 behave differently which supports the cpu-overload possibility - under same conditions, I would sees 20%-ish CPU usage in Xcode for iPhone 6.
i do get the render too long messages on occasion, but not really sync-ed with the problem and only upon occasion. I'm going to look more closely though. It's a little odd, but most all of those messages I get are at 52% of budget. "TAAE: Warning: render took too long (0.003016s, 51.96% of budget). Expect glitches." This seems within budget though - perhaps the message is triggered at 50% I suspect.
At startup, I see this: "Buffer duration 0.0058, 256 frames (requested 0.005s, 221 frames)"
thanks again,
-dave
Hmm, that's it for my theories, I'm afraid
If you'd like me to take a look, maybe make a little sample app that demonstrates the issue?