|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Member
Iscritto dal: Sep 2005
Città: Bus PCI 1, periferica 0, funzione 0 (Torino)
Messaggi: 213
|
[C] leggere un file wave bit a bit
Ciao a tutti, ho un problema che mi assilla da qualche giorno, e non riesco a trovare la soluzione...
![]() Vorrei leggere un file .wav bit a bit, proprio fisicamente come è scritto sull'hdd, ma ho problemi quando si tratta di andare a leggere il file, il massimo che riesco a fare è un fread() ma praticamente mi vengono letti dei numeri interi positivi (che credo sia codice ascii ma non sono sicuro)... Ho provato anche ad aprire il file in modalità binaria con fopen(file,"rb") ma niente da fare, non cambia nulla... C'è qualcuno che potrebbe dirmi come implementare una cosa del genere con C ?? (Io utilizzo Dev-Cpp per lo sviluppo) Grazie 1000 anticipatamente ![]()
__________________
Ho concluso affari con: Ippo 2001, Klintf, albert78, Piripikkio, starsky, oldfield e IL0V€INT€R. da EVITARE zarovat |
![]() |
![]() |
![]() |
#2 | ||
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Sappi che non è comunque banalissimo leggere un file wave (ma neanche complicatissimo!). I file wave hanno un formato e una struttura ben precisa. I dati e le informazioni contenute in un file wave sono suddivise in quelli che vengono chiamati chunk. Un tipico file wave ha in genere come minimo 3 chunks: un chunk iniziale di tipo "RIFF" che è la testata del file, un altro chunk di tipo "fmt" che contiene le informazioni generali sui campioni audio e un terzo chunk di tipo "data" che contiene i campioni audio veri e propri. Le specifiche del formato wave le trovi facilmente su internet. Ecco alcuni link: 1) Wotsit (cerca poi lì dentro il formato wave) 2) Wave Files - The Sonic Spot 3) WAVE PCM soundfile format A questo punto capisci che bisognerebbe sapere cosa vuoi fare di preciso. Ci sono sostanzialmente almeno 2 possibilità per estrarre i dati da un file wave. La prima è quella di imparare le specifiche e la struttura dei file wave ed usare le funzioni di base dell'I/O (fopen, fread, ecc...) per leggere e decodificare i dati contenuti nel file. La seconda è quella di utilizzare funzioni o meglio librerie già fatte per leggere i dati in un file wave. La Microsoft mette a disposizione una serie di funzioni Win32 per gestire proprio i file audio. Tutta la documentazione relativa alla gestione dei multimedia file in Win32 la trovi a partire da questo link: MSDN - Multimedia File I/O Quote:
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||
![]() |
![]() |
![]() |
#3 |
Member
Iscritto dal: Sep 2005
Città: Bus PCI 1, periferica 0, funzione 0 (Torino)
Messaggi: 213
|
L'idea è venuta fuori ad un mio amico che deve stendere una monografia che fa vedere come da un file .wav si può campionarlo e quantizzarlo emulando praticamente quello che è un mp3, con la teoria studiata ai corsi di Elaborazione dei Segnali...
Praticamente se non ho capito male a lui servirebbe lo stream di bit da campionare e quantizzare, però da quanto ho capito da quello che mi hai scritto i file wav hanno una struttura particolare... Ok allora dò un'occhiata e ti faccio sapere... Ma in particolare, poi avendo a portata di mano la struttura del file wav e il formato con cui devo leggere i dati, quindi poi va bene l'uso di fread() giusto? Ho dato meglio un'occhiata alla fread e ho letto che è fatta così size_t fread(void *ptr, size_t dim, size_t nmemb, FILE *stream) solo che non riesco a capire bene come devo usare "dim" e "nmemb"...ho anche spulciato fra gli header, ma ho trovato niente sullo struct "size_t"...
__________________
Ho concluso affari con: Ippo 2001, Klintf, albert78, Piripikkio, starsky, oldfield e IL0V€INT€R. da EVITARE zarovat |
![]() |
![]() |
![]() |
#4 | ||
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
![]() Quote:
Per quanto riguarda la fread() ed anche l'opposta fwrite(), i due parametri dim e nmemb servono per specificare alle due funzioni quanti byte leggere/scrivere secondo la seguente formula: dim * nmemb; In pratica leggono un certo numero di blocchi specificato da nmemb, ognuno di lunghezza dim. Nota importante: le due funzioni restituiscono un valore di tipo size_t che indica il numero di elementi letti. Se metti dim=10 e nmemb=2 e la fread va a buon fine cioè legge 20 bytes, ti restituisce 2 (non 20!!). Ti faccio subito un esempio per la lettura del primo blocco RIFF del file wave (nota, presuppongo l'utilizzo in Windows, poiché userò dei tipi di dati definiti nel Platform SDK di Windows): Codice:
#pragma pack(1) typedef struct { CHAR id[4]; DWORD length; } RIFF_HEADER; #pragma pack() RIFF_HEADER riff_hdr; size_t len_read; len_read = fread (&riff_hdr, 1, sizeof (RIFF_HEADER), f); if (len_read == sizeof (RIFF_HEADER)) { ..ok lettura corretta.. }
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||
![]() |
![]() |
![]() |
#5 |
Member
Iscritto dal: Sep 2005
Città: Bus PCI 1, periferica 0, funzione 0 (Torino)
Messaggi: 213
|
Perfetto...
Cercando in internet sulla base di quello che mi hai scritto ho trovato questo codice... Codice:
void Load_Wave_File(char *fname) { FILE *fp; fp = fopen(fname,"rb); if (fp) { BYTE id[4], *sound_buffer; //four bytes to hold 'RIFF' DWORD size; //32 bit value to hold file size short format_tag, channels, block_align, bits_per_sample; //our 16 values DWORD format_length, sample_rate, avg_bytes_sec, data_size, i; //our 32 bit values fread(id, sizeof(BYTE), 4, fp); //read in first four bytes if (strcmp(id, "RIFF")) { //we had 'RIFF' let's continue fread(&size, sizeof(DWORD), 1, fp); //read in 32bit size value fread(id, sizeof(BYTE), 4, fp); //read in 4 byte string now if (strcmp(id,"WAVE")) { //this is probably a wave file since it contained "WAVE" fread(id, sizeof(BYTE), 4, fp); //read in 4 bytes "fmt "; fread(&format_length, sizeof(DWORD),1,fp); fread(&format_tag, sizeof(short), 1, fp); //check mmreg.h (i think?) for other // possible format tags like ADPCM fread(&channels, sizeof(short),1,fp); //1 mono, 2 stereo fread(&sample_rate, sizeof(DWORD), 1, fp); //like 44100, 22050, etc... fread(&avg_bytes_sec, sizeof(short), 1, fp); //probably won't need this fread(&block_align, sizeof(short), 1, fp); //probably won't need this fread(&bits_per_sample, sizeof(short), 1, fp); //8 bit or 16 bit file? fread(id, sizeof(BYTE), 4, fp); //read in 'data' fread(&data_size, sizeof(DWORD), 1, fp); //how many bytes of sound data we have sound_buffer = (BYTE *) malloc (sizeof(BYTE) * data_size); //set aside sound buffer space fread(sound_buffer, sizeof(BYTE), data_size, fp); //read in our whole sound data chunk } else printf("Error: RIFF file but not a wave file\n"); } else printf("Error: not a RIFF file\n"); } } Domanda extra: E se volessi sentire questo file wave, (una volta streamizzato in memoria) dovrei andare ad utilizzare funzioni proprie di windows perchè sarebbe praticamente impossibile scrivere da zero una procedura che faccia riprodurre alla scheda audio lo stream giusto? Grazie ancora!
__________________
Ho concluso affari con: Ippo 2001, Klintf, albert78, Piripikkio, starsky, oldfield e IL0V€INT€R. da EVITARE zarovat |
![]() |
![]() |
![]() |
#6 | ||
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
![]() Il mio consiglio è quello di creare delle strutture per gestire gli header dei chunk. Poi comunque fai tu ... Quote:
Altrimenti c'è l'approccio a basso livello. Tu leggi e decodifichi il file per conto tuo e tramite un sistema di buffering basato su callback/eventi puoi passare a Windows i campioni da riprodurre man mano che servono. Tenersi tutto l'intero file wave in memoria va bene solo se il file è davvero piccolo. Tieni presente infatti che i file wave sono abbastanza "spreconi" in fatto di spazio occupato, proprio perché tipicamente non sono compressi. Comunque trovi tutte le informazioni <qui>.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||
![]() |
![]() |
![]() |
#7 | |
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
if (strncmp (id, "RIFF", 4) == 0)
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
![]() |
![]() |
![]() |
#8 | |
Member
Iscritto dal: Sep 2005
Città: Bus PCI 1, periferica 0, funzione 0 (Torino)
Messaggi: 213
|
Quote:
Comunque ora sono riuscito a mettere in memoria il mio bel file wave, proprio come volevo, adesso mi metterò a pensare come posso realizzare una funzione a basso livello per "suonare" la memoria ![]() Grazie ancora andbin, sei un mago ![]()
__________________
Ho concluso affari con: Ippo 2001, Klintf, albert78, Piripikkio, starsky, oldfield e IL0V€INT€R. da EVITARE zarovat |
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 10:49.