没有声音播放时核心音频 CPU 使用率高

Posted

技术标签:

【中文标题】没有声音播放时核心音频 CPU 使用率高【英文标题】:Core audio high CPU usage when no sound playing 【发布时间】:2011-07-08 23:42:27 【问题描述】:

我刚刚开始学习 Core Audio,并制作了一个简单的测试应用程序来演奏三个不同的钢琴音符。除了一件小事之外,它似乎还不错。

起初,该应用程序使用了大约 7% 左右的 CPU(在活动监视器中可见),我认为这是正常的,因为它正在运行实时 AUGraph。然而,随着更多音符的播放,CPU 使用率不断增加,即使当时可能没有声音播放。

下面的时间线:

    启动应用程序。 CPU 使用率几乎为零。 播放音符,中等 CPU 使用率。 笔记完成,没有声音播放,中等 CPU 使用率。

代码:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification

    // Insert code here to initialize your application

    NewAUGraph(&audioGraph);

    AudioComponentDescription cd;
    AUNode outputNode;
    AudioUnit outputUnit;

    cd.componentManufacturer = kAudioUnitManufacturer_Apple;
    cd.componentFlags = 0;
    cd.componentFlagsMask = 0;
    cd.componentType = kAudioUnitType_Output;
    cd.componentSubType = kAudioUnitSubType_DefaultOutput;

    //AUGraphNewNode(audioGraph, &cd, 0, NULL, &outputNode);
    AUGraphAddNode(audioGraph, &cd, &outputNode);
    //AUGraphGetNodeInfo(audioGraph, outputNode, 0, 0, 0, &outputUnit);
    AUGraphNodeInfo(audioGraph, outputNode, &cd, &outputUnit);

    AUNode mixerNode;
    AudioUnit mixerUnit;

    cd.componentManufacturer = kAudioUnitManufacturer_Apple;
    cd.componentFlags = 0;
    cd.componentFlagsMask = 0;
    cd.componentType = kAudioUnitType_Mixer;
    cd.componentSubType = kAudioUnitSubType_StereoMixer;

    AUGraphAddNode(audioGraph, &cd, &mixerNode);
    AUGraphNodeInfo(audioGraph, mixerNode, &cd, &mixerUnit);

    AUGraphConnectNodeInput(audioGraph, mixerNode, 0, outputNode, 0);

    AUGraphOpen(audioGraph);
    AUGraphInitialize(audioGraph);
    AUGraphStart(audioGraph);

    AUNode synthNode;


    cd.componentManufacturer = kAudioUnitManufacturer_Apple;
    cd.componentFlags = 0;
    cd.componentFlagsMask = 0;
    cd.componentType = kAudioUnitType_MusicDevice;
    cd.componentSubType = kAudioUnitSubType_DLSSynth;

    AUGraphAddNode(audioGraph, &cd, &synthNode);
    AUGraphNodeInfo(audioGraph, synthNode, &cd, &synthUnit);

    AUGraphConnectNodeInput(audioGraph, synthNode, 0, mixerNode, 0);

    AUGraphUpdate(audioGraph, NULL);
    CAShow(audioGraph);



- (IBAction)playMusic:(id)sender 
    MusicDeviceMIDIEvent(synthUnit, 0x90, 60, 127, 0);
    sleep(1);
    MusicDeviceMIDIEvent(synthUnit, 0x90, 62, 127, 0);
    sleep(1);
    MusicDeviceMIDIEvent(synthUnit, 0x90, 64, 127, 0);


- (void)one:(id)sender 
    MusicDeviceMIDIEvent(synthUnit, 0x90, 60, 127, 0);


- (void)two:(id)sender 
    MusicDeviceMIDIEvent(synthUnit, 0x90, 62, 127, 0);


- (void)three:(id)sender 
    MusicDeviceMIDIEvent(synthUnit, 0x90, 64, 127, 0);

发生了什么事?我该如何解决这个问题?

谢谢。

【问题讨论】:

第一个想法 - 检查繁忙的循环。顺便说一句 - 在这个档案中找不到源代码 - 只有树和目录树:) 什么是忙循环以及如何检查它们?嗯...当我单击链接时,它会下载一个zip 文件。这就是项目中的所有代码。唯一的其他东西是 UI、xcodeproj 等。 您的代码是否在线程中运行?如果是 - 当您不播放音频时的情况是什么。当它不播放时,尝试在那里添加一些睡眠代码。另一方面 - 检查您是否正确关闭所有句柄并停止播放机制。 @spudwaffle:繁忙的循环只是代码中的一个循环(例如forwhile),尤其是一个运行大量时间的循环,它会消耗 CPU 时间并让你从快速返回运行循环。 您应该使用 Instruments 的 Time Profiler 工具来分析您的应用程序,并查看您的应用程序在其消耗的所有 CPU 时间中正在做什么。 【参考方案1】:

好吧,我想通了!

基本上,我只是忘了停止弹奏这些音符,尽管它们逐渐变得安静,但它们仍在弹奏并使计算机正常工作。

这可以通过将力度设置为0 再次播放音符来解决。因此,代码如下所示:

- (IBAction)playMusic:(id)sender 
    MusicDeviceMIDIEvent(synthUnit, 0x90, 60, 127, 0);
    MusicDeviceMIDIEvent(synthUnit, 0x90, 60, 0, 0);
    sleep(1);
    MusicDeviceMIDIEvent(synthUnit, 0x90, 62, 127, 0);
    MusicDeviceMIDIEvent(synthUnit, 0x90, 62, 0, 0);
    sleep(1);
    MusicDeviceMIDIEvent(synthUnit, 0x90, 64, 127, 0);
    MusicDeviceMIDIEvent(synthUnit, 0x90, 64, 0, 0);


- (void)one:(id)sender 
    MusicDeviceMIDIEvent(synthUnit, 0x90, 60, 127, 0);
    MusicDeviceMIDIEvent(synthUnit, 0x90, 60, 0, 0);


- (void)two:(id)sender 
    MusicDeviceMIDIEvent(synthUnit, 0x90, 62, 127, 0);
    MusicDeviceMIDIEvent(synthUnit, 0x90, 62, 0, 0);


- (void)three:(id)sender 
    MusicDeviceMIDIEvent(synthUnit, 0x90, 64, 127, 0);
    MusicDeviceMIDIEvent(synthUnit, 0x90, 64, 0, 0);

我想如果我想让音符播放更长时间,我可以在开始和停止音符之间等待。

感谢您的所有帮助:@user757808 @Peter Hosey @mbykov

【讨论】:

您实际上不应该发送停止消息吗? 0x80 ? MusicDeviceMIDIEvent(synthUnit, 0x80, 60, 127, 0); @drewish 那会更有意义!谢谢。 速度为 0 的 MIDI Note Off (0x80) 和 MIDI Note On (0x90) 都是停止 MIDI 音符的有效方法。【参考方案2】:

您的代码中 CPU 最重的部分是 AudioUnit 处理过程。尝试为用于播放媒体的硬件设置相同的采样率,以减少 CPU 负载。

AudiosessionSetProperty (kAudioSessionProperty_PreferredHardwareSampleRate, size, &float64);

只有一种方法可以阻止 AudioUnit 处理 - AUGraphStop。

我尝试了一切,退出活动监视器,关闭所有系统声音,只有帮助的是:

    Shift on 启动(安全启动) 打开 iTunes

如果您有时间,或者完全重新格式化 HD 并重新安装 Lion。

【讨论】:

我忘了说我在 Mac 上。这看起来只适用于 iOS。

以上是关于没有声音播放时核心音频 CPU 使用率高的主要内容,如果未能解决你的问题,请参考以下文章

播放音乐时,我的音频应用程序中没有收到通知或消息的声音 | AV音频播放器

使用 Python 录制或播放音频无法在 Mac 上运行:没有错误和没有声音

HTML5 音频 - 录制保存文件正常,但通过音频控制播放时没有声音

discord.js 机器人在没有声音的情况下播放音频

discord.js 机器人播放音频但没有声音?

电脑无法播放声音,提示没有音频设备,这该怎么办?