[Swift] 오디오 파일의 위상을 반전

소개



노이즈 캔슬링이나 보컬 추출에는 음성의 위상 반전을 이용합니다.
이번에는 Swift를 사용하여 위상 반전을 수행하는 방법을 소개합니다.

역 위상에 대한 기사는 여기

본편



사용할 프레임워크는 AVFoundationAccelerate입니다.
AVFoundation에서 음성 파일을 읽고 Accelerate에서 위상 반전 처리를 하는 등의 흐름입니다.
이번에는 쉽게 Playground를 사용하여 구현할 것입니다.

1. 위상 반전시키고 싶은 음성 파일을 준비



위상 반전시키고 싶은 음성 파일을 준비합니다. 이번에는 wav 형식으로 준비했습니다.

2. 오디오 파일 불러오기



오디오 파일을 로드합니다.
AVFoundation을 사용하므로 import하십시오.
Url은 각자 읽어주세요.
import AVFoundation
let inputUrl = URL(fileURLWithPath: NSHomeDirectory()+"/Desktop/"+"input.wav")
let outputUrl = URL(fileURLWithPath: NSHomeDirectory()+"/Desktop/"+"output.wav")

let input = try! AVAudioFile(forReading: inputUrl,commonFormat: .pcmFormatFloat32, interleaved: false)

3. 오디오 데이터를 버퍼로 읽어들입니다.



읽어들인 음성 파일의 내용을 읽어들이기 위한 버퍼와, 처리를 실시한 후에 출력하기 위한 버퍼를 준비합니다.
버퍼를 정의한 후 실제로 inputBuffer는 이전에 읽은 오디오 파일에서 내용의 오디오 데이터를 읽습니다.
guard let inputBuffer = AVAudioPCMBuffer(pcmFormat: input.processingFormat, frameCapacity: AVAudioFrameCount(input.length)),
      let outputBuffer = AVAudioPCMBuffer(pcmFormat: input.processingFormat, frameCapacity: AVAudioFrameCount(input.length)) else{
    fatalError()
}

do{
    try input.read(into: inputBuffer)
}catch{
    print(error.localizedDescription)
}

4. 버퍼로부터 음성 데이터 배열([[Float32]])을 추출한다.



꺼냅니다. (정확하게는 UnsafePointer<UnsafeMutablePointer<Float>> 형입니다)
배열은 Double형의 2차원 배열이 되어 있어 채널마다 음성 데이터의 진폭치가 들어가 있습니다.
let inputFloat32ChannelData = inputBuffer.floatChannelData!
let outputFloat32ChannelData = outputBuffer.floatChannelData!

5. 음성 데이터를 역상으로 변환



4에서 꺼낸 2차원 배열에 대해 채널마다 음성 데이터 배열의 각 요소에 -1을 곱하면 역 위상이 됩니다.
for문 등으로 배열을 주사해도 할 수 없는 일은 없지만, 계산량이 너무 시간이 걸리므로, Accelarelate 프레임워크의 함수를 사용하는 것으로 합니다.
vDSP_vsmul은 Float32 유형의 배열에 대해 스칼라 배를 수행하는 함수입니다.
이 함수의 제 4 인수가 출력하고 싶은 배열 포인터를 나타내므로 output을 지정합니다.
for channel in 0 ..< Int(inputBuffer.format.channelCount) {
    let input: UnsafeMutablePointer<Float32> = inputFloat32ChannelData[channel]
    let output: UnsafeMutablePointer<Float32> = outputFloat32ChannelData[channel]

    var scalar:Float = -1.0
    vDSP_vsmul(input, 1, &scalar, output, 1, vDSP_Length(inputBuffer.frameLength))
}
outputBuffer.frameLength = inputBuffer.frameLength

6. 출력 형식 설정


let settings: [String: Any] = [
    AVFormatIDKey: outputBuffer.format.settings[AVFormatIDKey] ?? kAudioFormatLinearPCM,
    AVNumberOfChannelsKey: outputBuffer.format.settings[AVNumberOfChannelsKey] ?? 2,
    AVSampleRateKey: outputBuffer.format.settings[AVSampleRateKey] ?? 44100,
    AVLinearPCMBitDepthKey: outputBuffer.format.settings[AVLinearPCMBitDepthKey] ?? 16
]

7.출력



이전 형식 설정에 따라 출력을 수행합니다.
그러면 1로 지정된 outputUrl 위치에 파일이 생성됩니다.
do{
    let output = try AVAudioFile(forWriting: outputUrl, settings: settings, commonFormat: .pcmFormatFloat32, interleaved: false)
    try output.write(from: outputBuffer)
}
catch{
    print(error.localizedDescription)
}

정말 역위상인지 확인



이전 기사 하지만 사용한 Audacity라는 소프트웨어를 사용합니다. (win도 mac에서도 사용할 수 있습니다)
Audacity에 입력 파일과 생성된 출력 파일을 가져와서 재생합니다.
제대로 반전할 수 있다면 소리가 무너지고 아무것도 들리지 않습니다.



사이고에게



읽어 주셔서 감사합니다.

이번에 작성한 코드는 다음 리포지토리에 있습니다.
htps : // 기주 b. 코 m / px9 / ゔ ぇ r 타우 오 P 하세

좋은 웹페이지 즐겨찾기