我正在尝试生成一个可以用作节拍器的.mp3(带重音/重音音符)。我是PHP流和LAME的新手。使用this documentation,我已经对它进行了尝试 - 但我认为我没有正确使用这些流:
<?php
// mp3=/Bottle_120_4_4_16.mp3 (Bottle 4/4 time, 120bpm - 4 measures (16 beats))
$mp3 = strtolower(str_replace('/', '', $_GET['mp3']));
$m = explode('_', $mp3);
$sound = $m[0];//bottle
$BPM = $m[1];//120
$time_a = $m[2];//4
$time_b = $m[3];//4
$nBeats = $m[4];//16
header('Content-Type: audio/mpeg');
header('Content-Disposition:attachment;filename='.$mp3);
header('Pragma: no-cache');
$stream = fopen('php://output', 'a');
// GENERATE PCM
$sampleRate = 48000;
$channels = 1;//Mono
$bytePerSample = 2;
$bytesInSecond = ($sampleRate * $bytePerSample * $channels);
$beatLenInSec = (60 / $BPM);
if ($time_b == 8){
$beatLenInSec = ($beatLenInSec / 2);
}
$bytesInBeat = intval($beatLenInSec * $bytesInSecond);
$bytesInBeat = (intval($bytesInBeat / $bytePerSample) * $bytePerSample);
$accentFileName = 'sound/'.$sound.'/wav/'.$sound.'-accent_ws.wav';
$noteFileName = 'sound/'.$sound.'/wav/'.$sound.'-note_ws.wav';
$PCMDataPosition = 58;
$fileA = fopen($accentFileName, 'r');
$fileB = fopen($noteFileName, 'r');
$data = '';
for ($i = 0; $i < $nBeats; $i++) {
if (($i % $time_a) == 1){
fseek($fileA, $PCMDataPosition);
$data = fread($fileA, $bytesInBeat);
} else {
fseek($fileB, $PCMDataPosition);
$data = fread($fileB, $bytesInBeat);
}
fwrite($stream, $data);
}
$lame = fopen('php://output', 'a');
// LAME ENCODE
$path = '/home/html/';
system($path.'bin/lame -r -s 48.00 -m m -b 16 - - '.$stream.' '.$lame);
fclose($stream);
fclose($lame);
?>
我正在做的事情需要两个流吗?
答案 0 :(得分:0)
不,不需要两个流,一个就够了。
然而,在标准输出上转换文件并不是一个好主意,最好使用临时文件来轻松处理错误。
这是一个如何操作的示例(在Ubuntu 13.10上测试)
<?php
class Wav2Mp3 {
public $mp3;
public $BPM;
public $sound;
public $time_a;
public $time_b;
public $nBeats;
public $bytesInBeat;
public function __construct($mp3) {
// mp3=/Bottle_120_4_4_16.mp3 (Bottle 4/4 time, 120bpm - 4 measures (16 beats))
$this->mp3 = basename(strtolower($mp3));
$m = explode('_', $this->mp3);
if (is_array($m) && (count($m) == 5)) {
$this->sound = $m[0]; // bottle
$this->BPM = $m[1]; // 120
$this->time_a = $m[2]; // 4
$this->time_b = $m[3]; // 4
$this->nBeats = $m[4]; // 16
if ($this->nBeats <= 0) {
throw new Exception("Invalid Beats ({$this->nBeats})");
}
// GENERATE PCM
$sampleRate = 48000;
$channels = 1; // Mono
$bytePerSample = 2;
$bytesInSecond = ($sampleRate * $bytePerSample * $channels);
if ($this->BPM > 0) {
$beatLenInSec = (60 / $this->BPM);
if ($this->time_b == 8) {
$beatLenInSec /= 2;
}
$bytesInBeat = intval($beatLenInSec * $bytesInSecond);
$this->bytesInBeat = intval($bytesInBeat / $bytePerSample) * $bytePerSample;
//die(print_r($this,true));
} else {
throw new Exception("Invalid BPM ({$this->BPM})");
}
} else {
throw new Exception("Invalid file name format '{$mp3}'");
}
}
public function readWav($filename) {
if ($fp = @fopen($filename, 'r')) {
$data = FALSE;
if (fseek($fp, 58) == 0) {
$data = fread($fp, $this->bytesInBeat);
} else {
fclose($fp);
throw new Exception("Seek failure '{$filename}'");
}
fclose($fp);
if ($data === FALSE) {
throw new Exception("Read failure '{$filename}'");
}
return($data);
} else {
throw new Exception("Open failure '{$filename}'");
}
}
public function writeMp3($filename, $accent, $note) {
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("file", $filename, "w"),
2 => array("file", "/dev/null", "w")
);
// LAME ENCODE
$process = proc_open("/usr/bin/lame -r -s 48.00 -m m -b 16 - -", $descriptorspec, $pipes);
if (is_resource($process)) {
for ($i = 0; $i < $this->nBeats; $i++) {
fwrite($pipes[0], (($i % $this->time_a) == 1) ? $accent : $note);
}
foreach ($descriptorspec as $i => $dsc) {
if (isset($pipes[$i]) && is_resource($pipes[$i])) {
fclose($pipes[$i]);
}
}
proc_close($process);
} else {
throw new Exception("Process open failure");
}
}
public function convert() {
$path = 'sound/'.$this->sound.'/wav';
$accent = $this->readWav($path.'/'.$this->sound.'-accent_ws.wav');
$note = $this->readWav($path.'/'.$this->sound.'-note_ws.wav');
$outfile = tempnam('/tmp', 'snd');
$this->writeMp3($outfile, $accent, $note);
if (file_exists($outfile) && filesize($outfile)) {
return($outfile);
} else {
@unlink($outfile);
throw new Exception("Conversion failure");
}
}
}
try {
$w = new Wav2Mp3('/Bottle_120_4_4_16.mp3');
$filename = $w->convert();
header('Content-Type: audio/mpeg');
header('Content-Disposition: attachment; filename='.basename($filename));
header('Pragma: no-cache');
readfile($filename);
unlink($filename);
} catch (Exception $e) {
die($e->getMessage().PHP_EOL);
}
?>