【问题标题】:AVPlayer playback of single channel audio stereo->monoAVPlayer 播放单声道音频立体声->单声道
【发布时间】:2013-03-02 12:29:48
【问题描述】:

在我的 iPad/iPhone 应用程序中,我正在使用 AVPlayer 播放视频。视频文件有一个立体声音频轨道,但我只需要以单声道播放该轨道的一个通道。部署目标是 iOS 6。我该如何实现呢?非常感谢您的帮助。

【问题讨论】:

    标签: ios cocoa-touch core-audio avplayer


    【解决方案1】:

    我现在终于找到了这个问题的答案 - 至少对于 iOS 6 上的部署而言。您可以轻松地将 MTAudioProcessingTap 添加到现有的 AVPlayer 项目中,并在期间将选定的通道样本复制到另一个通道你的进程回调函数。这是一个很好的教程,解释了基础知识:http://chritto.wordpress.com/2013/01/07/processing-avplayers-audio-with-mtaudioprocessingtap/

    这是我目前的代码,大部分是从上面的链接中复制的。

    在 AVPlayer 设置期间,我为音频处理分配回调函数:

    MTAudioProcessingTapCallbacks callbacks;
    callbacks.version = kMTAudioProcessingTapCallbacksVersion_0;
    callbacks.clientInfo = ( void *)(self);
    callbacks.init = init;
    callbacks.prepare = prepare;
    callbacks.process = process;
    callbacks.unprepare = unprepare;
    callbacks.finalize = finalize;
    
    MTAudioProcessingTapRef tap;
    // The create function makes a copy of our callbacks struct
    OSStatus err = MTAudioProcessingTapCreate(kCFAllocatorDefault, &callbacks,
                                              kMTAudioProcessingTapCreationFlag_PostEffects, &tap);
    if (err || !tap) {
        NSLog(@"Unable to create the Audio Processing Tap");
        return;
    }
    assert(tap);
    
    // Assign the tap to the input parameters
    audioInputParam.audioTapProcessor = tap;
    
    // Create a new AVAudioMix and assign it to our AVPlayerItem
    AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
    audioMix.inputParameters = @[audioInputParam];
    playerItem.audioMix = audioMix;
    

    这里是音频处理函数(实际上只需要处理):

    #pragma mark Audio Processing
    
    void init(MTAudioProcessingTapRef tap, void *clientInfo, void **tapStorageOut) {
        NSLog(@"Initialising the Audio Tap Processor");
        *tapStorageOut = clientInfo;
    }
    
    void finalize(MTAudioProcessingTapRef tap) {
        NSLog(@"Finalizing the Audio Tap Processor");
    }
    
    void prepare(MTAudioProcessingTapRef tap, CMItemCount maxFrames, const AudioStreamBasicDescription *processingFormat) {
        NSLog(@"Preparing the Audio Tap Processor");
    }
    
    void unprepare(MTAudioProcessingTapRef tap) {
        NSLog(@"Unpreparing the Audio Tap Processor");
    }
    
    void process(MTAudioProcessingTapRef tap, CMItemCount numberFrames,
             MTAudioProcessingTapFlags flags, AudioBufferList *bufferListInOut,
             CMItemCount *numberFramesOut, MTAudioProcessingTapFlags *flagsOut) {
        OSStatus err = MTAudioProcessingTapGetSourceAudio(tap, numberFrames, bufferListInOut, flagsOut, NULL, numberFramesOut);
        if (err) NSLog(@"Error from GetSourceAudio: %ld", err);
    
        SIVSViewController* self = (SIVSViewController*) MTAudioProcessingTapGetStorage(tap);
    
        if (self.selectedChannel) {
    
            int channel = self.selectedChannel;
    
            if (channel == 0) {
                bufferListInOut->mBuffers[1].mData = bufferListInOut->mBuffers[0].mData;
            } else {
                bufferListInOut->mBuffers[0].mData = bufferListInOut->mBuffers[1].mData;
            }
        }
    }
    

    【讨论】:

    • 您好,正在寻找在一个耳机通道上播放 TTS 声音的解决方案。您的代码可能会有所帮助,或者您有什么建议吗?
    • 嗨,Ben,我刚刚编辑了答案并添加了源代码。希望对您有所帮助。
    • 有谁知道你会怎么用 Swift 写这个。似乎无法让它工作?
    • 嗨,我无法在包含它的对象之后正确解除分配 Tap 处理器,请在此处查看我的问题:es.stackoverflow.com/questions/111080/…
    猜你喜欢
    • 2022-12-22
    • 2015-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多