이 확장 프로그램은 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(Resource Interchange File Format) 사양을 준수합니다. 모든 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
4byte를 차지하며 고정값은 "WAVE"이다.
$FileFormat = array(0x57, 0x41, 0x56, 0x45); // WAVE
4. Subchunk1ID
4바이트를 차지하며 고정값 "ftm"(4자리 공백 완성에 유의)
$Subchunk1ID = array(0x66, 0x6D, 0x74, 0x20); // fmt
5. Subchunk1Size
4byte를 차지하며, 데이터가 PCM일 경우 값은 16이다.
$Subchunk1Size = array(0x10, 0x0, 0x0, 0x0); // 16 little endian
6. AudioFormat
데이터가 PCM인 경우 2바이트를 차지하며, 다른 값은 데이터가 어떤 방식으로든 압축되었음을 나타냅니다.
$AudioFormat = array(0x1, 0x0); // PCM = 1 little endian
7. NumChannels
AudioRecord의 채널 구성에 해당하는 2바이트를 차지합니다. 모노 = 1, 스테레오 = 2
if ($numchannels == 2) {
$fmt->NumChannels = array(0x2, 0x0); // 立体声为2
} else {
$fmt->NumChannels = array(0x1, 0x0); // 单声道为1
}
8. SampleRate
8000, 16000, 44100과 같은 샘플링 주파수인 AudioRecord의 SampleRateInHz에 해당하는 4바이트를 차지합니다.
$SampleRate = self::getLittleEndianByteArray($samplerate);
9. ByteRate
4byte를 차지하고, 값은 SampleRate * BlockAlign이다.
self::getLittleEndianByteArray($samplerate * $numchannels * ($bitspersample / 8));
10. BlockAlign
2바이트를 차지하고 값은 NumChannels * BitsPerSample / 8입니다.
self::getLittleEndianByteArray($numchannels * ($bitspersample / 8), true);
11. BitsPerSample
AudioRecord의 audioFormat에 해당하는 2바이트를 차지합니다. 8비트 = 8, 16비트 = 16
self::getLittleEndianByteArray($bitspersample, true);
12. Subchunk2ID
고정값 "data"인 4바이트를 차지합니다.
$Subchunk2ID = array(0x64, 0x61, 0x74, 0x61); // data
13. Subchunk2Size
오디오 데이터의 길이를 나타내는 4byte를 차지하는데, 이는 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바이트 정보가 실제로 계산되고 파일 수정 포인터가 파일의 시작 부분을 가리킨 다음 새로 생성된 데이터로 수정됩니다.