PDA

View Full Version : [C] File audio MP3: devo leggerne l'Header x saperne la lunghezza in tempo?!


Matrixbob
13-06-2007, 13:15
Ebbene 1 mio incubo è diventato realtà! :O
Devo derminare anche per gli MP3 e gli AVI la rispettiva lunghezza in tempo. :eek:

Praticamente questo 3D potrebbe essere considerato il gemello di quest'altro, o la sua continuazione:
[C] File audio WAV: devo leggerne l'Header x saperne la lunghezza in tempo?! (http://www.hwupgrade.it/forum/showthread.php?t=1473617)

Spero che si possano poi mettere in rilievo x tutti gli altri utenti a venire.

Intanto inizio a Goglare x vedere cosa trovo, inizialmente avevo anche pensato di trasformare il file MP3 in WAV, ma adesso vedo se ci sono altre strade. :)

Matrixbob
13-06-2007, 13:18
Mooolto improbabile, ma magari esiste una qualche libreria unica o per ogni tipo del MIME possibile:
[RSS/ATOM] Gli enclosure video, di che tipo possono essere?! (http://www.hwupgrade.it/forum/search.php?searchid=2783530)

[EDIT]
Info trovate su questo forum da tenere da conto:
C# Riprodurre Mp3 (http://www.hwupgrade.it/forum/showthread.php?t=1477838)
[C#]File mp3 (http://www.hwupgrade.it/forum/showthread.php?t=1471084)
c++ e mp3 (http://www.hwupgrade.it/forum/showthread.php?t=1329395)
[C][libreria almp3 di allegro] Strano problema... (http://www.hwupgrade.it/forum/showthread.php?t=1247398)

andbin
13-06-2007, 14:14
La soluzione che ho pensato io è di usare le funzioni MCI (Media Control Interface) di Windows.

Con MCI è possibile gestire qualunque audio/video a patto di avere l'apposito codec. A partire da Windows 2000 il codec per MP3 c'è.

Ho scritto questo sorgente di prova, non è il massimo come struttura e gestione degli errori ma è una buona base di partenza.

#define STRICT
#include <windows.h>
#include <stdio.h>

int main (int argc, char *argv[])
{
MCIERROR mciErr;
MCI_OPEN_PARMS mciOpen;
MCI_SET_PARMS mciSet;
MCI_STATUS_PARMS mciStatus;
MCI_GENERIC_PARMS mciGen;

if (argc == 2)
{
mciOpen.dwCallback = (DWORD_PTR) NULL;
mciOpen.lpstrDeviceType = (char*) MCI_ALL_DEVICE_ID;
mciOpen.lpstrElementName = argv[1];
mciOpen.lpstrAlias = NULL;

if ((mciErr = mciSendCommand ((MCIDEVICEID) NULL, MCI_OPEN, MCI_OPEN_ELEMENT | MCI_WAIT, (DWORD) &mciOpen)) == 0)
{
mciSet.dwCallback = (DWORD_PTR) NULL;
mciSet.dwTimeFormat = MCI_FORMAT_MILLISECONDS;

if ((mciErr = mciSendCommand (mciOpen.wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT | MCI_WAIT, (DWORD) &mciSet)) == 0)
{
mciStatus.dwCallback = (DWORD_PTR) NULL;
mciStatus.dwItem = MCI_STATUS_LENGTH;

if ((mciErr = mciSendCommand (mciOpen.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) &mciStatus)) == 0)
{
printf ("Lunghezza: %lu millisecondi\n", mciStatus.dwReturn);
}
}

mciGen.dwCallback = (DWORD_PTR) NULL;

mciErr = mciSendCommand (mciOpen.wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD) &mciGen);
}
}

return 0;
}
Note:
1) Linkare con la libreria winmm.lib.

2) Ho provato con un file .AVI e funziona. Non ho potuto provare .WAV e .MP3 perché sono in ufficio e non ho la scheda audio. :rolleyes: Sembra infatti che se non c'è la possibilità di fare "output", il messaggio MCI_OPEN fallisce (il ragionamento non fa una piega ... se non posso riprodurre, cosa apro il file a fare? :D ).

Matrixbob
13-06-2007, 18:02
I get it!
Adesso spesa lampo sotto casa e stasera lo provo.
TNX. :D

andbin
13-06-2007, 19:53
Provato adesso a casa con .wav, .mid (MIDI), .mov (QuickTime) e .mp3. Funziona benone.

Matrixbob
13-06-2007, 21:52
Provato adesso a casa con .wav, .mid (MIDI), .mov (QuickTime) e .mp3. Funziona benone.

Provato con WAV & MP3, adesso provo 1 AVI.

Se funziona allora per la miseriaccia, qui ti sei superato, con meno codice si fa D+!

Queste librerie MCI devono essere di fatto superiori alle Windows' MultiMedia (File) I/O (MMIO), ovvero "mmsystem.h" (http://www.borg.com/~jglatt/tech/mmio.htm).
Tra l'altro sono tutte incluse nello stesso windows.h.

Per completezza:
MCI su MSDN (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_mci.asp)
Con MCI si può gestire qualunque formato audio-video a patto di avere un apposito CoDec.
A partire da Win2k il CoDec per MP3 ad esempio c'è nel SO.

ed il POST gemello:
[C] File audio WAV: devo leggerne l'Header x saperne la lunghezza in tempo?! (http://www.hwupgrade.it/forum/showthread.php?t=1473617)

andbin
14-06-2007, 11:51
Queste librerie MCI devono essere di fatto superiori alle Windows' MultiMedia (File) I/O (MMIO), ovvero "mmsystem.h" (http://www.borg.com/~jglatt/tech/mmio.htm).
Tra l'altro sono tutte incluse nello stesso windows.h.Beh, sono a due livelli diversi. Le funzioni mmioXXX permettono di accedere direttamente a file RIFF, mentre MCI è una interfaccia generica ad alto livello per poter operare su risorse multimediali di diverso tipo.

Matrixbob
14-06-2007, 12:10
Beh, sono a due livelli diversi. Le funzioni mmioXXX permettono di accedere direttamente a file RIFF, mentre MCI è una interfaccia generica ad alto livello per poter operare su risorse multimediali di diverso tipo.

Ma non è buona norma della programmazione usare il + alto livello là dove è possibile?!
In modo da non reinventare la ruota intendo ...

Cosa ci guadagno a lavorare con le MMIO al posto di queste ultime MCI?!
Ci guadagno in controllo?!
Ci perdo in portabilità verso Linux?!

andbin
14-06-2007, 12:55
Ma non è buona norma della programmazione usare il + alto livello là dove è possibile?!
In modo da non reinventare la ruota intendo ...Dipende sempre da cosa si deve fare realmente. Con le funzioni mmioXXX hai il controllo completo di un file RIFF. Puoi leggere gli header, i campioni audio, ecc... Con MCI no. MCI poi ha il difetto a cui avevo accennato prima: se non c'è un dispositivo di riproduzione (scheda audio) i file audio non li apri con MCI.

Cosa ci guadagno a lavorare con le MMIO al posto di queste ultime MCI?!
Ci guadagno in controllo?!L'unico guadagno è appunto il controllo sul file.

Ci perdo in portabilità verso Linux?!In ogni caso, visto che le funzionalità di "multimedia" sono profondamente diverse tra differenti sistemi operativi.

Matrixbob
14-06-2007, 13:19
Dipende sempre da cosa si deve fare realmente. Con le funzioni mmioXXX hai il controllo completo di un file RIFF. Puoi leggere gli header, i campioni audio, ecc... Con MCI no. MCI poi ha il difetto a cui avevo accennato prima: se non c'è un dispositivo di riproduzione (scheda audio) i file audio non li apri con MCI.

E' un riferimento indiretto della API del SO immagino, non un riferimento diretto del HW. Giusto?!
Intendo che le API controllano se è presente l'HW con qalche System Call e se questo NON c'è sono impostate per dare errore e crepare.
Tutto in maniera trasparente al programmatore.


L'unico guadagno è appunto il controllo sul file.

Per imparare ad arrangiarmi e NON + a chiedere, anche se è bello discorrere con altri programmatori:
ogni volta che voglio programmare qualcosa in C, come in questo caso lo smanettamento nei sistemi multimediali, devo andare a vedere su MSDN se c'è qualcosa che fa al caso mio e poi decidere cosa voglio e poi procedere?!


In ogni caso, visto che le funzionalità di "multimedia" sono profondamente diverse tra differenti sistemi operativi.

Quindi finchè programmo in C la portabilità è 1 sogno.
Cosa ci vorrebbe, il JAVA?!

tomminno
14-06-2007, 14:17
Quindi finchè programmo in C la portabilità è 1 sogno.
Cosa ci vorrebbe, il JAVA?!

Guarda che là fuori è pieno di librerie multipiattaforma per leggere i file multimediali.
Dopotutto visto che sono solo dei parser di strutture predefinite non c'è motivo per cui debbano essere legati ad una specifica piattaforma software.

andbin
14-06-2007, 14:18
E' un riferimento indiretto della API del SO immagino, non un riferimento diretto del HW. Giusto?!
Intendo che le API controllano se è presente l'HW con qalche System Call e se questo NON c'è sono impostate per dare errore e crepare.
Tutto in maniera trasparente al programmatore.Esatto, le funzioni MCI controlleranno, penso in qualche modo, se c'è un device di riproduzione apposito per quel tal media.
Tra le API per il multimedia c'è una funzione UINT waveOutGetNumDevs(VOID) che fa nient'altro che ritornare il numero di dispositivi audio di output (sul mio PC d'ufficio che non ha scheda audio, ritorna un bel 0). È ipotizzabile che MCI usi questa funzione per sapere se è possibile riprodurre un file audio. Ovviamente non ne posso essere sicuro .....

Per imparare ad arrangiarmi e NON + a chiedere, anche se è bello discorrere con altri programmatori:
ogni volta che voglio programmare qualcosa in C, come in questo caso lo smanettamento nei sistemi multimediali, devo andare a vedere su MSDN se c'è qualcosa che fa al caso mio e poi decidere cosa voglio e poi procedere?!Se ti riferisci al solo Windows, sì. MSDN è la bibbia per chi sviluppa su Windows.
Poi comunque chiedi pure, se hai dubbi.

Quindi finchè programmo in C la portabilità è 1 sogno.Ci sono librerie apposite cross-platform ma il problema è solo "spostato". Non sei quindi tu a doverti preoccupare della compatibilità ma c'è stato qualcun'altro che si è preoccupato di "incapsulare" i dettagli sulle differenze tra i vari S.O. e di esporre al programmatore una API comune.

Cosa ci vorrebbe, il JAVA?!Java in effetti ha delle API standard per il multimedia. ;)

Matrixbob
14-06-2007, 14:59
Guarda che là fuori è pieno di librerie multipiattaforma per leggere i file multimediali.
Dopotutto visto che sono solo dei parser di strutture predefinite non c'è motivo per cui debbano essere legati ad una specifica piattaforma software.

Sarà pur pieno ma:

1]
Non riesco a trovarle, manco googlando o coi tools di Google, saranno in decima pagina forse. :boh:

2]
Se ci sono, non son ben conosciute o descritte, non sono pubblicizzate insomma. :(

3]
Se ci fosse 1 posto dove trovarle tutte, un po' come DistroWatch.com per le distribuzioni di Linux, tutto sarebbe + semplice.

4]
Penso che ci saranno anche N librerie x stampare a video, ma io mi riferivo a qualcosa di "standard" o CMQ "standard de facto".

Matrixbob
14-06-2007, 15:13
Esatto, le funzioni MCI controlleranno, penso in qualche modo, se c'è un device di riproduzione apposito per quel tal media.
Tra le API per il multimedia c'è una funzione UINT waveOutGetNumDevs(VOID) che fa nient'altro che ritornare il numero di dispositivi audio di output (sul mio PC d'ufficio che non ha scheda audio, ritorna un bel 0). È ipotizzabile che MCI usi questa funzione per sapere se è possibile riprodurre un file audio. Ovviamente non ne posso essere sicuro .....

Ma queste librerie MMIO & MCI si possono propriamente chiamare Application Programming Interface (API) (http://it.wikipedia.org/wiki/Application_programming_interface) ?!!
Una applicazione sviluppata con queste windows.h inside la posso usare SOLO su Windows XP e Windows Vista?!


Se ti riferisci al solo Windows, sì. MSDN è la bibbia per chi sviluppa su Windows.
Poi comunque chiedi pure, se hai dubbi.

Prima o poi come tutti vorrei imparare a prendere il volo da solo, ma la trovo molto dura per ora. :(


Ci sono librerie apposite cross-platform ma il problema è solo "spostato". Non sei quindi tu a doverti preoccupare della compatibilità ma c'è stato qualcun'altro che si è preoccupato di "incapsulare" i dettagli sulle differenze tra i vari S.O. e di esporre al programmatore una API comune.

Quindi se queste API si basano sun System Call, le stesse API si preoccuperano di scegliere quale System Call di SO fare, almeno questo immagino.


Java in effetti ha delle API standard per il multimedia. ;)

Già il C++ ed il C# non mi paiono completamente standarizzati, quindi il Java mi affascina parecchio.
Il fatto di utilizzare la struttura PILA (STACK) ad esempio con la propria classe ed i propri metodi e fare le estensioni, etc... lo trovo una figata.

tomminno
14-06-2007, 16:59
Sarà pur pieno ma:

1]
Non riesco a trovarle, manco googlando o coi tools di Google, saranno in decima pagina forse. :boh:


Le prime che mi vengono in mente: libmad, lame (si può usare anche per decodificare gli mp3), libavcodec (guardati un pò FFMpeg).


2]
Se ci sono, non son ben conosciute o descritte, non sono pubblicizzate insomma. :(


FFMpeg è abbastanza conosciuto, lame tanto sconosciuto poi non è.


3]
Se ci fosse 1 posto dove trovarle tutte, un po' come DistroWatch.com per le distribuzioni di Linux, tutto sarebbe + semplice.


Basta impostare le parole giuste su google.
Se cerchi "mp3 decoder source" nella prima pagina trovi 2 delle 3 alternative che ti ho dato.


4]
Penso che ci saranno anche N librerie x stampare a video, ma io mi riferivo a qualcosa di "standard" o CMQ "standard de facto".

In un mondo variegato trovare "standard de facto" è un'utopia.
Inoltre se cerchi uno standard de facto sicuramente non puoi usare le API Win32 che standard non sono.

Comunque solo per ribadire che la portabilità in C non è per niente un'utopia, anzi è il linguaggio più portabile che esista.
Pensa un pò per quante piattaforme è disponibile Java (la JVM chissà con cosa sarà scritta...), il C ANSI ne supporta anche di più!

Matrixbob
16-06-2007, 14:11
printf ("Lunghezza: %lu millisecondi\n", mciStatus.dwReturn);
%lu indica "intero lungo senza segno"?! :stordita:
Quindi da 32 a 64 bit?! :mbe:

... dovrebbe essere così perchè L indica il "long double" mi pare e quindi con la virgola mobile.

andbin
16-06-2007, 19:45
%lu indica "intero lungo senza segno"?!Esatto, un unsigned long int, a 32 bit (che poi è il tipo di dato DWORD).

L indica il "long double" mi pare e quindi con la virgola mobile.Esatto.

Matrixbob
28-06-2007, 11:10
Sempre con Andbin stiamo lavorando al fatto che fallisce la lettura dei file MP4 intesi come contenitore A-V in AVI's style.

Col codice che segue viene riportato a video il nomero del errore:

#define STRICT
#include <windows.h>
#include <stdio.h>

int main (int argc, char *argv[])
{
MCIERROR mciErr;
MCI_OPEN_PARMS mciOpen;
MCI_SET_PARMS mciSet;
MCI_STATUS_PARMS mciStatus;
MCI_GENERIC_PARMS mciGen;
char stringa[512];

if (argc == 2)
{
mciOpen.dwCallback = (DWORD_PTR) NULL;
mciOpen.lpstrDeviceType = (char*) MCI_DEVTYPE_DIGITAL_VIDEO;
mciOpen.lpstrElementName = argv[1];
mciOpen.lpstrAlias = NULL;

if ((mciErr = mciSendCommand ((MCIDEVICEID) NULL, MCI_OPEN, MCI_OPEN_ELEMENT | MCI_WAIT, (DWORD) &mciOpen)) == 0)
{
mciSet.dwCallback = (DWORD_PTR) NULL;
mciSet.dwTimeFormat = MCI_FORMAT_MILLISECONDS;

if ((mciErr = mciSendCommand (mciOpen.wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT | MCI_WAIT, (DWORD) &mciSet)) == 0)
{
mciStatus.dwCallback = (DWORD_PTR) NULL;
mciStatus.dwItem = MCI_STATUS_LENGTH;

if ((mciErr = mciSendCommand (mciOpen.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD) &mciStatus)) == 0)
{
printf ("Lunghezza: %lu millisecondi\n", mciStatus.dwReturn);
}
else
{
mciGetErrorString(mciErr, stringa, 512);
printf("\nERRORE 1: %d> %s\n", mciErr, stringa);
}

}
else
{
mciGetErrorString(mciErr, stringa, 512);
printf("\nERRORE 2: %d> %s\n", mciErr, stringa);
}

mciGen.dwCallback = (DWORD_PTR) NULL;
mciErr = mciSendCommand (mciOpen.wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD) &mciGen);
}
else
{
mciGetErrorString(mciErr, stringa, 512);
printf("\nERRORE 3: %d> %s\n", mciErr, stringa);
}

return 100;
}
else
{
printf("\nERRORE 4!\n");
return -100;
}

}

, che risulta essere:

http://img526.imageshack.us/img526/9639/erroreia1.gif

Quindi 281 - 256 (della base) = 25


#define MCIERR_MULTIPLE (MCIERR_BASE+24)
#define MCIERR_EXTENSION_NOT_FOUND (MCIERR_BASE+25)
#define MCIERR_OUTOFRANGE (MCIERR_BASE+26)


Il che dovrebbe indicare:

MCIERR_EXTENSION_NOT_FOUND:
"Impossibile determinare il tipo di dispositivo dall'estensione data."
"The specified extension has no device type associated with it. Specify a device type."
"L'estensione specificata non ha tipo di dispositivo connesso con esso. Specifichi un tipo di dispositivo."

Il che mi lascia così :eek: perchè non capisco che cavolo di dispositivo stia cercando. :boh:
Come si specificano i dispositivi?! :mbe:

Matrixbob
28-06-2007, 11:25
Questo link:
Impossibile determinare la periferica dall'estensione di nome di file specificato (http://support.microsoft.com/kb/171667/it)

lo si trova cercando su Google la stringa che si è fatta stampare nel codice:
mciGetErrorString(mciErr, stringa, 512);
printf("\nERRORE 1: %d> %s\n", mciErr, stringa);

Quindi basta andare ad aggiungere la stringa:
mp4 con valore MPEGVideo
in quella chiave di registro.

http://img522.imageshack.us/img522/3574/mciextensionswv5.png

Matrixbob
12-07-2007, 21:09
Possibile che installando dei CoDec differenti la funzione che usa le MCI scazzi la lunghezza del file?

Io ho questo MP3:
iTourist_presentazione.mp3 (http://oasi.asti.it/Homes/Borrino/iTourist_presentazione.mp3)
da 1m17s e invece mi ritorna una bella lunghezza di 2m21s ovvero 141632ms.

Praticamente dal K-Lite sono passato al:
ffdshow (http://x264.nl/)
+
Haali (http://haali.cs.msu.ru/mkv/MatroskaSplitter.exe)

Matrixbob
12-07-2007, 21:33
L'esperimento che ho fatto pare dire proprio di si:

http://img102.imageshack.us/img102/70/asd3is4.gif

[NB]
L'esperimento è consistito nel usare l'uno o l'altro pacco.
Niente D+. ...