Vamos a platicar #13 - It´s no over (yet)
Hola de nuevo a todos. Ha pasado el tiempo desde la última vez que algo se publico por acá. Los tiempos han cambiado y cada vez es menos común que la gente recurra a este tipo de sitios para buscar información.
En los próximos días este sitio cumplirá diez años; si bien es cierto que desde hace un par, todo ha venido en declive, es importante mencionar que trataré de continuar con el, mas que nada por todo lo que representa para mi.
Por ahora es todo y cómo de costumbre le agradezco a todos los que se toman el tiempo de pasar a leer.
Los sigo leyendo.
Bienvenido el 2026
Hola de nuevo a todos. El día de hoy solo escribo para hacer lo que usualmente hago cada fin de año. Es cierto que el blog ha disminuido en la cantidad de post que se publican, pero si de algo estoy seguro, es que este es mi lugar. Ahora mas que nunca, debemos de crear conocimiento y que sea la mente humana la que predomine sobre la máquina.
Por el momento es todo y al igual que cada año, nos seguiremos leyendo por acá. Que el 2026 sea un año bueno para todas las personas que se toman la molestia de leer.
Los leo luego
Vamos a programar #106 - Agregando imagenes a archivos FLAC parte 2.
Hola de nuevo a todos, el día de hoy vamos a continuar con mas de los archivos FLAC.
En el post anterior vimos cómo es que esta estructurado la parte que conforma la imagen en un archivo FLAC. Hoy, al igual que en otras ocasiones, antes de escribir el programa en c#, vamos a insertar la imagen "a mano" solo usando un editor Hexadecimal; el que siempre uso es XVI32 que puedes descargar de su sitio oficial. Cómo archivo de prueba voy a usar una canción en formato FLAC, para que sea sencillo seguir los pasos, te recomiendo usar el mismo archivo que puedes descargar aquí. Pero al igual que las otras canciones, si no posees el original, debes de eliminarlo al terminar de hacer las pruebas. La caratula del álbum también la puedes descargar de aquí.Una vez todo listo, procederemos a abrir el archivo FLAC con XVI32. Hay que tomar en cuenta que a partir de este momento, cuando escribamos un numero en decimal simplemente será el numero, cuando hagamos referencia a un numero en binario, será bxxxxxxxx y en hexadecimal sera 0xXX
Una vez abierto, vamos a desplazarnos por el archivo. Si hacemos memoria, los primeros cuatro bytes, corresponden al identificador del archivo que es "fLaC" inmediatamente después de este, viene el bloque con la información del stream. este tiene un tamaño fijo de 34 bytes (en bits son: 16+16+24+24+20+3+5+36+128 = 272 bits = 34 bytes), que es lo que nos indica el byte en la dirección 0x05 hasta 0x07 que es la secuencia 0x00, 0x00, 0x22 que al convertirlo a decimal nos da treinta y cuatro, hay que recordar que en el tamaño no se incluye el encabezado. En XVI32, nos podemos desplazar cierto numero de bytes. Al terminar de leer el encabezado del bloque con la información del stream, deberíamos de estar en la dirección 0x07 posicionamos el cursor en el byte siguiente y presionamos la tecla de "control" y la tecla "b", eso le indicará a XVI32 que estamos marcando el inicio de lo que queremos seleccionar, luego vamos al menú "edit>>block <n> chars" e introducimos tantos bytes cómo nos dijo el encabezado del bloque, en este caso fueron treinta y cuatro.
Con esto estará resaltado todo el bloque. Esto solo lo hacemos con el fin de que todo resulte mas claro, pero este bloque no lo vamos a modificar, asi que avanzamos al siguiente.
![]() | ||
| Se puede apreciar todo el bloque. |
Inmediatamente después de la selección, viene el siguiente bloque. Por ahora los que nos interesan son o el bloque de la imagen (aunque en este ejemplo no existe) o el bloque de "padding". De cualquier forma vamos a leer los bloques hasta que encontremos alguno. Para eso simplemente repetimos el paso anterior.
En nuestra secuencia, leemos 0x04, 0x00, 0x01 y 0x58 (el tamaño es 0x0158) que al convertirlo a decimal nos da 344, el primer byte nos dice que este es el bloque "Vorbis Comment", nuevamente marcamos esa cantidad de bytes después del encabezado.
Algo importante que debemos de recordar, es que debemos de repetir todo hasta que encontremos el marcador del ultimo bloque. Si continuamos leyendo, tenemos la secuencia 0x81, 0x00, 0x1E y 0xD0, esta es relevante porque al convertir el primer byte a binario, nos da b10000001 y justamente el primer bit (de izquierda a derecha) nos dice que este es el último bloque y además que es del tipo "padding" y que tiene una longitud de 7,888 bytes, procedemos a marcarlos.
Con esto ya tenemos toda la información que necesitamos. antes que nada, necesitamos ver si el tamaño reservado (padding) es suficiente para nuestra imagen, si descargaste la imagen al inicio, estas deben de ser sus propiedades.
Para poder inscrustar la imagen necesitamos un espacio 180,677 bytes mas el encabezado, el espacio que tenemos es de 7,888 y claramente es insuficiente, por lo que vamos a reemplazar el bloque en su totalidad.
Preparando la imagen.
Vamos a usar Xvi32 para crear el bloque completo. Primero preparamos el bit que describe el bloque. EN este caso, va a ser el ultimo bloque, pero ademas sera del tipo "PICTURE", el primer bit es b1, seguido de la descripción que es b110, al unirlos para formar el byte tenemos b10000110 que es 134 en decimal o 0x86. En XVI32 podemos insertar directamente los dígitos hexadecimales en el panel de lado izquierdo, si queremos insertar 134 decimal simplemente lo convertimos a hexadecimal y lo escribimos tal cual. Antes de continuar, guardamos lo que llevamos con el nombre de "Picture block.bin".
para calcular el tamaño total, primero vamos a construir al bloque APIC.
- Tipo de imagen por ahora usaremos 0x03 (cubierta frontal del disco) usa 4 bytes.
- 0x00, 0x00, 0x00, 0x03, en XVI32 vamos al menú "Edit>>Inser string"
- El tamaño del tipo MIME , usaremos "image/jpeg" que tiene una longitud de 10 bytes.
- 0x00, 0x00, 0x00, 0x0A.
- La cadena de texto "image/jpeg".
- Usando el comando insertar escribimos literal image/jpeg.
- El tamaño de la descripción , usaremos la misma secuencia "image/jpeg" que tiene una longitud de 10 bytes.
- 0x00, 0x00, 0x00, 0x0A.
- La cadena de texto "image/jpeg".
- Usando el comando insertar escribimos literal image/jpeg.
- El ancho de la imagen
- 0x00, 0x00, 0x00, 0x00
- El alto de la imagen
- 0x00, 0x00, 0x00, 0x00
- La profundidad de color
- 0x00, 0x00, 0x00, 0x00
- El indice de colores
- 0x00, 0x00, 0x00, 0x00
- El tamaño de la imagen en bytes de la imagen
- la imagen pesa 180,677 bytes que es 0x02C1C5 que queda para insertarlo cómo 0x00, 0x02, 0xC1, 0xC5
- Los datos de la imagen.
- Abrimos la imagen con XVI32, seleccionamos todos los bytes, los copiamos y los pegamos inmediatamente después de nuestro último byte.
![]() | |
| Así debería de lucir nuestra secuencia antes de insertar los datos de la imagen. |
Guardamos el archivo como APIC.bin e inspeccionamos sus propiedades para obtener el tamaño.
Volvemos a abrir "Picture block.bin" e insertamos el tamaño de "APIC.bin", en este caso 180,729 es 0x02C1F9 y en la secuencia es: 0x02, 0xC1, 0xF9. Una vez escrito, Abrimos "APIC.bin" y seleccionamos todos los datos, los copiamos y pegamos en "picture block.bin" inmediatamente después de la secuencia actual.
Con esto ya tenemos todo listo para unir las partes.Para eso, seleccionaremos y copiaremos todos los datos previos al bloque que vamos a sustituir (en nuestro archivo FLAC). Los copiamos y pegamos, luego el bloque que creamos y finalmente el resto del archivo FLAC.
Para simplifica un tanto las cosas, y si quieres ir directo al grano, de nuestro archivo original, primero seleccionaremos los primeros 390 bytes, los copiamos y los pegamos en un nuevo archivo, luego abrimos "picture block.bin", seleccionamos todo y lo insertamos en el archivo que creamos, luego en nuestro archivo original, nos desplazamos a la posición 8,282, usando el comando "go to" en el menú "address" y de ahí seleccionamos todo el resto del archivo, lo copiamos y lo insertamos en el nuevo, si todo fue bien deberíamos de tener nuestro archivo FLAC con su caratula.
Al inspeccionarlo tenemos que todo fue como es debido.
Y bien, por ahora es todo, el objetivo de hacer los pasos a mano, es para ayudar a comprender que es lo que el programa va a hacer. En el siguiente post escribiremos el código en C# que nos ayudara.
Los leo luego.
Vamos a programar #106 - Agregando imagenes a archivos FLAC parte 1.
Hola de nuevo a todos. Tiempo ha pasado desde la última vez que un post se publicó. Cómo no es bueno dejar cosas pendiente, el día de hoy vamos a continuar con mas programación.
En alguno de los post anterior, vimos cómo leer los metadatos de los archivos FLAC, vimos cómo recuperar información importante: álbum, artista, título de la canción (solo por mencionar algunos), pero además, vimos cómo leer la imagen del archivo; eso si contiene una. El día de hoy, nos concentraremos en cómo está estructurado solo esta parte y servirá de preámbulo para hacer un programa en c# que escriba la imagen en el archivo.
Antes que nada, recordemos cómo esta estructurada la imagen. Hay que recordar que sigue los lineamientos de la etiqueta APIC de las etiquetas ID3v2. Desde este momento, toda la notación estará en bytes (al menos que se indique lo contrario).
- <4> El tipo de imagen que va a representar.
- 0 - Other
- 1 - 32x32 pixels 'file icon' (PNG only)
- 2 - Other file icon
- 3 - Cover (front)
- 4 - Cover (back)
- 5 - Leaflet page
- 6 - Media (e.g. label side of CD)
- 7 - Lead artist/lead performer/soloist
- 8 - Artist/performer
- 9 - Conductor
- 10 - Band/Orchestra
- 11 - Composer
- 12 - Lyricist/text writer
- 13 - Recording Location
- 14 - During recording
- 15 - During performance
- 16 - Movie/video screen capture
- 17 - A bright coloured fish
- 18 - Illustration
- 19 - Band/artist logotype
- 20 - Publisher/Studio logotype
- <4> El tamaño de el tipo de archivo (MIME Type).
- <N> La cadena de texto con el tipo de archivo (Solo usaremos "image/jpeg" o "image/png" ).
- <4> El tamaño de la descripción de la imagen.
- <N> La cadena de texto con la descripción de la imagen.
- <4> El ancho de la imagen en píxeles.
- <4> El alto de la imagen en píxeles.
- <4> La profundidad de colo de la imagen.
- <4> Para imágenes con indice de color, el número de colores a usar.
- <4> El tamaño de la imagen en bytes
- <N> Los datos de la imagen.
![]() |
| En esta imagen se puede apreciar cada apartado (si no se ve bien hay que darle zoom). |
Lo relevante de todo esto, y si miras bien la imagen, es los apartados cuatro, cinco, seis, siete; son totalmente innecesarios y se pueden dejar en cero o 0x00, 0x00, 0x00, 0x00; aun sin se establecen estas propiedades, en la documentacion oficial, no se aconseja hacer uso de ellas al momento de mostrar la imagen.
Habiendo descrito lo anterior, solo queda escribir código en c# para agregar la imagen.
Y bien, por ahora es todo. cómo de costumbre, hago la promesa de que trataré de publicar mas seguido. realmente agradezco a todos los que se toman la molestia de darse una vuelta por acá.
Los sigo leyendo.
Cumplimos 9 años.
Hola de nuevo a todos. Un día cómo hoy pero de hace nueve años nació el blog de Xwork.
Si bien la actividad del blog ha bajado a un nivel de cero. Eso no implica que me haya olvidado de el, afortunadamente para mi, he llegado a una etapa nueva de mi vida y por ahora es a lo que le dedico mi atención. Eso no implica que el blog haya muerto, simplemente estoy disfrutando el momento.
Eso no quiere decir que me haya olvidado que este sitio lo cree en primer lugar para pasar las situaciones complicadas, por eso, ahora con una nueva compañera, es cuestión de retomarlo (ahora con compañía).
Sin mas que decir, espero que los artículos ya disponibles, sean de utilidad sin importar que el mas viejo tenga nueve años (el conocimiento es atemporal). En algún momento continuaremos, pero por ahora solo me queda agradecer a aquellos que expectantes se dan una vuelta de vez en vez.
Sin mas que decir. Gracias y cómo siempre los sigo leyendo.
Att: XWork (y ahora con EV).
Vamos a programar #105 - Enmascaramiento y secuencias de bits - Camino a ClockView 3.0
Hola de nuevo a todos, el día de hoy vamos a ver como hacer uso del enmascaramiento y cómo ahorrar un poco de memoria para algunos tipos de variables.
Desde hace tiempo actualicé ClockView, si no sabes de lo que hablo, puedes darte una vuelta por el post de la versión dos.
Desde el principio planee poner una serie de alarmas muy similares a las de un reloj casio que tengo, este tiene la particularidad de que se puede establecer por fecha: es decir, si queremos que suene el tres de julio, eso hará; por mes: es decir, si establecemos solo el mes, sonará todos los días de octubre (por solo decir una fecha); por año: la alarma sonará todos los días del año. Además se podía establecer para que la alarma sonara ciertos días de la semana, está función me es realmente útil, ya que normalmente solo algunos días de la semana requiero de la alarma (aunque ya no tanto, creo que llegué a la edad en que le gano al despertador).
Si recordamos la versión anterior de clock view, este, carecía de una función de alarma, pero el modulo de reloj en tiempo real DS1302, además de llevar la cuenta del tiempo, posee la capacidad de llevar los días de la semana. Para poder guardar los datos de los días de la semana en los cuales queremos que la alarma suene, vamos a usar un solo byte.
Para eso, podemos estructurar los días de la semana cómo se muestra en la siguiente imagen:
Oportunamente para nosotros, la semana consta de siete días, y cada byte consta de ocho bits, con lo que podemos asignar un valor cómo se muestra en la imagen anterior. Pero mas que su valor numérico, debemos de ver cómo es su representación en binario.
Pero ahora que hemos asignado un valor a cada día de la semana ¿cómo debemos de usarlos? Antes de entrar esos detalles, supongamos que queremos que la alarma suene los días: domingo, jueves y sábado, deberíamos de hacer algo cómo lo que sigue:
- Tomar el valor del primer día deseado.
- Tomar el valor del segundo día deseado
- Aplicar el operador "or" a ambos números y asignarlos a una variable.
- Si se desean agregar mas días, al valor anterior se le aplica de nuevo el operador "or" junto con el día a agregar
Si lo convertimos a código en c, quedaría algo cómo lo que sigue:
uint8_t BuildTheDaysOfAlarms(uint8_t TheDay1, uint8_t TheDay2)
{
return TheDay1|TheDay2;
}
Entonces los días que queremos usar en la alarma quedarían cómo:
- 00000001 or 00100000 or 01000000 = 01010001.
- que es igual en decimal a: 1 or 16 or 64 = 81.
- Lunes a viernes = 00111110 = 62.
- Sábado = 01000000 = 64
- 62 and 64 = 0.
- El día no está en el rango.
- Lunes, miércoles y viernes = 00101010 = 42.
- Miércoles = 00001000 = 8
- 42 and 8 = 8
- El día está en el rango.
Cumplimos 8 años.
Hola de nuevo a todos. El día de hoy solo escribo para recordar que un día cómo hoy pero de hace ocho años, nació el Blog de Xwork. Siempre le voy a agradecer a todos los que se toman la molestia de venir a leer aunque sea un poco. Si bien la cantidad de publicaciones ha disminuido de forma drástica, tengan por seguro que va a seguir habiendo, a inicio de año planifique todo y de hecho se iba a ir publicando un post al mes, pero por razones que son difíciles de comprender aun para mi, algo salio mal en mayo y todos los post que se iban a publicar, simplemente desaparecieron. Estoy arreglando todo y en cuanto este listo, se subirán de uno por uno.
Sin más que decir, solo quiero agradecer una vez mas a todos los que me leen.
Nos seguimos leyendo.
Att. Xwork.
El Video Correcto #10 - VEncoder y subtitulos.
Hola de nuevo a todos, el día de hoy vamos a ver cómo insertar subtitulos en los videos que se codifiquen con VEncoder.
Hay que recordar que VEncoder es una interfaz de usuario para FFMPEG; si bien la idea es mantener los mas simple posible todo, para lograr resultados complejos, es necesario hacer ajustes complejos. Antes de continuar, me gustaría recapitular cual fue la idea de VEncoder. El programa inicialmente nació cómo una herramienta para convertir los videos para que el Play Station Portable pudiera reproducirlos, incluso era parte de un programa llamado PSP Manager, y cómo su nombre lo pudiera sugerir, servía para manejar el contenido multimedia de la consola. Poco a poco cada una de las partes se separó y dieron origen a VEncoder y AEncoder que a diferencia de PSP Manager, no tuvieron tanta relevancia.
He usado mi PSP desde el 2010 y de las pocas cosas que no he logrado entender, es cómo funciona la opción de los subtítulos en el reproductor de video.
Recientemente me he encontrado con gente para la cual la consola es algo totalmente nuevo y he compartido algunos videos con esas personas, pero cómo los tiempos cambian, ahora resulta más sencillo encontrar contenido que no está en nuestro idioma por lo que resulta necesario encontrar una forma de incluirlos. Cómo mencioné hace poco, a pesar de que la PSP tiene (o eso según el menú) la capacidad de reproducir subtítulos, nunca supe cómo usarlos.
FFMPEG tiene la capacidad de reproducir subtítulos, pero antes de detallar cómo es que funcionan, hay que resaltar algo importante. Hay dos formas de incrustar los subtítulos; la primera es sencilla, se dota de un archivo que tiene la transcripción de los diálogos con los tiempos para cada uno, el reproductor los lee y los muestra sobre el video, a esto le podemos llamar "subtítulos por software". La otra forma es similar, tenemos un archivo con las transcripciones pero solo las usamos al momento de codificar el video y justo en la codificación, vamos a modificar la imagen correspondiente al tiempo del fotograma, de tal forma que el texto quede cómo parte de la misma, con eso bastará para que los subtítulos queden de forma permanente en el video.
Para lograr esto, usaremos FFMPEG junto con VEncoder (el cual actualizare pronto para que la opción "Si hay subtítulos 'quemarlos'" funcione). En VEncoder, hay una ficha llamada "Parámetros adicionales" dentro, hay una ficha llamada "video". FFMPEG soporta varios tipos de subtítulos, archivos SRT o archivos ASS, los primeros son mas sencillos, pues solo incluyen el dialogo y el tiempo en que deben de aparecer; los segundos incluyen "estilos" y efectos (transiciones, diferentes ubicaciones para el texto).
Primero veamos un ejemplo de cómo insertar un archivo SRT.
-vf "subtitles='I\:\\\VIDEOS\\\Track3.srt'"
-vf "ass='I\:\\\VIDEOS\\\Track3.srt'"
![]() |
| No es precisamente el mismo cuadro, pero se ven lo subtítulos "quemados" |
Learning machine #18 - Programando en Pascal - Estructuras de datos (Record).
Hola de nuevo a todos, el día de hoy vamos a continuar con mas del aprendizaje del lenguaje de programación en pascal.
"En el capítulo anterior de <<Learning machine>>" vimos cómo es que se usan los arreglos de una o varias dimensiones. Hoy vamos a ver cómo es que se usan las estructuras de datos o "Record" (registro en español). Un registro básicamente es un conjunto de variables bajo un mismo nombre o tipo.
Para crear un registro, hay que crear un tipo usando la palabra "Type" seguido del nombre o identificador que le daremos al registro, hasta aquí todo es igual a cuando creamos los tipos, ahora la diferencia viene en que hay que asignarlo al tipo "Record", es decir tendríamos algo cómo: "Type NombreDelRegistro = Record" una vez creado, dentro de este nuevo tipo, agregaremos "campos"; cada campo sera una variable de cualquiera de los tipos soportados por Pascal. Una vez agregados todos los campos, finalizaremos la declaracion, con la palabra reservada "end;". Para apreciar un poco mejor cómo es todo el proceso, tomemos el siguiente ejemplo:
Type MiCancion = Record Cancion,Artista,Album : string; Year : Integer; BeatPerMinute : single end;
Con esto habremos creado un nuevo registro llamado "MiCancion"; este contendrá los campos: "Cancion, Artista, Album, Year y BeatPerMinute" del tipo "string, string, string, integer y single" respectivamente. Para poder usar el registro, crearemos variables del tipo que acabamos de crear.
Si queremos acceder a los campos, bastará con escribir el nombre de la variable seguido de "." y despues el nombre del campo. Para visualizar mejor cómo es que se hace, observemos el siguiente código:
KillerQueen.Cancion := 'Killer Queen.flac'; KillerQueen.Artista := 'Queen'; KillerQueen.Album := 'Sheer Heart Attack'; KillerQueen.Year := 1974; KillerQueen.BeatPerMinute := 117.27; writeln(KillerQueen.Cancion); writeln(KillerQueen.Artista); writeln(KillerQueen.Album); writeln(KillerQueen.Year); writeln(KillerQueen.BeatPerMinute);
Una forma de agilizar el acceso al registro, es hacer uso de la palabra reservada "with", para ello, escribiremos "with" seguido del nombre del registro al cual queremos acceder seguido de de la palabra reservada "do", luego "begin", para poder acceder a los miembros solo bastará con escribir el nombre de cada campo; y cómo cada sección, la finalizaremos con su respectivo "end;". Ahora revisemos el siguiente código que ejemplifica lo anterior.
with Epitaph do begin Cancion := 'Epitaph.flac'; Artista := 'King Crimson'; Album := 'In the court of the crimson king'; Year := 1969; BeatPerMinute := 100.37; end;
Los registros son utiles a la hora de trabajar con estructuras de datos ya que una vez que se crean y se asignan los valores correspondientes, todo el conjunto pasara a ser parte de la misma variable y si por ejemplo asignamos "KillerQueen := Epitaph" tendremos una copia exacta del primero.
Solo por si se ofrece, dejo el código de un programa completo que hace uso de los registros.
program Registros(output);
uses crt, sysutils;
Type MiCancion = Record
Cancion,Artista,Album : string;
Year : Integer;
BeatPerMinute : single
end;
var
KillerQueen, Epitaph : MiCancion;
begin
KillerQueen.Cancion := 'Killer Queen.flac';
KillerQueen.Artista := 'Queen';
KillerQueen.Album := 'Sheer Heart Attack';
KillerQueen.Year := 1974;
KillerQueen.BeatPerMinute := 117.27;
writeln(KillerQueen.Cancion);
writeln(KillerQueen.Artista);
writeln(KillerQueen.Album);
writeln(KillerQueen.Year);
writeln(KillerQueen.BeatPerMinute);
with Epitaph do
begin
Cancion := 'Epitaph.flac';
Artista := 'King Crimson';
Album := 'In the court of the crimson king';
Year := 1969;
BeatPerMinute := 100.37;
end;
writeln(Epitaph.Cancion);
writeln(Epitaph.Artista);
writeln(Epitaph.Album);
writeln(Epitaph.Year);
writeln(Epitaph.BeatPerMinute);
readln();
end.Y bien, por ahora es todo. El código lo puedes copiar para probarlo. Antes de terminar, hay que aclarar algo, si bien en español, se puede leer "Record" cómo registro, no hay que confundirlo con "Register" que es una cosa completamente diferente (que eventualmente veremos).
Los leo luego.
Bienvenido el 2024
Hola de nuevo a todos, el día de hoy solo escribo para desearles a todos un buen año 2024. Cómo ya se va haciendo costumbre este año trataré de publicar al menos una entrada al mes; el año 2023 fue particularmente bueno y contrario a lo que se pensaría, esa fue la razón por la cual la actividad del blog bajo a niveles no vistos antes. Es bueno ver que aun hay gente que espera seguir leyendo los artículos y que los temas son bastante atinados para ellos. Sin más que decir, espero que sigan pasando a leer.
![]() |
| Si, 2024 y sigo usando mi PSP. |
Los leo luego.






























