我有一个AVAudioEngine设置和一个正在播放一些背景音乐的AVAudioPlayerNode。
我正在尝试找到一种最佳方法,以在2秒的时间内在节点上创建音量渐弱。我正在考虑使用CADisplayLink来执行此操作。我想知道是否有人在这种情况下有经验,可以在方法上给我建议吗?
我正在尝试使用AVAudioEngine来录制麦克风和声音文件(当用户点击按钮时播放的声音).我已将mic inputNode连接到mainMixer,以及一些用于播放声音文件的AVAudioPlayerNodes.我在mainMixer上安装了一个水龙头来捕获声音并将其写入文件.声音也会传送到扬声器.
这是我的音频图的基本布局:
-------------
mic --> | |
| mainMixer | --> speaker
file --> | |
-------------
|
tap
(writes to file)
Run Code Online (Sandbox Code Playgroud)
默认情况下,声音通过接收器/耳机扬声器而不是iPhone底部的扬声器播放.
不幸的是,这意味着通过扬声器输出的声音太低而且难以听到 - 我希望用户能够在播放和录制时听到声音文件.所以我希望通过底部扬声器播放声音效果.
如果我改变音频会话以使用底部扬声器进行播放,我会得到一个反馈循环,因为麦克风输入和底部扬声器播放的声音再次由麦克风拾取.(奇怪的是,这适用于iPad,没有创建反馈循环.当然,iPad没有耳机,因此在该设备上,声音总是通过主扬声器听到.)
我有两个问题:
是否可以仅将声音文件路由到底部扬声器?我不想通过任何扬声器输出麦克风的声音.但是,应记录麦克风和声音文件的声音.
为什么我在iPhone上获得反馈循环但不在iPad上?是否可以通过底部扬声器输出所有声音而无需获得反馈回路?
我正在创建一个AVAudioFile,用于将声音写入声音文件.如果文件已经存在,我想将framePosition移动到文件的末尾,以便在最后继续写入,而不是替换现有文件.
我做了一些测试,尝试将文件中的缓冲区读入一个具有不同URL的新文件,以便它不会覆盖原始文件.当我尝试将缓冲区读入新文件时,我遇到了崩溃:
let audioFile = try AVAudioFile(forReading: [URL to existing .caf file])
let audioFrameCount = AVAudioFrameCount(UInt32(audioFile.length))
let audioBuffer = AVAudioPCMBuffer(PCMFormat: audioFile.processingFormat, frameCapacity: audioFrameCount)
let newAudioFile = try AVAudioFile(forWriting: [another URL], settings: self.engine.mainMixerNode.outputFormatForBus(0).settings)
try newAudioFile.readIntoBuffer(audioBuffer, frameCount: audioFrameCount!) <-- CRASHES ON THIS LINE
Run Code Online (Sandbox Code Playgroud)
崩溃日志:因未捕获的异常'com.apple.coreaudio.avfaudio'而终止应用程序,原因:'error -50'
伙计,我真的很讨厌CoreAudio崩溃日志.他们绝对没有告诉我!
是不是可以将数据读入为写入而创建的文件中?
UPDATE
好的,所以经过一些建议我做了一些改变.基本上,这些是我正在采取的步骤:
但是,写入后,新文件的长度为0.
这是我的代码:
//Check if a file already exists. If so continue to record at the end of it
var audioBuffer : AVAudioPCMBuffer!
var audioFrameCount : AVAudioFrameCount!
if (NSFileManager.defaultManager().fileExistsAtPath(self.audioRecordURL.path!)) …Run Code Online (Sandbox Code Playgroud) 我有一个应用程序,可以在选择音调按钮时更改音频的音调,现在我正在使用它installTapOnBus来保存文件,但是在我按下音调按钮后会调用此方法,因此仅保存了部分音频,我想保存整个音频无论何时选择音高按钮,有什么办法
此方法用于播放音频
-(void)playAudio
{
NSError *err = nil;
audioEngine = [[AVAudioEngine alloc] init];
AudioFileplayer = [[AVAudioPlayerNode alloc] init];
pitch = [[AVAudioUnitTimePitch alloc] init];
reverb = [[AVAudioUnitReverb alloc] init];
[audioEngine stop];
[AudioFileplayer stop];
[audioEngine reset];
file = [[AVAudioFile alloc] initForReading:[NSURL URLWithString:[self filePath]] error:&err];
[audioEngine attachNode:AudioFileplayer];
[audioEngine attachNode:pitch];
[audioEngine attachNode:reverb];
[audioEngine connect:AudioFileplayer to:reverb format:nil];
[audioEngine connect:reverb to:pitch format:nil];
[audioEngine connect:pitch to:audioEngine.outputNode format:nil];
[reverb loadFactoryPreset:AVAudioUnitReverbPresetLargeRoom2];
[AudioFileplayer scheduleFile:file atTime:nil completionHandler:^{
AudioFileplayer = nil;
}];
[audioEngine prepare];
[audioEngine startAndReturnError:&err];
if (err != nil) …Run Code Online (Sandbox Code Playgroud) 我在对从麦克风中提取的音频进行下采样时遇到问题。我正在使用 AVAudioEngine 通过以下代码从麦克风中获取样本:
assert(self.engine.inputNode != nil)
let input = self.engine.inputNode!
let audioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 8000, channels: 1, interleaved: false)
let mixer = AVAudioMixerNode()
engine.attach(mixer)
engine.connect(input, to: mixer, format: input.inputFormat(forBus: 0))
do {
try engine.start()
mixer.installTap(onBus: 0, bufferSize: 1024, format: audioFormat, block: {
(buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
//some code here
})
} catch let error {
print(error.localizedDescription)
}
Run Code Online (Sandbox Code Playgroud)
此代码在 iPhone 5s 上运行良好,因为麦克风输入为 8000Hz,并且缓冲区填充了来自麦克风的数据。
问题是我希望能够从 iPhone 6s(及更高版本)录制麦克风以 16000Hz 录制的内容。奇怪的是,如果我将 mixernode 与引擎 mainmixernode 连接起来(使用以下代码):
engine.connect(mixer, to: mainMixer, format: …Run Code Online (Sandbox Code Playgroud) 尝试使用该模式AVAudioSession放入.playAndRecord类别AVAudioSessionModeMeasurement会导致该.defaultToSpeaker选项被忽略,从而导致听筒(也称为接收器)静静地播放输出。
我正在使用AudioKit开发一个音频应用程序,它涉及定期停止AudioKit,重新安排或替换AKNode子类链,然后重新启动AudioKit.这一直顺利进行,直到我尝试过AKMicrophone.
如果AKMicrophone在初始声音链中存在,即,当我第一次调用时AudioKit.start(,它可以正常工作.但是,如果我AKMicrophone在之前的调用之后的某个时刻进入声音链AudioKit.start(),则应用程序将在下一次AudioKit.start()调用时崩溃,从而产生以下错误消息:
...[avae] AVAudioEngine.mm:149:-[AVAudioEngine prepare]: Engine@0x1c0007170: could not initialize, error = -10875
...[mcmx] 338: input bus 0 sample rate is 0
...[avae] AVAEInternal.h:103:_AVAE_CheckNoErr: [AVAudioEngineGraph.mm:1266:Initialize:
(err = AUGraphParser::InitializeActiveNodesInOutputChain(ThisGraph, kOutputChainOptimizedTraversal, *GetOutputNode(), isOutputChainActive)): error -10875
Run Code Online (Sandbox Code Playgroud)
为了说明,以下代码顺利运行:
let mic = AKMicrophone()
if let input = AudioKit.inputDevice {
try! mic.setDevice(input)
}
AudioKit.output = mic
AudioKit.start()
Run Code Online (Sandbox Code Playgroud)
但是如果它之前被调用AudioKit.start()就会崩溃:
AudioKit.output = AKOscillator()
AudioKit.start()
AudioKit.stop()
let mic = AKMicrophone()
if let input = …Run Code Online (Sandbox Code Playgroud) 我想将此代码用于VoIP服务。
我正在使用网络套接字并与之一起发送:let data = self.toNSData(PCMBuffer: buffer)和播放:let audioBuffer = self.toPCMBuffer(data: data) 在另一台设备上)
我曾经使用过:https://github.com/Lkember/IntercomTest 并对其进行了处理,但是数据量很大。我觉得41100速率对于发送数据来说是一个很大的大小,我想将较低速率的缓冲区减小到8000。
但是我不知道如何在没有错误的情况下降低采样率!
我的失败代码如下:
@IBAction func start(_ sender: Any) {
var engine = AVAudioEngine()
let input = engine.inputNode
let bus = 0
let localAudioPlayer: AVAudioPlayerNode = AVAudioPlayerNode()
let mixer = AVAudioMixerNode()
let fmt = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 8000, channels: 1, interleaved: false)
engine.attach(mixer)
engine.connect(input, to: mixer, format: input.outputFormat(forBus: 0))
mixer.volume = 0
engine.connect(mixer, to: localAudioPlayer, format: fmt)
localAudioPlayer.installTap(onBus: bus, bufferSize: 512, format: fmt) …Run Code Online (Sandbox Code Playgroud) 我正在尝试查找有关如何使用AVAudioEngine的详细文档。有谁知道我在哪里可以找到它?
我已经找到了这个,但是与文档丰富的UI东西相比,它似乎是极简陋的。
https://developer.apple.com/documentation/avfoundation/avaudioengine
是这个吗?是否有至少我可以细读的头文件,例如AUGraph(在不推荐使用之前)。
我正在使用 AVAudioEngine 播放和录制音频。对于我的用例,我需要在开始录制音频时准确地播放声音。目前,我的录音似乎在播放声音之前就开始了。如何让声音和录音同时开始?理想情况下,我希望录音开始和声音同时播放,而不是在后期处理中同步它们。
这是我目前的代码:
class Recorder {
enum RecordingState {
case recording, paused, stopped
}
private var engine: AVAudioEngine!
private var mixerNode: AVAudioMixerNode!
private var state: RecordingState = .stopped
private var audioPlayer = AVAudioPlayerNode()
init() {
setupSession()
setupEngine()
}
fileprivate func setupSession() {
let session = AVAudioSession.sharedInstance()
try? session.setCategory(.playAndRecord, options: [.mixWithOthers, .defaultToSpeaker])
try? session.setActive(true, options: .notifyOthersOnDeactivation)
}
fileprivate func setupEngine() {
engine = AVAudioEngine()
mixerNode = AVAudioMixerNode()
// Set volume to 0 to avoid audio feedback while recording.
mixerNode.volume = …Run Code Online (Sandbox Code Playgroud) avaudioengine ×10
ios ×6
swift ×6
audio ×3
avfoundation ×3
core-audio ×2
audiokit ×1
avaudiofile ×1
buffer ×1
iphone ×1
objective-c ×1
swift3 ×1