Skripti tekee siniaallon annettujen parametrien avulla.
Parametrit:
Parametrit luetaan GET:istä, joten tiedostoon voi helposti laittaa linkin ilman lomaketta. Ainoa pakollinen parametri on taajuus(frequency). Samplerate on oletuksena 44100(CD-laatu) ja pituus 1 sekunti.
Wav formaatti: https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ (englanniksi)
Siniaalto: https://www.ohjelmointiputka.net/koodivinkit/24431-vb6-wav-aaltoa
Aalto.php
<?php #Tarkistetaan, että taajuus on asetettu if(isset($_GET['frequency']) && $_GET['frequency'] != '' && is_numeric($_GET['frequency'])) { #Tiedoston headerit header("Content-Type: audio/wav"); header("Content-Disposition: attachment; filename=".$_GET['frequency'].".wav"); #Taajuus $taajuus = $_GET['frequency']; #Näytteenottotaajuus $not = $_GET['samplerate']; if(!isset($_GET['samplerate']) ) $not = 44100; #Pituus $pituus = $_GET['lenght']; if(!isset($_GET['lenght'])) $pituus = 1; #Kerrotaan pituus näytteenottotaajuudella $pituus *= $not; #Wave-data taulukko $wave = array(); #ChunkID $wave[0] = 82; #R $wave[1] = 73; #I $wave[2] = 70; #F $wave[3] = 70; #F #ChunkSize $tmp = IntToBytes(28 + $pituus, 8); $wave[4] = $tmp[0]; $wave[5] = $tmp[1]; $wave[6] = $tmp[2]; $wave[7] = $tmp[3]; #Format $wave[8] = 87; #W $wave[9] = 65; #A $wave[10] = 86; #V $wave[11] = 69; #E #Subchunk1ID $wave[12] = 102; #f $wave[13] = 109; #m $wave[14] = 116; #t $wave[15] = 32; # #Subchunk1Size $tmp = IntToBytes(16, 8); $wave[16] = $tmp[0]; $wave[17] = $tmp[1]; $wave[18] = $tmp[2]; $wave[19] = $tmp[3]; #AudioFormat $tmp = IntToBytes(1, 4); $wave[20] = $tmp[0]; $wave[21] = $tmp[1]; #NumChannels $tmp = IntToBytes(1, 4); $wave[22] = $tmp[0]; $wave[23] = $tmp[1]; #SampleRate $tmp = IntToBytes($not, 8); $wave[24] = $tmp[0]; $wave[25] = $tmp[1]; $wave[26] = $tmp[2]; $wave[27] = $tmp[3]; #ByteRate $tmp = IntToBytes($not, 8); $wave[28] = $tmp[0]; $wave[29] = $tmp[1]; $wave[30] = $tmp[2]; $wave[31] = $tmp[3]; #BlockAling $tmp = IntToBytes(1, 4); $wave[32] = $tmp[0]; $wave[33] = $tmp[1]; #BitsPerSample $tmp = IntToBytes(8, 4); $wave[34] = $tmp[0]; $wave[35] = $tmp[1]; #Subchunk2ID $wave[36] = 100; #d $wave[37] = 97; #a $wave[38] = 116; #t $wave[39] = 97; #a #Subchunk2Size $tmp = IntToBytes($pituus, 8); $wave[40] = $tmp[0]; $wave[41] = $tmp[1]; $wave[42] = $tmp[2]; $wave[43] = $tmp[3]; #Siniaalto for($i = 0; $i < $pituus; $i++) $wave[] = 128 + sin($taajuus / $not * $i * 2 * pi()) * 127; #Kirjoitetaan äänitiedosto for ($i = 0; $i < count($wave); $i++) { echo chr($wave[$i]); } #Lopetetaan ohjelma exit; } #Muuttaan numero tavu-taulukoksi function IntToBytes($x, $b) { #Heksoiksi $t = dechex($x); #Tehdään heksasta tarpeeksi pitkä $t = str_pad($t, $b, "0", STR_PAD_LEFT); #Muutetaan heksat taulukkoon desimaaleiksi for($i = 0; $i < $b / 2; $i++) $u[] = hexdec(substr($t, $i * 2, 2)); #Käännetään taulukko $u = array_reverse($u); #Palautetaan arvo return $u; } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title></title> </head> <body> <form method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>"> <table style="text-align: left"> <tr><th>Taajuus</th><td><input type="text" name="frequency" value="1000" maxlength="5" /></td></tr> <tr><th>Näytteenottotaajuus</th><td><input type="text" name="samplerate" value="44100" maxlength="6" /></td></tr> <tr><th>Pituus sekunteina</th><td><input type="text" name="lenght" value="1" maxlength="5" /></td></tr> <tr><td></td><td><input type="submit" value="Kuuntele" /></td></tr> </table> </form> </body> </html>
PHP_SELF ilman htmlspecialchars-funktiota on väärä valinta actioniin, koska käyttäjä voi syöttää siihen HTML-koodia (ja siis myös JS-koodia) ja jakaa muille haitallisia linkkejä. Formin voi lähettää samalle skriptille jättämällä actionin tyhjäksi, tai jos skriptin tiedostonimi kiinnostaa, basename(__FILE__)
olisi viisaampi vaihtoehto.
Käyttämäsi ChunkSize taitaa myös olla pielessä, ja lisäksi olet toteuttanut tiedoston luonnin aika vaikeaselkoisesti, pitkästi ja sekä muistia että prosessoritehoa tuhlaivesti. Näin se onnistuu paljon huomattavasti tiiviimmin ja tehokkaammin:
<?php function wav($freq, $rate, $seconds) { $freq = intval($freq); if ($freq < 0) { $freq = 440; } $rate = intval($rate); if (!$rate) { $rate = 44100; } $samples = intval($rate * floatval($seconds)); if (!$samples) { $samples = $rate; } $data = "RIFF"; $data .= pack("V", $samples + 36); $data .= "WAVEfmt "; $data .= pack("VvvVVvv", 16, 1, 1, $rate, $rate, 1, 8); $data .= "data"; $data .= pack("V", $samples); $data .= str_repeat(" ", $samples); $k = $freq * 2 * pi() / $rate; for ($i = 0; $i < $samples; ++$i) { $data[$i + 44] = chr(128 + round(127 * sin($k * $i))); } header("Content-Type: audio/wav"); header("Content-Disposition: attachment; filename={$freq}.wav"); die($data); } if (!empty($_GET)) { wav(@$_GET["freq"], @$_GET["rate"], @$_GET["seconds"]); }
Aihe on jo aika vanha, joten et voi enää vastata siihen.