适当量的信封为AVAudioUnitSampler与AVFoundation [英] Proper Volume Envelopes for AVAudioUnitSampler with AVFoundation

查看:299
本文介绍了适当量的信封为AVAudioUnitSampler与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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆