从 Springboard 返回后导致通用跳过的 AudioUnits

Posted

技术标签:

【中文标题】从 Springboard 返回后导致通用跳过的 AudioUnits【英文标题】:AudioUnits causing universal skipping after returning from Springboard 【发布时间】:2011-05-25 20:25:28 【问题描述】:

我在使用 AudioUnits 的应用程序中遇到问题。所有应用程序的音频(包括未通过 AudioUnits 播放的音频)将在退出 Springboard 并返回应用程序后开始跳过。

我将问题分解为一个新的单独测试应用程序。以下是重复它的步骤:

使用 AVAudioPlayer。 创建、删除,然后再创建一个 音频单元 退出跳板 返回应用 来自 AvAudioPlayer 的音频将开始跳过

这是我使用的一些代码:

- (IBAction)restartAudioUnit 

    MySoundStream* audioUnitClass;
    audioUnitClass = Load();
    [audioUnitClass release];
    audioUnitClass = Load();


请原谅冗长的代码转储,但 AudioUnits 很复杂,我很确定我只是错误地设置或删除它们。

MySoundStream 类:

OSStatus UnitRenderCB(void* pRefCon, AudioUnitRenderActionFlags* flags, const AudioTimeStamp* timeStamp, UInt32 busNum, UInt32 numFrames, AudioBufferList*  pData)

    OSStatus tErr = noErr;

    //Do Nothing

    return tErr;


@implementation MySoundStream

-(void) dealloc 

    [self Unload];

    [super dealloc];


-(void) Unload 

    OSStatus tErr = noErr; 
    tErr = AudioUnitUninitialize(OutUnit);


@end

MySoundStream* Load()

    OSStatus tErr = noErr;
    AudioComponentInstance tRIO;
    AudioComponentDescription tRIOCD;
    AURenderCallbackStruct tRIOCB;
    AudiostreamBasicDescription tAUF;

    tRIOCD.componentType = kAudioUnitType_Output;
    tRIOCD.componentSubType = kAudioUnitSubType_RemoteIO;
    tRIOCD.componentManufacturer = kAudioUnitManufacturer_Apple;
    tRIOCD.componentFlags = 0;
    tRIOCD.componentFlagsMask = 0;

    AudioComponent tRIOC = AudioComponentFindNext(NULL, &tRIOCD);
    tErr = AudioComponentInstanceNew(tRIOC, &tRIO);
    if (tErr != noErr) return NULL;

    int tOutEnable = 1;

    tErr = AudioUnitSetProperty(tRIO, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &tOutEnable, sizeof(tOutEnable));
    if (tErr != noErr) return NULL; 

    tAUF.mSampleRate = 44100.00;
    tAUF.mFormatID = kAudioFormatLinearPCM;
    tAUF.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    tAUF.mFramesPerPacket = 1;
    tAUF.mChannelsPerFrame = 2;
    tAUF.mBitsPerChannel = 16;
    tAUF.mBytesPerPacket = 4;
    tAUF.mBytesPerFrame = 4;

    tErr = AudioUnitSetProperty(tRIO, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &tAUF, sizeof(tAUF));
    if (tErr != noErr) return false;

    MySoundStream* pRet = [MySoundStream alloc];

    tRIOCB.inputProc = UnitRenderCB;
    tRIOCB.inputProcRefCon = pRet;
    tErr = AudioUnitSetProperty(tRIO, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, 0, &tRIOCB, sizeof(tRIOCB));
    if (tErr != noErr) delete pRet; return NULL; 

    tErr = AudioUnitInitialize(tRIO);
    if (tErr != noErr) delete pRet; return NULL; 

    pRet->OutUnit = tRIO;

    return pRet;

如果有人能看出我对这个 AudioUnit 做错了什么,那将非常有帮助。

编辑: 上传完整的源代码。 Here

    按播放声音(可能需要耳机) 按重启AudioUnit 返回跳板 重新进入 TestAudioUnit 应用

音频将跳过

【问题讨论】:

【参考方案1】:

当应用程序重新初始化时,您正在调用AudioUnitInitialize(),这不好。您只需在您的应用启动时调用一次AudioUnitInitialize(),并且您不必在每次应用进入前台时都构建整个 AU 图。

【讨论】:

对不起,如果我不清楚。我调用 AudioUnitInitialize,然后是 Uninit,然后在应用程序运行时再次调用 Init。好像我正在关闭单元,重新配置它,然后重新启动它。这是不允许的吗?然后在重新配置后我退出到 Spring 并返回,没有调用 AudioUnit 任何东西。 我可能在调查此问题时发现了我的错误。有一个我没有调用的 AudioSessionInitialize,文档说应该调用一次,然后再也不会调用,这就是你所指的吗? 在更新中添加了源,正在调用 AudioSessionInitialize。 @TurqMage 是的,您应该只在程序的初始化中调用 AudioSessionInitialize 一次。多次调用它(即,当您的应用程序进入前台或重新启动音频子系统时)并不好。在您的委托中使用didFinishLaunchingWithOptions 对其进行一次调用,而不是其他任何地方。【参考方案2】:

改用 AUGraph 来设置我的音频单元路径,我的运气更好。

【讨论】:

以上是关于从 Springboard 返回后导致通用跳过的 AudioUnits的主要内容,如果未能解决你的问题,请参考以下文章

Stream skip()跳过前N个子元素

Stream skip()跳过前N个子元素

Stream skip()跳过前N个子元素

从 Springboard 启动应用程序显着延迟

编写一个 shell 脚本,该脚本将返回您的存储库 git [重复] 跳过的文件列表

如何解决 Sitecore 计划任务在添加后 10 分钟内被跳过的问题?