
GNU OctaveでWavetableを作成する方法 Part2(FM/RM/AM合成)
ノコギリ波と矩形波
前回紹介したSignalパッケージを使用します。SignalにはSawtoothとSquareという関数があります。
y = sin (t) %サイン波
y = sawtooth (t, width) %ノコギリ波
y = square (t, duty) %矩形波
サイン関数と比較すると、入力できる項目が一つ増えていることが分かります。sawtoothでは「width」, squareでは「duty」という項目があります。
sawtoothの「width」は値を0から1まで指定できます。スウィープさせることで、ノコギリ波→三角波→ノコギリ波と変化します。widthの値が0.5の状態で三角波となります。
squareの「duty」は矩形波のduty比を変更できます。0から100まで指定できます。dutyの指定無し、またはdutyの値が50の時、通常の矩形波となります。
それぞれの波形の機能を使用して、Wavetableを作成します。
for ループ構文
まずWavetable作成には、for ループ構文を使用します。for文というのは配列要素を順番に取り出し、ループさせるものです。繰り返しの処理によって、複数のファイルを順番に生成できます。
for x = 1 : 10
...
end
上記のようにforのとなりに配列を配置します。x = 1 : 10は1から10まで繰り返すということです。
簡単な例を。
clear;
pkg load signal
pkg load ltfat
rootname = 'sine';
extension = '.wav';
FS = 44100;
wl = 2048;
for x = 1 : 5
waveform = sin(linspace(0, x*2*pi, wl+1));
waveform = waveform(1:wl);
filename = [rootname, '-',num2str(x), extension]; %num2strは数値を文字列に変換
audiowrite(filename,waveform, FS, 'BitsPerSample' , 32);
end
上記のコードは 1から5までの数をループ処理しています。実行すると、連番でファイルが5つ生成されます。
sine-1.wav %基音
sine-2.wav %第二倍音
sine-3.wav %第三倍音
sine-4.wav %第四倍音
sine-5.wav %第五倍音
Wavetableの作成
ノコギリ波と矩形波の関数を用いて、Wavetableを作成します。
ノコギリ波
clear;
pkg load signal
pkg load ltfat
rootname = 'saw';
extension = '.wav';
FS = 44100;
wl = 2048;
wn = 256; %生成する波形の数
table = [];
for k=1: wn
%----------------------------------------------------------------------
waveform = sawtooth(linspace(0,2*pi,wl+1),k/wn);
%----------------------------------------------------------------------
waveform = waveform(1:wl);
filename = [rootname, '-',num2str(k), extension];
audiowrite(filename,waveform, FS, 'BitsPerSample' , 32);
table =[table waveform];
end
filename = [rootname, extension];
audiowrite(filename,table, FS, 'BitsPerSample' , 32);

wn = 256が生成する波形の数です。
table =[]; で空の配列を作成します。tableに波形を順番に格納するために使用します。
ループ処理でWavetableをワンフレームごとに出力していますが、不要な場合、audiowriteの部分をコメントアウトしてください。
矩形波
clear;
pkg load signal
pkg load ltfat
rootname = 'sq';
extension = '.wav';
FS = 44100;
wl = 2048;
wn = 256; %生成する波形の数
table = []; %空の配列
for k=1: wn
%----------------------------------------------------------------------
waveform = square(linspace(0,2*pi,wl+1),100*k/wn);
%----------------------------------------------------------------------
waveform = waveform(1:wl);
filename = [rootname, '-',num2str(k), extension];
audiowrite(filename,waveform, FS, 'BitsPerSample' , 32);
table =[table waveform];
end
filename = [rootname, extension];
audiowrite(filename,table, FS, 'BitsPerSample' , 32);

ノコギリ波との違いは、矩形波のdutyの部分の範囲が0から100なので、dutyのところに100を乗算しています。
FM合成
FMはFrequency Modulationの略で、周波数変調を意味します。減算方式のアナログシンセサイザーではできないような金属音などのきらびやかな音色を作成できます。
FM合成のコード

Mod = sin(linspace(0, 2*pi,wl+1));
FM = sin(Mod + linspace(0, 2 * pi, wl+1));
上記のスクリプトで分かる通り、前回の位相のシフトとほぼ同じです。位相シフトの値をサイン波に置き換えただけです。FM合成は周波数変調と言われていますが、実際は位相変調です。
clear;
pkg load signal
pkg load ltfat
rootname = 'sq';
extension = '.wav';
FS = 44100;
wl = 2048;
wn = 256; %生成する波形の数
Modamt = linspace(0,1,wn); %モジュレーション量の配列
table = [];
for k=1: wn
%----------------------------------------------------------------------
Mod = 8 * Modamt(k) * sin(linspace(0, 2 * 2*pi,wl+1)); %モジュレーション
waveform = sin(Mod + linspace(0, 2 * pi, wl+1)); %キャリア
%----------------------------------------------------------------------
waveform = waveform(1:wl);
%filename = [rootname, '-',num2str(k), extension];
%audiowrite(filename,waveform, FS, 'BitsPerSample' , 32);
table =[table waveform];
end
filename = [rootname, extension];
audiowrite(filename,table, FS, 'BitsPerSample' , 32);

このようにFMのWavetableは簡単に作成できます。後は、周波数と振幅の変更やオペレーターの組み合わせなどを変更することで、様々なWavetableを作成できます。ただし、WavetableでのFM合成は、周期波形同士を組み合わせているので、通常のFMシンセのように非整数倍の周波数比のオペレーターを組み合わせた音色は作成できません。
例えば、ベルのようなサウンドを作成したい場合は、オペレータを3.5:1の組み合わせの周波数比を使用しますが、Wavetableの場合は周波数比を2:7とし、整数倍同士の組み合わせにしなければなりません。
RM合成
RM合成はRing Modulationの略で、振幅変調の一種です。
RM合成のコード
RM = sin(linspace(0, 2*pi,wl+1));
Wave = RM .* sin(linspace(0, 2 * pi, wl+1)); % .*
これも前回の振幅の変更とほぼ一緒で、数値を周期波形に変えているだけです。前回と違うのは、乗算が「*」が「.*」になっています。要素同士の乗算には直前にピリオドを打ってください。
clear;
pkg load signal
pkg load ltfat
rootname = 'RM';
extension = '.wav';
FS = 44100;
wl = 2048;
wn = 32;
table = [];
for k= 2: wn
%----------------------------------------------------------------------
RM = sin(linspace(0, k * 2*pi,wl+1));
waveform = RM .* sin(linspace(0, 2 * pi, wl+1));
%----------------------------------------------------------------------
waveform = waveform(1:wl);
filename = [rootname, '-',num2str(k), extension];
audiowrite(filename,waveform, FS, 'BitsPerSample' , 32);
table =[table waveform];
end
filename = [rootname, extension];
audiowrite(filename,table, FS, 'BitsPerSample' , 32);

AM合成
AM合成はAmplitude Modulationの略で、振幅変調を意味します。
RM合成との違いは、モジュレーターの振幅の範囲がRMの-1から1ではなく、0から1になっていることです。

AM合成のコード
AM = (sin(linspace(0, 2 *pi, wl+1))+1)/2; %Modulator
Wave = Mod .*sin(linspace(0, 2 *pi, wl+1)); % .*
clear;
pkg load signal
pkg load ltfat
rootname = 'AM';
extension = '.wav';
%Define the length and sampling frequency of the waveform.
FS = 44100; %Sampling frequency=44.1khz
wl = 2048; %Wave Length 2048sample(Serum)
wn = 32; %Number of waveforms to generate
table = [];
%-------------------------------------------------------------------
for k = 2:wn
AM = (sin(linspace(0, k * 2 *pi, wl+1))+1)/2; %Modulator
waveform = AM .*sin(linspace(0, 2 *pi, wl+1));
waveform = waveform(1:wl);
table = [table waveform];
end
%-------------------------------------------------------------------
filename = [rootname, extension];
audiowrite(filename,table, FS, 'BitsPerSample' , 32);

次回は、ウェーブシェーピングを紹介します。
RMとAMのスペクトルの違い
Ring Modulationの波形

Amplitude Modulationの波形
