ほぼあらゆる音をつくる方法(How to Make Almost Any Sound)

1.ライブラリ

1.1 ADSR関数
function e=ADSR(A,D,S,R,gate,duration)
e=zeros(1,duration);
if A~=0
    for n=1:A,
        e(n)=1-exp(-5*(n-1)/A);
    end
end
if D~=0
    for n=A+1:gate,
        e(n)=S+(1-S)*exp(-5*(n-1-A)/D);
    end
else
    for n=A+1:gate,
        e(n)=S;
    end  
end
if R~=0
    for n=gate+1:duration,
        e(n)=e(gate)*exp(-5*(n-gate+2)/R);
    end
end
1.2 IIR_LPF関数
function [b,a]=IIR_LPF(fc,Q)
fc=tan(pi*fc)/(2*pi);
a(1)=1+2*pi*fc/Q+4*pi*pi*fc*fc;
a(2)=(8*pi*pi*fc*fc-2)/a(1);
a(3)=(1-2*pi*fc/Q+4*pi*pi*fc*fc)/a(1);
b(1)=4*pi*pi*fc*fc/a(1);
b(2)=8*pi*pi*fc*fc/a(1);
b(3)=4*pi*pi*fc*fc/a(1);
a(1)=1;
1.3 IIR_HPF関数
function [b,a]=IIR_HPF(fc,Q)
fc=tan(pi*fc)/(2*pi);
a(1)=1+2*pi*fc/Q+4*pi*pi*fc*fc;
a(2)=(8*pi*pi*fc*fc-2)/a(1);
a(3)=(1-2*pi*fc/Q+4*pi*pi*fc*fc)/a(1);
b(1)=1/a(1);
b(2)=-2/a(1);
b(3)=1/a(1);
a(1)=1;
1.4 IIR_resonator関数
function [b,a]=IIR_resonator(fc,Q)
fc=tan(pi*fc)/(2*pi);
a(1)=1+2*pi*fc/Q+4*pi*pi*fc*fc;
a(2)=(8*pi*pi*fc*fc-2)/a(1);
a(3)=(1-2*pi*fc/Q+4*pi*pi*fc*fc)/a(1);
b(1)=2*pi*fc/Q/a(1);
b(2)=0;
b(3)=-2*pi*fc/Q/a(1);
a(1)=1;
1.5 Hanning_window関数
% Hanning_window.m
function w=Hanning_window(N)
w=zeros(1,N);
if mod(N,2)==0
    for n=1:N,
        w(n)=0.5-0.5*cos(2*pi*(n-1)/N);
    end 
else
    for n=1:N,
        w(n)=0.5-0.5*cos(2*pi*(n-0.5)/N);
    end 
end
1.6 sinc関数
function y=sinc(x)
if x==0.0
    y=1.0;
else
    y=sin(x)/x;
end

2.楽器音

「Pythonではじめる 音のプログラミング(オーム社)」のサポートサイトにて、フルスクラッチ合成による36種類の楽器音のサンプルを公開しています。

3.サウンドエフェクト

「Pythonで作るエフェクタ(CQ出版社 Interface 2023年6月号)」のサポートサイトにて、10種類のエフェクタのサンプルを公開しています。
3.1 ディレイ
使用前(delay0.wav)

使用後(delay1.wav)

% delay1.m
clear;
fs=44100;
bits=16;

s0=wavread('delay0.wav');
length_of_s=length(s0);

s1=zeros(1,length_of_s);
a=0.8;
d=fs*0.375;
repeat=1;
for n=1:length_of_s,
    s1(n)=s0(n);
    for i=1:repeat,
        m=floor(n-i*d);
        if m>=1
            s1(n)=s1(n)+power(a,i)*s0(m);
        end
    end
end

sound(s1,fs);
wavwrite(s1,fs,bits,'delay1.wav');
3.2 リバーブ
使用前(reverb0.wav)

インパルス応答(impulse_response.wav)

使用後(reverb1.wav)

% reverb1.m
clear;
fs=44100;
bits=16;

s0=wavread('reverb0.wav');

b=wavread('impulse_response.wav',44100);
a(1)=1;
s1=filter(b,a,s0);

sound(s1,fs);
wavwrite(s1,fs,bits,'reverb1.wav');
3.3 トレモロ
使用前(tremolo0.wav)

使用後(tremolo1.wav)

% tremolo1.m
clear;
fs=44100;
bits=16;

s0=wavread('tremolo0.wav');
length_of_s=length(s0);

s1=zeros(1,length_of_s);
depth=0.8;
rate=8;
for n=1:length_of_s,
    a=1.0+depth*sin(2.0*pi*rate*(n - 1)/fs);
    s1(n)=a*s0(n);
end

sound(s1,fs);
wavwrite(s1,fs,bits,'tremolo1.wav');
3.4 ビブラート
使用前(vibrato0.wav)

使用後(vibrato1.wav)

% vibrato1.m
clear;
fs=44100;
bits=16;

s0=wavread('vibrato0.wav');
length_of_s=length(s0);

s1=zeros(1,length_of_s);
d=fs*0.025;
depth=fs*0.01;
rate=0.5;
for n=1:length_of_s,
    tau=d+depth*sin(2.0*pi*rate*(n-1)/fs);
    t=n-tau;
    m=floor(t);
    delta=t-m;
    if m>0 & m+1<=length_of_s
        s1(n)=s1(n)+delta*s0(m+1)+(1.0-delta)*s0(m);
    end
end

sound(s1,fs);
wavwrite(s1,fs,bits,'vibrato1.wav');
3.5 コーラス
使用前(chorus0.wav)

使用後(chorus1.wav)

% chorus1.m
clear;
fs=44100;
bits=16;

s0=wavread('chorus0.wav');
length_of_s=length(s0);

s1=zeros(1,length_of_s);
d=fs*0.025;
depth=fs*0.01;
rate=0.1;
for n=1:length_of_s,
    s1(n)=s0(n);
    tau=d+depth*sin(2.0*pi*rate*(n-1)/fs);
    t=n-tau;
    m=floor(t);
    delta=t-m;
    if m>0 & m+1<=length_of_s
        s1(n)=s1(n)+delta*s0(m+1)+(1.0-delta)*s0(m);
    end
end

sound(s1,fs);
wavwrite(s1,fs,bits,'chorus1.wav');
3.6 フランジャ(フィードバックなし)
使用前(flanger0.wav)

使用後(flanger1.wav)

% flanger1.m
clear;
fs=44100;
bits=16;

s0=wavread('flanger0.wav');
length_of_s=length(s0);

s1=zeros(1,length_of_s);
d=fs*0.003;
depth=fs*0.002;
rate=0.25;
for n=1:length_of_s,
    s1(n)=s0(n);
    tau=d+depth*sin(2.0*pi*rate*(n-1)/fs);
    t=n-tau;
    m=floor(t);
    delta=t-m;
    if m>0 & m+1<=length_of_s
        % no feedback
        s1(n)=s1(n)+delta*s0(m+1)+(1.0-delta)*s0(m);
    end
end

s1=s1/max(s1)*0.5;

sound(s1,fs);
wavwrite(s1,fs,bits,'flanger1.wav');
3.7 フランジャ(フィードバックあり)
使用前(flanger0.wav)

使用後(flanger2.wav)

% flanger2.m
clear;
fs=44100;
bits=16;

s0=wavread('flanger0.wav');
length_of_s=length(s0);

s1=zeros(1,length_of_s);
d=fs*0.003;
depth=fs*0.002;
rate=0.25;
for n=1:length_of_s,
    s1(n)=s0(n);
    tau=d+depth*sin(2.0*pi*rate*(n-1)/fs);
    t=n-tau;
    m=floor(t);
    delta=t-m;
    if m>0 & m+1<=length_of_s
        % feedback
        s1(n)=s1(n)+0.7*(delta*s1(m+1)+(1.0-delta)*s1(m));
    end
end

s1=s1/max(s1)*0.5;

sound(s1,fs);
wavwrite(s1,fs,bits,'flanger2.wav');
3.8 ラジオボイス
使用前(radiovoice0.wav)

使用後(radiovoice1.wav)

% radiovoice1.m
clear;
fs=44100;
bits=16;

s0=wavread('radiovoice0.wav');
length_of_s=length(s0);

s1=zeros(1,length_of_s);
I=2;
J=2;
fc=1000;
Q=10;
[b,a]=IIR_resonator(fc/fs,Q);
for n=1:length_of_s,
    for m=1:J+1,
        if n-m+1>0
            s1(n)=s1(n)+b(m)*s0(n-m+1);
        end
    end
    for m=2:I+1,
        if n-m+1>0
            s1(n)=s1(n)-a(m)*s1(n-m+1);
        end
    end
end

s1=s1/max(s1)*0.5;

sound(s1,fs);
wavwrite(s1,fs,bits,'radiovoice1.wav');
3.9 ワウ
使用前(wah0.wav)

使用後(wah1.wav)

% wah1.m
clear;
fs=44100;
bits=16;

s0=wavread('wah0.wav');
length_of_s=length(s0);

s1=zeros(1,length_of_s);
I=2;
J=2;
depth=800;
rate=2;
for n=1:length_of_s,
    fc=1000+depth*sin(2*pi*rate*(n-1)/fs);
    Q=2;
    [b,a]=IIR_resonator(fc/fs,Q);
    for m=1:J+1,
        if n-m+1>0
            s1(n)=s1(n)+b(m)*s0(n-m+1);
        end
    end
    for m=2:I+1,
        if n-m+1>0
            s1(n)=s1(n)-a(m)*s1(n-m+1);
        end
    end
end

s1=s1/max(s1)*0.5;

sound(s1,fs);
wavwrite(s1,fs,bits,'wah1.wav');
3.10 ボコーダ
音声(vocal.wav)

楽器音(synth.wav)

ロボットボイス(vocoder1.wav)

% vocoder1.m
clear;
fs=44100;
bits=16;

s0=wavread('synth.wav');
s1=wavread('vocal.wav');
length_of_s=length(s0);

s2=zeros(1,length_of_s);

d=zeros(1,length_of_s);
d(1)=0;
for n=2:length_of_s,
    d(n)=s1(n)-0.98*s1(n-1);
end
for n=1:length_of_s,
    s1(n)=d(n);
end

N=1024;

x=zeros(1,N);
b=zeros(1,N);
w=Hanning_window(N);
Y=zeros(1,N);

number_of_frame=floor((length_of_s-N/2)/(N/2));

band_width=8;
number_of_band=N/2/band_width;

for frame=1:number_of_frame,
    offset=N/2*(frame-1);
    for n=1:N,
        x(n)=s0(offset+n)*w(n);
    end
    X=fft(x,N);
    for n=1:N,
        b(n)=s1(offset+n)*w(n);
    end
    B=fft(b,N);
    
    for k=1:N,
        B(k)=abs(B(k));
    end
    for band=1:number_of_band,
        offset=band_width*(band-1);
        a=0;
        for k=1:band_width,
            a=a+B(offset+k);
        end
        a=a/band_width;
        for k=1:band_width,
            B(offset+k)=a;
        end
    end
    B(1)=0;
    B(N/2+1)=0;
    for k=2:N/2,
        B(N-k+2)=B(k);
    end
    
    for k=1:N,
        Y(k)=X(k)*B(k);
    end
    y=real(ifft(Y,N));
    
    offset=N/2*(frame-1);
    for n=1:N,
        s2(offset+n)=s2(offset+n)+y(n);
    end
end

s2=s2/max(s2)*0.5;

sound(s2,fs);
wavwrite(s2,fs,bits,'vocoder1.wav');
3.11 ディストーション(対称クリッピング)
使用前(distortion0.wav)

使用後(distortion1.wav)

% distortion1.m
clear;
fs=8000;
bits=16;

s0=wavread('distortion0.wav');
length_of_s=length(s0);

s1=zeros(1, length_of_s);
gain=100;
level=0.1;
for n=1:length_of_s,
    s1(n)=s0(n)*gain;
    if s1(n)>=1
        s1(n)=1;
    elseif s1(n)<=-1
        s1(n)=-1;
    end
    s1(n)=s1(n)*level;
end

sound(s1,fs);
wavwrite(s1,fs,bits,'distortion1.wav');
3.12 ディストーション(半波整流)
使用前(distortion0.wav)

使用後(distortion2.wav)

% distortion2.m
clear;
fs=8000;
bits=16;

s0=wavread('distortion0.wav');
length_of_s=length(s0);

s1=zeros(1, length_of_s);
gain=10;
level=0.2;
for n=1:length_of_s,
    s1(n)=s0(n)*gain;
    if s1(n)>=1
        s1(n)=1;
    elseif s1(n)<0
        s1(n)=0;
    end
    s1(n)=s1(n)*level;
end

sound(s1,fs);
wavwrite(s1,fs,bits,'distortion2.wav');
3.13 ディストーション(全波整流)
使用前(distortion0.wav)

使用後(distortion3.wav)

% distortion3.m
clear;
fs=8000;
bits=16;

s0=wavread('distortion0.wav');
length_of_s=length(s0);

s1=zeros(1, length_of_s);
gain=10;
level=0.2;
for n=1:length_of_s,
    s1(n)=abs(s0(n))*gain;
    if s1(n)>=1
        s1(n)=1;
    end
    s1(n)=s1(n)*level;
end

sound(s1,fs);
wavwrite(s1,fs,bits,'distortion3.wav');
3.14 ピッチシフタ
使用前(pitchshifter0.wav)

使用後(pitchshifter1.wav)

% pitchshifter1.m
clear;
fs=44100;
bits=16;

s0=wavread('pitchshifter0.wav');
length_of_s0=length(s0);

rate=0.5; % 0.5 <= rate < 1.0

length_of_s1=ceil(length_of_s0/rate);
s1=zeros(1,length_of_s1);

template_size=floor(fs * 0.01); % 10 ms
pmin=floor(fs * 0.005); % 5 ms
pmax=floor(fs * 0.02); % 20 ms

x = zeros(1,template_size);
y = zeros(1,template_size);
r=zeros(1,pmax+1);

offset0=0;
offset1=0;

while offset0+pmax*2<=length_of_s0,
    for n=1:template_size,
        x(n)=s0(offset0+n);
    end
    rmax=0;
    p=pmin;
    for m=pmin:pmax,
        for n=1:template_size,
            y(n)=s0(offset0+m+n);
        end
        r(m)=0;
        for n=1:template_size,
            r(m)=r(m)+x(n)*y(n);
        end
        if r(m)>rmax
            rmax=r(m);
            p=m;
        end
    end
    for n=1:p,
        s1(offset1+n)=s0(offset0+n);
    end
    for n=1:p,
        s1(offset1+p+n)=s0(offset0+p+n)*(p-n)/p;
        s1(offset1+p+n)=s1(offset1+p+n)+s0(offset0+n)*n/p;
    end
    q=round(p*rate/(1-rate));
    for n=p+1:q,
        if offset0+n>length_of_s0
            break;
        end
        s1(offset1+p+n)=s0(offset0+n);
    end
    offset0=offset0+q;
    offset1=offset1+p+q;
end

pitch=1/rate;

length_of_s2=length_of_s0;
s2=zeros(1,length_of_s0);

N=16;

for n=1:length_of_s2,
    t=pitch*n;
    ta=floor(t);
    if t==ta
        tb=ta;
    else
        tb=ta+1;
    end
    for m=tb-N/2:ta+N/2,
        if m>0 & m<=length_of_s1
            s2(n)=s2(n)+s1(m)*sinc(pi*(t-m))*(0.5+0.5*cos(2*pi*(t-m)/(N*2+1)));
        end
    end
end

sound(s2,fs);
wavwrite(s2,fs,bits,'pitchshifter1.wav');

メディアネットワーク実験

サウンドプログラミング1
サウンドプログラミング2

Facebookページ

https://www.facebook.com/almostanysound

参考文献

青木 直史, ``Pythonではじめる音のプログラミング - コンピュータミュージックの信号処理 - ,'' オーム社, 2022.
青木 直史, ``ゼロからはじめる音響学,'' 講談社, 2014.
青木 直史, ``サウンドプログラミング入門 - 音響合成の基本とC言語による実装 - ,'' 技術評論社, 2013.
青木 直史, ``C言語ではじめる音のプログラミング - サウンドエフェクトの信号処理 - ,'' オーム社, 2008.
青木 直史, ``ディジタル・サウンド処理入門 - 音のプログラミングとMATLAB(Octave・Scilab)における実際 - ,'' CQ出版社, 2006.

Last Modified: April 25 12:00 JST 2023 by Naofumi Aoki
E-mail: aoki@ime.ist.hokudai.ac.jp