muhku / FreeStreamer

A low-memory footprint streaming audio player for iOS and OS X
http://muhku.github.io/FreeStreamer/
Other
2.11k stars 436 forks source link

Player sometime never leaves STKAudioPlayerStateBuffering state #433

Closed zsaraf closed 5 years ago

zsaraf commented 5 years ago

I'm using this library to build a radio iOS app that has a directory of Icecast streams that the user can click on and listen to.

This library works very well 95% of the time, but 5% of the time, the player gets stuck in the STKAudioPlayerStateBuffering state and never changes, not reporting any errors at all. It seems like some kind of a race condition. Any idea why this could be happening?

- (BOOL)startAudioIO
{
    NSError *error = nil;

    AVAudioSessionCategory category = AVAudioSessionCategoryPlayAndRecord;
    AVAudioSessionCategoryOptions options = AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionDefaultToSpeaker;
    if ([AVAudioSession sharedInstance].category != category || [AVAudioSession sharedInstance].categoryOptions != options) {
        [[AVAudioSession sharedInstance] setCategory:category withOptions:options error:&error];
        if (error) {
            NSLog(@"STKAudioPlayer: Error setting category on audio session.");
            return NO;
        }
    }

    [[AVAudioSession sharedInstance] setActive:YES error:&error];
    if (error) {
        NSLog(@"STKAudioPlayer: Error starting audio session.");
        return NO;
    }

    return YES;
}

- (void)setupPlayer
{
    STKAudioPlayerOptions options;
    options.bufferSizeInSeconds = 2;

    _audioPlayer = [[STKAudioPlayer alloc] initWithOptions:options];
    _audioPlayer.delegate = self;

    [_audioPlayer appendFrameFilterWithName:@"FFT" block:^(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames)
     {
         uint16_t bytesPerSample = bytesPerFrame / channelsPerFrame;

         if (bytesPerSample == 2) {
             vDSP_vflt16((short *)frames, 1, self->_floatInputBuffer, 1, frameCount * channelsPerFrame);
         } else if (bytesPerSample == 4) {
             vDSP_vflt32((int *)frames, 1, self->_floatInputBuffer, 1, frameCount * channelsPerFrame);
         } else {
             NSLog(@"STKAudioPlayer: Other bytePerSample sizes are not supported. TODO(zsaraf): Test for this now!");
         }

         // 2^(n-1) because it is a signed number where n = 16 (short *)
         const float nBits = pow(2, (bytesPerSample * 8) - 1);
         vDSP_vsdiv(self->_floatInputBuffer, 1, &nBits, self->_floatNormalizedInputBuffer, 1, channelsPerFrame * frameCount);

         [[DFFTManager shared] processFFTWithInputBuffers:self->_fftArgBuffer inputChannels:channelsPerFrame numberOfSamples:frameCount interleaved:YES];
     }];
}

- (void)startStreamWithUrl:(NSString *)streamUrl
                streamName:(NSString *)streamName
               streamImage:(NSString *)streamImage
     streamCreatorUsername:(NSString *)streamCreatorUsername
{
    // Set values in case we get disconnected and need to reconnect.
    self->_streamUrl = streamUrl;
    self->_streamName = streamName;
    self->_streamImage = streamImage;
    self->_streamCreatorUsername = streamCreatorUsername;

    // Begin stream.
    dispatch_async(dispatch_get_main_queue(), ^{
        [self startAudioIO];

        if (self->_audioPlayer == nil) {
            [self setupPlayer];
        }

        [self->_audioPlayer play:streamUrl];
    });
}

- (void)stopStream
{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self->_audioPlayer stop];

        [self cleanupStream];
   });
}

Any ideas at all on where to look?

Thanks Zach

zsaraf commented 5 years ago

Sorry, wrong library :)