且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在 PHP 中生成 wav 音调

更新时间:2022-10-15 15:19:41

问题在于您的算法将数字写为文本.而 .wav 文件对数据二进制进行编码.>

您可以使用例如 pack 对数据进行分组.

$freqOfTone = 440;$sampleRate = 44100;$samplesCount = 80000;$振幅 = 0.25 * 32768;$w = 2 * pi() * $freqOfTone/$sampleRate;$samples = array();for ($n = 0; $n < $samplesCount; $n++) {$samples[] = (int)($amplitude * sin($n * $w));}$srate = 44100;//采样率$bps = 16;//每个样本的位数$bps = $bps/8;//每个样本的字节数///我编辑过$str = call_user_func_array("pack",array_merge(array("VVVVVvvVVvvVVv*"),数组(//标题0x46464952,//RIFF160038,//文件大小0x45564157,//波0x20746d66,//fmt"(块)16,//块大小1,//压缩1,//n通道$srate,//采样率$Bps*$srate,//字节/秒$Bps,//块对齐$bps,//位/样本0x61746164,//数据"160000//块大小),$samples//数据));$myfile = fopen("sine.wav", "wb") or die("无法打开文件!");fwrite($myfile, $str);fclose($myfile);

这会生成这个文件.

请注意,您不能重复使用上述标题.有些方面是硬编码的,不同(如文件大小、通道数、比特率等).但是,如果您阅读文档,您可以轻松地相应地修改标题.

I would like to generate a sine tone in php. But constructing my wav I need to give the values in bytes. I don't know how to do that:

Here is the code I have:

$freqOfTone = 440;
$sampleRate = 44100;
$samplesCount = 80000;

$amplitude = 0.25 * 32768;
$w = 2 * pi() * $freqOfTone / $sampleRate;

//$dataArray = new


$text = "RIFF"
."80036"
."WAVE"
."fmt "
."16"
."1"
."1"
."44100"
."44100"
."1"
."8"
."data"
."80000";

for ($n = 0; $n < $samplesCount; $n++)
{
    $text .= (int)($amplitude *  sin($n * $w)); 
}


$myfile = fopen("sine.wav", "w") or die("Unable to open file!");

fwrite($myfile, $text);

fclose($myfile);

The problem is that you algorithm writes the numbers as text. Whereas a .wav file encodes the data binary.

You can use for instance pack to group data.

$freqOfTone = 440;
$sampleRate = 44100;
$samplesCount = 80000;

$amplitude = 0.25 * 32768;
$w = 2 * pi() * $freqOfTone / $sampleRate;

$samples = array();
for ($n = 0; $n < $samplesCount; $n++) {
    $samples[] = (int)($amplitude *  sin($n * $w));
}

$srate = 44100; //sample rate
$bps = 16; //bits per sample
$Bps = $bps/8; //bytes per sample /// I EDITED

$str = call_user_func_array("pack",
    array_merge(array("VVVVVvvVVvvVVv*"),
        array(//header
            0x46464952, //RIFF
            160038,      //File size
            0x45564157, //WAVE
            0x20746d66, //"fmt " (chunk)
            16, //chunk size
            1, //compression
            1, //nchannels
            $srate, //sample rate
            $Bps*$srate, //bytes/second
            $Bps, //block align
            $bps, //bits/sample
            0x61746164, //"data"
            160000 //chunk size
        ),
        $samples //data
    )
);
$myfile = fopen("sine.wav", "wb") or die("Unable to open file!");
fwrite($myfile, $str);
fclose($myfile);

This produces this file.

Note that you can't just reuse the above header. Some aspects were hardcoded that differ (like the size of the file, number of channels, bitrate, etc.). But if one reads the documentation, one can easily modify the header accordingly.