Ekstensi ini dapat dengan cepat mengkonversi file gelombang suara format PCM menjadi file audio format WAV. Saat ini, ekstensi ini hanya memberikan solusi untuk proyek perusahaan.
Referensi tambahannya ada di helviojunior/WaveGenerator, terima kasih khusus kepada Anda!
composer require jade/pcm-to-wav
use PcmToWav e P cmToWave ;
$input_file = ' ./file/test.pcm ' ; // 准备输入的文件
$output_file = ' ./file/test.wav ' ; // 预计输出的文件
$data = PcmToWav e::init( $pcm_file , $wav_file ) ; // 调用转换
进入扩展包目录
cd vendor/jade/pcm-to-wav
composer install
cd test
php Test.php
PCM
dan WAV
? PCM
: PCM (Modulasi Kode Pulsa ---- perekaman modulasi kode pulsa). Yang disebut perekaman PCM
adalah mengubah sinyal analog seperti suara menjadi rangkaian pulsa simbolis dan kemudian merekamnya. Sinyal PCM
adalah sinyal digital yang terdiri dari 1
, 0
, dan simbol lainnya tanpa proses pengkodean atau kompresi apa pun. Dibandingkan dengan sinyal analog, sinyal ini kurang rentan terhadap noise dan distorsi pada sistem transmisi. Rentang dinamisnya lebar dan kualitas suaranya cukup bagus.
WAV
: WAV
adalah format file audio lossless. WAV
mematuhi spesifikasi PIFF (Resource Interchange File Format). Semua WAV
memiliki header file, yang berisi parameter pengkodean aliran audio. WAV tidak memiliki aturan tegas dan cepat untuk menyandikan aliran audio Selain PCM
, hampir semua penyandian yang mendukung spesifikasi ACM
dapat menyandikan aliran audio WAV.
PCM
dan WAV
Sederhananya, PCM
adalah data asli audio, dan WAV
adalah wadah yang merangkum data audio, dan formatnya sangat sederhana, hanya menambahkan beberapa informasi header terkait data audio di awal data.
Pertama, mari kita lihat aturan format WAV, seperti gambar di bawah ini
Setelah memahami aturan-aturan ini, kita bisa mulai coding
1. ChunkID
menempati 4 byte, nilai tetap "RIFF"
$ChunkID = array(0x52, 0x49, 0x46, 0x46); // RIFF 16进制的0x52等于10进制中的82,82对应的ASCII码为R
2. ChunkSize
menempati 4 byte, dan nilainya adalah 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size).
$ChunkSize = array(0x0, 0x0, 0x0, 0x0);
$ChunkSize = self::getLittleEndianByteArray(36 + $dataSize);
3. Format
menempati 4byte, nilai tetap "WAVE"
$FileFormat = array(0x57, 0x41, 0x56, 0x45); // WAVE
4. Subchunk1ID
menempati 4 byte, nilai tetap "ftm" (perhatikan penyelesaian spasi 4 digit)
$Subchunk1ID = array(0x66, 0x6D, 0x74, 0x20); // fmt
5. Subchunk1Size
menempati 4byte, dan jika datanya PCM, nilainya 16
$Subchunk1Size = array(0x10, 0x0, 0x0, 0x0); // 16 little endian
6. AudioFormat
menempati 2 byte. Jika datanya adalah PCM, nilainya adalah 1. Nilai lain menunjukkan bahwa data telah dikompresi dengan cara tertentu.
$AudioFormat = array(0x1, 0x0); // PCM = 1 little endian
7. NumChannels
menempati 2 byte, sesuai dengan channelConfig di AudioRecord, Mono = 1, Stereo = 2
if ($numchannels == 2) {
$fmt->NumChannels = array(0x2, 0x0); // 立体声为2
} else {
$fmt->NumChannels = array(0x1, 0x0); // 单声道为1
}
8. SampleRate
menempati 4 byte, sesuai dengan sampleRateInHz di AudioRecord, yang merupakan frekuensi pengambilan sampel, seperti 8000, 16000, 44100
$SampleRate = self::getLittleEndianByteArray($samplerate);
9. ByteRate
menempati 4byte, dan nilainya adalah SampleRate * BlockAlign
self::getLittleEndianByteArray($samplerate * $numchannels * ($bitspersample / 8));
10. BlockAlign
menempati 2 byte, dan nilainya adalah NumChannels * BitsPerSample / 8
self::getLittleEndianByteArray($numchannels * ($bitspersample / 8), true);
11. BitsPerSample
menempati 2byte, sesuai dengan audioFormat di AudioRecord, 8bits = 8, 16bits = 16
self::getLittleEndianByteArray($bitspersample, true);
12. Subchunk2ID
menempati 4byte, nilai tetap "data", yaitu
$Subchunk2ID = array(0x64, 0x61, 0x74, 0x61); // data
13. Subchunk2Size
menempati 4byte, yang menggambarkan panjang data audio, yaitu ukuran file pcm.
self::getLittleEndianByteArray(filesize($filename));
14. Data
menyumbang byte ukuran file pcm, mewakili data audio PCM asli.
deskripsi metode getLittleEndianByteArray
getLittleEndianByteArray
terutama memproses angka yang diteruskan dan mengubahnya menjadi data yang perlu digunakan. Panjang array akan dikembalikan berdasarkan jumlah byte.
private static function getLittleEndianByteArray($lValue, $short = false)
{
$b = array(0, 0, 0, 0);
$running = $lValue / pow(16, 6);
$b[3] = floor($running);
$running -= $b[3];
$running *= 256;
$b[2] = floor($running);
$running -= $b[2];
$running *= 256;
$b[1] = floor($running);
$running -= $b[1];
$running *= 256;
$b[0] = round($running);
if ($short) { // 为 `true` 时返回长度为2的数组
$tmp = array_slice($b, 0, 2);
$b = $tmp;
}
return $b;
}
Informasi 44 byte pertama di seluruh file pada dasarnya telah dijelaskan. Mari kita bicara tentang implementasi pemrosesan file kelas. Logika pemrosesan di sini pertama-tama membuat file dengan hanya 44 byte untuk sementara, dan kemudian menambahkan data file PCM
ke dalam file tersebut. Terakhir, menurut aturan format WAV, informasi header 44-byte sebenarnya dihitung dan penunjuk modifikasi file menunjuk ke awal file, dan kemudian dimodifikasi ke data yang baru dihasilkan.