Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: PHP: Siniaaltoääni

Hennkka [13.12.2010 17:39:58]

#

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>

Metabolix [05.01.2011 19:13:35]

#

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"]);
}

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta