Xwork's Blog

The lord is waiting to take your hand.

Vamos a programar #54 - ID3 y LUA.

No hay comentarios.
Hola de nuevo a todos, el día de hoy vamos a ver código en LUA que sirve para extraer las imágenes embebidas en un MP3. No es lo lo más optimizado, pero a veces lo que cuenta es conseguir nuestro objetivo.


Antes de continuar, es recomendable que leas uno de los post antiguos del blog en cual se explica cómo hacer de manera "artesanal" todo el procedimiento, a veces ayuda un poco saber exactamente que es lo que vamos a hacer para comprender.

Para poder probar el código vamos a necesitar un interprete de LUA para windows (o para PC con cualquier sistema operativo). Si usas windows al igual que yo, recomiendo usar ZeroBrane Studio, es gratuito para todos pero el autor muestra links para donaciones (si puedes apoyarlo hazlo, siempre le cae bien una bebida a cualquier programador independiente). ZeroBrane además de contener el interprete de lua, es un IDE que sirve para depurar código. Es muy importante instalar localmente una copia del interprete para poder abrir los archivos desde nuestro disco duro.

El código.

Con el interprete ya instalado veamos el código.

-----------De la documentación disponible en http://www.id3.org para la versión 2---------------
--[[
Para la version 2.2
	Header for 'Attached picture', ID: "APIC">
	Text encoding   $xx
	MIME type       <text string> $00
	Picture type    $xx
	Description     <text string according to encoding> $00 (00)
	Picture data    <binary data>
Para la version 2.0
	Attached picture   "PIC"
	Frame size         $xx xx xx
	Text encoding      $xx
	Image format       $xx xx xx
	Picture type       $xx
	Description        <textstring> $00 (00)
	Picture data       <binary data>
]]
function WriteImage(NombreDeLaCancion,NombreDeLaImagen)
--Abrimos el archivo en modo de lectura binario
	local Rdata = io.open(NombreDeLaCancion,"rb")
--Ponemos el puntero al inicio del archivo
	Rdata:seek("set")
--Ahora leemos los primeros 1024b del archivo, si no encontramos aquí la etiqueta "APIC" o "PIC" asumimos que el archivo no tiene imagen embebida
	local Sdata = Rdata:read(1024)
--En esta variable Guardaremos la ubicación del La etiqueta "APIC"
	local GotIt = string.find(Sdata,"APIC")
--Si GotIt es nil en este punto, buscamos la etiqueta PIC
	if GotIt == nil then
		GotIt = string.find(Sdata,"PIC")
	end
--
--Si la variable GotIt tiene cualquier valor diferente de nil; procedemos a buscar el tipo de imagen que este embebida.
	if GotIt ~= nil then
		local GotPNG =string.find(Sdata,string.char(137)..string.char(80)..string.char(78)..string.char(71))
	--Obtenemos la versión
		local GetVer = string.find(Sdata,"APIC")
--La comprobación es simple ya llegados a este punto; si uno es falso el otro debe de ser verdadero.		
--Regresamos el puntero a la posición en donde se encontró la etiqueta APIC y leemos la longitud de la etiqueta
		local b1,b2,b3,b4
		local TagSize	
		if GetVer ~= nil then
			Rdata:seek("set",GotIt+3)
			b1=string.byte(Rdata:read(1))*256*256*256
			b2=string.byte(Rdata:read(1))*256*256
			b3=string.byte(Rdata:read(1))*256
			b4=string.byte(Rdata:read(1))
			TagSize = b1+b2+b3+b4+10
		else
			Rdata:seek("set",GotIt+2)
			b1=string.byte(Rdata:read(1))*256*256
			b2=string.byte(Rdata:read(1))*256
			b3=string.byte(Rdata:read(1))
			TagSize = b1+b2+b3+5
		end
--Si los datos dicen que la imagen es JPG
		if GotPNG  == nil then
			local JPicInit = string.find(Sdata,string.char(255)..string.char(216)..string.char(255))
			Rdata:seek("set",JPicInit-1)
			IMGData = Rdata:read(TagSize-(JPicInit-GotIt))
			local MPImg = io.open(NombreDeLaImagen..".jpg","wb")
			MPImg:write(IMGData)
			MPImg:flush()
			MPImg:close()
			MPImg=nil
		else
			local PPicInit = string.find(Sdata,string.char(137).."PNG")
			local TagDMP
			if GetVer then
				TagDMP=8
			else
				TagDMP=6
			end
			Rdata:seek("set",PPicInit-1)
			local IMGData = Rdata:read(TagSize-(PPicInit-GotIt))
			MPImg = io.open(NombreDeLaImagen..".png","wb")
			MPImg:write(IMGData)
			MPImg:flush()
			MPImg:close()
			MPImg=nil
		end
	end
	Rdata:close()
	Rdata = nil
end

print("Inserta la ubicacion de un mp3")
local FILE = io.read();
print("Inserta un nombre de archivo")
local SavePlace = io.read();
WriteImage(FILE, SavePlace);

Primero que nada, LUA dispone de funciones de lectura y escritura bastante similares a los de C. Para usar un lector, debemos de iniciarlo pasando dos parámetros, uno de ellos es el archivo que queremos leer (o nuestra canción) y el segundo parámetro es el modo en cual se abrirá; en este caso, usamos "rb" que indicará que leeremos el archivo de forma "binaria".

Al igual que en C, disponemos de una función que sirve para desplazarnos en el archivo que tenemos abierto. Antes de continuar, hay que aclarar algo; LUA no es un lenguaje orientado a objetos pero tiene una sintaxis que ayuda a simularlo y para el código anterior es lo mismo "Rdata:seek("set");" que "Rdata = io.seek("set");" y lo mismo para todos los procedimiento provenientes de cualquier "clase" así que una vez que se inicializa una variable del tipo "io", podemos usar el nombre que le dimos seguido de dos puntos para acceder a los sub-métodos. Entonces, usando "seek" sin ningún parámetro adicional a "set", le indicamos que queremos mover el puntero al inicio del archivo (byte cero)

Cuando ya iniciamos todo, leemos los primeros 1024 bytes del archivo y al igual que en C#, vamos a buscar cualquiera de las etiquetas que se usan para indicar una imagen; es decir: "APIC" o "PIC". Algo que probablemente olvide decir en el primer post sobre imágenes en los MP3's es la importancia de buscar primero "APIC" a algunos les resultará obvio cual es la razón pero a otros no. La razón es simple si buscamos PIC (que corresponde a la versión 2), el resultado de la búsqueda sera verdadero si existe "APIC" porque esta contiene toda la cadena de caracteres que buscamos, en cambio si buscamos "APIC" primero, si no se encuentra, eso no significa que necesariamente no exista "PIC".

Para realizar la búsqueda de la etiqueta, una vez que leímos todos los bytes en los cuales podría estar, creamos un flag llamado "GotIt" del tipo "boolean" y a esta le asignamos el resultado de la función "string.find()" usando cómo parámetros "Sdata" que es una copia de "Rdata" (los 1024 bytes leídos) y es en donde buscará la cadena de texto que le pasamos en el segundo parámetro.

Repetimos lo anterior 4 veces, la primera es para buscar "APIC", la segunda para buscar "PIC" luego si la variable "GotIt" resulta "true" en cualquiera de las dos funciones, hacemos una nueva búsqueda pero ahora en lugar de las etiquetas de imagen, buscamos el tipo de imagen; ya sea PNG o JPG, pero para hacerlo, hacemos uso de de los caracteres que sirven de "encabezado" para los archivos PNG, cómo ya estamos dentro de la condición en la cual si se encontró una etiqueta de imagen, solo hacemos una comprobación y si no encontramos al "encabezado" del archivo PNG entonces la imagen es JPG

Para calcular el tamaño de las imágenes, hay que recordar que seguido de la etiqueta, los cuatro bytes siguientes  para la versión tres y los tres bytes siguiente en la versión dos, indican cual es el tamaño de total de la etiqueta, para poder saber cual es el valor, bastará con multiplicar cada byte por potencias de 256, empezando de izquierda a derecha por 256^3 para la versión 3 y 256^2 para la versión dos.

Finalmente  guardamos la imagen haciendo uso de un escritor de archivos que se usa igual al de C, es decir creamos el archivo e indicamos cual es el modo en el cual se trabajara, cuando usamos "wb" indicamos que abriremos un archivo pra escribir de forma binaria, si el archivo no existe, se creara uno nuevo.

Para poder usar la función, en ZeroBrane presionaremos F6 y en la parte inferior, el programa no preguntará por la ubicación de una canción seguido de la ubicación que usaremos para guardar la imagen, para este ultimo es importante solo indicar la ruta y el nombre del archivo sin extensión, dentro del programa al determinar si la imagen es jpg o png automáticamente agrega la extensión adecuada.

Si observas bien, el archivo de imagen solo tiene la ruta y el nombre, pero no la extensión.


Y bien por ahora es todo, el código lo puedes copiar y pegar para probarlo.

Los leo luego.

No hay comentarios. :

Publicar un comentario

El reto de Xwork #3.

No hay comentarios.
Hola de nuevo a todos, el día de hoy solo vengo a dejar el reto de Xwork.

Si llevas tiempo visitando el blog no tardarás tanto en encontrar la respuesta.

Hay que recordar  que el primer desafio solo fue resuelto por el usuario Zed0008 (que ya tienen su lugar en el salon de la fama). Y que el reto #2 sigue abierto.

Los leo luego.

No hay comentarios. :

Publicar un comentario

¡¡Feliz aniversario!!

No hay comentarios.
Hola de nuevo a todos el día de hoy vamos a ver un poco de la historia del surgimiento de este blog.

Primer imagen representativa del blog.

Hace exactamente dos años, un día 21 de junio, me di a la tarea de empezar con este blog. Aunque al inicio era un poco escéptico sobre que tanta aceptación podría llegar a tener, al paso del tiempo me di cuenta de la aceptación que poco a poco iba tomando lo que me motivo a continuar con los proyectos.

Durante mucho tiempo acumule software que jamas publiqué y que solo se iba perdiendo entre montañas de CD-Roms y sectores defectuosos de discos duros. Nunca me moleste en "presumir" que hice tal programa o que X programa que subi a MEGA (R.I.P) se descargo tantas veces que pude comprar una cuenta premium por un mes. Nunca pensé que todo el código fuente que escribí le resultara útil a alguien más.

Segunda imagen representativa del blog (Primer aniversario).
Pero un día en una charla con una persona ella me dijo: "Oye eso es un buen pedazo de software, deberías de publicarlo (palabras más, palabras menos a lo mejor algo ni remotamente cerca)". Yo le comente que en veces anteriores ya había subido mis programas a sitios cómo Taringa o Directorio Warez (que valían la pena en aquel entonces) y si bien fueron un éxito en el 2006 no sabia realmente cómo poder explicar el código; programas como PSP manager, VEncoder, Unit Converter, Registry Cracker, Autorun Killer, Play List M (PC), Office MPM (Office 2000 modificado), M-Copier, M-Essentials, M-AEncoder, MPlayer y varios programas más a pesar que eran creaciones mías, se basaban en el trabajo de otros por lo que no los entendía al cien por ciento. Aun así decidí actualizar algunos y otros simplemente quedaron en el olvido. Aprovechando que en el 2016 ya tenía mucha más experiencia y entendía más como programar, decidí aceptar la idea que ella me dio y así fue cómo empezó este blog.

Cómo cualquier cosa, en el transcurso de estos dos años han habido altas y bajas, temporadas en las que fluyen las ideas cómo si de un río se tratara, pero hay ocasiones en las que otras cosas me distraen de hacer algo que valga la pena publicar, pero me he dado cuenta que la gente se sigue dando vueltas por acá y eso ayuda mucho a seguir.

Tercera imagen representativa del blog (Segundo aniversario).
Y bien por ahora es todo, en los siguientes días habrá más publicaciones (con suerte también colaboraciones). No te olvides de visitar al nuevo blog de MIING, en el encontrarás libros de ingeniería realmente útiles, es una nueva adición a la red de blogs que quiero crear y que sean útiles (no cómo la basura inmunda que abunda en el 99% del Internet).

Los leo luego. ¡¡Gracias Totales!!

No hay comentarios. :

Publicar un comentario

Bienvenidos a la cultura de lo desechable.

2 comentarios
La imagen fue tomada de: Revista Quaestionis

Es bien sabido por todos que en la actualidad se usan los servicios "en la nube" para guardar información. Ahí depositamos toda nuestra vida: la fotos con nuestros amigos, nuestra música favorita, nuestras series favoritas y todo lo relacionado a nuestro teléfono.


Hace 20 años nos resultaba difícil el poder guardar una canción completa en un disquete por la simple y sencilla razón que estos solo pueden almacenar 1.44 MB o 2.88 MB en el mejor de los casos y una canción de cuatro minutos ocupa 8 MB.


Con el tiempo este tipo de problemas se resolvieron y poco a poco se empezaron a ver volúmenes de información bestiales en algo tan pequeño cómo una uña. Hoy en la actualidad es muy común ver unidades USB flash de 16 GB en promedio, tarjetas de memoria micro SD de igual capacidad y ambas por un precio ridículamente bajo o alto; eso si lo comparamos con el almacenamiento tradicional o mejor dicho del disco duro tradicional que en la actualidad pueden ser de 320 GB para el usuario promedio.


Con tantos datos cualquiera pensaría que la gente optaría por tener una copia de su canción favorita, el vídeo más visto de Internet almacenado para verlo un poco después y a la hora que sea; mas no fue asi. Junto al auge del almacenamiento masivo también se dio el auge de los dispositivos móviles, cualquier experto en el 2004 hubiese pronosticado que al ir incrementando los dispositivos móviles, a demanda de almacenamiento también lo haría... Y no fue así, solo por un tiempo se dio esa tendencia pero después Apple presento lo que seria la introducción al almacenamiento masivo en la nube y todo cambio.


El servicio de ICloud sirve para almacenar todos los archivos; <primordialmente> del dispositivo de Apple; llámese Ipod, Ipad o Iphone. El hecho de poder acceder a una foto; por ejemplo; que se tomó desde un IPhone y verla en un IPad que tiene una pantalla mucho más grande y sin hacer nada adicional, significó una revolución.


Poco a poco empezaron a proliferar los servicios que ofrecían almacenamiento en la nube y algunos fueron un poco más allá. Todas las personas que poseen un smartphone no solo lo usaran para llamar por teléfono o enviar e-mail, también lo usaran para otras cosas cómo jugar, oír música o ver videos y aquí es cuando entra el ingenio.


Cómo mencione un poco más arriba, el almacenamiento ha crecido de forma exponencial, los dispositivos multimedia tambien lo hicieron y con esto también lo hizo el contenido y a pesar que 64GB pueda parecer mucho, si lo llenamos con video de alta calidad solo podríamos almacenar de 10 a 30 horas de este. Ahora imaginemos que guardamos nuestra serie favorita en mi caso es Monk y se divide en ocho temporadas de 16 capítulos y cada uno dura 40 minutos, usando la métrica anterior tenemos que dura 64 horas y requeriría 128 GB para poder almacenarla.


Tomando en cuenta que también quiero escuchar música y quiero ver otras series, resulta imposible tenerlo todo a la mano. A alguien se le ocurrió este problema y dijo "usemos la nube" y así fue cómo empezaron a surgir servicios cómo netflix y todos los derivados para el consumo de video; y spotify para el consumo de audio. Anteriormente existían servicios que almacenaban archivos pero solo hacían eso, si querías hacer uso de un archivo mp3 tenías que descargarlo.


Poco a poco estos servicios empezaron a dominar el mercado y ahora resulta difícil de alguien que no haya utilizado en alguna de las ocasiones alguno de estos servicios. Para algunos es una ventaja y resulta en cierta parte razonable, nunca me he preguntado donde están mis discos de soda estéreo de la década de los 90's incluso es más fácil buscar la canción en spotify que buscar el disco, el lector y mis audífonos.


Pero por otro lado y a partir de aquí son solo especulaciones mías. El hecho de tener todo disponible a la mano, hace que la gente se acostumbre a eso. Algo no esta disponible, entonces no debe de ser bueno o tengo todo el mundo por ver pero no se por donde empezar. A lo mejor exagero un poco, pero las nuevas generaciones al nacer inmersos en estás cosas, se dan el lujo de hacer lo mismo con las personas, se reemplazan amigos más rápido que lo que cambian de zapatos, tienen parejas que solo duran dos o tres meses, se casan y el "amor" dura un par de años. Resultaría un tanto injusto decir que es debido a Netflix pero de algo no hay duda, vivimos en la cultura de lo desechable.


P:D: Me invitaron a escribir aquí por los dos años de este blog, no cuenten con volver a leer nada que provenga de mi. Además cualquiera daría por muerto al dueño.

2 comentarios :

Publicar un comentario

Inutil apps #4 - Visualizador de sonido (pt. 2.)

No hay comentarios.
Hola de nuevo a todos, el día de hoy vamos a continuar con la construcción del visualizador de sonido.


En el post anterior vimos cómo hacer las conexiones en el diagrama, hoy solo veremos cómo ensamblarlo.

Para que se más vistoso decidí hacer una caja de 100 cm x 10 cm x 10 cm con madera de 0.4 cm. para eso corte 2 pedazos de 100 cm x 10cm y once pedazos de 10 cm x 10 cm para usarlos cómo divisores.



Para unir todo simplemente use clavos de 1.27 cm y pedazo de madera de 9 cm x 2 cm x 2 cm. Odio admitirlo, pero de esta parte no gusto tanto el resultado porque se así:


Y se notan más cuando la luz se enciende pero a pesar de todo decidi mantener el diseño cómo simple recordatorio de que hay que planear bien todo desde el principio.

Luego pegue los LED's usando silicón caliente, puesto que esto esta diseñado para no moverse mucho, en lugar de usar clavos o un pegamento más potente, el silicón cumple con su trabajo a la perfección y por eso también lo use en los espaciadores.


Cuando terminé de pegar los LED's use cable "rainbow" de 8 buses (que era la que tenía a la mano) + dos cables 28 AWG para hacer las conexiones hacia el circuito controlador, hay que recordar que el integrado LM3915 /14/16 va a manejar cada LED  desde su cátodo por lo que estos deben de ir por separado. Para el anodo, igual use cable 28 AWG, cada modulo LED usa 20 mA por lo que suponiendo que todos estén encendidos a su máxima capacidad, solo circularan 200mA por este cable.


Finalmente solo conecte el circuito ya hecho, todo parecía funcionar de maravilla, pero aqui vuelvo a remarcar la importancia de planear estás cosas. A pesar de que es un proyecto que llevo "haciendo" desde el 2014 (15?) cuando por pura casualidad le dije a una amiga sobre mi adicción a las luces sensibles al sonido y ella me consiguió los primero lm3915 (que todos esos murieron en nombre del progreso). Hasta ahora que en teoría ya debería de tener una idea clara de que y cómo hacerlo. Simplemente no aprendí nada ya que no tome en consideración el espacio para anclar debidamente todo el circuito y simplemente lo deje así; colgando.

Aunque es una mala practica dejar las cosas "cómo queden", por está ocasión la dejare así, ya que el resultado es igual a cómo lo imaginé hace mucho.

Y bien, por ahora es todo, no olvides revisar el post anterior donde están los diagramas.

Los leo luego.

P.D:
Lo admito.

No hay comentarios. :

Publicar un comentario

¡¡Cumplimos 2 años!!

No hay comentarios.
Hola de nuevo a todos, el día de hoy solo escribo  para agradecer a todos los que han hecho crecer al blog y motivarme para continuar con el.


Han pasado muchas cosas y hoy con certeza puedo afirmar que el blog ha llegado tan lejos gracias a los lectores.

Sin más que decir por ahora solo me queda agradecer.

Feliz segundo año. Los leo luego.

No hay comentarios. :

Publicar un comentario

Inútil apps #4 -Visualizador de sonido.

No hay comentarios.
Desde que era pequeño, siempre tuve fascinación por las luces audioritmicas, recuerdo que mi papá tenía un Boom-Box (a grabadora) que tenia un visualizdaor de 10 niveles (un LED por nivel). El efecto que lograba era bastante llamativo y tal mosco a la luz, no podía evitar ser atraído por esta.


El día de hoy vamos a hacer un visualizador de sonido. usando uno de los integrados más comunes: el LM3915.

Para empezar revisemos el siguiente esquema:

El circuito integrado LM3915 se encarga de medir niveles de voltaje y es capaz de manejar 10 LED's.
Antes de continuar revisemos para que sirve cada una de las entradas del integrado

  1. Pin 1 - Salida de LED.
  2. Pin 2 - Tierra.
  3. Pin 3 - VCC (3 ~ 35V).
  4. Pin 4 - Divisor bajo
  5. Pin 5 - Input
  6. Pin 6 - Divisor alto.
  7. Pin 7 - Referencia de salida.
  8. Pin 8 - Ajuste de referencia.
  9. Pin 9 - Selector de modo.
  10. Pin 10 ~ Pin 18 - Salida de LED's
Para poder hacer el proyecto entonces necesitaremos los siguientes componentes:

  • U1 - Circuito integrado LM3915 (14/16).
  • D1 - Diodo 1N5819
  • R1 - Resistencia 680 Ohms
  • R2 - Resistencia 150 Ohms
  • R3 - Resistencia 10 KiloOhms
  • C1 - Capacitor electrolitico 10 micro Faradios.
  • LED1 ~ 10. Diodo LED.
Para empezar, el circuito integrado LM3915 tiene la capacidad de entregar de desde 2 mA hasta 30 mA, para poder ajustar la corriente que va a circular en cada salida, debemos de tomar en cuenta la siguiente formula:

  • 12.5/R1
En nuestro caso tenemos que la resistencia R1 tiene un valor de 680 Ohms por lo que sustituyendo tenemos:

  • 12.5/680 = 18.3 mA
Con 18.3mA tenemos la cantidad suficiente de corriente para manejar casi cualquier LED. Al establecer la corriente, no nos tendremos que preocupar por poner resistencias entre los LED's y VCC puesto que el integrado se encargara de administrar: pero hay que resaltar que si solo se va a hacer uso de un solo LED a cada salida, es recomendable bajar el voltaje al cual trabajaremos, si no lo hacemos, todo el voltaje sera disipado por el integrado y la vida útil de este se reducirá.
Si se quiere hacer uso de 12V podemos usar segementos de LED como los siguientes:


Este tipo de módulos son muy comunes, al hacer la medición cada segmento consume 20mA, para poder calcular la resistencia adecuada podemos re-acomodar la formula de tal forma que si queremos saber que resistencia debemos usar tendremos algo cómo lo que sigue:

  • 12.5/I (donde I es la corriente).
Y sustituyendo tenemos:

  • 12.5/0.02 =  625 Ohms
Ahora imaginemos que queremos usar 25 mA, solo bastará que se sustituya el nuevo valor de la corriente:

  • 12.5/0.025 = 500 Ohms.
Si se requiere una mayor corriente para manejar corrientes de mas de 30 mA, se deberá de usar algún transistor, si se le exige más corriente al integrado, este simplemente se quemará.

Para la entrada de señal, el circuito esta diseñado para ser conectado a la salida de un amplificador con niveles de 0V a 9V, para poder variar la sensibilidad, debemos de cambiar la corriente que circula por el pin8. Por ahora solo dejare esta versión, pero si necesitas saber cual es el valor de las resistencias para los voltaje, puedes leer la hoja de datos del integrado.

Para poder controlar cómo se va a mostrar los niveles, disponemos de dos modos:

  1. Modo Barra.
  2. Modo Punto.
El modo barra consiste en que todos los niveles se encenderán si hay uno superior activo, supongamos que tenemos el LED 8 encendido, entonces los LED's del 1 al 8 estarán encendidos, aunque parezca un poco obvio, es importante mencionarlo para contrastarlo con el modo punto; en el modo punto solo el LED 8 debe de estar encendido, solo este lo estará, es decir ninguno que no sea el del nivel actual estará encendido. Si se usa el modo punto, debemos de usar una resistencia de 1 a 10KOhms entre el PIN 1 y su respectivo LED, si no se pone, cuando el nivel sea diferente al del LED 1, este presentará un ligero resplandor.

El modulo rojo debería de estar totalmente apagado, pero sin la resistencia no lo hacer (aunque pienso que quueda bien)


Y bien, por ahora es todo, en el siguiente post, veremos cómo armar el circuito y trataremos de hacer un empaque para que se vea un poco mejor.

Los leo luego.

No hay comentarios. :

Publicar un comentario