2015-01-20 3 views
6

Я хотел бы генерировать синус-тон в php. Но, построив мой wav, мне нужно дать значения в байтах. Я не знаю, как это сделать:Создать тэг wav в PHP

Вот код, у меня есть:

$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); 
+2

Вы записываете данные в «текст». Волновой файл является «двоичным». –

+2

Что @CommuSoft пытается сказать, что вам нужно написать байтовые значения, а не текстовое содержимое. Например, вместо того, чтобы писать '' 44100'', вы должны написать байты '0xAC44'. –

+0

@ Ismael Miguel - Тогда почему он не использует значение байта для 80036? – lopata

ответ

5

Проблема заключается в том, что вы алгоритм записывает число как текст. В то время как файл .wav кодирует двоичный файл данных.

Вы можете использовать, например, pack для группировки данных.

$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); 

Это производит это file.

Обратите внимание, что вы не можете просто повторно использовать вышеуказанный заголовок. Некоторые аспекты были жестко запрограммированы, которые отличаются (например, размер файла, количество каналов, битрейт и т. Д.). Но если вы читаете documentation, можно легко изменить заголовок соответственно.

+3

Не забудьте также изменить 'fopen (« sine.wav »,« w »)' в 'fopen (« sine.wav »,« w + b »)' (знайте последний параметр). Это позволяет избежать того, что Windows переводит '\ r \ n' (CRLF) в' \ r' (CR). –

+0

@IsmaelMiguel: На самом деле это может быть просто 'fopen (« sine.wav »,« wb »)', '+' не требуется. –

+0

@RocketHazmat Это не требуется, но всегда можно использовать его. Просто чтобы гарантировать, что файл будет усечен. –

Смежные вопросы