我正在开发一个应用程序,以便人们可以通过应用程序记录和更改他们的声音并分享它.基本上我有很多东西,现在是时候请你帮忙了.这是我的播放功能,播放录制的音频文件并添加效果.
private func playAudio(pitch : Float, rate: Float, reverb: Float, echo: Float) {
// Initialize variables
audioEngine = AVAudioEngine()
audioPlayerNode = AVAudioPlayerNode()
audioEngine.attachNode(audioPlayerNode)
// Setting the pitch
let pitchEffect = AVAudioUnitTimePitch()
pitchEffect.pitch = pitch
audioEngine.attachNode(pitchEffect)
// Setting the platback-rate
let playbackRateEffect = AVAudioUnitVarispeed()
playbackRateEffect.rate = rate
audioEngine.attachNode(playbackRateEffect)
// Setting the reverb effect
let reverbEffect = AVAudioUnitReverb()
reverbEffect.loadFactoryPreset(AVAudioUnitReverbPreset.Cathedral)
reverbEffect.wetDryMix = reverb
audioEngine.attachNode(reverbEffect)
// Setting the echo effect on a specific interval
let echoEffect = AVAudioUnitDelay()
echoEffect.delayTime = NSTimeInterval(echo)
audioEngine.attachNode(echoEffect)
// Chain …Run Code Online (Sandbox Code Playgroud) 我正试图通过Apples Multipeer Connectivity框架将音频从麦克风传输到另一部iPhone.要做到音频捕获和播放我使用AVAudioEngine(非常感谢艺术Fistman"的回答在这里).
我通过在输入上安装一个麦克风来接收来自麦克风的数据,从中我得到一个AVAudioPCMBuffer,然后我将其转换为一个UInt8数组,然后我将其流式传输到另一部手机.
但是当我将数组转换回AVAudioPCMBuffer时,我得到一个EXC_BAD_ACCESS异常,编译器指向我再次将字节数组转换为AVAudioPCMBuffer的方法.
以下是我正在处理,转换和流式传输输入的代码:
input.installTap(onBus: 0, bufferSize: 2048, format: input.inputFormat(forBus: 0), block: {
(buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
let audioBuffer = self.typetobinary(buffer)
stream.write(audioBuffer, maxLength: audioBuffer.count)
})
Run Code Online (Sandbox Code Playgroud)
我对将数据转换两种功能(摘自Martin.R的答案在这里):
func binarytotype <T> (_ value: [UInt8], _: T.Type) -> T {
return value.withUnsafeBufferPointer {
UnsafeRawPointer($0.baseAddress!).load(as: T.self)
}
}
func typetobinary<T>(_ value: T) -> [UInt8] {
var data = [UInt8](repeating: 0, count: MemoryLayout<T>.size)
data.withUnsafeMutableBufferPointer {
UnsafeMutableRawPointer($0.baseAddress!).storeBytes(of: value, as: T.self)
}
return data …Run Code Online (Sandbox Code Playgroud) 我对信号处理几乎一无所知,目前我正在尝试在Swift中实现一个函数,该函数会在声压级增加时触发事件(例如,当人尖叫时)。
我正在通过这样的回调进入AVAudioEngine的输入节点:
let recordingFormat = inputNode.outputFormat(forBus: 0)
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat){
(buffer : AVAudioPCMBuffer?, when : AVAudioTime) in
let arraySize = Int(buffer.frameLength)
let samples = Array(UnsafeBufferPointer(start: buffer.floatChannelData![0], count:arraySize))
//do something with samples
let volume = 20 * log10(floatArray.reduce(0){ $0 + $1} / Float(arraySize))
if(!volume.isNaN){
print("this is the current volume: \(volume)")
}
}
Run Code Online (Sandbox Code Playgroud)
将其转换为浮点数组后,我尝试通过计算平均值来大致估算声压级。
但这给我带来了很大的价值波动,即使iPad只是坐在一个很宽敞的房间里也是如此:
this is the current volume: -123.971
this is the current volume: -119.698
this is the current volume: -147.053
this is the current …Run Code Online (Sandbox Code Playgroud) 为了同时进行可用的播放和录制,我们使用这些方法来设置AVAudioSession类别:
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:NULL];
Run Code Online (Sandbox Code Playgroud)
通过这样做,输出音频端口从线路输出扬声器切换到内置扬声器.在循环录制窗口中,我们需要同时从线路输出扬声器和麦克风录音进行播放.要在设置AVAudioSession类别后从线路输出扬声器播放声音,我们使用一种设置输出音频端口的方法:
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
我们尝试使用AVAudio Engine安排录制和播放.AVAudioEngine连接结构:
// input->inputMixer->mainEqualizer ->tap
// 0 0 |0
// |
// |
// |0 0 0
// recordPlayerNode?recordMixer?meteringMixer?|
// 0 1 0 0 |
// |->mainMixer->out
// |
// volumePlayer?|
// 0 1
Run Code Online (Sandbox Code Playgroud)
执行overrideOutputAudioPort后,录制功能将停止在iPhone 6S及更高版本上运行.我们以这种方式进行录制:
if(self.isHeadsetPluggedIn)
{
volumePlayer.volume = 1;
}
else
{
volumePlayer.volume = 0.000001;
}
[volumePlayer play];
[mainEqualizer installTapOnBus:0 bufferSize:0 format:tempAudioFile.processingFormat block:^(AVAudioPCMBuffer *buf, AVAudioTime *when)
{ …Run Code Online (Sandbox Code Playgroud) 我正在使用Xamarin.iOS作为使用AVAudioEngine的应用程序.
有时我得到这个例外:
AVFoundation_AVAudioPlayerNode_Play由于未捕获的异常'com.apple.coreaudio.avfaudio'而终止应用程序,原因:'必需条件为false:_engine-> IsRunning()'
这指向我的代码:
private Dictionary<AudioTrack, AVAudioPlayerNode> _dicPlayerNodes;
private void PlayAudio()
{
try
{
NSError err;
if (Engine.StartAndReturnError(out err))
{
foreach (var audioTrack in _dicPlayerNodes)
{
AVAudioPlayerNode node = audioTrack.Value;
node.Play();
}
}
else
{
Messenger.Publish(new AudioErrorMessage(this) { Platform = "IOS", Code = Convert.ToInt32(err.Code), Message = err.LocalizedDescription ?? err.Description });
_exceptionHandlerService.PostHockeyApp(new Exception($"{err.Code} {err.Description}"));
}
}
catch (Exception ex)
{
_exceptionHandlerService.PostExceptionAsync(ex).Forget();
}
}
Run Code Online (Sandbox Code Playgroud)
我不明白怎么可能有这个异常引擎没有运行,因为在我的代码中我启动它并获得错误,如果它无法启动...然后播放它.
此外,我有一个尝试捕获在这种情况下不工作:(所以我的应用程序刚刚崩溃.
有什么建议或想法吗?
我来到这个主题,但它无法帮助我理解:https: //forums.developer.apple.com/thread/27980
IOS版本:10.3.3
设备:ipad 2
Xamarin.ios:11.2.0.11
谢谢
AVAudioMixerNodes当我尝试将两个连接到 的麦克风输入时,我遇到了崩溃AVAudioEngine。我无法在网上找到如何管理两个或多个节点到同一输入的文档。
处理有多个节点监听麦克风的情况的正确方法是什么?
我在后台线程上调用这三个方法:
private func setupSession() {
let session = AVAudioSession.sharedInstance()
do {
try session.setCategory(.playAndRecord, options: [.mixWithOthers])
if session.isInputGainSettable {
try session.setInputGain(0.2)
}
try session.setActive(true, options: .notifyOthersOnDeactivation)
} catch let error as NSError {
LoggerManager.shared.error(error: error, message: "Error while setting up AVAudioSession Category/Active status")
}
}
private func setupMixerNodes() {
analyzerNode = AVAudioMixerNode()
analyzerNode.volume = 0
volumeNode = AVAudioMixerNode()
volumeNode.volume = 0
engine.attach(analyzerNode)
engine.attach(volumeNode)
}
private func makeConnections() {
/* input microphone */
let inputNode = …Run Code Online (Sandbox Code Playgroud) 我正在为 iOS 应用程序创建这个简单的录音机和编辑器界面:
音频被记录到用于创建波形的浮点数组中。录制后,我将浮动数据复制到一个AVAudioPCMBuffer用于播放的AVAudioPlayerNode. 我能够从一开始就播放缓冲区,但我不知道如何只播放缓冲区的一部分。该scheduleSegment功能仅适用于文件。
我正在为 iOS 制作一个基本的音乐应用程序,按下音符会播放相应的声音。我正在尝试让存储在缓冲区中的多个声音以最小的延迟同时播放。但是,我每次只能播放一种声音。
我最初使用多个 AVAudioPlayer 对象设置声音,为每个播放器分配一个声音。虽然它确实同时播放多个声音,但它似乎无法同时启动两个声音(似乎它会在第一个声音启动后稍微延迟第二个声音)。此外,如果我以非常快的速度按下音符,引擎似乎无法跟上,并且在我按下后面的音符后,后面的声音就会很好地开始。
我正在尝试解决这个问题,从我所做的研究来看,使用 AVAudioEngine 播放声音似乎是最好的方法,我可以在缓冲区数组中设置声音,然后让它们播放从这些缓冲区中。
class ViewController: UIViewController
{
// Main Audio Engine and it's corresponding mixer
var audioEngine: AVAudioEngine = AVAudioEngine()
var mainMixer = AVAudioMixerNode()
// One AVAudioPlayerNode per note
var audioFilePlayer: [AVAudioPlayerNode] = Array(repeating: AVAudioPlayerNode(), count: 7)
// Array of filepaths
let noteFilePath: [String] = [
Bundle.main.path(forResource: "note1", ofType: "wav")!,
Bundle.main.path(forResource: "note2", ofType: "wav")!,
Bundle.main.path(forResource: "note3", ofType: "wav")!]
// Array to store the note URLs
var noteFileURL = [URL]()
// One audio file per …Run Code Online (Sandbox Code Playgroud) 每次我停止/暂停音频引擎(使用AVAudioEnginesstop()或pause())时,状态栏上都会出现一个红色的麦克风图标一秒钟。
一段时间后,这开始很烦人,每次我暂停/停止引擎时,顶部都会出现红色。
在 iOS 13 中启用音频背景模式功能时会发生这种情况。
要重现这一点,请创建一个新的单视图项目,并将其添加到视图控制器:
private let engine = AVAudioEngine()
Run Code Online (Sandbox Code Playgroud)
而在viewDidAppear:
engine.connect(
engine.inputNode,
to: engine.mainMixerNode,
format: engine.inputNode.inputFormat(forBus: 0)
)
try? engine.start()
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.engine.pause() // or self.engine.stop()
}
Run Code Online (Sandbox Code Playgroud)
记住要启用音频背景模式,添加NSMicrophoneUsageDescription的Info.plist,并在iOS的13设备上运行。接受麦克风权限并重新运行应用程序。您将看到红色麦克风图标闪烁一次。
有没有办法摆脱这个?
我到处寻找,但找不到解决这个问题的方法。我正在寻找一种方法来更改将AVAudioEngine在 macOS 上使用的输入/输出设备。
当简单地播放音频文件时,以下内容按预期工作:
var outputDeviceID:AudioDeviceID = xxx
let result:OSStatus = AudioUnitSetProperty(outputUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &outputDeviceID, UInt32(MemoryLayout<AudioObjectPropertyAddress>.size))
if result != 0 {
print("error setting output device \(result)")
return
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我初始化音频输入(使用let input = engine.inputNode),那么当我尝试启动引擎时,我会收到错误消息:
AVAEInternal.h:88 必需条件为 false: [AVAudioEngine.mm:1055:CheckCanPerformIO: (canPerformIO)]
我知道我的播放代码没问题,因为如果我避免更改输出设备,那么我可以听到麦克风和音频文件,如果我更改输出设备但不初始化文件,则文件会播放inputNode到指定的目的地。
除此之外,我一直在尝试更改输入设备,我从各个地方了解到以下应该执行此操作:
let result1:OSStatus = AudioUnitSetProperty(inputUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Output, 0, &inputDeviceID, UInt32(MemoryLayout<AudioObjectPropertyAddress>.size))
if result1 != 0 {
print("failed with error \(result1)")
return
}
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用 - 在大多数情况下它会抛出错误(10853),尽管如果我选择同时具有输入和输出的声卡,它会成功 - 看来当我尝试设置输出或输入节点时它实际上是为两者设置设备。
我认为这意味着一个AVAudioEngine实例只能处理一个设备,但是它很高兴使用默认设备(麦克风和扬声器/耳机),所以我相信这不是问题。查看一些解决方案,我看到网上人们只是简单地更改默认输入,但这并不是一个非常好的解决方案。
有谁知道这是否可能?
值得注意的是,这kAudioOutputUnitProperty_CurrentDevice是唯一可用的属性,没有等效的kAudioInputUnitProperty_CurrentDevice键,因为据我了解, …
avaudioengine ×10
swift ×7
ios ×5
avfoundation ×3
objective-c ×2
audio ×1
c# ×1
core-audio ×1
ios13 ×1
macos ×1
swift3 ×1
volume ×1
xamarin ×1
xamarin.ios ×1