问题标签 [avaudioplayernode]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
ios - 使用 AVAudioPlayerNode 播放片段时,我可以注册两个不同的回调,调度完成和播放完成吗?
我正在使用 AVAudioPlayerNode 在 Swift 中构建多轨音频播放器。在安排要播放的音频片段时,我希望在安排完成时以及文件播放完成时/是否完成时收到通知。Swift API 的编写方式似乎只能注册其中一个。如果调用短函数:
一旦文件被安排(不播放,只是安排播放),回调就会被调用,你不能传递任何特殊参数,只是一个基本的闭包。
当调用更高级的函数时,你可以指定你想要的回调类型,但是你必须选择一个并且只有一个:
枚举 AVAudioPlayerNodeCompletionCallbackType 可以是以下之一:dataConsumed、dataRendered 或 dataPlayedBack
不幸的是我必须选择一个,但我真的需要两个。计划完成和 dataPlayedBack 时需要通知我。
有没有办法做到这一点?
swift - 播放完成后在 AVAudioPlayerNode 上调用 stop() 会导致崩溃
我有一个 AVAudioPlayerNode 对象,它在播放完成后发送一个回调。该回调会触发应用程序中的许多其他功能,其中一个会发送一条礼貌的 stop() 消息。出于某种原因,在 AVAudioPlayerNode 完成时调用 stop() 会导致崩溃。在此处的代码中,我对其进行了缩写,以便 AVAudioPlayerNode 立即调用 stop 来演示效果(而不是包括我的整个应用程序)。您可以清楚地看到它崩溃了。我不明白为什么。要么 a) 节点仍在播放并且 stop() 停止它,要么 b) 它完成播放并且可以忽略停止。
我的猜测是,这是一些边缘情况,它位于文件缓冲区的最后,并且处于模棱两可的状态,没有更多的缓冲区剩余,但从技术上讲仍在播放。也许调用 stop() 会尝试刷新剩余的缓冲区并且它们是空的?
ios - AVAudioengine 播放/循环音频,多个按钮
我有这个按钮来播放和循环一个 wav。但是,如果我有另一个带有另一个循环的按钮怎么办?我希望第二个循环一旦按下就开始播放,但是,第一个循环必须完成他的“回合”。反之亦然(播放并循环第二个循环,按下按钮第一个循环并接管)
avaudioengine - 如何将 AVAudioUnitVarispeed 添加到同时播放多个声音的工作 AVAudioEngine
我正在为 iOS 制作音乐应用程序。我想同时播放 5 个文件。这已经在这个线程的帮助下工作了:如何使用连接到 AVAudioEngine 混音器的节点同时从缓冲区播放多个声音
现在我需要使用 AVAudioUnitVarispeed 更快地播放所有文件。我不能让它工作。
这是代码:
如果我替换此代码同时播放 5 个音符
和
...并调用 playSound()。
但后来我没有实现 AVAudioUnitVarispeed (speedControl) ......
那么,如何添加 AVAudioUnitVarispeed 的代码呢?
谢谢您的帮助。
ios - 在 iOS 上一次可以播放多少个声音 - AVAudioPlayer vs. AVAudioEngine & AVAudioPlayerNode
我有一个应用程序,其中有一组大约 50 个声音,长度范围从大约 300 毫秒到大约 4 秒。需要在精确的时间播放各种声音组合(一次最多可以触发 10 个)。有些声音需要以短至 100 毫秒的间隔重复。
我已经将其实现为 AVAudioPlayers 的二维数组,所有这些都在应用程序启动时加载了声音。每个声音有几个播放器,以适应快速重复的声音。特定声音的播放器在严格轮换中重复使用。当安排了新的声音时,该声音的最旧播放器将停止并且其当前时间设置为 0,因此声音将从头开始重复,下次使用 player.play(atTime:) 进行安排。有一个线程可以在播放新声音之前大约 300 毫秒安排新的声音集。
这一切都很好,直到某个点因设备而异。最终,随着声音播放得更快,和/或安排了更多同时的声音,一些声音将拒绝播放。
我正在考虑使用混合器节点切换到 AVAudioEngine 和 AVAudioPlayerNodes。有谁知道这种方法是否可以处理更多的同时声音?我的猜测是,这两种方法都转化为一组相当相似的 CoreAudio 函数,但我实际上并没有编写代码来测试这个假设——在我这样做之前,我希望其他人可能在我之前探索过这个问题。我之前对CoreAudio很深入,我希望能够使用这些方便的高级功能来代替!
另外,有没有人知道当声音开始时触发关闭的方法?记录的功能允许回调关闭,但我能够在声音开始时触发事件的唯一方法是为 DispatchQueue 创建一个高质量的服务队列。不幸的是,根据系统负载,排队事件的执行时间可能与预定时间相差最多约 50 毫秒,这并不像我希望的那样精确。
swift - 如何使用 AVAudioPlayerNode 播放 PCM 16 位?
我有应用程序通过网络从 opus 解码流音频到 pcm,输出数据是 PCM 16 位,我成功解码,但是当我尝试使用 AVAudioEngine 播放它失败时,我无法将采样率从 44100 更改为 48000作品生成。
这是我用来播放音频的代码的一部分
这是我将 pcm 数据转换为 AVAudioPCMBuffer 的方法
在循环中我使用这个
ios - Swift iOS 中的实时音高转换
我想实现一个 iOS 应用程序(快速),它可以改变手机麦克风输入的音高,并在用户以最小延迟(最多几毫秒)说话时通过扬声器播放修改后的声音。到目前为止,我有以下代码:
但是,一旦我运行该应用程序,我就会收到以下错误:
任何解决此问题的帮助表示赞赏。
编辑:
我认为问题在于installTap
从未调用过回调函数,因此链被破坏了。
如果我使用 AVFoundation 的时间效果来处理实时麦克风输入的方法是正确的,如何解决这个错误?
或者,如果我的方法方向错误,如何以最小延迟(最多延迟几毫秒)实时更改设备麦克风的输入音高?
ios - 使用 AVAudioEngine 从内存中播放立体声音频缓冲区
我正在尝试在我的 iOS 应用程序中从内存(而不是文件)播放立体声音频缓冲区,但是当我尝试将 AVAudioPlayerNode 'playerNode' 附加到 AVAudioEngine 'audioEngine' 时,我的应用程序崩溃了。我得到的错误代码如下:
我不知道这是否是由于我声明 AVAudioEngine、AVAudioPlayerNode 的方式,我生成的缓冲区是否有问题,或者我是否错误地附加了节点(或其他原因!)。我有一种感觉,这与我创建新缓冲区的方式有关。我正在尝试从两个单独的“单声道”阵列制作立体声缓冲区,也许它的格式不正确。
我已经宣布audioEngine:AVAudioEngine!和 playerNode:AVAudioPlayerNode!全球:
然后我加载我的应用程序将要处理的单声道源音频文件(不会播放此文件中的数据,它将被加载到数组中,处理然后加载到新缓冲区中):
然后将数组发送到卷积函数两次,每次都返回一个新数组。这是因为单声道源文件需要成为立体声音频缓冲区:
maxSignalLength 变量当前是输入信号的长度 + 正在与之卷积的脉冲响应 (normalisedImpulseResponse) 的长度,目前为 256。这将在某个时候成为适当的变量。
然后我声明并加载新的缓冲区及其格式,我感觉错误就在这里,因为这将是播放的缓冲区:
请注意,我没有创建交错缓冲区,我将立体声音频数据加载到缓冲区中,如下所示(我认为这也可能是错误的):
音频也限制在 -1 和 1 之间的值。
然后我终于(试图)将缓冲区加载到音频节点,将音频节点附加到音频引擎,启动音频引擎然后播放节点。
我在运行时遇到的错误是:
它没有显示发生此错误的行。我已经坚持了一段时间,并且尝试了很多不同的东西,但似乎没有很清楚的信息关于从内存播放音频而不是从我能找到的 AVAudioEngine 文件中播放音频。任何帮助将不胜感激。
谢谢!
编辑#1:更好的标题
编辑#2:更新 - 我已经找到了我收到错误的原因。这似乎是由于在将 playerNode 附加到 audioEngine 之前设置它引起的。交换顺序阻止程序崩溃并抛出错误:
但是,我没有任何声音。使用与输入信号相同的方法创建 outputBuffer 的浮点数组后,并用断点查看其内容,它似乎是空的,所以我也必须错误地将数据存储到 outputBuffer。
swift - AVAudio 和离线手动渲染模式 - 无法将更高频率的缓冲区写入输出文件
我正在读取输入文件并使用离线手动渲染模式,我想执行幅度调制并将结果写入输出文件。
为了测试,我产生纯正弦波——这适用于低于 6.000 Hz 的频率。对于更高的频率(我的目标是使用大约 20.000 Hz),信号(因此监听输出文件)会失真,并且频谱在 8.000 Hz 处结束 - 不再有纯频谱,在 0 到 8.000 Hz 之间有多个峰值。
这是我的代码片段:
我的问题:有s.th。我的代码错了吗?或者有谁知道如何生成具有更高频率正弦波的输出文件?
我想手动渲染模式不够快,无法处理更高的频率。
更新:与此同时,我确实用 Audacity 分析了输出文件。上图为 1.000 Hz 的波形,下图为 20.000 Hz 的波形:
奇怪的是,随着频率的升高,幅度趋近于零。此外,我在第二个频谱中看到更多频率。
与结果相关的一个新问题是以下算法的正确性:
我确实检查了采样率,即 48000 - 我知道当采样频率大于被采样信号的最大频率的两倍时,可以忠实地重建原始信号。
更新 2:
我更改了如下设置:
现在输出信号的质量更好,但并不完美。我得到更高的幅度,但在频谱分析仪中总是不止一个频率。也许解决方法可以包括应用高通滤波器?
与此同时,我确实使用了一种 SignalGenerator,将经过处理的缓冲区(使用正弦波)直接传输到扬声器——在这种情况下,输出是完美的。我认为将信号路由到文件会导致此类问题。
avaudioengine - 不为连续安排的文件调用 AVAudioPlayerNode 完成回调
使用 调度文件或缓冲区时AVAudioPlayerNode
,您可以提交完成回调。您还可以指定应调用回调的事件,选项为:
在大多数情况下,这可以按预期工作。dataRendered
但是,当一个接一个地调度文件时,如果类型为或,则不会调用最后一个文件以外的文件的回调dataPlayedBack
。
这是一个演示该问题的独立示例。(此代码可以粘贴在 Xcode iOS 'App' 模板中的 'ViewController.swift' 文件的内容上。该项目需要包含代码中引用的音频文件才能工作。)
这是我得到的输出:
如您所见,回调函数会为缓冲区的所有三个实例调用,但只为文件的最后一个实例调用。
同样,它仅用于dataRendered
或dataPlayedBack
不调用回调。对于dataConsumed
,它可以正常工作。
有没有人遇到过这个?任何人都可以确认这种行为吗?这似乎是一个错误,但也有可能我做错了什么。
编辑:
这是响应评论中提出的想法的另一个版本的代码。在这个版本中,不再调度同一个文件实例三次,而是连续调度同一个文件的三个实例:
结果是一样的。除了多次读取同一个文件的实用性之外,这是一个有趣的诊断,因为它提供了有关行为的更多信息。如果它是一个错误,它似乎与预定文件是否是相同的 AVAudioFile 实例无关。