Problems using AEBlockChannel on iPhone device

Hi Michael,

thanks for this awesome framework. I'm having some issues using AEBlockChannel. The following code uses frame-level timing in a "FOR loop" to keep transitions accurate, this snippet is based in the metronome script concept and triggers drum loops, which are audio channels made of AEAudioFilePlayers, one per each drum part (snare, toms, hi-hat, kick and cymbals). The first loop is triggered once the countdown time has ended, and calculates switching time (in frames) to the next drum loop.

- (void)startPlaybackBlockChannel {

    // the metronome and playback control
    self.metronomeBlockChannel = [AEBlockChannel channelWithBlock:^(const AudioTimeStamp *time, UInt32 frames, AudioBufferList *audio) {
    
        static int next_beat_frame = 0;
        // meter counter
        static int meterCount = 1;
                
        // checks for _isPlaying flag
        if (!_isPlaying) {
            frames = 0;
            next_beat_frame = 0;
            meterCount = 1;

            if (_total_frames > 0) {
                [self stop];
            }
        } else {
            // counting frames
           for (int i=0; i<=frames; i++) { 
                // countdown to start
                if (_total_frames < (int)_start) {
                    _low.volume = 1; _high.volume = 1;
                } else {
                    if (_metronomeButton.selected == NO) {
                        _low.volume = 0; _high.volume = 0;
                    } else {
                        _low.volume = 1; _high.volume = 1;
                    }
                }
            
                if (_total_frames == (int)_start) {
                    // removes countdown signal
                    [self setCountdownAnimation:-1];
                   // this function changes drums' pieces (currently 4 or 5 AEAudioPlayers so far), 
                   // basically a FOR loop setting channelIsPlaying property to YES.
                    [_currentLoop startInstrumentPlayback];
                    // setting _isPlaying to YES, and getting into this block from now on till it returns to NO.
                    _isPlaying = YES;
                }
                
                // if we reach the current tempo, the next drum will be triggered
                if (_changeTempoAt == _total_frames) {
                    
                   // this index controls if this block should playing the full session
                   int index = [session.slots indexOfObject:_currentLoop] + 1;
                   // stop if session has ended
                    if (index == [session.slots count] && _sessionCounter == 0) {
                        _isPlaying = NO;
                        break;
                    }
                        
                    // this index restarts if we repeat the session and we reached the end
                    if (index == [session.slots count] && _sessionCounter > 0) {
                        index = 0;
                        _sessionCounter--;
                    }
                
                    // stop current drum parts. FOR loop setting channelIsPlaying property to NO
                    [_currentLoop stopInstrumentPlayback];
                                
                    // gets next drums
                    _currentLoop = [session.slots objectAtIndex:index];
                   
                   next_beat_frame = _total_frames;
                    
                    // start next drum parts
                    [_currentLoop startInstrumentPlayback];
                    
                    // updating descriptive labels
                   [self animateLabels];
                    
                   // calculates frames n-times to enable repeating
                   _changeTempoAt += _currentLoop.frameLength;
                                    
                   // calculates metronome ticks
                   _frames_between_beats = 44100/(_currentLoop.tempo/60.);
                
                   // check meter
                    _meter = [self calculateMeter:_currentLoop.meter];
                    meterCount = 1;
                }
            
                // beat handling and initial countdown animations
                if (next_beat_frame == _total_frames) {
                    
                    if (meterCount == 1) {
                        _high.currentTime = 0;
                        _high.channelIsPlaying = YES;
                    } else {
                        _low.currentTime = 0;
                        _low.channelIsPlaying = YES;
                    }
                
                    if (_total_frames < (int)_start)
                        [self setCountdownAnimation:_meter - meterCount];
                    
                    meterCount++;
                
                    if (meterCount == _meter+1) {
                        meterCount = 1;
                    }
                
                    next_beat_frame += _frames_between_beats;
                
                }
            
                
                // increment the count
                _total_frames++;
            }
        }
    }];
    
    // adding the block channel to the audio controller
    [_audioController addChannels:[NSArray arrayWithObject:_metronomeBlockChannel]];
}

At the beginning, I was using AEBlockScheduler to coordinate loop switching and UI updates based on time events. Using AEBlockChannel for this process makes more sense,  and my UI events and track transitions are really accurate.

The problem is that my app runs perfectly on the iPhone simulator, but there's no sound on my iPhone 5 device. I assume the problem is not preparing the AEAudioFilePlayers, because I triggered them from outside the frame loop and they are playing correctly.

Do you have any idea what could be causing this?

Thanks.

Comments

Sign In or Register to comment.