Это расширение позволяет быстро конвертировать файлы звуковых волн формата PCM в аудиофайлы формата WAV. В настоящее время оно предоставляет решения только для проектов компании.
Расширенная ссылка находится в helviojunior/WaveGenerator, вам отдельное спасибо!
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
и WAV
? PCM
: PCM (импульсно-кодовая модуляция — запись с импульсно-кодовой модуляцией). Так называемая PCM
запись предназначена для преобразования аналоговых сигналов, таких как звук, в символические последовательности импульсов и их последующей записи. Сигнал PCM
представляет собой цифровой сигнал, состоящий из 1
, 0
и других символов без какой-либо обработки кодирования или сжатия. По сравнению с аналоговыми сигналами он менее восприимчив к шуму и искажениям в системе передачи. Динамический диапазон широкий, а качество звука может быть неплохим.
WAV
: WAV
— это формат аудиофайлов без потерь WAV
соответствующий спецификации PIFF (формат файла обмена ресурсами). Все WAV
имеют заголовок файла, который содержит параметры кодирования аудиопотока. WAV не имеет жестких правил кодирования аудиопотоков. Помимо PCM
, почти все кодировки, поддерживающие спецификацию ACM
могут кодировать аудиопотоки WAV.
PCM
и WAV
Проще говоря, PCM
— это исходные данные аудио, а WAV
— это контейнер, инкапсулирующий аудиоданные, и его формат очень прост. Он просто добавляет некоторую информацию заголовка, связанную с аудиоданными, в начале данных.
Во-первых, давайте посмотрим на правила формата WAV, как показано ниже.
Поняв эти правила, мы можем приступить к кодированию.
1. ChunkID
занимает 4 байта, фиксированное значение "RIFF"
$ChunkID = array(0x52, 0x49, 0x46, 0x46); // RIFF 16进制的0x52等于10进制中的82,82对应的ASCII码为R
2. ChunkSize
занимает 4 байта, а значение равно 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size). Если исходные данные — PCM, то оно упрощается до 36 + SubChunk2Size.
$ChunkSize = array(0x0, 0x0, 0x0, 0x0);
$ChunkSize = self::getLittleEndianByteArray(36 + $dataSize);
3. Format
занимает 4 байта, фиксированное значение «WAVE».
$FileFormat = array(0x57, 0x41, 0x56, 0x45); // WAVE
4. Subchunk1ID
занимает 4 байта, фиксированное значение «ftm» (обратите внимание на пробел из 4 цифр)
$Subchunk1ID = array(0x66, 0x6D, 0x74, 0x20); // fmt
5. Subchunk1Size
занимает 4 байта, а когда данные в формате PCM, значение равно 16.
$Subchunk1Size = array(0x10, 0x0, 0x0, 0x0); // 16 little endian
6. AudioFormat
занимает 2 байта. Когда данные имеют формат PCM, значение равно 1. Другие значения указывают на то, что данные каким-либо образом сжаты.
$AudioFormat = array(0x1, 0x0); // PCM = 1 little endian
7. NumChannels
занимает 2 байта, что соответствует ChannelConfig в AudioRecord, Mono = 1, Stereo = 2.
if ($numchannels == 2) {
$fmt->NumChannels = array(0x2, 0x0); // 立体声为2
} else {
$fmt->NumChannels = array(0x1, 0x0); // 单声道为1
}
8. SampleRate
занимает 4 байта, что соответствует значению sampleRateInHz в AudioRecord, которое соответствует частоте дискретизации, например 8000, 16000, 44100.
$SampleRate = self::getLittleEndianByteArray($samplerate);
9. ByteRate
занимает 4 байта, а значение равно SampleRate * BlockAlign.
self::getLittleEndianByteArray($samplerate * $numchannels * ($bitspersample / 8));
10. BlockAlign
занимает 2 байта, а значение NumChannels * BitsPerSample/8
self::getLittleEndianByteArray($numchannels * ($bitspersample / 8), true);
11. BitsPerSample
занимает 2 байта, что соответствует audioFormat в AudioRecord, 8 бит = 8, 16 бит = 16.
self::getLittleEndianByteArray($bitspersample, true);
12. Subchunk2ID
занимает 4 байта, фиксированное значение «данных», т.е.
$Subchunk2ID = array(0x64, 0x61, 0x74, 0x61); // data
13. Subchunk2Size
занимает 4 байта, что описывает длину аудиоданных, то есть размер файла PCM.
self::getLittleEndianByteArray(filesize($filename));
14. Data
составляют байты размера файла PCM, представляющие исходные аудиоданные PCM.
Описание метода getLittleEndianByteArray
getLittleEndianByteArray
в основном обрабатывает переданные числа и преобразует их в данные, которые необходимо использовать. Длина массива будет возвращена в зависимости от количества байтов.
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;
}
Первые 44 байта информации во всем файле были в основном объяснены. Давайте поговорим о реализации файлов классов обработки. Здесь логика обработки сначала временно создает файл размером всего 44 байта, а затем добавляет данные файла PCM
в файл. Наконец, в соответствии с правилами формата WAV, фактическая 44-байтовая информация заголовка фактически вычисляется, и указатель модификации файла указывает на начало файла, а затем изменяется на вновь сгенерированные данные.