标签: avaudioengine

SWIFT - 是否可以从AVAudioEngine或AudioPlayerNode保存音频?如果有,怎么样?

我一直在寻找Swift文档以保存AVAudioEngine的音频输出,但我找不到任何有用的提示.
有什么建议吗?

解决方案 我找到了解决方法,这要归功于matt的答案.这里有一个示例代码,说明如何在通过AVAudioEngine传递音频之后保存音频(我认为在技术上它是之前的)

newAudio = AVAudioFile(forWriting: newAudio.url, settings: nil, error: NSErrorPointer()) 
//Your new file on which you want to save some changed audio, and prepared to be bufferd in some new data...

var audioPlayerNode = AVAudioPlayerNode() //or your Time pitch unit if pitch changed   

//Now install a Tap on the output bus to "record" the transformed file on a our newAudio file.
audioPlayerNode.installTapOnBus(0, bufferSize: (AVAudioFrameCount(audioPlayer.duration)), format: opffb){
        (buffer: AVAudioPCMBuffer!, time: AVAudioTime!)  in 

        if (self.newAudio.length) …
Run Code Online (Sandbox Code Playgroud)

avasset swift avaudioengine avaudiofile avaudioplayernode

6
推荐指数
1
解决办法
2942
查看次数

AVAudioConverter float32/48khz - > int16/16khz转换失败

此方法处理来自AVAudioEngine的输入节点上的installTap的回调.我已经确认我正在获取mono float32/48000hz缓冲区数据,我想将其转换为mono int16/16000hz.

var converter: AVAudioConverter? = nil
var convertBuffer: AVAudioPCMBuffer? = nil
let targetFormat = AVAudioFormat(commonFormat: AVAudioCommonFormat.pcmFormatInt16, sampleRate: 16000, channels: 1, interleaved: false)

func recordCallback(buffer: AVAudioPCMBuffer, time: AVAudioTime) {
    if converter == nil {
        convertBuffer = AVAudioPCMBuffer(pcmFormat: targetFormat, frameCapacity: buffer.frameCapacity)
        convertBuffer?.frameLength = convertBuffer!.frameCapacity
        converter = AVAudioConverter(from: buffer.format, to: convertBuffer!.format)
        converter?.sampleRateConverterAlgorithm = AVSampleRateConverterAlgorithm_Normal
        converter?.sampleRateConverterQuality = .max
    }

    guard let convertBuffer = convertBuffer else { return }

    log.info("Converter: \(self.converter!)")
    log.info("Converter buffer: \(self.convertBuffer!)")
    log.info("Converter buffer format: \(self.convertBuffer!.format)")
    log.info("Source buffer: \(buffer)")
    log.info("Source buffer …
Run Code Online (Sandbox Code Playgroud)

avfoundation ios swift avaudioengine

6
推荐指数
1
解决办法
939
查看次数

AVAudioPCMBuffer 的播放段

我正在为 iOS 应用程序创建这个简单的录音机和编辑器界面:

记录器/编辑器界面的屏幕截图

音频被记录到用于创建波形的浮点数组中。录制后,我将浮动数据复制到一个AVAudioPCMBuffer用于播放的AVAudioPlayerNode. 我能够从一开始就播放缓冲区,但我不知道如何只播放缓冲区的一部分。该scheduleSegment功能仅适用于文件。

swift avaudioengine avaudiopcmbuffer avaudioplayernode

6
推荐指数
1
解决办法
1586
查看次数

如何使用连接到 AVAudioEngine 混音器的节点同时播放缓冲区中的多个声音

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

avfoundation ios swift avaudioengine avaudioplayernode

6
推荐指数
1
解决办法
2289
查看次数

在 iOS 13 中暂停/停止 AVAudioEngine 时,状态栏会显示麦克风图标片刻

每次我停止/暂停音频引擎(使用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)

记住要启用音频背景模式,添加NSMicrophoneUsageDescriptionInfo.plist,并在iOS的13设备上运行。接受麦克风权限并重新运行应用程序。您将看到红色麦克风图标闪烁一次。

有没有办法摆脱这个?

swift avaudioengine ios13

6
推荐指数
0
解决办法
634
查看次数

如何设置AVAudioEngine输入输出设备(swift/macos)

我到处寻找,但找不到解决这个问题的方法。我正在寻找一种方法来更改将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键,因为据我了解, …

macos core-audio swift avaudioengine

6
推荐指数
1
解决办法
2319
查看次数

带有AVAudioEngine的自定义AVAudioUnit在set provider块上崩溃

我有以下代码块应该创建一个产生正弦波的AVAudioNode,但它在标有 - [AUAudioUnitV2Bridge setOutputProvider:]的行上崩溃:发送到实例的无法识别的选择器.

什么想法可能是错的?

// TEST  
AudioComponentDescription mixerDesc;  
mixerDesc.componentType = kAudioUnitType_Generator;  
mixerDesc.componentSubType = kAudioUnitSubType_ScheduledSoundPlayer;  
mixerDesc.componentManufacturer = kAudioUnitManufacturer_Apple;  
mixerDesc.componentFlags = 0;  
mixerDesc.componentFlagsMask = 0;  

[AVAudioUnit instantiateWithComponentDescription:mixerDesc options:kAudioComponentInstantiation_LoadInProcess completionHandler:^(__kindof AVAudioUnit * _Nullable audioUnit, NSError * _Nullable error) {  
    NSLog(@"here");  

    // Crashes here  
    audioUnit.AUAudioUnit.outputProvider = ^AUAudioUnitStatus(AudioUnitRenderActionFlags *actionFlags, const AudioTimeStamp *timestamp, AUAudioFrameCount frameCount, NSInteger inputBusNumber, AudioBufferList *inputData)  
    {  
        const double amplitude = 0.2;  
        static double theta = 0.0;  
        double theta_increment = 2.0 * M_PI * 880.0 / 44100.0;  
        const int channel …
Run Code Online (Sandbox Code Playgroud)

core-audio avaudioengine

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

AVAudioEngine警告:"不推荐使用Carbon Component Manager来托管音频单元"

我正在为Mac编写我的第一个音频应用程序,它加载外部音频单元并使用它通过AVAudioEngine实例播放声音,我一直看到这个警告:

警告:140:此应用程序或其使用的库正在使用已弃用的Carbon Component Manager来托管Audio Units.将来的版本中将删除对此的支持.此外,这使主机与版本3音频单元不兼容.请转到AudioComponent.h中的API.

我已经从使用AVAudioUnitComponents转换到AudioComponents(现在通过这个api访问),我希望能解决这个问题,但是当我调用start()我的引擎时,我仍然会看到这个警告.

任何想法在这里出了什么问题?据我所知,我不再使用已弃用的API.AVAudioEngine是否有可能在引擎盖下使用已弃用的API?

这是我正在使用的代码的片段.我正在调用selectInstrument我使用AudioComponents API检索的描述.

public func selectInstrument(withDescription description: AudioComponentDescription, callback: @escaping SelectInstrumentCallback) {
    AVAudioUnit.instantiate(with: description, options: []) { avAudioUnit, error in
        guard let unit = avAudioUnit else {
            callback(nil)
            return
        }

        self.disconnectCurrent()
        self.connect(unit: unit)

        unit.auAudioUnit.requestViewController { viewController in
            callback(viewController)
        }
    }
}

private func disconnectCurrent() {
    guard let current = currentInstrument else { return }
    self.engine.disconnectNodeInput(engine.mainMixerNode)
    self.engine.detach(current)
    self.currentInstrument = nil
    self.engine.stop()
}

private func connect(unit: AVAudioUnit) {
    let hardwareFormat …
Run Code Online (Sandbox Code Playgroud)

macos avfoundation audiounit ios avaudioengine

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

AVAudioUnitSampler在耳机路由改变后生成正弦波,iOS 11 iPhone

使用AVAudioUnitSampler时,我在iPhone(iOS 11)上遇到了一个奇怪的问题.

假设我有一个用钢琴声音初始化的AVAudioUnitSampler.因此,每次连接或断开耳机时,我都会听到钢琴声音加上正弦波音,声音越大,连接/断开耳机的次数越多.

因此,对我而言,每次耳机插入/拔出时都会感觉到,新的音频单元采样器将内部连接到声音输出(并且,由于它是未初始化的,因此仅产生正弦波音调).

以下类已经显示了该问题.请注意,我正在使用AudioKit来处理MIDI信号并触发采样器(虽然在这一端,一切似乎工作正常,即.startNote()stopNote()正确调用):

class MidiController: NSObject, AKMIDIListener {

    var midi = AKMIDI()
    var engine = AVAudioEngine()
    var samplerUnit = AVAudioUnitSampler()

    override public init() {
        super.init()

        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleRouteChange),
            name: .AVAudioSessionRouteChange,
            object: nil)

        midi.openInput()
        midi.addListener(self)
        engine.attach(samplerUnit)
        engine.connect(samplerUnit, to: engine.outputNode)
        startEngine()
    }

    func startEngine() {
        if (!engine.isRunning) {
            do {
                try self.engine.start()
            } catch  {
                fatalError("couldn't start engine.")
            }
        }
    }

    @objc func handleRouteChange(notification: NSNotification) {
        let deadlineTime = DispatchTime.now() + …
Run Code Online (Sandbox Code Playgroud)

iphone audiounit ios avaudioengine audiokit

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

如何抑制通过访问macOS上的AVAudioEngine的inputNode生成的警告

我具有以下用于在macOS上获取实时麦克风输入的测试代码:

import AVFoundation // for AVAudioEngine

class Mic
{
    public let audioEngine = AVAudioEngine()

    func startRecording() throws
    {
        print("- - -")
        let inputNode = audioEngine.inputNode
        print("- - -")

        if inputNode.inputFormat(forBus: 0).sampleRate == 0 {
            exit(0);
        }

        let recordingFormat = inputNode.outputFormat(forBus: 0)
        inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
            print( "YES! Got some samples!")
        }

        audioEngine.prepare()

        try audioEngine.start()
    }

    func stopRecording()
    {
        audioEngine.stop()
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到输出:


2019-07-22 16:26:36.773244 + 0300 realtime_mic [8111:540360] [plugin] AddInstanceForFactory:没有为ID F8BB1C28-BAE8-11D6-9C31-00039315CD46注册的工厂
2019-07-22 …

macos core-audio suppress-warnings avaudioengine

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