レッツコンボリューション
「Add distortion through waveshaping and convolution」チュートリアルを進めています。畳み込みの処理をして、キャビネット(ギターキャビネット)の音質の特性を音に付加していくみたいな処理になります。
畳み込みについては、以前のこちらの記事で勉強しておりますので、ご参照ください。
今回のサウンドは次のようになりました。
最初の音声が、今までの歪んだ音声で、4秒からの音声が、畳み込みでギターアンプキャビネットの特性を付加したものです。
※ノイジーで不快な?音なので、音量を小さくしてから再生することをお勧めします。
かなりギターアンプっぽさが出てきているね〜
こんな人の役に立つかも
・JUCEのDSPチュートリアルを勉強している人
・JUCEチュートリアルの「Add distortion through waveshaping and convolution」を進めている人
準備
今回の畳み込み処理には、インパルスレスポンスの音声データが必要になります。公式のチュートリアルのZIPでダウンロードできるデータ内に「Resoueces」フォルダがあります。今回は、この中の「guitar_amp.wav」を使いますので、JUCEプロジェクトフォルダ内に「Resoueces」フォルダを配置しておく必要があります。
実装
CabSimulatorクラス
ここからは、PluginProcessor.hの「CabSimulator」クラスをカスタマイズしていきます。
privateなメンバとprocessorChainにDSPモジュールのdsp::Convolutionを追加します。
private:
//==============================================================================
//以下のenumを追加します。
enum
{
convolutionIndex
};
//[2]processorChainを追加して、Convokutionクラスを追加します。
juce::dsp::ProcessorChain<juce::dsp::Convolution> processorChain;
};
reset関数を以下のように変更します。
void reset() noexcept {
processorChain.reset();
}
次に、prepare関数です。チュートリアルの内容は、少しプログラムの内容が間違っているようです。
void prepare(const juce::dsp::ProcessSpec& spec)
{
//以下の変更を行いました。
//juce::ignoreUnused(spec);
processorChain.prepare(spec);
}
コンストラクタで、ギターアンプのインパルスレスポンスの音声ファイルを読み込みます。
public:
//==============================================================================
CabSimulator()
{
auto dir = juce::File::getCurrentWorkingDirectory();
int numTries = 0;
while (!dir.getChildFile("Resources").exists() && numTries++ < 15)
dir = dir.getParentDirectory();
//以下のプログラムを追加しました。
auto& convolution = processorChain.template get<convolutionIndex>();//[1]
//[2]
convolution.loadImpulseResponse (dir.getChildFile ("Resources").getChildFile ("guitar_amp.wav"),
juce::dsp::Convolution::Stereo::yes,
juce::dsp::Convolution::Trim::no,
1024);
}
[1]では、processorChain内から、convolutionのDSPモジュールの参照を取得しています。[2]でloadImpulseResponse関数を使って、インパルスレスポンスファイルの読み出しを行います。第3引数に、音声ファイルのサイズが入ります。インパルスレスポンスの音声データをaudacityで開いてみると、1024くらいのデータ数で波形が無音になっているので、とても短い音声であることがわかります。
音声処理関数、processを実装します。
template <typename ProcessContext>
void process(const ProcessContext& context) noexcept
{
//juce::ignoreUnused(context);
processorChain.process(context);
}
AudioEngineクラス
前回からの記事の続きを行なっている場合、以前の記事で、音声処理全体をまとめるクラスの、AudioEngineクラス内のCabSimulatorの処理を外しましたので、これを復活させました。
class AudioEngine : public juce::MPESynthesiser
{
public:
//...略...
private:
enum
{
distortionIndex,
cabSimulatorIndex//ここを復活させました。/*,
reverbIndex*/
};
//2番目のDSP処理のCabSimulatorを復活させました。
juce::dsp::ProcessorChain<Distortion<float>, CabSimulator<float>/*, juce::dsp::Reverb*/> fxChain;