配列の乗算

scilabには3つの乗算がある。

単純な数と配列の乗算


x = [1,2 ; 3,4]
y = 10
y * x
           

を実行すると以下の結果が得られる


-->x = [1,2 ; 3,4]
 x  =
 
    1.    2.  
    3.    4.  
 
-->y = 10
 y  =
 
    10.  
 
-->y * x
 ans  =
 
    10.    20.  
    30.    40.  
           

単純な数と配列の乗算では、各要素に数が乗算される。

配列と配列の乗算


x = [1,2]
y = [10;20]
x * y
y * x
           

を計算すると結果は以下のようになる。

 

-->x = [1,2]
 x  =
 
    1.    2.  
 
-->y = [10;20]
 y  =
 
    10.  
    20.  
 
-->x * y
 ans  =
 
    50.  
 
-->y * x
 ans  =
 
    10.    20.  
    20.    40.  
           

このように、「*」演算を配列に対して行うと、線形代数の行列の積と同じ方法で積が計算される。線形代数の行列の積について思い出せない場合はよく復習しておこう。

なお、転置は「'」(シングルクオート)で行うことができる。


x = [1,0]
a = [1,1;1,-1] * 2 ^ (-0.5)
a * x'
a ^ 2 * x'
a ^ 3 * x'
a ^ 4 * x'

これはベクトル (1,0)を45度ずつ回転させることに相当する。結果は以下のように45度ずつ座標が回転する。

 

-->x = [1,0]
 x  =
 
    1.    0.  
 
-->a = [1,1;1,-1] * 2 ^ (-0.5)
 a  =
 
    0.7071068    0.7071068  
    0.7071068  - 0.7071068  
 
-->a * x'
 ans  =
 
    0.7071068  
    0.7071068  
 
-->a ^ 2 * x'
 ans  =
 
    1.  
    0.  
 
-->a ^ 3 * x'
 ans  =
 
    0.7071068  
    0.7071068  
 
-->a ^ 4 * x'
 ans  =
 
    1.  
    0.  
          

要素毎の積

.*

を使うと、要素毎に乗算をした結果を計算する。


x = [1,2]
y = [10,20]
x .* y
x' * y

を実行すると以下のような結果が得られる。

 

-->x = [1,2]
 x  =
 
    1.    2.  
 
-->y = [10,20]
 y  =
 
    10.    20.  
 
-->x .* y
 ans  =
 
    10.    40.  
 
-->x' * y
 ans  =
 
    10.    20.  
    20.    40.  
          

それでは以下の結果はどうなるだろうか?


x = [1,2,3]
y = [10,20,30]
x .* y
x' * y
x * y'
x * y
          

 

音に対する演算

先に wav ファイル で読み込んだ x1 に対して演算を行ってみる。


x1 = loadwave("x1.wav");
x11 = x1 + 0.2;
x12 = x1 * 0.2;
x13 = x1 + 1;
x14 = x1 * 5;
sound(x11,44100);

           

x11は音としては変化がない。

x12~x14を同様に再生すると、

x12は小さな音になる(すでに説明済)

x13,x14は歪んだ音になる。これは 1.0以上は再生範囲を超えるため。

音と音の積算

次に音と音の積算を行ってみる。

ハ長調を演奏するデータを使って確認してみよう。


stacksize(1e8);
fs=44100; x=zeros(1:20*fs);
w=0:10000; t=w/fs;
for i=0:14
    s=i*fs/4;
    n=int((i+2)/7*12+.4);
    f=440*2^(n/12);
    x(w+s+1) = x(w+s+1) + sin(2*%pi*f*t) * .1;
end
sound(x,fs);
           

このプログラムではxにハ長調の音階が作られて、それが再生される。

以下の赤文字の部分を追記してみよう。


stacksize(1e8);
fs=44100; x=zeros(1:20*fs);
w=0:10000; t=w/fs;
for i=0:14
    s=i*fs/4;
    n=int((i+2)/7*12+.4);
    f=440*2^(n/12);
    x(w+s+1) = x(w+s+1) + sin(2*%pi*f*t) * .1;
end
a = 0.1;
sound(a * x,fs);
           

音が非常に小さくなる。aの値を5.0にすると今度は非常に大きくなる。

このように数値と配列の積では、各要素に数値が乗算される。音の波形に数値を乗算した場合は音量が増減する。

次にaを以下のようにして、ヘッドホンで聴いてみよう。


stacksize(1e8);
fs=44100; x=zeros(1:20*fs);
w=0:10000; t=w/fs;
for i=0:14
    s=i*fs/4;
    n=int((i+2)/7*12+.4);
    f=440*2^(n/12);
    x(w+s+1) = x(w+s+1) + sin(2*%pi*f*t) * .1;
end
a=[1;0];
sound(a * x,44100);
           

左チャンネルから再生される。a=[0;1]なら右チャンネル、a=[1;1]なら中央から再生される。

このように 2 × n の配列を再生するとステレオになる。以下のプログラムは左右で別々の音階を演奏する。

 

stacksize(1e8);
fs=44100; x=zeros(1:20*fs);y=zeros(1:20*fs);
w=0:10000; t=w/fs;
for i=0:14
    s=i*fs/4;
    n=int((i+2)/7*12+.4); 
    f=440*2^(n/12);
    x(w+s+1) = x(w+s+1) + sin(2*%pi*f*t) * .1;
    n=int((14-i+2)/7*12+.4); 
    f=440*2^(n/12);
    y(w+s+1) = y(w+s+1) + sin(2*%pi*f*t) * .1;
end
sound([x;y],44100);
           

2つの音を乗算してみよう。

サンプル同士の値を掛け合わせるためには、 「.*」という記号を用いるのだった。

 

stacksize(1e8);
fs=44100; x=zeros(1:20*fs);y=zeros(1:20*fs);
w=0:10000; t=w/fs;
for i=0:14
    s=i*fs/4;
    n=int((i+2)/7*12+.4); 
    f=440*2^(n/12);
    x(w+s+1) = x(w+s+1) + sin(2*%pi*f*t) * .1;
    n=int((14-i+2)/7*12+.4); 
    f=440*2^(n/12);
    y(w+s+1) = y(w+s+1) + sin(2*%pi*f*t) * .1;
end
sound(x .* y,44100);
           

音が小さく、まったくへんな音階になった。音と音を乗算するとこのようにまったく異なる音になってしまう。x と y を加算すれば音を重ねることができる。

行列の乗算を使えば、音を左右のチャンネルの間でいったりきたりすることもできる。

 

stacksize(1e8);
fs=44100; x=[1,1]' * zeros(1:20*fs);
w=0:10000; t=w/fs;
for i=0:14
    s=i*fs/4;
    n=int((i+2)/7*12+.4); 
    f=440*2^(n/12);
    a=[sin(s/10000);-sin(s/10000)] + 1;
    x(:,w+s+1) = x(:,w+s+1) + a * sin(2*%pi*f*t) * .1;
end
sound(x ,44100);
           
           

なお、乗算でも加算と同様に、配列のサイズが合ってなければエラーになる。エラーの際は 2つの音の合成 を参照して変数のサイズを確認するとよい。