标签: avaudioengine

以编程方式淡出AVAudioPlayerNode的音量

我有一个AVAudioEngine设置和一个正在播放一些背景音乐的AVAudioPlayerNode。

我正在尝试找到一种最佳方法,以在2秒的时间内在节点上创建音量渐弱。我正在考虑使用CADisplayLink来执行此操作。我想知道是否有人在这种情况下有经验,可以在方法上给我建议吗?

iphone objective-c ios swift avaudioengine

5
推荐指数
2
解决办法
998
查看次数

AVAudioEngine可录制麦克风和声音文件,避免反馈循环

我正在尝试使用AVAudioEngine来录制麦克风和声音文件(当用户点击按钮时播放的声音).我已将mic inputNode连接到mainMixer,以及一些用于播放声音文件的AVAudioPlayerNodes.我在mainMixer上安装了一个水龙头来捕获声音并将其写入文件.声音也会传送到扬声器.

这是我的音频图的基本布局:

         -------------
mic  --> |           |
         | mainMixer | --> speaker
file --> |           |
         -------------
               |
              tap
        (writes to file)
Run Code Online (Sandbox Code Playgroud)

默认情况下,声音通过接收器/耳机扬声器而不是iPhone底部的扬声器播放.

不幸的是,这意味着通过扬声器输出的声音太低而且难以听到 - 我希望用户能够在播放和录制时听到声音文件.所以我希望通过底部扬声器播放声音效果.

如果我改变音频会话以使用底部扬声器进行播放,我会得到一个反馈循环,因为麦克风输入和底部扬声器播放的声音再次由麦克风拾取.(奇怪的是,这适用于iPad,没有创建反馈循环.当然,iPad没有耳机,因此在该设备上,声音总是通过主扬声器听到.)

我有两个问题:

  1. 是否可以仅将声音文件路由到底部扬声器?我不想通过任何扬声器输出麦克风的声音.但是,应记录麦克风和声音文件的声音.

  2. 为什么我在iPhone上获得反馈循环但不在iPad上?是否可以通过底部扬声器输出所有声音而无需获得反馈回路?

audio avfoundation ios avaudioengine

5
推荐指数
0
解决办法
549
查看次数

即使文件存在,AVAudioFile.length也为0

我正在创建一个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

好的,所以经过一些建议我做了一些改变.基本上,这些是我正在采取的步骤:

  1. 检查文件是否已存在.
  2. 如果是,打开它进行读取并获取音频缓冲区.
  3. 创建一个用于写入的新文件(使用相同的文件URL)
  4. 使用writeFromBuffer将缓冲区从旧文件写入新文件
  5. 将新文件的framePosition移动到最后,以便我可以继续写入/记录它.

但是,写入后,新文件的长度为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)

core-audio swift avaudioengine avaudiofile

5
推荐指数
1
解决办法
1377
查看次数

在后台保存音频文件

我有一个应用程序,可以在选择音调按钮时更改音频的音调,现在我正在使用它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)

audio avaudioplayer ios avaudioengine

5
推荐指数
1
解决办法
1490
查看次数

AVAudioEngine 下采样问题

我在对从麦克风中提取的音频进行下采样时遇到问题。我正在使用 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)

audio core-audio swift avaudioengine swift3

5
推荐指数
1
解决办法
2821
查看次数

AVAudioSession的PlayAndRecord类别和AVAudioSessionModeMeasurement与defaultToSpeaker选项不兼容吗?

尝试使用该模式AVAudioSession放入.playAndRecord类别AVAudioSessionModeMeasurement会导致该.defaultToSpeaker选项被忽略,从而导致听筒(也称为接收器)静静地播放输出。

ios avaudiosession swift avaudioengine

5
推荐指数
1
解决办法
573
查看次数

添加AKMicrophone时崩溃

我正在使用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)

ios avaudioengine audiokit

5
推荐指数
1
解决办法
306
查看次数

如何用8000 PCM格式的AVAudioEngine录制和播放?

我想将此代码用于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)

buffer avfoundation avaudioplayer swift avaudioengine

5
推荐指数
1
解决办法
711
查看次数

AVAudioEngine文档

我正在尝试查找有关如何使用AVAudioEngine的详细文档。有谁知道我在哪里可以找到它?

我已经找到了这个,但是与文档丰富的UI东西相比,它似乎是极简陋的。

https://developer.apple.com/documentation/avfoundation/avaudioengine

是这个吗?是否有至少我可以细读的头文件,例如AUGraph(在不推荐使用之前)。

avaudioengine

5
推荐指数
1
解决办法
122
查看次数

同步 AVAudioPlayerNode 并开始录制 AVAudioEngine

我正在使用 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)

avfoundation ios swift avaudioengine

5
推荐指数
1
解决办法
214
查看次数