【发布时间】:2015-04-26 16:49:48
【问题描述】:
如何为 AVAudioUnitSampler 正确创建音量包络?
基本上我想添加一个攻击阶段,其中音量在几毫秒内逐渐减弱以避免点击。另外我想添加一个释放阶段,以便在停止播放音符后音量逐渐消失。
到目前为止我做了什么:
我设置了一个代表我的采样率的全局计时器。 为此,我使用了间隔长度为 1 个样本的 NSTimer(对于 44100 的采样率,一个样本持续时间为 1/44100)。这样一来,人们就不会听到音量“跳跃”导致“咔哒”声。也许我需要过采样到两倍的采样率。
只要增益低于某个阈值,计时器就会调用增加 masterGain 的函数。我增加的量是通过将所需增益和当前增益的差异除以采样率然后将该量除以所需的衰减时间来计算的。 (在下面的例子中,为了便于阅读,我使用了一个固定值)
达到阈值后,我删除计时器并停止注释。
-> 我认为这种方法相当复杂,尤其是当我也使用发布阶段时。
请检查我的示例代码。我使用 UIButton touchDown 来触发播放的音符。请告诉我您是否知道一种更简单的方法来随着时间的推移自动执行值/构建音量淡入/淡出。
谢谢
import UIKit
import AVFoundation
class ViewController: UIViewController {
var engine: AVAudioEngine!
var sampler: AVAudioUnitSampler!
var error: NSError?
var timer: NSTimer = NSTimer()
override func viewDidLoad() {
super.viewDidLoad()
engine = AVAudioEngine()
sampler = AVAudioUnitSampler()
engine.attachNode(sampler)
engine.connect(sampler, to: engine.mainMixerNode, format: nil)
if !engine!.startAndReturnError(&error) {
if let error = error {
println("Engine could not start!")
println(error.localizedDescription)
}
}
}
@IBAction func touchDown(sender: UIButton, forEvent event: UIEvent) {
sampler.startNote(66, withVelocity: 66, onChannel: 0)
sampler.masterGain = -90
timer = NSTimer.scheduledTimerWithTimeInterval (1/44100, target: self, selector: "updateVolume", userInfo: nil, repeats: true)
}
func updateVolume() {
if sampler.masterGain <= -10 {
sampler.masterGain = sampler.masterGain + 0.1
println("volume updated")
} else {
timer.invalidate()
}
}
}
【问题讨论】:
标签: ios swift audio avfoundation