• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: audiounit stop callback at end of file
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: audiounit stop callback at end of file


  • Subject: Re: audiounit stop callback at end of file
  • From: wm schauweker <email@hidden>
  • Date: Sun, 15 Apr 2012 12:27:47 -0700 (PDT)

One way I've done it is as follows:
o assumption: "player" class has a start and a stop method (which are probably exposed as start/stop buttons by a GUI class).
o audio callback checks for end of input, and found, sends a message via "NotificationCenter"
o main class has registered for notification, and so receives the message.
o main class  - the message handler - calls the audio stop method.
o important: the handler has two parts, separated by a call to "performSelectorOnMainThread. (Otherwise, you get into a nasty situation where effectively you are calling a main thread routine from a callback thread.


Here are some snippets:

/**
 * Play/Stop button handler.
 */
- (IBAction)play:(id)sender {
    if (! [ [self player ] isPlaying ]) {
        ...          
        // Register for notification when playback has ended naturally.
        [ [ NSNotificationCenter defaultCenter ] addObserver:self selector:@selector(playbackEnded:) name:@"PlaybackEnded" object:nil ];
        ...
    } else {
        [ [ NSNotificationCenter defaultCenter ] removeObserver:self name:@"PlaybackEnded" object:nil ];
        [self performSelectorOnMainThread:@selector(asynchPlaybackStop) withObject:nil waitUntilDone:FALSE];
    }
}

// Called by NotificationCenter when playback of a recording has finished.
- (void)playbackEnded:(NSNotification *)note {
    [ [ NSNotificationCenter defaultCenter ] removeObserver:self name:@"PlaybackEnded" object:nil ];
    // Note that the player is actually stopped from this level.
    [self performSelectorOnMainThread:@selector(asynchPlaybackStop) withObject:nil waitUntilDone:FALSE];
    [ self setViewState ];
}

// This is the code to stop playing
- (void) asynchPlaybackStop {
    ...
    [ [ self player ] stopPlaying ];
    ...
}

// This is code from the callback - when end-of input is detected
...
// End of input reached - notify any listeners.
// NOTE!! OBJECTIVE C.
[[NSNotificationCenter defaultCenter] postNotificationName:@"PlaybackEnded" object:nil];
 // NOTE!! END OBJECTIVE C.





From: Robert Carroll <email@hidden>
To: email@hidden
Sent: Sunday, April 15, 2012 1:54 PM
Subject: audiounit stop callback at end of file

Hi,

The callback code used in the MixerHost sample code is set up for looping audio files. The loop happens when the current samplenumber reaches the frameTotalForSound value and gets reset to 0.

What is a safe way to exit the callback when the end of the audio file data is reached? Exiting the for..loop or commenting out the code line that resets the samplenumber gives me a digital noise burst at the end of the file that is playing.

any suggestions would be appreciated.


thanks,

rob



static OSStatus inputRenderCallback (
                                     
                                     void                        *inRefCon,      // A pointer to a struct containing the complete audio data 
                                     //    to play, as well as state information such as the  
                                     //    first sample to play on this invocation of the callback.
                                     AudioUnitRenderActionFlags  *ioActionFlags, // Unused here. When generating audio, use ioActionFlags to indicate silence 
                                     //    between sounds; for silence, also memset the ioData buffers to 0.
                                     const AudioTimeStamp        *inTimeStamp,   // Unused here.
                                     UInt32                      inBusNumber,    // The mixer unit input bus that is requesting some new
                                     //        frames of audio data to play.
                                     UInt32                      inNumberFrames, // The number of frames of audio to provide to the buffer(s)
                                     //        pointed to by the ioData parameter.
                                     AudioBufferList             *ioData         // On output, the audio data to play. The callback's primary 
                                     //        responsibility is to fill the buffer(s) in the 
                                     //        AudioBufferList.
                                     ) {
    
    soundStructPtr    soundStructPointerArray   = (soundStructPtr) inRefCon;
    UInt32            frameTotalForSound        = soundStructPointerArray[inBusNumber].frameCount;
    BOOL              isStereo                  = soundStructPointerArray[inBusNumber].isStereo;
    
    // Declare variables to point to the audio buffers. Their data type must match the buffer data type.
    AudioUnitSampleType *dataInLeft;
    AudioUnitSampleType *dataInRight;
    
    dataInLeft                 = soundStructPointerArray[inBusNumber].audioDataLeft;
    if (isStereo) dataInRight  = soundStructPointerArray[inBusNumber].audioDataRight;
    
    // Establish pointers to the memory into which the audio from the buffers should go. This reflects
    //    the fact that each Multichannel Mixer unit input bus has two channels, as specified by this app's
    //    graphStreamFormat variable.
    AudioUnitSampleType *outSamplesChannelLeft;
    AudioUnitSampleType *outSamplesChannelRight;
    
    outSamplesChannelLeft                 = (AudioUnitSampleType *) ioData->mBuffers[0].mData;
    if (isStereo) outSamplesChannelRight  = (AudioUnitSampleType *) ioData->mBuffers[1].mData;
    
    // Get the sample number, as an index into the sound stored in memory,
    //    to start reading data from.
    UInt32 sampleNumber = soundStructPointerArray[inBusNumber].sampleNumber;
    
    // Fill the buffer or buffers pointed at by *ioData with the requested number of samples 
    //    of audio from the sound stored in memory.
    for (UInt32 frameNumber = 0; frameNumber < inNumberFrames; ++frameNumber) {
        
        outSamplesChannelLeft[frameNumber]                 = dataInLeft[sampleNumber];
        if (isStereo) outSamplesChannelRight[frameNumber]  = dataInRight[sampleNumber];
        
        sampleNumber++;
        
        // After reaching the end of the sound stored in memory--that is, after
        //    (frameTotalForSound / inNumberFrames) invocations of this callback--loop back to the 
        //    start of the sound so playback resumes from there.
        if (sampleNumber >= frameTotalForSound) sampleNumber = 0;  //commenting this outremoves loop, but creates noise at end of file
        //if (sampleNumber == frameTotalForSound) break;  //digital noize !!
    }
    
    // Update the stored sample number so, the next time this callback is invoked, playback resumes 
    //    at the correct spot.
    soundStructPointerArray[inBusNumber].sampleNumber = sampleNumber;
    
    return noErr;
_______________________________________________ Do not post admin requests to the list. They will be ignored. Coreaudio-api mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: This email sent to email@hidden
References: 
 >audiounit stop callback at end of file (From: Robert Carroll <email@hidden>)

  • Prev by Date: Re: newbie question on setting up Ivory instrument unit
  • Next by Date: AUGraphInitialize returns -10877
  • Previous by thread: audiounit stop callback at end of file
  • Next by thread: AUGraphInitialize returns -10877
  • Index(es):
    • Date
    • Thread