Play loop sound (from file) with dynamic intervals?

Hello,

first of all thanks a lot for providing this great framework.
I want to play a certain sound effect from a file at dynamic interval times.
So let's say I have this array [0, 1043, 5456, 6001, 10020] that contains time information in milliseconds.
What I want to achieve is to play the sound at the very beginning (0 ms), then at 1043 ms, then at 5456 ms, then at 6001 ms, then at 10020 ms while this last playback equals the 0 ms.
So the next playback would be 1043 ms later... and so on (in a loop).
Could anybody please give me a hint on this one?

Thanks a lot!

Comments

  • Hi there,

    a small update on this one. I was able to implement a single loop cycle like this:

    @implementation ViewController {
        AEAudioController *_audioController;
        AppDelegate *_appDelegate;
        NSMutableArray *_timeIntervals;
        int intervalIndex;
        BOOL isPlaying;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        intervalIndex = 0;
    
        _timeIntervals = [[NSMutableArray alloc] init];
        [_timeIntervals addObject:[NSNumber numberWithDouble:0.0]];
        [_timeIntervals addObject:[NSNumber numberWithDouble:3043.0]];
        [_timeIntervals addObject:[NSNumber numberWithDouble:8456.0]];
        [_timeIntervals addObject:[NSNumber numberWithDouble:16001.0]];
        [_timeIntervals addObject:[NSNumber numberWithDouble:35020.0]];
    
        isPlaying = NO;
    
        _appDelegate = [[UIApplication sharedApplication] delegate];
        _audioController = [_appDelegate audioController];
    }
    
    - (IBAction)btnPlayAudioTouched:(id)sender {
        isPlaying = YES;
    
        while(isPlaying) {
    
            NSURL *file = [[NSBundle mainBundle] URLForResource:@"drum01" withExtension:@"mp3"];
            AEAudioFilePlayer *aeAudioFilePlayer = [AEAudioFilePlayer audioFilePlayerWithURL:file error:NULL];
    
            //current timeInterval
            double currentTimeInterval = [[_timeIntervals objectAtIndex:intervalIndex] doubleValue];
            double currentTimeIntervalInSecs = currentTimeInterval / 1000;
    
            [aeAudioFilePlayer playAtTime:AECurrentTimeInHostTicks() + AEHostTicksFromSeconds(currentTimeIntervalInSecs)];
    
            [_audioController addChannels:[NSArray arrayWithObject:aeAudioFilePlayer]];
    
            intervalIndex++;
            if(intervalIndex == _timeIntervals.count) {
                isPlaying = NO;
                intervalIndex = 0;
            }
        }
    }
    

    From what I can see, this outputs a correct audio result. But I guess I might run into memory issues as soon as the timeIntervals array contains many more elements...

    On top, this sample only runs one loop cycle. In order to "fix" this, the only thing I can come up with is to pre-calculate the next many timeStamps while hoping that many is enough for the user. If not - the user won't hear a sound anymore. It seems to me that this approach is not scalable / elegant at all.
    I'd appreciate any help on this one.

    Thanks a lot.

  • edited August 2016

    You were close, @fr3sh - you need to use the "regionStartTime" and "regionDuration" properties of the player, as well as "loop". The timestamp passed to "playAtTime" is the time that you're going to play at (as in, the world time).

  • Hi @Michael,

    thanks for helping. I'm not quite sure I get your hint. From what I found out, "regionStartTime" and "regionDuration" both refer to timestamps inside an audio file. So let's say my drum01.mp3 file has a total duration time of 0.26 secs.
    I could do this in order to simply loop the file:

    NSURL *file = [[NSBundle mainBundle] URLForResource:@"drum01" withExtension:@"mp3"];
        AEAudioFilePlayer *aeAudioFilePlayer = [AEAudioFilePlayer audioFilePlayerWithURL:file error:NULL];
        //In this trivial case the next two lines could be left out as the duration equals the total duration and it starts from the beginning... setting loop to YES should be enough.
        aeAudioFilePlayer.regionStartTime = 0.0;
        aeAudioFilePlayer.regionDuration = 0.26;
        aeAudioFilePlayer.loop = YES;

    What I can do is specifying which part of the audio file needs to be looped:

    NSURL *file = [[NSBundle mainBundle] URLForResource:@"drum01" withExtension:@"mp3"];
        AEAudioFilePlayer *aeAudioFilePlayer = [AEAudioFilePlayer audioFilePlayerWithURL:file error:NULL];
        aeAudioFilePlayer.regionStartTime = 0.1;
        aeAudioFilePlayer.regionDuration = 0.16;
        aeAudioFilePlayer.loop = YES;

    This results in a loop of a smaller chunk of the audio file (last 0.16 secs).
    Still I don't know how this could help me solving my problem. I want the audio file to be played completely. The only thing that needs to by dynamically adjusted is the time gap between each loop.
    I also tried setting the regionDuration to a bigger value than the audio file length. But this does not extend the time gap neither.

  • Oh, I beg your pardon, I'd misread your problem! Sorry about that.

  • Hello @Michael,

    no problem at all.
    Still, any thoughts on how to call the audio sequence without having to throw all resources to it?
    Is there a more elegant way to solve this?

    Thanks a lot!

  • edited August 2016

    Off the top of my head, I think I'd probably use the player's completion block to schedule the next player(s) for the successive time interval. So, keep a mutable array of players, and initialise enough players to begin with so that you can then schedule more once the first one finishes. Each time a player finishes, add some more for the next interval. Probably something like that =)

    If these are very short audio samples you may be better off using AUSampler, too (which isn't supported directly in TAAE, but it's an audio unit so you can use AEAudioUnitChannel/AEAudioUnitModule.

    It might also be worth checking out AudioKit.

  • Hi @Michael,

    thank you very much for your tipps! I'll look into them.
    Thanks a lot!!

Sign In or Register to comment.