PHP MP3 ID3

  • wphilipw
  • Student
  • Student
  • No Avatar
  • Registrado: Jun 29, 2006
  • Mensajes: 87
  • Loc: PA, US
  • Status: Offline

Nota Marzo 18th, 2008, 1:45 pm

He estado trabajando en el lector un MP3 ID3 tag, y por ahora sólo lee ID3v1 que está bien, pero cuando estoy teniendo un problema con la etiqueta de APIC (integrado imagen de la placa) por cualquier razón no puedo conseguir un tamaño exacto en ella, y no puedo averiguar dónde está mi error, funciona muy bien para leer las etiquetas de otros en el MP3, pero no el APIC, se detiene a medio camino a través de algunas imágenes y como el 90% a través de otros...Realmente no lo entiendo, y sé que la mente múltiples tipo mejor que uno, es así, ¿alguien se lo suficiente como para mirar a través de esto y decirme dónde está mi error? gracias!
Código: [ Select ]
function shift7_8($num) {
$num_1 = bindec(str_pad(substr($num, 0, 4), 8, "0", STR_PAD_LEFT));
$num_2 = bindec(substr($num, 4, 8));
$num_3 = bindec(substr($num, 12, 8));
$num_4 = bindec(substr($num, 20, 8));
$num = $num_1 . $num_2 . $num_3 . $num_4;
unset($num_1, $num_2, $num_3, $num_4);
return $num;
}

function id3_read($file) {
// BEGIN ID3 READ

// OPEN MP3 FILE
$mp3 = fopen($file, "r");

// ID3 HEADER READ

// READ THE "ALWAYS PRESENT "ID3"
$id3['base'] = fread($mp3, 3);
// GET THE HEX ID3 VERSION AND CONVERT IT
$id3['version'] = "";
for ($x = 0; $x < 2; $x++) {
$id3['version'] .= str_pad(dechex(ord(fread($mp3, 1))), 2, "0", STR_PAD_LEFT);
}
$id3['version'] = str_split($id3['version']);
if ($id3['version'][0] == "0") { $id3['version'][0] = ""; }
if ($id3['version'][2] == "0") { $id3['version'][2] = ""; }
$id3['version'] = "2." . $id3['version'][0] . $id3['version'][1] . "." . $id3['version'][2] . $id3['version'][3];
// GET THE ID3 BINARY FLAGS - STANDARDS STORED IN FIRST 4 BITES
for ($x = 0; $x < 1; $x++) {
$id3['flags'] = str_pad(decbin(ord(fread($mp3, 1))), 8, "0", STR_PAD_LEFT);
}
$id3['flags'] = str_split($id3['flags']);
// GET THE 4 ID3 SIZE BYTES AND CONVERT THEM TO 8 BIT NUMBERS.
$id3['size'] = "";
for ($x = 0; $x < 4; $x++) {
$id3['size'] .= str_pad(decbin(ord(fread($mp3, 1))), 8, "0", STR_PAD_LEFT);
}
$id3['size'] = shift7_8($id3['size']);

// IF THERE IS AN EXTENDED HEADER, SKIP IT
if ($id3_['flags'][1] == 1) {
// GET THE 4 ID3 EXT HEADER SIZE BYTES AND CONVERT THEM TO 8 BIT NUMBERS.
$id3_exthead_size = "";
for ($x = 0; $x < 4; $x++) {
$id3_exthead_size .= str_pad(decbin(ord(fread($mp3, 1))), 7, "0", STR_PAD_LEFT);
}
$id3_exthead_size = shift7_8($id3_exthead_size);
// SKIP THE EXT HEADER
$tmp = fread($mp3, ($id3_exthead_size - 4));
unset($tmp, $id3_exthead_size);
}

// READ FRAME HEADERS AND LOAD FRAMES INTO ARRAY
$v = 0;
$r = 0;
while ($v < $id3['size']) {
// GET FRAME ID
$id3['frames'][$r]['id'] = "";
for ($x = 0; $x < 4; $x++) {
$id3['frames'][$r]['id'] .= chr(hexdec(str_pad(dechex(ord(fread($mp3, 1))), 2, "0", STR_PAD_LEFT)));
}
if (!preg_match('/[A-Z0-9][A-Z0-9][A-Z0-9][A-Z0-9]/', $id3['frames'][$r]['id']) || $id3['frames'][$r]['id'] == "") {
unset ($id3['frames'][$r]);
break;
break;
}
// GET THE 4 FRAME SIZE BYTES AND CONVERT THEM TO 8 BIT NUMBERS.
$id3['frames'][$r]['size'] = "";
for ($x = 0; $x < 4; $x++) {
$id3['frames'][$r]['size'] .= str_pad(decbin(ord(fread($mp3, 1))), 7, "0", STR_PAD_LEFT);
}
$id3['frames'][$r]['size'] = shift7_8($id3['frames'][$r]['size']);
echo $id3['frames'][$r]['size'];
// GET THE 2 FRAME FLAG BYTES
$id3['frames'][$r]['flags'] = "";
for ($x = 0; $x < 2; $x++) {
$id3['frames'][$r]['flags'] .= str_pad(dechex(ord(fread($mp3, 1))), 2, "0", STR_PAD_LEFT);
}
// SKIP A BYTE - (TEXT ENCODING)...
$temp = fread($mp3, 1);
unset($temp);
// IF NOT APIC, THEN GET THE FRAME CONTENT
if ($id3['frames'][$r]['id'] != "APIC") {
$id3['frames'][$r]['content'] = fread($mp3, ($id3['frames'][$r]['size'] - 1));
} else {
$tmp = fread($mp3, 1);
while (str_pad(dechex(ord($tmp)), 2, "0", STR_PAD_LEFT) != "00") {
$id3['frames'][$r]['mime'] .= $tmp;
$id3['frames'][$r]['size'] = $id3['frames'][$r]['size'] - 1;
$tmp = fread($mp3, 1);
}
echo $id3['frames'][$r]['size'];
$id3['frames'][$r]['picture_type'] = fread($mp3, 1);
$id3['frames'][$r]['size'] = $id3['frames'][$r]['size'] - 2;
$tmp = fread($mp3, 1);
while (str_pad(dechex(ord($tmp)), 2, "0", STR_PAD_LEFT) != "00") {
$id3['frames'][$r]['description'] .= $tmp;
$id3['frames'][$r]['size'] = $id3['frames'][$r]['size'] - 1;
$tmp = fread($mp3, 1);
}
unset ($tmp);
$id3['frames'][$r]['size'] = $id3['frames'][$r]['size'] - 1;
$id3['frames'][$r]['content'] = fread($mp3, ($id3['frames'][$r]['size']));
}
// INCREMENT FRAME NUMBER AND START OVER
$v = $v + 10 + $id3['frames'][$r]['size'];
$r++;
}
// END ID3 READ

// CLOSE MP3 FILE & RETURN VALUES
fclose($mp3);
return $id3;
}
  1. function shift7_8($num) {
  2. $num_1 = bindec(str_pad(substr($num, 0, 4), 8, "0", STR_PAD_LEFT));
  3. $num_2 = bindec(substr($num, 4, 8));
  4. $num_3 = bindec(substr($num, 12, 8));
  5. $num_4 = bindec(substr($num, 20, 8));
  6. $num = $num_1 . $num_2 . $num_3 . $num_4;
  7. unset($num_1, $num_2, $num_3, $num_4);
  8. return $num;
  9. }
  10. function id3_read($file) {
  11. // BEGIN ID3 READ
  12. // OPEN MP3 FILE
  13. $mp3 = fopen($file, "r");
  14. // ID3 HEADER READ
  15. // READ THE "ALWAYS PRESENT "ID3"
  16. $id3['base'] = fread($mp3, 3);
  17. // GET THE HEX ID3 VERSION AND CONVERT IT
  18. $id3['version'] = "";
  19. for ($x = 0; $x < 2; $x++) {
  20. $id3['version'] .= str_pad(dechex(ord(fread($mp3, 1))), 2, "0", STR_PAD_LEFT);
  21. }
  22. $id3['version'] = str_split($id3['version']);
  23. if ($id3['version'][0] == "0") { $id3['version'][0] = ""; }
  24. if ($id3['version'][2] == "0") { $id3['version'][2] = ""; }
  25. $id3['version'] = "2." . $id3['version'][0] . $id3['version'][1] . "." . $id3['version'][2] . $id3['version'][3];
  26. // GET THE ID3 BINARY FLAGS - STANDARDS STORED IN FIRST 4 BITES
  27. for ($x = 0; $x < 1; $x++) {
  28. $id3['flags'] = str_pad(decbin(ord(fread($mp3, 1))), 8, "0", STR_PAD_LEFT);
  29. }
  30. $id3['flags'] = str_split($id3['flags']);
  31. // GET THE 4 ID3 SIZE BYTES AND CONVERT THEM TO 8 BIT NUMBERS.
  32. $id3['size'] = "";
  33. for ($x = 0; $x < 4; $x++) {
  34. $id3['size'] .= str_pad(decbin(ord(fread($mp3, 1))), 8, "0", STR_PAD_LEFT);
  35. }
  36. $id3['size'] = shift7_8($id3['size']);
  37. // IF THERE IS AN EXTENDED HEADER, SKIP IT
  38. if ($id3_['flags'][1] == 1) {
  39. // GET THE 4 ID3 EXT HEADER SIZE BYTES AND CONVERT THEM TO 8 BIT NUMBERS.
  40. $id3_exthead_size = "";
  41. for ($x = 0; $x < 4; $x++) {
  42. $id3_exthead_size .= str_pad(decbin(ord(fread($mp3, 1))), 7, "0", STR_PAD_LEFT);
  43. }
  44. $id3_exthead_size = shift7_8($id3_exthead_size);
  45. // SKIP THE EXT HEADER
  46. $tmp = fread($mp3, ($id3_exthead_size - 4));
  47. unset($tmp, $id3_exthead_size);
  48. }
  49. // READ FRAME HEADERS AND LOAD FRAMES INTO ARRAY
  50. $v = 0;
  51. $r = 0;
  52. while ($v < $id3['size']) {
  53. // GET FRAME ID
  54. $id3['frames'][$r]['id'] = "";
  55. for ($x = 0; $x < 4; $x++) {
  56. $id3['frames'][$r]['id'] .= chr(hexdec(str_pad(dechex(ord(fread($mp3, 1))), 2, "0", STR_PAD_LEFT)));
  57. }
  58. if (!preg_match('/[A-Z0-9][A-Z0-9][A-Z0-9][A-Z0-9]/', $id3['frames'][$r]['id']) || $id3['frames'][$r]['id'] == "") {
  59. unset ($id3['frames'][$r]);
  60. break;
  61. break;
  62. }
  63. // GET THE 4 FRAME SIZE BYTES AND CONVERT THEM TO 8 BIT NUMBERS.
  64. $id3['frames'][$r]['size'] = "";
  65. for ($x = 0; $x < 4; $x++) {
  66. $id3['frames'][$r]['size'] .= str_pad(decbin(ord(fread($mp3, 1))), 7, "0", STR_PAD_LEFT);
  67. }
  68. $id3['frames'][$r]['size'] = shift7_8($id3['frames'][$r]['size']);
  69. echo $id3['frames'][$r]['size'];
  70. // GET THE 2 FRAME FLAG BYTES
  71. $id3['frames'][$r]['flags'] = "";
  72. for ($x = 0; $x < 2; $x++) {
  73. $id3['frames'][$r]['flags'] .= str_pad(dechex(ord(fread($mp3, 1))), 2, "0", STR_PAD_LEFT);
  74. }
  75. // SKIP A BYTE - (TEXT ENCODING)...
  76. $temp = fread($mp3, 1);
  77. unset($temp);
  78. // IF NOT APIC, THEN GET THE FRAME CONTENT
  79. if ($id3['frames'][$r]['id'] != "APIC") {
  80. $id3['frames'][$r]['content'] = fread($mp3, ($id3['frames'][$r]['size'] - 1));
  81. } else {
  82. $tmp = fread($mp3, 1);
  83. while (str_pad(dechex(ord($tmp)), 2, "0", STR_PAD_LEFT) != "00") {
  84. $id3['frames'][$r]['mime'] .= $tmp;
  85. $id3['frames'][$r]['size'] = $id3['frames'][$r]['size'] - 1;
  86. $tmp = fread($mp3, 1);
  87. }
  88. echo $id3['frames'][$r]['size'];
  89. $id3['frames'][$r]['picture_type'] = fread($mp3, 1);
  90. $id3['frames'][$r]['size'] = $id3['frames'][$r]['size'] - 2;
  91. $tmp = fread($mp3, 1);
  92. while (str_pad(dechex(ord($tmp)), 2, "0", STR_PAD_LEFT) != "00") {
  93. $id3['frames'][$r]['description'] .= $tmp;
  94. $id3['frames'][$r]['size'] = $id3['frames'][$r]['size'] - 1;
  95. $tmp = fread($mp3, 1);
  96. }
  97. unset ($tmp);
  98. $id3['frames'][$r]['size'] = $id3['frames'][$r]['size'] - 1;
  99. $id3['frames'][$r]['content'] = fread($mp3, ($id3['frames'][$r]['size']));
  100. }
  101. // INCREMENT FRAME NUMBER AND START OVER
  102. $v = $v + 10 + $id3['frames'][$r]['size'];
  103. $r++;
  104. }
  105. // END ID3 READ
  106. // CLOSE MP3 FILE & RETURN VALUES
  107. fclose($mp3);
  108. return $id3;
  109. }

gracias de nuevo a todos y cada uno que eche un vistazo a esto.
  • Anonymous
  • Bot
  • No Avatar
  • Registrado: 25 Feb 2008
  • Mensajes: ?
  • Loc: Ozzuland
  • Status: Online

Nota Marzo 18th, 2008, 1:45 pm

  • wphilipw
  • Student
  • Student
  • No Avatar
  • Registrado: Jun 29, 2006
  • Mensajes: 87
  • Loc: PA, US
  • Status: Offline

Nota Marzo 20th, 2008, 3:01 pm

BTW, resuelto!
  • phreak2day
  • Born
  • Born
  • No Avatar
  • Registrado: Sep 06, 2010
  • Mensajes: 1
  • Status: Offline

Nota Septiembre 7th, 2010, 4:29 am

¡Hola! Tengo el mismo problema y he estado golpeando mi cabeza contra la pared durante más de 2 meses y no he encontrado una solución. ¿Me podría decir, si usted recuerda, lo que hizo para resolver el problema? Sigo recibiendo pegado leyendo el marco de APIC, quiere evitar por completo, pero me parece que no puede omitirlo durante el proceso de lectura. Este programa que estoy escribiendo es para un examen que tengo y que necesito para terminar en los próximos días lo antes posible lo que voy a estar muy agradecidos por cualquier ayuda que puede dar.



EDIT:

Solucionado! Al menos, parece ser. :P
OK, así que para cualquier otra persona que pueda tener este problema en el futuro (la manera de dejar de leer el marco APIC), esto es lo que estaba haciendo y cómo lo resolvió.

Lo que estaba haciendo:
En el sitio oficial (id3 <dot> org), que es HORRIBLE , Dice que "El tamaño de la etiqueta ID3v2 está codificado con cuatro bytes, donde el bit más significannot (bit 7) está ajustado a cero en cada byte, haciendo un total de 28 bits. Los bits a cero se ignoran...". Tomé esa lógica y appyed al leer el tamaño de la etiqueta y todos los tamaños de marco. Para ponerlo en código que yo estaba haciendo esto:
<C #> Fragmento
sizeOfTheTag int = wich tamaño es <el read> ;
readerPosition int;
tagByteArray byte [] = new byte [sizeOfTheTag];
/ /...
/ / Cuando el marco APIC ID que se encuentra (esto fue en una función, pero todo se reduce a esto):
frameSize = ((tagByteArray [readerPosition] <<21) | (tagByteArray [readerPosition + 1] <<14) | (tagByteArray readerPosition [+ 2] <<7) | (tagByteArray [readerPosition + 3]));
readerPosition + = frameSize; / / (intentar) saltarse el marco APIC
/ / No!

¿Cómo lo resolví:
Me pasaba horas y horas tratando de encontrar el origen del problema fue así que comencé a leer un archivo mp3 en vista hexagonal con Notepad + + y comparar sus posiciones marco con el tamaño que tengo de leer el modo indicado. Entonces me volví la vista a binario y tryed para hacer una transformación manual del tamaño de marco APIC. Hacerlo en el modo indicado (como el sitio oficial de los estados) se ve así:
/ / Un tamaño de ejemplo se lee en forma binaria como esto:
00000000 | 00000011 | 00111001 | 01000011
/ / Entonces dejamos de lado todos los bits primero y sale esto:
_0000000 | _0000011 | _0111001 | _1000011
/ / Y entonces todo es "apretados" y conseguir que:
____0000 | 00000000 | 11011100 | 11000011
/ / Cuando se convierte en un número decimal se obtiene:
56515

Eso offcourse,, era demasiado pequeña y la posición de lector de mantenerse caer en el marco de APIC. Así que traté de obtener el tamaño de fotograma a no ignorar el primer bit, así:
/ / El tamaño mismo ejemplo se lee en forma binaria como esto:
00000000 | 00000011 | 00111001 | 01000011
/ / Cuando nosotros no ignorar todos los primer bit que sale esto:
00000000 | 00000011 | 00111001 | 01000011
/ / Y cuando todo está "apretados" y obtenemos:
00000000 | 00000011 | 00111001 | 01000011
/ / Y luego cuando se convierte en un número decimal se obtiene:
211267

Eso es una gran diferencia! Y ahora puede leer fácilmente el tamaño del marco de la APIC y pasar por alto que, por ahora. Tal vez más tarde malos tratar de leer / cambiarlo. gif "alt = =":)" título" Smile "> Así, el nuevo código para leer el tamaño es:
<C #> Fragmento
frameSize = ((tagByteArray [readerPosition] <<24) | (tagByteArray [readerPosition + 1] <<16) | (tagByteArray [readerPosition + 2] <<8) | (tagByteArray [readerPosition + 3]));
Todo lo demás sigue igual.

Espero que esto ayudará a todos los demás que se este problema para que no tengas que perder tanto tiempo como yo. Lo único que no sé es por qué esto no ha efectuado la lectura de todos los tamaños de otro marco. Pero a quién le importa cuando funciona, ¿no? ;)



Si tropieza con algún problema malos agregar un comentario. ;)

Publicar Información

  • Total de mensajes en este tema: 3 mensajes
  • Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 123 invitados
  • No puede abrir nuevos temas en este Foro
  • No puede responder a temas en este Foro
  • No puede editar sus mensajes en este Foro
  • No puede borrar sus mensajes en este Foro
  • No puede enviar adjuntos en este Foro
 
 

© 2011 Unmelted, LLC. Ozzu® es una marca registrada de Unmelted, LLC