贝多芬 5.0.0

贝多芬 5.0.0

测试已测试
Lang语言 SwiftSwift
许可证 没有声明
发布最后发布2021年9月
SPM支持SPM

Vadym Markov 维护。



贝多芬 5.0.0

Beethoven

CI Status Version Carthage Compatible Swift License Platform

Beethoven 是一个音频处理Swift库,提供了一个易于使用的接口来解决音乐信号音调检测的古老问题。您可以在 维基百科 上阅读更多关于这个主题的内容。

基本工作流程是从输入/输出源获取音频缓冲区,将其转换为可处理格式,并应用一种音调估计算法以找到基频。对于最终用户来说,这仅关系到选择估计算法和实现代理方法。

Beethoven 被设计成灵活、可定制且高度可扩展。

库的主要目的是收集Swift实现的多种时域和频域算法,针对单音调音高提取,不同速率的精度和速度,以覆盖尽可能多的音调检测场景、乐器和人类声音。当前的实现可能也不完美,并且显然还有改进的空间。这意味着 贡献 非常重要,并且备受欢迎!

目录

Beethoven Icon

关键特性

  • 使用 AVAudioEngine 和音频节点进行音频信号跟踪。
  • 通过一个可用的 "转换器" 预处理音频缓冲区。
  • 音调估计。

使用

配置

使用Config结构体配置缓冲区和估计策略,该结构体用于初始化PitchEngine。对于需要从设备输出跟踪信号的情况,存在一个名为audioUrl的参数,其目的是指向您的音频文件的URL。

// Creates a configuration for the input signal tracking (by default).
let config = Config(
  bufferSize: 4096,
  estimationStrategy: .yin
)

// Creates a configuration for the output signal tracking.
let config = Config(
  bufferSize: 4096,
  estimationStrategy: .yin,
  audioUrl: URL
)

Config也可以不带有任何参数进行实例化

// Input signal tracking with YIN algorithm.
let config = Config()

音高引擎

PitchEngine是您将要使用的用于查找音高的主要类。它可以使用配置和委托实例化。

let pitchEngine = PitchEngine(config: config, delegate: pitchEngineDelegate)

这两个参数都是可选的,默认使用标准配置,并且可以在稍后设置delegate

let pitchEngine = PitchEngine()
pitchEngine.delegate = pitchEngineDelegate

PitchEngine使用PitchEngineDelegate在开始音高检测时报告结果或错误

func pitchEngine(_ pitchEngine: PitchEngine, didReceivePitch pitch: Pitch)
func pitchEngine(_ pitchEngine: PitchEngine, didReceiveError error: Error)
func pitchEngineWentBelowLevelThreshold(_ pitchEngine: PitchEngine)

要开始或停止音高跟踪过程,只需使用相应的PitchEngine方法即可

pitchEngine.start()
pitchEngine.stop()

信号跟踪

存在2个信号跟踪类

  • InputSignalTracker使用AVAudioInputNode从实时录音输入(麦克风)中获取音频缓冲区。
  • OutputSignalTracker使用AVAudioOutputNodeAVAudioFile播放音频文件并从播放输出获取音频缓冲区。

变换

变换是音频处理的第一步,其中将 AVAudioPCMBuffer 对象转换为浮点数数组。它也是一个实现不同种类优化的地方。然后数组会保存在内部 Buffer 结构的 elements 属性中,该结构还包含可选的 realElementsimagElements 属性,这些属性在后续计算中可能非常有用。

目前有3种变换方式

通过实现 Transformer 协议,可以轻松添加新的变换策略

public protocol Transformer {
  func transform(buffer: AVAudioPCMBuffer) -> Buffer
}

估计

音高检测算法(PDA)是一种用于估计音高或基频的算法。音高是一种心理声学现象;在选择 algorithms 时需要考虑输入源、允许的误差率和所需性能。

已实现的算法列表

通过实现 EstimatorLocationEstimator 协议,可以轻松添加新的估计算法

protocol Estimator {
  var transformer: Transformer { get }

  func estimateFrequency(sampleRate: Float, buffer: Buffer) throws -> Float
  func estimateFrequency(sampleRate: Float, location: Int, bufferCount: Int) -> Float
}

protocol LocationEstimator: Estimator {
  func estimateLocation(buffer: Buffer) throws -> Int
}

然后应将其添加到 EstimationStrategy 枚举类型,并在 EstimationFactory 结构的 create 方法中加入。通常,缓冲区变换应在单独的结构或类中执行,以保持代码库更加整洁和可读。

错误处理

由于一些困难,比如攻击瞬态、低频和高频等,音高检测不是一个简单任务。同时,它是一个实时处理,所以我们无法完全避免各种错误。为此,有一系列的错误类型需要妥善处理。

信号跟踪错误

public enum InputSignalTrackerError: Error {
  case inputNodeMissing
}

录制权限错误

PitchEngine 在启动时请求 AVAudioSessionRecordPermission,但如果权限被拒绝,它会产生相应的错误

public enum PitchEngineError: Error {
  case recordPermissionDenied
}

音高估计错误

在音高估计过程中可能会发生一些错误

public enum EstimationError: Error {
  case emptyBuffer
  case unknownMaxIndex
  case unknownLocation
  case unknownFrequency
}

音高检测的具体细节

目前,贝多芬仅在单声录音上执行音高检测。

基于Stackoverflow 答案

音高检测很大程度上取决于您想要处理的音乐内容。从单声录音中提取音高(即单个乐器或声音)与从多声部混合中提取单个乐器(例如,从多声部录音中提取旋律)不同。

对于单声部音高提取,有各种算法可以在时域和频域中实现(维基百科)。

然而,如果您想要从多声部材料中提取旋律,这两者都不会很好地工作。多声部音乐的旋律提取仍然是一个研究问题。

示例

Beethoven Tuner Example

查看调音器示例,了解如何在实际场景中使用贝多芬进行音调调整。它使用YIN
估计算法,由@glaurent采用,在电吉他和原声吉他的弦音高检测中似乎相当准确。

安装

贝多芬可通过CocoaPods获取。要安装它,只需将以下行添加到Podfile中

pod 'Beethoven'

贝多芬也可通过Carthage获取。要安装,只需将以下内容写入Cartfile中

github "vadymmarkov/Beethoven"

贝多芬也可手动安装。只需下载并将文件夹拖放到您的项目中。

组件

贝多芬使用Pitchy库从指定的频率中获取音乐音高,包括音符、音阶和偏差。

作者

Вадим Марков,[email protected]

贡献

有关更多信息,请查看CONTRIBUTING文件。

许可

Beethoven遵循MIT许可。有关更多信息,请查看LICENSE文件。