サーバー上のmp3ファイルをチェックして結果を取得するためのコードを作成していますが、それらの一部に誤った同期があるかどうかがわかります。要するに、私はfread()関数を使用してPHPでこれらのファイルをロードし、変数でストリームを取得しています。そのストリームを分割して、id3v1(不要、同期の対象ではありません)、id3v2(主な問題)、およびオーディオの個別のストリームを取得した後、id3v2ストリームに対してそのスキームを実装する必要があります。
ID3v2の公式ドキュメントによると:
「非同期スキーム」の唯一の目的は、ID3v2タグを既存のソフトウェアと可能な限り互換性のあるものにすることです。ファイルが新しいソフトウェアによってのみ処理される場合は、「非同期」タグは使用できません。非同期化は、MPEG 2レイヤーI、II、IIIおよびMPEG2.5ファイルでのみ行うことができます。
タグ内で誤った同期が検出されると、最初の誤った同期バイトの後に1つのゼロ化されたバイトが挿入されます。ID3エンコーダーによって変更される必要がある正しい同期の形式は次のとおりです。
%11111111 111xxxxx
そして、次のように置き換える必要があります。
%11111111 00000000 111xxxxx
これには、すべての$ FF 00の組み合わせを変更する必要があるという副作用があるため、デコードプロセスの影響を受けません。したがって、非同期化中に、すべての$FF00の組み合わせを$FF0000の組み合わせに置き換える必要があります。
非同期の使用法を示すには、「ID3フラグ」の最初のビットを設定する必要があります(注:そのビットを見つけました)。このビットは、タグに修正された誤った同期が含まれている場合にのみ設定する必要があります。タグに誤った同期が含まれていない場合にのみ、ビットをクリアする必要があります。
エンコーダで圧縮方式を使用する場合は、後で非同期方式を適用する必要があることに注意してください。圧縮された「非同期」ファイルをデコードするときは、「非同期スキーム」を最初に解析し、後で解凍する必要があります。
私の質問は次のとおりです。
- このビットパターンを検索して置き換える方法
%11111111 111xxxxx
は%11111111 00000000 111xxxxx
? - 逆に、このビットパターンを検索して置き換える方法
%11111111 00000000 111xxxxx
は%11111111 111xxxxx
?
... preg_replace()を使用します。
これまでに作成したコードは完全に機能し、あと1行しかありません(正確には2行です)。
<?php
// some basic checkings here, such as 'does file exist'
// and 'is it readable'
$f = fopen('test.mp3', 'r');
// ...rest of my code...
$pattern1 = '?????'; // pattern from 1st question
$id3stream = preg_replace($pattern1, 'something1', $id3stream);
// ...extracting frames...
$pattern1 = '?????'; // pattern from 2nd question
$id3stream = preg_replace($pattern2, 'something2', $id3stream);
// ..do more job...
fclose($f);
?>
preg_replace()関数を使用してこれらの2行を機能させる方法は?
PS私はある種のループでバイトごとにそれを読み取る方法を知っていますが、これは正規表現を使用して可能であると確信しています(ところで、正直なところ、私は正規表現を吸います)。
詳細が必要な場合はお知らせください。
もう一つ...
現在、このパターンを使用しています
$pattern0 = '/[\x00].*/';
echo preg_replace($pattern0, '', $input_string);
最初のゼロバイトから最後まで文字列の一部を切り取ります。これを行うための正しい方法ですか?
アップデート
(@マリオの答え)。
最初の数回のテストで...このコードは正しい結果を返しました。
// print original stream
printStreamHex($stream_original, 'ORIGINAL STREAM');
// adding zero pads on unsync scheme
$stream_1 = preg_replace(':([\\xFF])([\\xE0-\\xFF]):', "$1\x00$2", $stream_original);
printStreamHex($stream_1, 'AFTER ADDING ZEROS');
// reversing process
$stream_2 = preg_replace(':([\\xFF])([\\x00])([\\xE0-\\xFF]):', "$1$3", $stream_1);
printStreamHex($stream_2, 'AFTER REMOVING ZEROS');
echo "Status: <b>" . ($stream_original == $stream_2 ? "OK" : "Failed") . "</b>";
しかし、数分後、すべてが期待どおりの結果のように見えても、ストリームにFFE0+ペアが残っている特定のケースを見つけました。
ORIGINAL STREAM
+-----------------------------------------------------------------+
| FF E0 DB 49 53 BE 3B E0 90 40 EA 2B 3A 61 FF FA |
| 84 E0 A9 99 1F 39 B5 E1 54 FF E7 ED B8 B1 3A 36 |
| 88 01 69 CA 7D 47 FA E1 70 7C 85 34 B8 1A FF FF |
| FF F8 21 F9 2F FF F7 17 67 EB 2A EB 6E 41 82 FF |
+-----------------------------------------------------------------+
AFTER ADDING ZEROS
+-----------------------------------------------------------------+
| FF 00 E0 DB 49 53 BE 3B E0 90 40 EA 2B 3A 61 FF |
| 00 FA 84 E0 A9 99 1F 39 B5 E1 54 FF 00 E7 ED B8 |
| B1 3A 36 88 01 69 CA 7D 47 FA E1 70 7C 85 34 B8 |
| 1A FF 00 FF FF 00 F8 21 F9 2F FF 00 F7 17 67 EB |
| 2A EB 6E 41 82 FF |
+-----------------------------------------------------------------+
AFTER REMOVING ZEROS
+-----------------------------------------------------------------+
| FF E0 DB 49 53 BE 3B E0 90 40 EA 2B 3A 61 FF FA |
| 84 E0 A9 99 1F 39 B5 E1 54 FF E7 ED B8 B1 3A 36 |
| 88 01 69 CA 7D 47 FA E1 70 7C 85 34 B8 1A FF FF |
| FF F8 21 F9 2F FF F7 17 67 EB 2A EB 6E 41 82 FF |
+-----------------------------------------------------------------+
Status: OK
ストリームに次のようなFF FF FF FF
ものが含まれている場合は、に置き換えられますFF 00 FF FF 00 FF
が、である必要がありますFF 00 FF 00 FF 00 FF
。そのFF FF
ペアは再びmp3同期を誤ってしまうので、私の使命はFFE0+
オーディオストリームの前にすべてのパターンを回避することです(ID3v2タグストリームで。mp3はFFE0+
バイトペアで始まり、オーディオデータの最初に最初に出現する必要があるため)。FFE0 +バイトペアなしでストリームを取得するまで、同じ正規表現をループできることがわかりました。ループを必要としない解決策はありますか?
素晴らしい仕事@マリオ、どうもありがとう!