Envelope

2003/8/23 平野拓一（東京工業大学）
2003/8/23 Takuichi Hirano (Tokyo Institute of Technology)

Wave ファイルの読み込み

SetDirectory["c:/hira2/public_html/hobby/edu/sonic_wave/envelope/fig_\
math_doc"]

<< Miscellaneous`Audio`;

WaveFormPiano = 
        ReadSoundfile["GrandPiano.wav", 
          PrintHeader -> True];

音を出して確認

ListPlay[WaveFormPiano, SampleRate -> 22050, 
      PlayRange -> {-2^16, 2^16}]

時間波形を描く

ListPlot[
      WaveFormPiano, 
ImageSize -> {160, 
          120}, 
PlotRange -> {-2^16, 
          2^16}, 
PlotJoined -> 
        True, 
PlotStyle -> {RGBColor[1, 0, 1], 
          AbsoluteThickness[2]}, 
Ticks -> 
        None, 
Frame -> 
        True, 
FrameTicks -> 
        None, 
FrameLabel -> {"Time", "Amplitude\
", "", ""}]

１周期を切り取る

[入力パラメータ]
smprate: wave ファイルのサンプリングレート
freq: 解析する音の周波数（うまく１周期を切り出すために指定）
n1: 切り出しを開始するリスト要素の開始番号

smprate = 22050;
freq = (27.5*(2^3))*((((2^((1/12)))))^3);
t = (1/freq);
n1 = 20000;
n = Floor[(t/1)*smprate]*1;
WaveFormPiano2 = 
        Table[WaveFormPiano[[i + n1]], {i, 1, 
            n}];
TimeWaveFormPiano = 
        Table[{i, WaveFormPiano[[i + n1]]}, {i, 1, 
            n}];
\(\(ListPlot[
        TimeWaveFormPiano, 
ImageSize -> {160, 
            120}, 
PlotJoined -> 
          True, 
PlotStyle -> {AbsoluteThickness[2], 
            RGBColor[1, 0, 0]}, 
PlotRange -> 
          All, 
Ticks -> 
          None, 
Frame -> 
          True, 
FrameTicks -> 
          None, 
FrameLabel -> {"Time", "Amplitude", "", ""}];\)\)
n1 = n;

離散フーリエ変換してスペクトルを描く

<< Graphics`Graphics`;
FWaveFormPiano2 = 
        Fourier[WaveFormPiano2];
FWaveFormPiano2 = 
        Take[FWaveFormPiano2, {1, 
            Floor[Length[FWaveFormPiano2]/2]}];
\(\(BarChart[
        Abs[FWaveFormPiano2], 
ImageSize -> {160, 
            120}, 
PlotRange -> 
          All, 
Frame -> 
          True, 
FrameTicks -> {{}, {}, {}, {}}, 
FrameLabel -> {"Frequency", "Amplitude", "", ""}, 
BarStyle -> {RGBColor[1, 0, 
              1]}, 
BarEdgeStyle -> {}, 
BarGroupSpacing -> 0];\)\)
Arg2[z_] := 
        If[Abs[z] > (10^(-9)), Arg[z], 0];
Arg2[x_List] := Map[Arg2, x];
\(\(BarChart[
        Arg2[FWaveFormPiano2]*180\/π, 
ImageSize -> {160, 120}, 
PlotRange -> 
          All, 
Frame -> 
          True, 
FrameTicks -> {{}, {}, {}, {}}, 
FrameLabel -> {"Frequency", "Phase (deg)", "", ""}, 
BarStyle -> {RGBColor[0, 1, 
              1]}, 
BarEdgeStyle -> {}, 
BarGroupSpacing -> 0];\)\)

切り出した１周期をいくつも並べて周期波形を作り、音を聴いてみる

freq = 440*((((2^((1/12)))))^3);
t = (1/freq)*1;
dur = 1.0;
n2 = Ceiling[dur/t];
WaveFormPiano3 = 
        Flatten[Table[
            WaveFormPiano2, {i, 1, n2}]];
ListPlay[WaveFormPiano3, SampleRate -> 22050, 
        PlayRange -> {-2^16, 2^16}];

波形を選ぶ

WaveForm3 = WaveFormPiano3;

エンベロープを作る

[Reference]
Roland SC-88 VL, 取扱説明書, p.21

AttackTime = 
        0.01*dur;
DecayTime = 
        0.9*dur;
RelaseTime = 
        0.0*dur;
AttackLevel = 
        1;
SustainLevel = 0.0;

decayFunc[n_, a_, t1_, t_] := 
            (a/(((Cos[t1] - 1))^n))*(((Cos[t] - 1))^n);      

envelope[t_] := 
        (AttackLevel/AttackTime)*t  /;  
          0 ≤ t < AttackTime;
envelope[
          t_] := decayFunc[2, AttackLevel - SustainLevel, 1, 
              (1/DecayTime)*(t - (AttackTime + DecayTime))] + 
            SustainLevel  /;  
          AttackTime ≤ 
            t < (AttackTime + 
                DecayTime);
envelope[t_] := 
        SustainLevel  /;  (AttackTime + DecayTime) ≤ 
            t < (dur - RelaseTime);
envelope[
          t_] := decayFunc[2, SustainLevel, 1, 
            (1/RelaseTime)*(t - dur)]  /;  (dur - 
                RelaseTime) ≤ t < dur;
envelope[t_] := 0;

EnvelopeForm3 = 
            Table[envelope[(1/(n1*n2))*(i - 1)], {i, 1, n1*n2}];;

\(Plot[
        envelope[t], {t, 0, 
          dur}, 
ImageSize -> {160, 
            120}, 
PlotRange -> {0, 
            1.5*Max[AttackLevel, 
                SustainLevel]}, 
PlotStyle -> {RGBColor[1, 0, 1], 
            AbsoluteThickness[
              2]}, 
Epilog -> {{Dashing[{0.02, 0.02}], 
              Line[{{AttackTime, 0}, {AttackTime, 
                    AttackLevel}}]}, 
{Dashing[{0.02, 
                  0.02}], 
              Line[{{AttackTime + DecayTime, 0}, {AttackTime + DecayTime, 
                    SustainLevel}}]}, 
{Dashing[{0.02, 
                  0.02}], 
              Line[{{dur - RelaseTime, 0}, {dur - RelaseTime, 
                    SustainLevel}}]}, 
{Dashing[{0.02, 
                  0.02}], 
              Line[{{0, SustainLevel}, {AttackTime + DecayTime, 
                    SustainLevel}}]}, 
{Dashing[{0.02, 
                  0.02}], 
              Line[{{0, AttackLevel}, {AttackTime, 
                    AttackLevel}}]}}, 
Frame -> 
          True, 
FrameTicks -> {{{0, "Note On"}, {1, "Note Off"}}, {}, {}, {}}, 
FrameLabel -> {"Time", "Envelope", "", ""}
];\)
ListPlot[
      EnvelopeForm3, 
ImageSize -> {160, 
          120}, 
PlotJoined -> 
        True, 
PlotStyle -> {AbsoluteThickness[2], 
          RGBColor[1, 0, 0]}, 
PlotRange -> 
        All, 
Ticks -> 
        None, 
Frame -> 
        True, 
FrameTicks -> 
        None, 
FrameLabel -> {"Time", "Amplitude\
", "", ""}]

エンベロープをかける

WaveForm4 = EnvelopeForm3*WaveForm3;

ListPlay[WaveForm4, SampleRate -> 22050, 
        PlayRange -> {-(2^16), (2^16)}];

ListPlot[
      WaveForm4, 
ImageSize -> {160, 
          120}, 
PlotRange -> {-2^16, 
          2^16}, 
PlotJoined -> 
        True, 
PlotStyle -> {RGBColor[1, 0, 1], 
          AbsoluteThickness[2]}, 
Ticks -> 
        None, 
Frame -> 
        True, 
FrameTicks -> 
        None, 
FrameLabel -> {"Time", "Amplitude\
", "", ""}]