PHP で PCM wav ファイル作成 (2)

PHP で PCM wav ファイル作成 - yoyaのメモの続き

小豆を床に落としたような音が欲しくて、音声ファイルを作ってみたのが今日の話。
勿論、PHPで。

前回の記事で作った PHP で wav 音声作る function が結構便利なので、git に置いときました。

この makeWaveData.php を require して音を作って行きます。

注意

PHP で wav ファイルを作りましたがサイズが大きいので、MacOSX に入っている afconvert で変換した m4a の方を公開してます。

afconvert test.wav -f m4pf test.m4a

take0

まず sin 関数で正弦波を作って、それっぽい音が出るのを確認。

<?php

require_once('makeWaveData.php');

$sampleRate = 44100; // CD quality
$nChannel = 1; // 1:monoral, 2:stereo
$toneA = 440;
$sampleBits = 16; // 8 or 16

$period = 0.3; // seconds;
$data = '';
$theta = 0;
$theta_delta = $toneA * 2 * M_PI / $sampleRate;

$amp = 0x1000;
$totalSamples = $sampleRate * $period;

for ($i = 1 ; $i < $sampleRate * $period ; $i++) {
// signed 16-bit array (little endian)
    $v = 0 + 0x4000 * sin($theta);
    $data .= pack('v', $v); // acrovatic using for 'v'
    $theta += $theta_delta;
}

echo makeWaveData($data, $nChannel, $sampleBits, $sampleRate);

take1

mt_rand の乱数を入れてノイズにします。

$v = 0 + $amp * mt_rand() / mt_getrandmax();

take2

音量が徐々に下がる、いわゆる下降のエンベロープを付けます。

$v = 0 + $amp * ($totalSamples - $i) / $totalSamples * mt_rand() / mt_getrandmax();

take3

更に sin を混ぜます。但し周波数を1/100にして音程を感じさせないように。

$v = 0 + $volume  * mt_rand()/ mt_getrandmax() * sin($theta/100);

これだとマラカスですね。
ちょっと遠ざかったので、take2 に戻ります。

take2-2

take2 の音の長さを短くします。

< $period = 0.3; // seconds;
---
> $period = 0.05; // seconds;

take2-3

アタックを強くします。前半は急に音量を下げて後半はゆっくり下げる。

if ($i < $totalSamples/2) { // Decay
    $volume = ($totalSamples - $i*2) / $totalSamples + 0.5;
} else { // Release
    $volume = ($totalSamples - $i/2) / $totalSamples - 0.5;
}

これでいっかな。