女儿:爸爸,今天我在广场上看到一个人拿一把吉他自弹自唱,非常动听!
爸爸:街头艺人呗。
女儿:他的吉他能发出各种各样神奇的音效,一会儿是起势蓬勃的合唱效果,一会儿是余音绕梁的颤抖效果。您能帮我也买一个这样的电吉他吗?
爸爸:你不是有尤克里里吗?
女儿:但尤克里里没办法发出那种神奇音效啊!
爸爸:你只是觉得好玩。那种是电吉他配合各种效果器,是给音乐创作人用的。只有深谙乐理知识并且富有艺术创作灵感的人才配拥有。
女儿:(气)我就不配成为音乐创作人吗?!
爸爸:那倒也不是~ 我是怕你干什么事就三分钟热度。要知道精通一门技艺是需要持续不断的热情和兴趣。这些你都有吗?
女儿:当然有!
爸爸:(还是不相信)那这样吧,爸爸先给做一个调音软件,这样你就可以拿你的尤克里里弹出跟街头艺人的电吉他一样的音效了。
女儿:真的吗?我想试试!
<思路>
- 先录音(乐器的原始弹奏音),再过某个效果器,再等一段时间(例如3秒)把声音播放出来,就能听到调音后的效果。
- 先拿echos, flanger, chorus, temolo这四个效果器试试。四个效果器可以随时切换,就需要再加一个多路复用器(multiplexer)来做四选一。
<代码实现>
MyEngineerDaddy_5.cpp
#include <lark/lark.h>
#include <klogging.h>
#if defined(__APPLE__)
#define SUFIX ".dylib"
#elif defined(_WIN32)
#define SUFIX ".dll"
#else
#define SUFIX ".so"
#endif
int main()
{
const unsigned int rate = 48000;
const lark::SampleFormat format = lark::SampleFormat_S32;
const unsigned int chNum = 1;
const unsigned int frameDuration_ms = 20;
const lark::samples_t frameSizeInSamples = frameDuration_ms * rate / 1000;
lark::FIFO *fifo = lark::Lark::Instance().NewFIFO(
rate,
lark::SamplesToBytes(format, chNum, 1),
frameSizeInSamples * 8);
if (!fifo) {
KLOGE("Failed to new a FIFO");
return -1;
}
// Create the playback route named RouteA
lark::Route *playbackRoute = lark::Lark::Instance().NewRoute("RouteA");
if (!playbackRoute) {
KLOGE("Failed to create playbackRoute");
return -1;
}
// Create RouteA's blocks
const char *soFileName = "libblkstreamin" SUFIX;
lark::Parameters args;
args.push_back(std::to_string(rate));
args.push_back(std::to_string(format));
args.push_back(std::to_string(chNum));
lark::DataProducer *producer = fifo;
producer->SetBlocking(true);
args.push_back(std::to_string((unsigned long)producer));
lark::Block *blkStreamIn = playbackRoute->NewBlock(soFileName, true, false, args);
if (!blkStreamIn) {
KLOGE("Failed to new a block from %s", soFileName);
return -1;
}
soFileName = "libblkdelay" SUFIX;
args.clear();
args.push_back("3000000"); // delay 3 secs
lark::Block *blkDelay = playbackRoute->NewBlock(soFileName,