下がっているのに上がっている音を作ってみた
正確に言うと「下がっているのに上がっているように聞こえる音を作ってみた」です。
本記事は基本的にこちらの投稿についての解説になりますのでとりあえず聴いていただけると幸いです。元々は授業のレポートとして提出したものですが、そのレポートより詳しく書こうと思います。音に関する記事なのに音データが少なくて申し訳ありません。
はじめに「missing fundamental」という音の錯覚についてですが、こちらのサイトに分かりやすい説明がありました。
楽器の音には、基本となる周波数の整数倍の周波(倍音)が複数含まれており、人はその全体を基本となる周波数の音程として知覚します。
倍音のうちの高周波の方だけを聴いても、その周波数比から基本周波数(第一倍音)を脳が勝手に計算して知覚してしまうということです。
例えば、上の図では第一倍音(493Hz)のサイン波は実際には鳴っていませんが、実際に鳴っているサイン波の周波数間隔が493Hzであるため、この楽器音の音程は493Hzだということがわかります。第二、第三倍音が無くても同じように知覚されますが、てきとうに削りすぎてもダメで、もしも第四倍音(493×4Hz)と第六倍音(493×6Hz)だけが鳴っていたら第二倍音(493Hz×2Hz)の音程として知覚されると思います。
これを利用して作ってみた音のスペクトログラムが以下のような感じで、縦軸が周波数、横軸が時間です。上の方の赤い線が実際に音源に含まれている音、一番下の緑の線が聞いた時に知覚する第一倍音で、実際には鳴っていません。
音は8種類で、緑の線の音程的には左から順にドレミファソラシドとなっています。実際の音は冒頭のツイッターのリンクから聞けます。
実際に鳴っているサイン波の周波数は左から順に(ただし周波数は平均律です)
C3(261Hz)の第8~14倍音
D3(293Hz)の第7~12倍音
E3(329Hz)の第6~10倍音
F3(349Hz)の第5~9倍音
G3(392Hz)の第4~8倍音
A3(440Hz)の第3~7倍音
B3(493Hz)の第2~6倍音
C4(523Hz)の第1~5倍音(これは普通の音)
倍音の数は、視覚的に下降している印象を受けるように微調整しました。
最初の音なんかは第8倍音以降の音(2,000hz以上)しか鳴っていないのに、意外にも基音の補完がされているように聞こえて驚きました。
参考までに、wavファイルを作成したときのC言語のコードを載せておきます。インクルードしているwave.hというヘッダーファイルの中にはPCMフォーマットデータを格納するための構造体が定義されています。
全てのサイン波は同じ振幅で生成しているので周波数別の音の強弱によって印象を操作したりはしていません。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "wave.h"
void Sin_wave(int start,int end,double fundamental,MONO_PCM *pcm1,double Amplitude);
//サイン波のデータを格納する関数(開始ブロック位置、終了ブロック位置、周波数、MONO_PCM構造体(ポインタ)、振幅);
int main(void)
{
MONO_PCM pcm1;
int i;
double f;
pcm1.fs = 8000; /* サンプリング周波数 つまり8000ブロック=1秒 */
pcm1.bits = 16; /* ビット->量子化精度 */
pcm1.length = 8000*8; /* データ全体の標本化回数 */
pcm1.s = calloc(pcm1.length, sizeof(double)); /* メモリ確保 */
for(int i=8; i<15; i++){ /*第8~14倍音*/
f = 261.0*(double)i; /*261Hz->C3*/
Sin_wave(0, 8000, f, &pcm1, 0.05);
}
for(int i=7; i<13; i++){ /*第7~12倍音*/
f = 293.0*(double)i; /*293Hz->D3*/
Sin_wave(8000, 8000*2, f, &pcm1, 0.05);
}
for(int i=6; i<11; i++){ /*第6~10倍音*/
f = 329.0*(double)i; /*329Hz->E3*/
Sin_wave(8000*2, 8000*3, f, &pcm1, 0.05);
}
for(int i=5; i<10; i++){ /*第5~9倍音*/
f = 349.0*(double)i; /*349Hz->F3*/
Sin_wave(8000*3, 8000*4, f, &pcm1, 0.05);
}
for(int i=4; i<9; i++){ /*第4~8倍音*/
f = 392.0*(double)i; /*392->G3*/
Sin_wave(8000*4, 8000*5, f, &pcm1, 0.05);
}
for(int i=3; i<8; i++){ /*第3~7倍音*/
f = 440.0*(double)i; /*440->A3*/
Sin_wave(8000*5, 8000*6, f, &pcm1, 0.05);
}
for(int i=2; i<7; i++){ /*第2~6倍音*/
f = 493.0*(double)i; /*493->B3*/
Sin_wave(8000*6, 8000*7, f, &pcm1, 0.05);
}
for(int i=1; i<6; i++){/*第1(基音)~5倍音*/
f = 523.0*(double)i; /*523->C4*/
Sin_wave(8000*7, 8000*8, f, &pcm1, 0.05);
}
mono_wave_write(&pcm1, "octave02.wav"); //ファイル出力
free(pcm1.s); /* メモリ解放 */
return 0;
}
void Sin_wave(int start,int end,double fundamental,MONO_PCM *pcm1,double Amplitude){
int n;
for(n = start;n < end;n++){
pcm1->s[n] += Amplitude * sin(2.0 * M_PI * fundamental * n / pcm1->fs);
}
}
参考書籍