Ist dies Möglich?

Wenn du es mit PHP machen willst, bleiben dir 3 Möglichkeiten.
1. Du arbeitest dich ein
2. Du suchst das Internet nach einem fertigen Script ab
3. Du sucht dir jemanden, der es dir schreibt (und wahrscheinlich auch einen Horrorpreis verlangen wird :))
 
Hi,

Werde mich mal einlesen, aber heut nicht mehr ^^.

Danke, vielleicht werde Ich einestages sogar mal hinbekommen :p !

Gruß Kevin
 
fanste hat gesagt.:
Wenn man im Int etwas darüber findet, ist es denke ich mal weniger ein Problem soetwas zu realisieren, aber ist dennoch ein verdammt großer Aufwand, bis das Script steht.
Ach komm, nu übertreib doch nicht gleich ;)

Weil ich es nicht lassen konnte, hier mal ein Beispielscript:
PHP:
<?php

/**
 * Einstellungen/Initialisierung
 */

// Samplingrate der Wavedatei
$samprate = 8000;
// Länge eines Tons in Sekunden
$soundlen = 0.25;

// Töne erzeugen
$lowsound = createPCMSound(440, $soundlen, $samprate);
$highsound = createPCMSound(880, $soundlen, $samprate);

$data = '';


/**
 * Datei einlesen
 */

$fp = fopen('test.dat', 'r');

while (($char = fgetc($fp)) !== false) {
	$byte = ord($char);
	for ($i = 7; $i >= 0; $i--) {
		$bit = $byte & (1 << $i);
		if ($bit == 0) {
			$data .= $lowsound;
		} else {
			$data .= $highsound;
		}
	}
}

fclose($fp);


/**
 * Wavedatei schreiben
 */

createWaveFile('mywave.wav', $data, $samprate);


/**
 * Funktionen
 */

/**
 * Erzeugt eine Bytefolge, die einen Ton im PCM-Format repräsentiert.
 * Sampleformat ist immer 8-bit mono.
 *
 * @param integer $freq		Frequenz des Tons
 * @param float $duration	Dauer des Tons
 * @param integer $samprate	Samplingrate
 *
 * @return string			Die erzeugte Bytefolge
 */
function createPCMSound($freq, $duration, $samprate = 8000)
{
	$sound = '';
	$samples = $duration * $samprate;
	$timestep = 1 / $samprate;
	$period = 1 / $freq;

	for ($sample = 0, $time = 0; $sample < $samples; ++$sample, $time = $sample * $timestep) {
		$amplitude = sin(($time / $period) * 2 * pi());
		// Amplitude von Bereich [-1;1] auf [0;255] bringen
		$bytevalue = floor(($amplitude + 1) / 2 * 255);
		$sound .= pack('C', $bytevalue);
	}

	return $sound;
}


/**
 * Schreibt eine Wavedatei aus Rohdaten und Samplingrate.
 * Das Sampleformat ist immer 8-bit mono.
 *
 * @param string $filename	Dateiname der zu erzeugenden Wavedatei
 * @param string $data		Rohdaten
 * @param integer $samprate	Verwendete Samplingrate
 */
function createWaveFile($filename, &$data, $samprate = 8000)
{
	$wavehdr = 'WAVEfmt '.pack('VvvVVvv',
		16,			// Chunklänge
		0x0001,		// Format WAVE_FORMAT_PCM
		0x0001,		// Kanäle
		$samprate,	// Samplingrate
		$samprate,  // Bytes pro Sekunde (bei 8-bit mono gleich der Samplingrate)
		1,			// Blockgröße
		8			// Bits pro Sample
	);
	
	$datalen = strlen($data);
	$datahdr = 'data'.pack('V', $datalen);

	$fp = fopen($filename, 'w');
	fwrite($fp, 'RIFF'.pack('V', strlen($wavehdr) + $datalen));
	fwrite($fp, $wavehdr);
	fwrite($fp, $datahdr);
	fwrite($fp, $data);
	fclose($fp);
}

?>

Funktioniert für kleine Dateien und kurze Tonlängen ganz passabel. Da aber sämtliche Rohdaten im Speicher generiert und erst dann in die Wavedatei geschrieben werden, kann es bei größeren Datenmengen zu hoher Speicher-/CPU-Belastung kommen. Aber das ließe sich mit etwas Aufwand auch abstellen.
 
Matthias Reitinger hat gesagt.:
Ach komm, nu übertreib doch nicht gleich ;)

Weil ich es nicht lassen konnte, hier mal ein Beispielscript:
PHP:
<?php

/**
 * Einstellungen/Initialisierung
 */

// Samplingrate der Wavedatei
$samprate = 8000;
// Länge eines Tons in Sekunden
$soundlen = 0.25;

// Töne erzeugen
$lowsound = createPCMSound(440, $soundlen, $samprate);
$highsound = createPCMSound(880, $soundlen, $samprate);

$data = '';


/**
 * Datei einlesen
 */

$fp = fopen('test.dat', 'r');

while (($char = fgetc($fp)) !== false) {
	$byte = ord($char);
	for ($i = 7; $i >= 0; $i--) {
		$bit = $byte & (1 << $i);
		if ($bit == 0) {
			$data .= $lowsound;
		} else {
			$data .= $highsound;
		}
	}
}

fclose($fp);


/**
 * Wavedatei schreiben
 */

createWaveFile('mywave.wav', $data, $samprate);


/**
 * Funktionen
 */

/**
 * Erzeugt eine Bytefolge, die einen Ton im PCM-Format repräsentiert.
 * Sampleformat ist immer 8-bit mono.
 *
 * @param integer $freq		Frequenz des Tons
 * @param float $duration	Dauer des Tons
 * @param integer $samprate	Samplingrate
 *
 * @return string			Die erzeugte Bytefolge
 */
function createPCMSound($freq, $duration, $samprate = 8000)
{
	$sound = '';
	$samples = $duration * $samprate;
	$timestep = 1 / $samprate;
	$period = 1 / $freq;

	for ($sample = 0, $time = 0; $sample < $samples; ++$sample, $time = $sample * $timestep) {
		$amplitude = sin(($time / $period) * 2 * pi());
		// Amplitude von Bereich [-1;1] auf [0;255] bringen
		$bytevalue = floor(($amplitude + 1) / 2 * 255);
		$sound .= pack('C', $bytevalue);
	}

	return $sound;
}


/**
 * Schreibt eine Wavedatei aus Rohdaten und Samplingrate.
 * Das Sampleformat ist immer 8-bit mono.
 *
 * @param string $filename	Dateiname der zu erzeugenden Wavedatei
 * @param string $data		Rohdaten
 * @param integer $samprate	Verwendete Samplingrate
 */
function createWaveFile($filename, &$data, $samprate = 8000)
{
	$wavehdr = 'WAVEfmt '.pack('VvvVVvv',
		16,			// Chunklänge
		0x0001,		// Format WAVE_FORMAT_PCM
		0x0001,		// Kanäle
		$samprate,	// Samplingrate
		$samprate,  // Bytes pro Sekunde (bei 8-bit mono gleich der Samplingrate)
		1,			// Blockgröße
		8			// Bits pro Sample
	);
	
	$datalen = strlen($data);
	$datahdr = 'data'.pack('V', $datalen);

	$fp = fopen($filename, 'w');
	fwrite($fp, 'RIFF'.pack('V', strlen($wavehdr) + $datalen));
	fwrite($fp, $wavehdr);
	fwrite($fp, $datahdr);
	fwrite($fp, $data);
	fclose($fp);
}

?>

Funktioniert für kleine Dateien und kurze Tonlängen ganz passabel. Da aber sämtliche Rohdaten im Speicher generiert und erst dann in die Wavedatei geschrieben werden, kann es bei größeren Datenmengen zu hoher Speicher-/CPU-Belastung kommen. Aber das ließe sich mit etwas Aufwand auch abstellen.

Einfach nur WOW :eek:
Werde das eben mal probieren!

Edit:
Habe es gerade eben mal getestet, ist abartig :D!
Funktioniert 1a, habe mir gerade eine 5 Byte Datei angehört in der "Jesus" stand :D!

Ich denke jetzt werde Ich es hinbekommen das ganze auch wieder zurückzu wandeln!
Spitze :)!

Edit2:
PHP:
        $bit = $byte & (1 << $i);
        if ($bit == 0) {
            $data .= $lowsound;
        } else {
            $data .= $highsound;
        }
In dem Teil legst du ja fest, wenn das Bit 0 oder eine andere Zahl ist, ob ein hoher oder tiefer Ton eingefügt werden soll.
Wenn Ich aber mal $bit ausgebe, kommen auch andere Zahlen vor, nicht nur 1 oder 0 ?
Und könntest du mal erklären was das hier macht:
PHP:
$bit = $byte & (1 << $i);
Dieses & und <<, was machen die denn :)?
 
Zuletzt bearbeitet:
kevkev hat gesagt.:
Ich denke jetzt werde Ich es hinbekommen das ganze auch wieder zurückzu wandeln!
Spitze :)!
Das Zurückwandeln wird wohl etwas komplizierter werden, ist aber keinesfalls unmöglich.

Edit2:
PHP:
        $bit = $byte & (1 << $i);
        if ($bit == 0) {
            $data .= $lowsound;
        } else {
            $data .= $highsound;
        }
In dem Teil legst du ja fest, wenn das Bit 0 oder eine andere Zahl ist, ob ein hoher oder tiefer Ton eingefügt werden soll.
Wenn Ich aber mal $bit ausgebe, kommen auch andere Zahlen vor, nicht nur 1 oder 0 ?
Die Variablenbezeichnung $bit ist zugegebenerweise etwas irreführend. Zur Erklärung der Werte:

Und könntest du mal erklären was das hier macht:
PHP:
$bit = $byte & (1 << $i);
Dieses & und <<, was machen die denn :)?
<< ist ein Bitshift-Operator. Er schiebt die Bits im linken Operanden um die durch den rechten Operanden gegebene Anzahl an Stellen nach links. So bekomme ich in den Schleifendurchläufen die Werte 1000000b, 01000000b, 00100000b usw.

& ist der binäre UND-Operator. Damit werden die beiden Operanden derart kombiniert, dass im Ergebnis genau die Bits gesetzt sind, die sowohl im linken als auch im rechten Operanden gesetzt sind. Beispielsweise gilt 1100b & 1010b == 1000b. Ist jetzt im rechten Operanden genau ein Bit gesetzt, dann ist das Ergebnis 0, falls im linken Operanden dieses Bit auch gesetzt ist und ungleich 0 (genauer: das Ergebnis ist dann gleich dem rechten Operanden), wenn es im linken Operanden nicht gesetzt ist. Alles klar? ;)
 
Ui...
Habe mir grad das ganze auch ein wenig angeschaut, aber für mich ist das unmöglich :).
Aber das heißt micht das du wieder dein "proof of conecpt" wieder machen mußt ;).

Wie gesagt, es ist zu spät, werde mir das morgen nocheinmal anschauen und rumprobieren :)!
 
@reima:
Ich hab mir das jetzt auch mal auf Wiki durchgelesen. Ist eigentlich garnicht so schwer, wie ich gedacht hätte. Aber ob ich das in so kurzer Form hinbekommen hätte, wer weis.

Könntest du mir erklären, wie genau das mit der Sinus-Berechnung funktioniert, oder mir eine Seite sagen, auf der das in guter verständlicher Form geschildert wird? Hatte das nämlich bisher noch nicht in der Schule. Kommt erst noch. :)
Ja, das auf Wiki habe ich gefunden. Aber da muss ich ersteinmal durchkommen und es auch verstehen ;)
 
Zuletzt bearbeitet:
fanste hat gesagt.:
Könntest du mir erklären, wie genau das mit der Sinus-Berechnung funktioniert, oder mir eine Seite sagen, auf der das in guter verständlicher Form geschildert wird?
Also… bei einer Frequenz ($freq) von x Hz muss die Lautsprechermembran x mal pro Sekunde schwingen. Das heißt, dass für eine einzelne Schwingung 1/x Sekunden Zeit bleiben. Das ist die Periodendauer ($period).

Wandert man beim Graphen der Sinusfunktion von 0 ausgehend auf der x-Achse nach rechts, so sieht man, dass nach genau 2*pi (und bei Vielfachen davon) eine komplette „Schwingung“ vollendet ist. Da wir aber abhängig von der Zeit ($time) alle $period Sekunden eine komplette Schwingung haben wollen, teilen wir $time durch $period und multiplizieren das Ergebnis mit 2*pi. Sind wir bspw. gerade eine halbe Periodendauer ($time = $period/2) fortgeschritten, so ergibt sich $time / $period * 2 * pi = $period / 2 / $period * 2 * pi = pi. Das entspricht genau einer halben Schwingung im Sinusgraphen – also genau was wir wollten.

Oder anders ausgedrückt: wir stauchen/strecken den Graphen der Sinusfunktion entlang der x-Achse derart, dass jeweils bei Vielfachen von $period eine komplette Schwingung vollendet ist. Der Faktor der Streckung ergibt sich zu 2*pi / $period. Am besten ist es, wenn man sich das mal mit Hilfe eines Funktionsplotters veranschaulicht :)
 
Zurück