【问题标题】:AudioUnits causing universal skipping after returning from Springboard从 Springboard 返回后导致通用跳过的 AudioUnits
【发布时间】: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

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

音频将跳过

【问题讨论】:

    标签: iphone objective-c ios audiounit


    【解决方案1】:

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

    【讨论】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-02
      • 1970-01-01
      • 2015-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多