点击安装在音频引擎上,只生成短文件



我正在开发一款应用程序,该应用程序允许用户录制音频,在更改音高时播放,然后将他们所做的事情记录为一个单独的文件。

代码似乎在工作,但新文件的持续时间只有0.37秒(原来是5秒)。我猜,当我从缓冲区中写入时,它会不断保存,从而只剩下最后一段。如果这是我的问题,我如何附加文件而不是重写它?

    let recordSettings:[String : AnyObject] = [
        AVFormatIDKey: NSNumber(unsignedInt:kAudioFormatAppleLossless),
        AVEncoderAudioQualityKey : AVAudioQuality.Max.rawValue,
        AVEncoderBitRateKey : 320000,
        AVNumberOfChannelsKey: 2,
        AVSampleRateKey : 44100.0
    ]

    var outputFile = AVAudioFile()
    let format = NSDateFormatter()
    format.dateFormat="dd-HH-mm-ss"
    let currentFileName = "recording-(format.stringFromDate(NSDate())).m4a"
    print(currentFileName)
    let documentsDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
    self.url2 = documentsDirectory.URLByAppendingPathComponent(currentFileName)
    let inputNode = engine.inputNode
    let bus = 0
    engine.mainMixerNode.installTapOnBus(bus, bufferSize: 2048, format: self.engine.mainMixerNode.inputFormatForBus(0)) {
        (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
        do {
            let outputFile = try AVAudioFile(forWriting: self.url2, settings: recordSettings, commonFormat: AVAudioCommonFormat.PCMFormatFloat32, interleaved: false)
            try outputFile.writeFromBuffer(buffer)
            outputFile.framePosition = outputFile.length
        } catch let error as NSError {
            NSLog("Error writing %@", error.localizedDescription)
        }
    }

更新代码创建持续时间为0.0:的文件

func play() {
    let duration = CMTimeGetSeconds(AVAsset(URL: url).duration)
    print("Duration")
    print(duration)
    let file = try! AVAudioFile(forReading: url)
    let buffer = AVAudioPCMBuffer(PCMFormat: file.processingFormat, frameCapacity: AVAudioFrameCount(file.length))
    do {
        try file.readIntoBuffer(buffer)
    } catch _ {
    }
    engine = AVAudioEngine()
    player = AVAudioPlayerNode()
    pitch.pitch = 500

    engine.attachNode(player)
    engine.attachNode(pitch)
    engine.connect(player, to: pitch, format: buffer.format)
    engine.connect(pitch, to: engine.mainMixerNode, format: nil)
    let format = NSDateFormatter()
    format.dateFormat="dd-HH-mm-ss"
    let currentFileName = "recording-(format.stringFromDate(NSDate())).m4a"
    print(currentFileName)
    let documentsDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
    self.url2 = documentsDirectory.URLByAppendingPathComponent(currentFileName)
    let outputFile = try! AVAudioFile(forWriting: url2, settings:  [
        AVFormatIDKey: NSNumber(unsignedInt:kAudioFormatAppleLossless),
        AVEncoderAudioQualityKey : AVAudioQuality.Max.rawValue,
        AVEncoderBitRateKey : 320000,
        AVNumberOfChannelsKey: 2,
        AVSampleRateKey : 44100.0
    ])
    done = false
    distortion.installTapOnBus(0, bufferSize: 2048, format: outputFile.processingFormat) {
        (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) in
        let dataptrptr = buffer.floatChannelData
        let dataptr = dataptrptr.memory
        let datum = dataptr[Int(buffer.frameLength) - 1]
        if self.done && fabs(datum) < 0.000001 {
            print("stopping")
            self.engine.stop()
            return
        }
        do {
            try outputFile.writeFromBuffer(buffer)
        } catch let error as NSError {
            NSLog("Error writing %@", error.localizedDescription)
        }
    }
        player.scheduleBuffer(buffer, atTime: nil, options: AVAudioPlayerNodeBufferOptions.Loops, completionHandler: {
            dispatch_async(dispatch_get_main_queue(),{
            self.done = true
            self.player.stop()
                self.engine.stop()
            print("complete")
            })
        })
    engine.prepare()
    do {
        try engine.start()
        player.play()
    } catch _ {
        print("Play session Error")
    }
}

请记住,installTapOnBus处理程序将被调用多次:每次缓冲区填满时。把它想象成一个循环。因此,每次通过该循环创建输出文件是没有意义的!您想创建一次输出文件,然后重复写入。因此,您的整体结构需要如下所示:

let outfile = try! AVAudioFile(forWriting: outurl, settings: // ...
node.installTapOnBus(bus, bufferSize: size, format: outfile.processingFormat) {
    (buffer : AVAudioPCMBuffer!, time : AVAudioTime!) in
        do {
            try outfile.writeFromBuffer(buffer)
        } catch {
            print(error)
        }
    }

另一件需要记住的事情是,只要引擎保持运行,你的缓冲区就会准确地填充和写入,所以不要过早地停止引擎(我不知道你是否在这样做,但重要的是要记住)。

最新更新