PDA

Ver la Versión Completa : archivo mp3+texto


2-D@monic
29-07-2008, 04:13:26
saludos en el foro, tengo un pequeño problema, no domino el manejo de archivos en delphi y el trabajo que tengo que hacer es unir un archivo mp3 + archivo de texto todo en un solo archivo maestro. bueno lo que tengo que hacer es almacenar el archivo mp3 y su letra en un solo archivo, alguna sugerencia?..... creo que mínimamente debe usar estructuras o no?

Saludos.

Neftali [Germán.Estévez]
29-07-2008, 09:01:29
Supongo que puedes "montar" un archivo con estructura propia, incluyendo las dos partes. Padrías añadir al inicio un número de bytes fijos para dar información del tamaño de cada archivo y luego incluir los dos ficheros.

Otra opción, tal vez más sencilla para empezar, sea comprimir ambos archivos en uno sólo. Una vez que tu aplicación los vaya a reproducir, descomprimirlos y trabajar con ellos por separado.

Khronos
29-07-2008, 10:08:47
Lo que te sugiere Neftali puede ser una buena solución, si no también puedes almacenar el archivo mp3 y el archivo de texto como archivo de recursos dentro de una dll o dentro del propio ejecutable.. Si buscas por el foro encontrarás varios ejemplos de como hacer esto.

Salu2

2-D@monic
29-07-2008, 18:38:10
OK creo que usaré lo de la estructura lo que no me ubico como definir la estructura del archivo, bueno creo que sería lo siguiente:

type
archivo_compuesto = packed record
tam_mp3:byte
tam_text:byte
cont_mp3://que tipo de dato
cont_text://que tipo de dato

Khronos
29-07-2008, 19:33:54
Hola,te sugiero algo como esto (lo estoy haciendo a ojo sin el compilador delante).



uses Classes;

procedure FusionarArchivos (mp3, text, salida: string);
var
FMp3, FText, FSalida: TFileStream;
begin

FSalida:= TFileStream.Create(salida, fmCreate);
FText:= TFileStream.Create(text, fmOpenRead or fmShareDenyWrite);
FMp3:= TFileStream.Create(mp3, fmOpenRead or fmShareDenyWrite);

FSalida.CopyFrom(FMp3, FMp3.size);
FSalida.CopyFrom(FText, FText.size);

FSalida.free;
FMp3.free;
FText.free;

end;



Basicamente sería algo como eso, tambien se me ocurre guardar al final de este archivo datos con el tamaño de cada archivo con un record, algo como esto:


type
Datos = packed record
Mp3Size : integer;
TextSize: integer;
end;


Lo puedes hacer con la clase TFileStream y la función WriteBuffer.. Para separar los archivos tendrías que obtener el tamaño de cada archivo y moverte a través de él... te recomiendo que sigas usando la clase TFileStream.

Espero haberte ayudado.

Salu2

2-D@monic
29-07-2008, 19:48:19
Ok Khronos......... voy a ir probando compilando.......

2-D@monic
31-07-2008, 04:01:50
hola que tal........ les cuento que me fue:
construí un registro con los tamaños de los archivos:

type
tamanio_mp3texto = packed record
tam_mp3:integer;
tam_texto:integer;
end;


y el procedimiento guardar:

procedure guardar(amp3,atexto,acompuesto:string);
var
mp3,texto,compuesto:TFileStream;
tamanios:tamanio_mp3texto;
begin
mp3:=TFileStream.Create(amp3,fmOpenRead);
texto:=TFileStream.Create(atexto,fmOpenRead);
compuesto:=TFileStream.Create(acompuesto,fmCreate);
compuesto.CopyFrom(mp3,mp3.Size);
compuesto.CopyFrom(texto,texto.Size);
tamanios.tam_mp3:=mp3.Size;
tamanios.tam_texto:=texto.Size;
compuesto.WriteBuffer(tamanios,SizeOf(tamanios));
compuesto.Free;
mp3.Free;
texto.Free;
end;


Ahora para recuperar el archivo compuesto y "copiar" la parte del archivo mp3 hago lo siguiente:


procedure abrir(acompuesto:string);
var
compuesto,mp3,texto:TFileStream;
tamanio:tamanio_mp3texto;
cont:PChar;
begin
compuesto:=TFileStream.Create(acompuesto,fmOpenRead);
mp3:=TFileStream.Create('c:\prueba.mp3',fmCreate);
//me ubico para leer los tamaños de los archivos:
compuesto.Position:=compuesto.Size-8;
//recupero el tamaño del archivo mp3 y del texto
compuesto.Read(tamanio,sizeof(tamanio));
//posiciono al principio para copiar al archivo mp3
compuesto.Position:=0;
while (compuesto.Position<=tamanio.tam_mp3) do
begin
compuesto.Read(cont,sizeof(cont));
mp3.Write(cont,sizeof(cont));
compuesto.Position:=compuesto.Position+1;
end;
mp3.Free;
compuesto.Free;
end


El problema es que no copia realmente el archivo como debería puesto que al tratar de abrirlo no reproduce y el tamaño del archivo no es el correcto.

Alguna sugerencia............

Saludos

rcarrillom
31-07-2008, 09:21:16
2-D@monic, creo que no te has explicado bien, si te refieres a incluir la letra de una canción en un archivo mp3, no es simplemente fusionar ambos, como has mencionado, ya que el resultado será desconocido para muchos reproductores al no respetar tú la estructura normal de un mp3; debes:

Comprender la estructura de un mp3 (http://en.wikipedia.org/wiki/MP3)
Conocer el ID3v2 (http://www.id3.org/)
Revisar el estandar Lyrics3v2 (http://www.id3.org/Lyrics3v2).Hay componentes en delphi que manejan el ID3 como las Audio Tools Library (http://mac.sourceforge.net/atl/); te recomiendo que revises el código de la unidad ID3v2.pas para que comprendas el manejo de archivos.

Ya nos contarás cómo te fué. ;)

2-D@monic
31-07-2008, 17:07:37
gracias por la recomendación [rcarrillom] pero el programa que estoy haciendo va fusionar el archivo mp3 con el txt para crear un nuevo archivo que solo pueda abrir el programa que estoy haciendo (con otra extensión), no hay necesidad de que otro reproductor lo haga puesto que ese no es el objetivo.
Como les iba diciendo no puedo separar los archivos una vez fusionados, hasta el momento puedo recuperar sus tamaños con

compuesto.Position:=compuesto.Size-8;
//recupero el tamaño del archivo mp3 y del texto
compuesto.Read(tamanio,sizeof(tamanio));

porque como ven la estructura contiene dos tipos integer.
Al momento de recuperar con

while (compuesto.Position<=tamanio.tam_mp3) do
begin
compuesto.Read(cont,sizeof(cont));
mp3.Write(cont,sizeof(cont));
compuesto.Position:=compuesto.Position+1;
end;

no me recupera el archivo como debería. tal vez pueda ser porque la variables cont es tipo pchar; no se me ocurre otro tipo de dato que tiene que ser buffer según la ayuda de delphi, bueno en realidad puse pchar por un ejemplo que tenía la ayuda.
el archivo que guarda es de menor tamaño (casi 25% más pequeño) que el archivo mp3 original.

también les quiero comentar que al fusionar los archivos los guarda bien puesto que el tamaño concuerda con el archivo original más el texto añadido.

alguna sugerencia.........

saludos.

2-D@monic
31-07-2008, 17:26:52
Bueno...... el objetivo es leer un archivo mp3, leer un archivo de texto, unir ambos y guardarlos en un archivo compuesto (esto ya es posible gracias al códio de khronos) con otra extensión, al momento abrir el archivo compuesto separar los archivos mp3 y texto, y leerlos separadamente; al momento de separarlos lo único que se debe hacer es leer el bloque mp3 y todo ese bloque guardarlo en un archivo mp3 (hasta el momento no me sale), de manera que pueda ser utilizado separadamente, lo mismo para el archivo de texto.

saludos.

2-D@monic
31-07-2008, 19:16:18
Ok.......... ya se cual era el problema...... como estoy haciendo uso de un archivo de acceso directo en el cual no se su estructura lo más lógico es copiar byte por byte hasta el tamaño der archivo mp3, con lo cual el tipo de variable buffer con el cual almaceno cada registro es tipo byte, además ya no necesito posicionar el puntero del registro puesto que la ller con redbuffer la salta al siguiente registro, entonces la función sería así:

procedure abrir(acompuesto:string);
var
compuesto,mp3,texto:TFileStream;
tamanio:tamanio_mp3texto;
cont:byte;
begin
compuesto:=TFileStream.Create(acompuesto,fmOpenRead);
mp3:=TFileStream.Create('c:\prueba.mp3',fmCreate);
//me ubico para leer los tamaños de los archivos:
compuesto.Position:=compuesto.Size-8;
//recupero el tamaño del archivo mp3 y del texto
compuesto.Read(tamanio,sizeof(tamanio));
//posiciono al principio para copiar al archivo mp3
compuesto.Position:=0;
while (compuesto.Position<=tamanio.tam_mp3) do
begin
compuesto.Read(cont,sizeof(cont));
mp3.Write(cont,sizeof(cont));
end;
mp3.Free;
compuesto.Free;
end


como ven copio byte por byte al archivo mp3, lo compilé ejecutó y creo el archivo mp3 tal y es...........
pero hay un problema...........
como ven en el archivo estoy guardando el archivo mp3 en una ubicación del disco duro, (para ver si reproduce) pero lo que debería ser es que se cargue en memoria para poder utilizarlo para reproducirlo...... como puedo hacer esto?. me explico, una vez "separado" el archivo mp3 y el de texto debo reproducir el archivo con mediaplayer pero como ven al declarar el archivo lo guarda en alguna ubicación..... lo que sería bueno es que al momento de cargarlo no se guarde en ningún lado sino que esté en la memoria y pueda darle esa dirección al componente mediaplayer para que lo reproduzca...... puedo hacer eso?......... la solución que se me viene a la cabeza es guardarlo temporalmente en el disco duro, reproducirlo desde esa dirección y una vez cerrado el programa eliminarlo.....

Alguna sugerencia........

saludos.

Khronos
31-07-2008, 22:18:21
Hola 2-D@monic, como te dije con los TFileStream se soluciona rapidamente.. Te hice un ejemplo que funciona perfectamente, une un archivo mp3 y un archivo de texto y te permite separarlos... está en el archivo adjunto.

Lo mejor es lo que tu dices, guardarlo temporalmente y luego eliminarlo..

Salu2

2-D@monic
01-08-2008, 04:20:30
Ok khronos todo bien......... creo que sí.... guardaré temporalmente los archivos.