Reputation: 680
I'm trying to record audio and apply real-time pitch shifting and write the output to an AVAudioFile
, all that using AudioKit
. At the same time, I want to play an audio file for the duration of the recording, using AVPlayer
.
The thing is that if I play an audio file during the recording, there's a very high-pitch feedback loop echoing very loudly! If on the other hand I perform the recording simply by using AVAudioRecorder
, there's zero feedback loop.
Here's how I record the processed and unprocessed audio using taps on AudioKit
's engine; (you'll notice that I set both AVAudioSession
's and AudioKit
's Settings
category.)
class PitchCorrectionAudioKitService {
private let engine = AudioEngine()
private var pitchShiftEffect: PitchShifter!
private var unprocessedAudioFile: AVAudioFile?
private var processedAudioFile: AVAudioFile?
// ------------------
@Injected private var pitchDetectionService: PitchDetectionRepository
// ------------------
init() {
guard let input = engine.input else { return }
pitchShiftEffect = PitchShifter(input)
engine.output = pitchShiftEffect
}
func start(baseNote: Note) {
handleAudioSessionCategory()
pitchDetectionService.start { data in
self.autoCorrectPitch(data, baseNote: baseNote)
}
try! engine.start()
engine.input?.avAudioNode.installTap(onBus: 0, bufferSize: 4096, format: nil) { buffer, time in
try! self.unprocessedAudioFile?.write(from: buffer)
}
engine.output?.avAudioNode.installTap(onBus: 0, bufferSize: 4096, format: nil) { buffer, time in
try! self.processedAudioFile?.write(from: buffer)
}
}
private func handleAudioSessionCategory() {
if UIDevice.primaryAudioDevice == .defaultSpeakers {
try! AVAudioSession.sharedInstance().setCategory(.playAndRecord, options: [.defaultToSpeaker, .allowBluetooth])
try! Settings.setSession(category: .playAndRecord, with: [.defaultToSpeaker, .allowBluetooth])
} else {
try! AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .videoRecording)
try! Settings.setSession(category: .playAndRecord)
}
try! AVAudioSession.sharedInstance().setActive(true)
}
}
The moment I start recording, I also play a music track;
private var musicTrackPlayer: AVPlayer?
musicTrackPlayer?.pause()
musicTrackPlayer?.volume = areHeadphonesConnected ? 0.4 : 0.01
musicTrackPlayer?.play()
Any ideas?
EDIT; I'm using version 5.6.1
.
Upvotes: 1
Views: 239
Reputation: 36
Recording while playing may not be a sensitive solution.
However, in IOS you can use AudioUnit(kAudioUnitSubType_VoiceProcessingIO)
to split the speaker and the mic.
Upvotes: 0