ほぼあらゆる音をつくる方法(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