在iOS中效果后保存音频

时间:2016-08-14 22:10:09

标签: ios swift avaudioengine avaudioplayernode

我正在开发一个应用程序,以便人们可以通过应用程序记录和更改他们的声音并分享它。基本上我有很多东西,现在是时候请你帮忙了。这是我的播放功能,播放录制的音频文件并添加效果。

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 all these up, ending with the output
        audioEngine.connect(audioPlayerNode, to: playbackRateEffect, format: nil)
        audioEngine.connect(playbackRateEffect, to: pitchEffect, format: nil)
        audioEngine.connect(pitchEffect, to: reverbEffect, format: nil)
        audioEngine.connect(reverbEffect, to: echoEffect, format: nil)
        audioEngine.connect(echoEffect, to: audioEngine.outputNode, format: nil)

        audioPlayerNode.stop()

        let length = 4000
        let buffer = AVAudioPCMBuffer(PCMFormat: audioPlayerNode.outputFormatForBus(0),frameCapacity:AVAudioFrameCount(length))
        buffer.frameLength = AVAudioFrameCount(length)

        try! audioEngine.start()


        let dirPaths: AnyObject = NSSearchPathForDirectoriesInDomains( NSSearchPathDirectory.DocumentDirectory,  NSSearchPathDomainMask.UserDomainMask, true)[0]
        let tmpFileUrl: NSURL = NSURL.fileURLWithPath(dirPaths.stringByAppendingPathComponent("effectedSound.m4a"))


        do{
            print(dirPaths)
            let settings = [AVFormatIDKey: NSNumber(unsignedInt: kAudioFormatMPEG4AAC), AVSampleRateKey: NSNumber(integer: 44100), AVNumberOfChannelsKey: NSNumber(integer: 2)]
            self.newAudio = try AVAudioFile(forWriting: tmpFileUrl, settings: settings)

            audioEngine.outputNode.installTapOnBus(0, bufferSize: (AVAudioFrameCount(self.player!.duration)), format: self.audioPlayerNode.outputFormatForBus(0)){
                (buffer: AVAudioPCMBuffer!, time: AVAudioTime!)  in

                print(self.newAudio.length)
                print("=====================")
                print(self.audioFile.length)
                print("**************************")
                if (self.newAudio.length) < (self.audioFile.length){

                    do{
                        //print(buffer)
                        try self.newAudio.writeFromBuffer(buffer)
                    }catch _{
                        print("Problem Writing Buffer")
                    }
                }else{
                    self.audioPlayerNode.removeTapOnBus(0)
                }

            }
        }catch _{
            print("Problem")
        }

        audioPlayerNode.play()

    }

我想问题是我是对audioPlayerNode的installTapOnBus,但受影响的音频是在audioEngine.outputNode上。但是我试图将toTapOnBus安装到audioEngine.outputNode,但是它给了我错误。我也尝试将效果连接到audioEngine .mixerNode但它也不是解决方案。那么你有保存受影响音频文件的经验吗?我怎样才能获得这种受影响的音频?

感谢任何帮助

谢谢

4 个答案:

答案 0 :(得分:4)

这似乎没有正确连接。我只是自己学习这一切,但我发现当你将它们连接到混音器节点时,效果会正确添加。此外,您需要点击调音台,而不是发动机输出节点。我刚刚复制了您的代码并做了一些修改以考虑到这一点。

module.exports = {

  attributes: {
    local: {
      type: 'json'
    },
    facebook: {
      type: 'json'
    },
    google: {
      type: 'json'
    }
  }
};

我也无法正确格式化文件。当我将输出文件的路径从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 playback-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) // Set up a mixer node let audioMixer = AVAudioMixerNode() audioEngine.attachNode(audioMixer) // Chain all these up, ending with the output audioEngine.connect(audioPlayerNode, to: playbackRateEffect, format: nil) audioEngine.connect(playbackRateEffect, to: pitchEffect, format: nil) audioEngine.connect(pitchEffect, to: reverbEffect, format: nil) audioEngine.connect(reverbEffect, to: echoEffect, format: nil) audioEngine.connect(echoEffect, to: audioMixer, format: nil) audioEngine.connect(audioMixer, to: audioEngine.outputNode, format: nil) audioPlayerNode.stop() let length = 4000 let buffer = AVAudioPCMBuffer(PCMFormat: audioPlayerNode.outputFormatForBus(0),frameCapacity:AVAudioFrameCount(length)) buffer.frameLength = AVAudioFrameCount(length) try! audioEngine.start() let dirPaths: AnyObject = NSSearchPathForDirectoriesInDomains( NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] let tmpFileUrl: NSURL = NSURL.fileURLWithPath(dirPaths.stringByAppendingPathComponent("effectedSound.m4a")) do{ print(dirPaths) let settings = [AVFormatIDKey: NSNumber(unsignedInt: kAudioFormatMPEG4AAC), AVSampleRateKey: NSNumber(integer: 44100), AVNumberOfChannelsKey: NSNumber(integer: 2)] self.newAudio = try AVAudioFile(forWriting: tmpFileUrl, settings: settings) audioMixer.installTapOnBus(0, bufferSize: (AVAudioFrameCount(self.player!.duration)), format: self.audioMixer.outputFormatForBus(0)){ (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) in print(self.newAudio.length) print("=====================") print(self.audioFile.length) print("**************************") if (self.newAudio.length) < (self.audioFile.length){ do{ //print(buffer) try self.newAudio.writeFromBuffer(buffer) }catch _{ print("Problem Writing Buffer") } }else{ self.audioMixer.removeTapOnBus(0) } } }catch _{ print("Problem") } audioPlayerNode.play() } 更改为m4a时,我终于开始工作了。另一个建议是caf参数没有nil。我使用了format。我希望这有帮助。我的音频效果/混音是有用的,虽然我没有链接我的效果。所以随时提问。

答案 1 :(得分:1)

只需将unsigned int参数从kAudioFormatMPEG4AAC更改为kAudioFormatLinearPCM,并将文件类型更改为.caf,对我的朋友肯定会有帮助

答案 2 :(得分:0)

对于任何有必要播放音频文件TWICE以保存它的人,我只是在相应的地方添加了以下行,它解决了我的问题。 可能会在将来帮助某人。

P.S:我使用了与上面检查的答案完全相同的代码,只是添加了这一行并解决了我的问题。

var source = "http://d.mimp3.eu/i/mS6mfOGoji8nmNKoba6Zg653/system-of-a-down-lonely-day.mp3";

audio = document.getElementById('audioToChange');

function addSource(){
	audio.setAttribute("src", source );
}
function removeSource(){
	audio.removeAttribute("src");
}
function clearSource () {
	audio.setAttribute("src", "" );
}
function clearANDremove () {
	audio.setAttribute("src", "" );
	audio.removeAttribute("src");
}

答案 3 :(得分:-1)

添加后我得到了

self.newAudio = try! AVAudioFile(forReading: tmpFileUrl)

像这样返回

Error
Domain=com.apple.coreaudio.avfaudio
Code=1685348671 "(null)" UserInfo={failed
call=ExtAudioFileOpenURL((CFURLRef)fileUR
L, &_extAudioFile)}