我的笔记

灵感、随想与新技术
02 6月 2020

音频开发实战(一)第一个插件 音量推子 (附源码)

通过前三节的《音频开发技术》系列教程,你已经有足够的基础。下面一起开发一个简单的小插件练练手吧!

创建一个名为MyGain的工程 -> 在IDE中打开


界面

打开PluginEditor.h头文件,在字段声明里加一个推子

1
2
3
4
5
6
7
// PluginEditor.h
...
private:
    MyGainAudioProcessor& processor;
    Slider mySlider;      // 声明一个推子 <-
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MyGainAudioProcessorEditor)
...

然后打开PluginEditor.cpp,在构造方法中配置这个推子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// PluginEditor.cpp
...
MyGainAudioProcessorEditor::MyGainAudioProcessorEditor (MyGainAudioProcessor& p)
    : AudioProcessorEditor (&p), processor (p)
{
    setSize (400, 300);

    mySlider.setBounds(0, 0, 200, 30);    // 推子大小与在界面上位置 <-
    mySlider.setSliderStyle(Slider::SliderStyle::LinearHorizontal);   // 推子什么样式 横的、竖的、圆...  <-
    mySlider.setTextBoxStyle(Slider::NoTextBox, true, 0, 0);          // 推子下方显示的文本框样式 <-
    mySlider.setRange(0, 1, 0.01);                                    // 推子根据进度返回0-1的数字 精度0.01 <-
   
    addAndMakeVisible(mySlider);
}
...


运算

打开PluginProcessor.h, 声明一个float型做音量

1
2
3
4
5
6
7
8
9
//PluginProcessor.h
...
    void getStateInformation (MemoryBlock& destData) override;
    void setStateInformation (const void* data, int sizeInBytes) override;

    float myVolume;                  // 声明一个float作音量 用来中转从PluginEditor.mySlider过来的值

private:
...

打开PluginProcessor.cpp, 修改processorBlock回调, 把里面内容全删了,这次设置音量直接用接口

1
2
3
4
5
6
7
//PluginProcessor.cpp
...
void MyGainAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
    buffer.applyGain(myVolume);           // 用AudioBuffer的接口 把myVolume变量的值设置为音量
}
...


连接界面与运算

回到PluginEditor.cpp,为mySlider编写一个监听方法,让推子被拖动时,就把推子的值赋给processor的myVolume中转变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// PluginEditor.cpp
...
MyGainAudioProcessorEditor::MyGainAudioProcessorEditor (MyGainAudioProcessor& p)
    : AudioProcessorEditor (&p), processor (p)
{
    setSize (400, 300);

    mySlider.setBounds(0, 0, 200, 30);    
    mySlider.setSliderStyle(Slider::SliderStyle::LinearHorizontal);  
    mySlider.setTextBoxStyle(Slider::NoTextBox, true, 0, 0);        
    mySlider.setRange(0, 1, 0.01);                                  

    mySlider.onValueChange = [this]() { processor.myVolume = mySlider.getValue(); };    // 监听方法:当推子值变动时(被用户拖动时)把推子的返回的值给processor里的myVolume变量 <-
   
    addAndMakeVisible(mySlider);
}
...

这样一个插件就写好了,生成一下放到宿主里试试

成功了!




‘[](){}’为C++的lambda表达式, 也叫匿名函数,你可以理解为它把一段代码作为一个变量使用,可以被传递,储存,在需要的时候被调用。匿名方法和普通方法一样:'{}’中的是函数体,'()’里的是传入参数,比如:

1
[](int x){x=100;}

而'[]’中则为捕获的参数,你可以理解为放进[]的本地变量可以在'{}’中的代码块里使用,如果不捕获,则不能使用。
在本例中,捕获的this就是当前这个PluginEditor对象,而processor和mySlider都是当前这个PluginEditor对象的成员变量。所以如果要用processor.xxx和mySlider.getValue(),就需要捕获当前这个PluginEditor对象。



点击这里下载源码



课程进度40%

上海外滩 – StudioEIM // MapleStory
  1. 上海外滩 – StudioEIM // MapleStory
  2. 神木村 – StudioEIM // MapleStory
  3. MapleStory – StudioEIM // MapleStory
  4. Pantheon – StudioEIM // MapleStory
  5. 逐梦飞翔 – StudioEIM // MapleStory
  6. 魔法密林 – StudioEIM // MapleStory