真・聴力検査 HACKS
- 3. say -v Ralph "poe"
#!/bin/sh
v=1
while [ $v -le 200 ]
do
vol=`echo "scale=2; ${v} / 100" | bc | sed -e 's/^./0./g'`
echo $vol
/usr/bin/osascript -e "set Volume ${vol}"
/usr/bin/say -r 250 -v Ralph "poe"
v=`expr $v + 1`
done
- 5. 聴力検査
• オージオメーター
• 英語で書くと audiometer
• 健康診断でお馴染み
• 「 ピーピーピー ポーポーポー
と音が
鳴ってる間はボタンを押してください」
• もっとオージオメーターを手軽に
- 6. ポー そして ピー
• say で poe とか pee とか変じゃない?
• 音程によって低音は Ralph さんとか、高音な
ら Ya-Ling さんとか、指名するのはなんか変
• そもそも機械的な音声のピーもポーも音程が
違うだけで同じ音色
• 何故 Ralph は poe と言わされたか?
- 7. 擬音語、奥深い
• カタカナで表現する擬音語
• 子音は attack (立ち上がり) による
• 母音は音程による (高 イ→エ→ア→オ→ウ
低)
• decay (減衰) は「ン」で表現
• Wikipedia の「子音」の項見るとすごい
※個人の感想であり、効果・効能を示すものではありません
- 10. 人間の口腔は複雑
• ボコーダー、トーキングモジュレータ、ワウ
ペダル、ワウワウミュート等は人間の口腔に
よる音色変化をシミュレート
• ボコーダー: YMO「Technopolis」
• トーキングモジュレータ: BON JOVI「Livin On a Prayer」、同じ BON JOVI で、 な
かやまきんに君がパスタに粉チーズかける時の BGM「It s My Life」
• ワウペダル: Jimi Hendrix「Voodoo Child」、B z 松本孝弘の音作り (マニアック)
• ワウワウミュート: Pee Wee Hunt「Somebody Stole My Gal」(吉本新喜劇のテーマ)
※個人の感想であり、効果・効能を示すものではありません
- 11. Mac で音を鳴らす
• say はやめて、純粋な音を鳴らす
• Perl で .wav (WAVE) ファイルを作ろう
• データ形式について軽く調べれば出来る
• ちなみに音に関しては完全にド素人。この
ネタのために、調べたり頭で考えながら
作った資料なのであんまり細かいこと言わ
ないでください
※個人の感想であり、効果・効能を示すものではありません
- 12. CD 音質
• 44100 Hz, 16bit, ステレオ
• 秒間 44100 サンプル
• 1 サンプル 16bit → 2 bytes
• ステレオはサンプルが左右交互に 2 つ
• block size は 2 bytes x 2 = 4 bytes
• 44100 (sample) x 4 (bytes) =176,400
bytes/sec ( 172.27KB 1.35Mbps)
- 13. WAVE データ形式
• RIFF (Resource Interchange File Format)
という汎用メタファイル形式
• RIFF ヘッダと RIFF データからなる
• WAVE データは RIFF データ内の
WAVE ヘッダとサブチャンクから構成
- 15. WAVE データ
内容 バイト数
RIFF ヘッダ 8
WAVE ヘッダ WAVE 4
fmt チャンク 24∼
data チャンク -
あくまで、音を鳴らすための最低限
- 16. RIFF ヘッダ
内容 バイト数
RIFF 識別子 RIFF 4
これより後ろのデータサイズ
4
(合計サイズ -8)
- 18. fmt チャンク
内容 バイト数
fmt 識別子 fmt 4
fmt チャンクの
これより後ろのデータサイズ
4
フォーマット ID (リニア PCM = 1) 2
チャンネル数
(モノ:1 ステレオ: 2)
2
サンプリングレート (Hz) 4
データ速度
(サンプリングレート x block size)
4
block size 2
bit 数 2
- 19. data チャンク
内容 バイト数
data 識別子 data 4
data チャンクの
4
これより後ろのデータサイズ
音声データ -
- 20. 音声データ
内容 バイト数
左チャンネルのサンプル 2
右チャンネルのサンプル 2
↑これが 1 ブロック
1 秒あたり 44100 ブロック
- 21. 音の基礎
• 440Hz (秒間 440 回振幅) の音はラ (A4)
• 半分の 220Hz、倍の 880Hz もラ
(A3, A5)
• A3∼A5 は用紙サイズではなく A がラを、
後ろの数字がオクターブを表す
• MIDI データだとオクターブが 1 つ下の扱い
- 22. 音の基礎
• オクターブ間の周波数を 12 分割したのが音
階 ((十二)平均律) で、世の中の音楽のデファ
クト
• 和声で平均律の不自然さに異を唱える思想
もあり。「音律」で Wikipedia
• 振幅の幅が音量
• 振幅の形が音色
- 23. 振幅の形 (波形)
• 代表: 正弦波 (sine)、矩形波 (square)、三角
波 (triangle)、のこぎり波 (sawtooth)
- 24. 楽器の音色の違い
• 波形の違い
• attack, decay の違い
• 基音 (fundamental tone) と倍音
(harmonics) の音量と組み合わせの違い
• トーンの違い
※個人の感想であり、効果・効能を示すものではありません
- 26. 純音
• アナログでは、ウィーンブリッジ発振回路
(Wien bridge oscillator) で実現可能
• デジタルでは量子化による誤差が生じる
• 「完全な正弦波は作れない」
• サンプリングレート、量子化ビット数を上
げることで近似的な音は作れる
※個人の感想であり、効果・効能を示すものではありません
- 27. オージオメータ仕様
• 125Hz, 250Hz, 500Hz, 1000Hz, 2000Hz,
4000Hz, 8000Hz を出力する
• シの音 (123.47Hz, 246.94Hz,
493.88Hz, 987.76Hz ...) に近い
• 音が鳴ってる箇所、無音の箇所の繰り返し
• 左右で鳴り分け (ステレオ)
- 29. WAVE で作る純音
sub make_sine {
my($hz, $sec, $lvol, $rvol) = @_;
my $maxno = 2 ** 16 / 2 - 1; # 32767
$lvol = $lvol / 100 * $maxno;
$rvol = $rvol / 100 * $maxno;
my $length = 44100 * $sec;
my $sound = '';
for my $pos (1 .. $length) {
my $val = sin 2 * 3.14 * $hz * ($pos / 44100);
$sound .= pack 'v', $val * $lvol; # left
$sound .= pack 'v', $val * $rvol; # right
}
return $sound;
}
- 30. WAVE で作る無音
sub make_silent {
my $sec = shift;
my $length = 44100 * $sec;
my $sound = '';
for my $pos (1 .. $length) {
$sound .= "0" x 4;
}
return $sound;
}
- 31. 純音無音の繰り返し
sub audiometer {
my($lr, $oct) = @_;
my $hz = 500 * 2 ** ($oct - 3);
my $data = '';
for my $vol (1 .. 20) {
my @vol_args = uc($lr) eq 'L' ? ($vol, 0) : (0, $vol);
$data .= make_sine($hz, 0.3, @vol_args);
$data .= make_silent(0.2);
}
return $data;
}
- 32. 忘れないで、ヘッダ
my $header = riff_header(length $data);
sub riff_header {
my $size = shift;
my $header = 'RIFF'; # RIFF header
$header .= pack 'V', $size + 36; # following data size
$header .= 'WAVE'; # WAVE header
$header .= 'fmt '; # fmt header
$header .= pack 'V', 16; # format chunk size
$header .= pack 'v', 1; # format id (PCM = 1)
$header .= pack 'v', 2; # monaural = 1, stereo = 2
$header .= pack 'V', 44100; # sampling rate (44.1kHz)
$header .= pack 'V', 44100 * 4; # byte/sec
$header .= pack 'v', 4; # block size (16bit stereo)
$header .= pack 'v', 16; # bit/sample
$header .= 'data'; # data header
$header .= pack 'V', $size; # data chunk size
return $header;
}
- 33. お洒落に PSGI で
my $app = sub {
my $env = shift;
my @path = $env->{REQUEST_URI} =~ m{^/([lr])/([1-7])/?$}i;
die "invalid path $env->{REQUEST_URI}" unless @path == 2;
my $wave = audiometer(@path);
return [
200,
[
'Content-Type' => 'audio/x-wav',
'Content-Length' => length($wave) + 44,
],
[
riff_header(length $wave),
$wave,
],
];
};
- 35. 応用: モスキート音
sub mosquito { return make_sine(17000, 10, 100, 100) }
• 17kHz 以上の音はモスキート音
• 若者には聞こえるらしいぜ
• はぁ、どうせ聞こえねーし
※個人の感想であり、効果・効能を示すものではありません
- 36. 応用: 簡易シーケンサ
sub tone_to_hz {
my $tone = shift;
my($scale, $shift, $octave) = $tone =~ /
^
([A-G]) # A-G
([-+b#]?) # -, +, b, #
([1-9]?) # 1-9
$
/x;
return 0 unless $scale;
my %tone_index = (
C => -9, D => -7, E => -5, F => -4, G => -2, A => 0, B => 2,
);
my $index = $tone_index{$scale};
if ($shift) {
my $num = $shift eq '+' || $shift eq '#' ? 1 : -1;
$index += $num;
}
if ($octave && $octave != 3) {
$index += ($octave - 3) * 12;
}
return 440 * (2 ** ($index / 12));
}
- 37. 応用: 簡易シーケンサ
sub sequence {
my $bpm = shift;
my $crotchet = 60 / $bpm;
my $seconds = +{
16 => $crotchet / 4,
8 => $crotchet / 2,
4 => $crotchet,
2 => $crotchet * 2,
1 => $crotchet * 4,
};
my $wave = '';
for my $data (@_) {
my($tone, $len, $vol) = @$data;
$vol ||= 80;
my $sec = 0;
for my $note (split /-/, $len) {
my $dotted = $tone =~ s/.$// ? 1 : 0;
$sec += $seconds->{$note} * ($dotted ? 1.5 : 1);
}
if ($tone eq '-') {
$wave .= make_silent($sec);
next;
}
$wave .= make_sine(tone_to_hz($tone), $sec, $vol, $vol);
}
return $wave;
}
- 38. 応用: 簡易シーケンサ
sub heavy_rotation { ['C#4', 4], # ン
my $bpm = shift;
['C#4', 4], # ガ
my $crotchet = 60 / $bpm;
return sequence( ['A3', 4], # ン
$bpm, ['F#3', 4], # な
['E3', 4], # I
['F#3', 4], # want ['F#3', 4], # っ
['G#3', '1-4'], # you ['G#3', 4], # て
['-', 4],
['A3', 4], # る
['E3', 4], # I
['F#3', 4], # need ['B3', 4], # mu
['G#3', '1-4'], # you ['B3', 4], # -
['-', 4], ['B3', 4], # si
['E3', 4], # I ['G#3', 4], # -
['F#3', 4], # love ['E3', 2], # c
['G#3', '1-4'], # you ['-', 4],
['-', 4], ['G#3', 4], # hea
['G#3', 4], # あ ['A3', 2], # vy
['C#3', 2], # -
['A3', 4], # た
['E3', 4], # ro
['B3', 2], # ま ['D#3', 4], # -
['G#3', 2], # の ['C#3', 4], # ta
['D#3', 4], # -
['F#3', 2], # な ['E3', 2], # tion
['E3', 2], # か );
}
['C#4', 4], # ガ