Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate wav tone in PHP

Tags:

php

wav

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);
like image 997
lopata Avatar asked Jan 20 '15 19:01

lopata


1 Answers

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.

like image 168
Willem Van Onsem Avatar answered Nov 02 '22 05:11

Willem Van Onsem