• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

Töne erzeugen

Redpadz

New member
Hallo.

weis nicht ganz genau wo das Thema hin gehört, daher erstmal hier.

Ich möchte auch einer Website Töne erzeugen und zwar wie folgt:

Der User gibt 2-15 Wertepaare vor die bestehen aus Frequenz und Millisekunden. Diese möchte ich dann in der angegebenen Reihenfolge so abspielen.

1. Wie programmiert man sowas am Besten?, welche Möglichkeiten gibt es da? Weis nicht, mit welchen Programmiersprachen das machbar wäre.

2. gibts für sowas irgendwo bekannte Beispiele (ich google schon seit Stunden)?

Gruß

RZ
 
Zuletzt bearbeitet:
Mit MATLAB geht sowas recht einfach - wenn du eine Webschnittstelle haben willst, würde ich auf HTML5 bauen und das <audio> verwenden. Da in allen Browsern, die HTML5 unterstützen, das WAVE-Format unterstützt wird, würde ich mir serverseitig etwas basteln, das eine WAVE-Datei aus den Wertepaaren laut dem WAVE-Format zusammenbastelt.

Im Netz hab' ich auf die Schnelle dazu nichts wirklich gefunden, aber WAVE mit PCM ist jetzt auch nicht so kompliziert...
 
Da mich das Thema gereitzt hat: SoundWave test
Ist jetzt nicht die Monsterimplementation, aber macht Geräusche.

Der Vollständigkeit halber noch die PHP-Files:

SoundWave_test.php:
PHP:
<?php
include_once("SoundWave.class.php");

$w = new SoundWave();
$w->channels = 1;
$w->bitsPerSample = 16;
$w->sampleRate = 44100;

header("Content-Type: audio/wav");
header('Content-Disposition: attachment; filename="SoundWave_test.wav"');
$data = array();
$numSamples = 0;
foreach ($_GET['frequency'] as $s => $f){
	$numSamples += $w->sampleRate * $_GET['duration'][$s];
}

$dataSize = $w->getDataBlockSize($numSamples);
echo
	$w->getRIFFBlock($dataSize + 4 + 16) .
	$w->getFormatBlock() .
	'data' . pack('V', $dataSize);

$a = pow(2, $w->bitsPerSample - 3);
$pi2 = 2 * pi();
foreach ($_GET['frequency'] as $s => $f){
	$samples = $w->sampleRate * $_GET['duration'][$s];
	for ($i = 0; $i < $samples; $i++){
		echo pack('v', $a - floor($a * cos($f * $i * $pi2 / $w->sampleRate)));
	}
}

?>

SoundWave.class.php:
PHP:
<?php

/**
 * Description of SoundWave
 *
 * @author kkapsner
 */
class SoundWave{
	/**
	 * Number of channels
	 * @var int
	 */
	public $channels = 1;
	/**
	 * Sample rate (1/s)
	 * @var int
	 */
	public $sampleRate = 44100;
	/**
	 * Bits per sample
	 * @var int
	 */
	public $bitsPerSample = 16;
	
	/**
	 * Bytes per sample
	 * @var int
	 */
	protected $sampleLength = false;
	/**
	 * Bytes per frame
	 * @var int
	 */
	protected $frameSize = false;
	/**
	 * Left shift for data to fit to bytes
	 * @var int
	 */
	protected $shift = false;
	public function fixParameter(){
		$this->sampleLength = $this->getSampleLength();
		$this->frameSize = $this->getFrameSize();
		$this->shift = $this->sampleLength * 8 - $this->bitsPerSample;
	}
	public function getSampleLength(){
		return floor(($this->bitsPerSample+7)/8);
	}
	public function getFrameSize(){
		return $this->channels * floor(($this->bitsPerSample+7)/8);
	}
	public function getDataBlockSize($numSamples){
		return $numSamples * $this->getFrameSize();
	}
	
	public function getSample($data){
		$pcmData = "";
		for ($i = 0; $i < $this->channels; $i++){
			$value = $data[$i] << $this->shift;
			for ($j = 0; $j < $this->sampleLength; $j++){
				$pcmData .= chr($value & 0xFF);
				$value >>= 8;
			}
		}
		return $pcmData;
	}
	
	public function getRIFFBlock($dataSize){
		return 'RIFF' . pack('V', $dataSize) . 'WAVE';
	}
	public function getFormatBlock(){
		$frameSize = $this->getFrameSize();
		$bytesPerSecond = $this->sampleRate * $frameSize;
		return 'fmt ' .
			pack('VvvV' . 'Vvv',
				16, 1, $this->channels, $this->sampleRate,
				$bytesPerSecond, $frameSize, $this->bitsPerSample
			);
	}
	public function getDataBlock($pcm){
		$sampleLength = ceil($this->bitsPerSample / 8);
		$shift = $sampleLength * 8 - $this->bitsPerSample;
		$pcmData = "";
		$samples = count($pcm);
		for ($t = 0; $t < $samples; $t++){
			$set = $pcm[$t];
			for ($i = 0; $i < $this->channels; $i++){
				$value = $set[$i] << $shift;
				for ($j = 0; $j < $sampleLength; $j++){
					$pcmData .= chr($value & 0xFF);
					$value >>= 8;
				}
			}
		}

		return 'data' . pack('V', $this->getDataBlockSize($pcm)) . $pcmData;
	}
	public function output($pcm){
		$dataBlock = $this->getDataBlock($pcm);
		$fmtBlock = $this->getFormatBlock();
		$riffBlock = $this->getRIFFBlock(strlen($dataBlock) + strlen($fmtBlock));
		return $riffBlock . $fmtBlock . $dataBlock;
	}
}

?>
- alles noch im PreBeta-Stadium...
 
Zurück
Oben