适当量的信封为AVAudioUnitSampler与AVFoundation [英] Proper Volume Envelopes for AVAudioUnitSampler with AVFoundation
问题描述
如何正确地创建卷信封的AVAudioUnitSampler?
基本上,我想添加一个攻击阶段,其中货量几毫秒,以避免点击变淡英寸此外,我想,这样的音量回采后淡出播放的音符添加一个释放阶段。
我做了什么至今:
我成立了一个全球性的定时器。它重新presents我的采样率。
为此,我使用的NSTimer与1个采样的间隔长度(对于44100一个样本的持续时间的采样速率是四万四千百分之一)。这样,人们不应该听到卷跳造成咔哒声。也许我需要过采样两次采样率。
定时器会调用递增masterGain只要增益低于某一阈值的功能。我递增量是通过由采样率然后通过所需的衰落时间除以这个数量除以在期望和电流增益的差计算。 (在下面的例子中我使用,方便阅读一个固定值)
阈值达到之后我删除计时器和停止注释。
- >我觉得这个做法是相当复杂的尤其是当我使用了一个释放阶段太
。请查看我的例子code。我用一个UIButton触地得分触发演奏的音符。请告诉我,如果你知道一个更简单的方法来随着时间的推移/自动值建立输入/输出音量淡入淡出。
感谢
进口的UIKit
进口AVFoundation 一流的ViewController:UIViewController的{
VAR引擎:AVAudioEngine!
VAR采样:AVAudioUnitSampler!
VAR错误:NSError?
VAR定时器:=的NSTimer的NSTimer() 覆盖FUNC viewDidLoad中(){
super.viewDidLoad() 发动机= AVAudioEngine()
采样= AVAudioUnitSampler() engine.attachNode(采样)
engine.connect(采样器,于:engine.mainMixerNode,格式:无) 如果发动机.startAndReturnError(安培;错误)!{
如果让错误= {错误
的println(发动机无法启动!)
的println(error.localizedDescription)
}
}
} @IBAction FUNC触地(发件人:UIButton的,forEvent事件:的UIEvent){
sampler.startNote(66,withVelocity:66,onChannel:0)
sampler.masterGain = -90
定时器= NSTimer.scheduledTimerWithTimeInterval(四万四千一百分之一,目标:自我,选择:updateVolume,用户信息:无,重复:真)
} FUNC updateVolume(){
如果sampler.masterGain< = -10 {
sampler.masterGain = sampler.masterGain + 0.1
的println(卷更新)
}其他{
timer.invalidate()
}
}
}
哇!这是做量信封的pretty复杂的方式!
你有没有想过使得它简单一点?而不是试图控制增益控制,我只是修改实际的声音传出来。首先,我只想有我的样本存储为载体。然后,我将创造另一种载体,将重新present我的音量包络。然后,我将创造播放一个新的样本,这将仅仅是由样本和幅度向量元素相乘的元素。下面是在MATLAB的例子。
%装入样品
[X,FS] = audioread('FILENAME.WAV');%得到你的样品长度
sampSize =长度(X);%创建音量包络。 (我只是使用高斯窗口在这里,您可以
%与任何类型的信封的替换要,只要该值是
%0和1之间)
ampEnv = gausswin(长度(X));你的两个向量的元素%乘法元素。
newSample = X * ampEnv。%绘制新的声音。
剧情(newSample);
另外,如果你正在寻找做实时它变得更棘手一点。如果延迟不是一个巨大的问题,在这里,我建议有这将存储outcoming样品你的声音,并开始应用振幅体的方法有轻微的前瞻窗口。
How to properly create Volume Envelopes for the AVAudioUnitSampler?
Basically I want to add a Attack Phase where the volume fades in over a couple of milliseconds to avoid clicks. Additionally I want to add a release phase so that the sound volume fades out after stoping to play the note.
What I did so far:
I set up a global Timer that represents my sample rate. For this I used a NSTimer with a interval length of 1 sample (for a sample rate of 44100 one sample duration is 1/44100). That way one should not hear volume "jumps" causing "clicks". Maybe I need to oversample to twice the sample rate.
The timer would call a function that incremented the masterGain as long as the gain is below a certain threshold. The amount I incremented was calculated by dividing the difference in desired and current gain by the sample rate then dividing this amount by the desired fade time. (In the example below I use a fixed value for easy reading)
After the threshold is reached I remove the timer and stop the note.
-> I think this approach is quite complex especially when I use a release phase too.
Please check my example code. I used a UIButton touchDown to trigger the played note. Please tell me if you know a much easier way to automate a value over time/ build a volume fade in/out.
Thanks
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()
}
}
}
Wow! That's a pretty complicated way of doing volume envelopes!
Have you thought about making it a bit simpler? Rather than trying to control the gain control, I would just modify the actual audio coming out. First I would just have my sample stored as a vector. Then, I would create another vector that would represent my volume envelope. Then, I would create a new sample for playback, which would just be an element by element multiplication of the sample and amplitude vectors. Here's an example in matlab.
%Load your sample
[x, Fs] = audioread('filename.wav');
%get the length of your sample
sampSize = length(x);
%Create volume envelope. (Im just using a Gaussian window here. You can
%replace it with any type of envelope you want so long as the values are
%between 0 and 1.)
ampEnv = gausswin(length(x));
%Multiply element by element of your two vectors.
newSample = x.*ampEnv;
%Plot your new sound.
plot(newSample);
Alternatively, if you're looking to do it in real time it becomes a bit more tricky. If delay isn't a massive issue here, I suggest having a slight lookahead window which would store the outcoming samples of you sounds and begin applying amplitude volume methods there.
这篇关于适当量的信封为AVAudioUnitSampler与AVFoundation的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!