原本打算根据另一个主题帖子的内容和上下文语境,写一点立体声录音制式(MS)方面的文字,但是原帖已锁定,缺乏讨论环境,暂时先放到一边吧。换个话题,另开一贴。关于MS,稍后再谈。
肤浅揭秘软件录音和DSP编程
燕子李三(Liyan78)
【摘要】 见标题
【关键词】 数字录音,跨平台,编程,DSP,二阶IIR,马甲,喷子
【Key words】Digital Recording, Cross-platform, Programming, DSP, Second order Infinite Impulse Response, MaJia, PenZi
【题外话】
写作本文实属无奈,一把年纪的人了,还要做这种没有技术含量的苦力,自嘲一下。但既然写了,就希望能有一点点保留的价值。有人说这里是专业的权威论坛,既然专业,不妨超前一点,尽管所涉及的技术或技巧早已是熟透的烂瓜,妇孺皆知,根本不值一提。另一点,此处高人太多,血盆大口等着撕咬我这样的“捣蛋分子”和“马甲”,言多必失,为避免自取其辱,干脆少说别人说过的,多给实打实的东西,有人称赞我干打雷不下雨,建议我从简单的开始,没问题,就从最简单的开始。
不敢大言不惭全球别无分号,但力求所述内容前无来者。欢迎批评。如需转载,拿去即可。作者“燕子李三”,注明与否全凭良心。
【要写什么】
这里是录音版块,而且大部分话题都围绕电脑数字录音,那么就写写这个。用什么DAW?你out了,真正牛B之人肯定不屑于用别人的,那么就一定自己写。我不牛B,因此不得不把团队中的小郑喊了过来,让他帮忙整理一下前些年帮洋人码的一堆垃圾,中用的拣了一下,为跟上时代,显得自己时尚一些,比如跨平台,支持64位、Win 7、OSX、iPhone、Linux之类,就看了看有关资料,做了去芜存菁和更省事的改写。至于省了什么事,用什么玩意省的,懂的人一看便知,不懂的说破大天也白扯。你们这个圈子里真有高手,我也是高手的学生和受益者,但我本人并无义务帮大师扫盲,我只是你们认为的马甲和喷子。如有不适,请自便。
至于代码的行文风格,这完全是字如其人,我还没有修炼到随时可以……(已修改)等等高尚无私的人生境界,我一向认为,不过是网络论坛而已,尽管良心只有一颗,但是动辄光荣的劣币驱良,抱成一团,其实很傻很天真,更是很多事物发展多年也不过如此的根本原因。故此,比照大师,尽量原始。真要把百十万行拉丁字母都发上来,我没这个耐心。
【整体架构】
对不住,我们这样的马甲不懂架构,也没什么规划论证,项目分析之类,无非MIDI和Digital Audio,不是什么高屋建瓴的了不起,就一技术工种,贱的象狗一样,实在不值得鼻孔朝天。读书人贪贫不贪多,活着就为一个玩弄文字和乱喷,又让你们失望了。
【GUI部分】
无关痛痒的就不浪费版面了。又好看又关键的部分见下。先看“头”:
class TrackPanel : public Component,
public ButtonListener,
public LabelListener,
public SliderListener,
public ComboBoxListener
{
public:
TrackPanel ();
~TrackPanel();
void paint (Graphics& g);
void resized();
void buttonClicked (Button* buttonThatWasClicked);
void labelTextChanged (Label* labelThatHasChanged);
void sliderValueChanged (Slider* sliderThatWasMoved);
void comboBoxChanged (ComboBox* comboBoxThatHasChanged);
void mouseDoubleClick (const MouseEvent& e);
// 其他方法暂略,这里都是大师,自然有更厉害的招数,献丑不如藏拙
// 此处有个小宏就不明示了,但这个是必须的
private:
friend class TracksPanelComponent;
//友元一把再说
TracksPanelComponent* forTrackPanel;
ToggleButton* slectButton;
Label* trackNameLabel;
Slider* volSlider;
//音量。都是一些可视化的小东西,下同
Slider* panSlider;
//声像
TextButton* muteButton;
//静音
TextButton* soloButton;
//独奏
MyComboBox* midiPortListBox;
//MIDI端口
MyComboBox* midiChannelListBox;
//MIDI通道
MyComboBox* bankListBox;
//音色库
MyComboBox* patchListBox;
//音色
MyComboBox* sendToListBox;
//发送
Slider* keyShiftSlider;
//变调
Slider* delaySlider;
//迟滞
Slider* rebSlider;
//混响
Slider* choursSlider;
//合唱
//……还有一些玩意。我太懒,就算了吧。
TrackPanel (const TrackPanel&);
//拷构
const TrackPanel& operator= (const TrackPanel&);
//=重载
};
下面这个小类,没有它,在音轨面板上点鼠标右键会出问题。其实就是派生一个改写mouseDown方法的ComboBox,不让它出现鼠标右键打架的问题,没什么技巧性。其他控件同理。
class MyComboBox:public ComboBox
{
public:
MyComboBox(const String& componentName = String::empty):ComboBox(componentName)
{
}
// 这个构函纯属空城计
void mouseDown(const MouseEvent& e)
{
if (e.mods.isLeftButtonDown())
showPopup();
// 取消本身的右键下拉,代之以本部分的右键菜单
}
};
定义:暂略吧。主要是太长,更多只是布局和定位,没什么可研究的。
音轨区的GUI,这个复杂一些,由于功能和操作模式的差别,实现思路各不相同。下一步据说会出现更唬人的玩法,究竟如何,我现在也不太了解。为避免无谓的争议和打压,不给出了。
几句废话。GUI部分(包括所有一切),还可用Qt类库。但是这个类库不开源,生成后必须要打包所必须的几个DLL,会无端增大文件体积,我认为它并不适合部署小规模的项目。用于开发数字音频方面的程序,很多东西还要重新“造轮子”,很烦人。但是,Qt的优势不小,做界面很类似写网页(HTML编码),而且用户、资料、现成的东西都很多,比较成熟。
走带条以录音按钮为例吧,同时一并给出操作区中一个简单的音轨排列条(显示波形的),多轨的波形显示区域基本同理,但复杂很多,我这里删减了大量代码,按大师给出的DEMO示例的原始模样列出来。注意作用域类模板那个recoder对象,这个是本模块的核心,其类随后给出。
class AudioRecord : public Component,
public ButtonListener
{
public:
AudioRecord (AudioDeviceManager& deviceManager_);
~AudioRecord();
void paint (Graphics& g);
void resized();
void buttonClicked (Button* buttonThatWasClicked);
//点击录音
void visibilityChanged();
//依然是那个小宏
private:
AudioDeviceManager& deviceManager;
//本机所安装的音频设备
ScopedPointer<AudioRecorder> recorder;
//作用域指针,录音模块核心
LiveAudioInputDisplayComp* liveAudioDisplayComp;//实时输入显示组件
Label* Label1;
TextButton* recordButton;
// 录音按钮
AudioRecord (const AudioDemoRecordPage&);//拷构
const AudioDemoRecordPage& operator= (const AudioDemoRecordPage&);//=重载
};
播放,暂停,倒带之类,随便一个搞过多媒体开发的Coder都会做,不凑字了。MIDI部分,不符本版主题,略。
GUI部分还有更多,例如paint绘图之类。太复杂的东西一时间说不清,水平也有限,略吧。