Posts

Post not yet marked as solved
2 Replies
2.4k Views
I am using AVAudioEngine to analyse some audio tracks and quite often the `while engine.manualRenderingSampleTime < sourceFile.length {` loop takes a moment to start receiving audio data. Looking at the soundwave looks like the input is simply delayed. This wouldn't be a problem if the length of the buffer would vary depending on this latency but the length unfortunately stays always the same, loosing the final part of the track.I took the code from the official tutorial and this seems to happen regardless if I add an EQ effect or not. Actually looks like the two analysis (with or without EQ) done one after the other return the same anomaly. let format: AVAudioFormat = sourceFile.processingFormat let engine = AVAudioEngine() let player = AVAudioPlayerNode() engine.attach(player) if compress { let eq = AVAudioUnitEQ(numberOfBands: 2) engine.attach(eq) let lowPass = eq.bands[0] lowPass.filterType = .lowPass lowPass.frequency = 150.0 lowPass.bypass = false let highPass = eq.bands[1] highPass.filterType = .highPass highPass.frequency = 100.0 highPass.bypass = false engine.connect(player, to: eq, format: format) engine.connect(eq, to: engine.mainMixerNode, format: format) }else{ engine.connect(player, to: engine.mainMixerNode, format: format) } do { let maxNumberOfFrames: AVAudioFrameCount = 4096 try engine.enableManualRenderingMode(.offline, format: format, maximumFrameCount: maxNumberOfFrames) } catch { fatalError("Could not enable manual rendering mode, \(error)") } player.scheduleFile(sourceFile, at: nil) do { try engine.start() player.play() }catch{ fatalError("Could not start engine, \(error)") } // buffer to which the engine will render the processed data let buffer: AVAudioPCMBuffer = AVAudioPCMBuffer(pcmFormat: engine.manualRenderingFormat, frameCapacity: engine.manualRenderingMaximumFrameCount)! // var pi = 0 // while engine.manualRenderingSampleTime < sourceFile.length { do { let framesToRender = min(buffer.frameCapacity, AVAudioFrameCount(sourceFile.length - engine.manualRenderingSampleTime)) let status = try engine.renderOffline(framesToRender, to: buffer) switch status { case .success: // data rendered successfully let flength = Int(buffer.frameLength) points.reserveCapacity(pi + flength) if let chans = buffer.floatChannelData?.pointee { let left = chans.advanced(by: 0) let right = chans.advanced(by: 1) for b in 0..<flength { let v:Float = max(abs(left[b]), abs(right[b])) points.append(v) } } pi += flength case .insufficientDataFromInputNode: // applicable only if using the input node as one of the sources break case .cannotDoInCurrentContext: // engine could not render in the current render call, retry in next iteration break case .error: // error occurred while rendering fatalError("render failed") } } catch { fatalError("render failed, \(error)") } } player.stop() engine.stop()I thought it was perhaps a simulator issue, but also on the device is happening. Am I doing anything wrong? Thanks!
Posted Last updated
.