簡體   English   中英

如何在Apple的MixerHost核心音頻示例中停止音頻文件的循環播放

[英]How to stop an audio file from looping in Apple's MixerHost Core Audio Example

我有一個應用程序,允許用戶使用音頻單元錄制節拍。 為了實現這一點,我從Apple的MixerHost示例代碼中修改了Mixer類。

目前我的聲音文件循環,我想停止。 我希望用戶能夠在聲音文件通過后保存混音。

循環的原因是inputrendercallback函數的以下部分的最后一行中的for loop

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;
    }

我意識到我需要改變if (sampleNumber >= frameTotalForSound) sampleNumber = 0; 為了告訴回調一旦樣本用盡就停止請求樣本,但是我在調​​用目標C中的方法比調整這個C-Struct要舒服得多。

有沒有人對如何做到這一點有任何想法?

謝謝。

我只能想象許多人一定遇到過這個音頻文件循環問題,因為MixerHost是Apple提供的少數幾個Core Audio示例之一。

我使用NSNotificationCenter解決了這個問題。 在譴責在C函數中使用Objective C之前,請注意我通過在MixerHost示例中模仿Apple代碼的其他部分來找到此解決方案。 例如,要暫停程序並指示已拔下耳機,或者設備已從底座連接器中移除,Apple會在MixerHostAudio類的audioRouteChangeListenerCallback使用通知中心:

 if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) {

            NSLog (@"Audio output device was removed; stopping audio playback.");
            NSString *MixerObjectPlaybackStateDidChangeNotification = @"MixerObjectPlaybackStateDidChangeNotification";
            [[NSNotificationCenter defaultCenter] postNotificationName: MixerObjectPlaybackStateDidChangeNotification object: audioObject]; 

我還決定在inputrendercallback函數中發布通知:

for (UInt32 frameNumber = 0; frameNumber < inNumberFrames; ++frameNumber) {

        if (sampleNumber == frameTotalForSound) {

            NSString *AudioFileFinishedPlaying = @"AudioFileFinishedPlaying";
            [[NSNotificationCenter defaultCenter] postNotificationName: AudioFileFinishedPlaying object: nil];
        }

        outSamplesChannelLeft[frameNumber]                 = dataInLeft[sampleNumber];
        if (isStereo) outSamplesChannelRight[frameNumber]  = dataInRight[sampleNumber];

        sampleNumber++;

...

然后我在程序的另一部分中使用addObserver:selector:name:object:方法來停止循環並執行與我的應用程序密切相關的其他任務。

我希望這有用。 如果有人有更好的解決方案,那么我願意接受它。 謝謝。

您不應在音頻處理或緩沖區回調的內部循環中使用任何Objective C消息。 沒有理由太多的周期開銷。 堅持在C結構中使用內在的C類型。 設置標志變量是可以的。 稍后在回調和內部音頻樣本循環之外進行任何所需的對象消息傳遞。

感謝您發布解決方案,它的工作原理與Apple宣布其他通知的方式並不矛盾。 幾點說明:

  1. 如果您要混合多個文件,這將在最短文件到達時停止播放器。

  2. 我嘗試了以下代碼(假設inputrendercallback函數的其余部分未更改):

    if(sampleNumber> = frameTotalForSound){NSLog(@“Reached the end!”); THIS.stopAUGraph; sampleNumber = 0; //如果有人想再玩一次}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM