View Full Version : [C++]Riprodurre un file audio
christiantric
30-10-2008, 11:17
Salve a tutti,
è da tanto che non sono alle prese con c++ per cui chiedo aiuto per una cosa che non ho mai fatto.
Devo riprodurre un file audio (qualsiasi formato va bene) al verificarsi di un certo evento.
Lavoro su un sistema unix (Linux Ubuntu Hardy) ed avevo letto qualcosa che faceva intendere si postesse fare con l'ausilio della sola <stdio.h>.
Potete darmi qualche suggerimento?
Grazie :D
Credo che sia possibile suonare un file audio su linux solo con stdio !!!
ma probabilmente devi aver installato dei driver che gestiscono la cosa.
ed a quel punto basta aprire il file giusto sotto /dev
vedi questo esempio credo che ti può essere di aiuto:
http://users.powernet.co.uk/kienzle/octave/matcompat/scripts/audio/aurecord.cc
anche questa guida credo ti sia utile:
http://www.oreilly.de/catalog/multilinux/excerpt/ch14-05.htm
christiantric
30-10-2008, 14:15
Grazie tglman ci dò subito un'occhiata!!:)
christiantric
31-10-2008, 12:08
Grazie alla guida sopra linkata forse ho capito che direzione prendere tuttavia non sto riuscedo a riprodurre il contenuto di un file audio.
L'esempio proposto per programmare /dev/dsp permette di registrare un audio di 3 secondi e di riprodurlo.
Ho visto che per registrare utilizza la funzione read allora ho pensato:
audio = open("/home/jacktric/Scrivania/Provadir/prova_audio.wav", O_RDONLY);
status = read(audio, buf, sizeof(buf)); /* mette il contenuto del file audio in buf */
status = write(fd, buf, sizeof(buf)); /* play it back */
per portare il contenuto del file "prova_audio.wav" nel buffer "buf".
In realtà però quando riproduco scrivendo nel file dsp mi viene fuori un suono pazzesco che nulla centra con quello della traccia!!
Vi prego come posso fare ci sto perdendo i giorni!!:muro:
tomminno
31-10-2008, 13:37
per portare il contenuto del file "prova_audio.wav" nel buffer "buf".
In realtà però quando riproduco scrivendo nel file dsp mi viene fuori un suono pazzesco che nulla centra con quello della traccia!!
Vi prego come posso fare ci sto perdendo i giorni!!:muro:
Per forza il file wav contiene anche degli header, mentre la scheda audio si aspetta solo campioni PCM.
Devi prima usare una libreria per leggere gli wav (o scrivertela da te) e poi passare i campioni ottenuti alla scheda audio.
Io ti consiglio la libreria libsndfile (http://www.mega-nerd.com/libsndfile/)
Oppure usi aplay richiamandolo con fork - exec. Certo funziona solo se è presente ALSA nel sistema.
christiantric
31-10-2008, 16:08
Signori per me state parlando arabo (sopratutto cionci) comunque vi ringrazio per il vostro intervento e mi metto subito a studiare le possibilità da voi esposte!!
Certo che se mi fareste un piccolo banale esempio se ce lo avete a portata...:D
christiantric
03-11-2008, 17:06
Ragazzi, ma è possibile che sia così difficile riprodurre un file audio?
Ci sto provando da giorni ormai...vi posto un pò di codice a cui sono giunto ditemi per favore cosa non va (ho usato la libreria libsndfile)
#include <stdio.h>
#include <linux/soundcard.h>
#include <sndfile.h>
int main()
{
int fd; /* sound device file descriptor */
int arg; /* argument for ioctl calls */
int status; /* return status of system calls */
int audio; /* audio da riprodurre file descriptor */
SF_INFO sfinfo;
sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_32;
sfinfo.samplerate = 22050;
sfinfo.channels = 1;
sfinfo.frames = 123456789 ;
char *filename ;
filename = "/home/jacktric/Scrivania/Provadir/prova_audio.wav";
/* apro il file audio da riprodurre in lettura */
SNDFILE* sf_audio;
sf_audio = sf_open(filename, SFM_READ, &sfinfo);
if (sf_audio == NULL) {
perror("open of file audio failed");
exit(1);
}
/* open sound device */
SNDFILE* sf_fd;
sf_fd = sf_open("/dev/dsp", SFM_WRITE, &sfinfo);
if (sf_fd == NULL) {
perror("open of /dev/dsp failed");
exit(1);
}
sf_command (sf_fd, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
/* Operazioni di lettura audio ed esecuzione */
int intptr[659924];
int status_read;
status_read = sf_read_int(sf_audio, intptr, 659924);
printf("status_read: %d\n", status_read);
int status_write;
status_write = sf_write_int(sf_fd, intptr, 659924);
printf("status_write: %d\n", status_write);
int close;
close = sf_close(sf_audio);
close = sf_close(sf_fd);
}
Ci sara' anche un motivo per cui i giochi sotto Linux non sono molto diffusi.
Sotto Windows, in C#
SoundPlayer sp = new SoundPlayer(@"C:\WINDOWS\Media\tada.wav");
sp.Play();
Ci sara' anche un motivo per cui i giochi sotto Linux non sono molto diffusi.
Le system call in unix/linux solitamente non implementano funzioni di alto livello, basta in ogni caso usare una libreria, OpenAL, SDL etc etc.
[OT]
Ci sara' anche un motivo per cui i giochi sotto Linux non sono molto diffusi. e mica solo quello: DirectX dove lo metti? :read:
Sotto Windows, in C#
SoundPlayer sp = new SoundPlayer(@"C:\WINDOWS\Media\tada.wav");
sp.Play();
niubboh, posso fare di meglio:
new SoundPlayer(@"C:\WINDOWS\Media\tada.wav").Play();
una sola riga :ciapet:
Le system call in unix/linux solitamente non implementano funzioni di alto livello in Windows invece si:
http://msdn.microsoft.com/en-us/library/ms712879.aspx
:Prrr:
Ci sta sempre OpenAL + ogg Vorbis... ma poi appunto puoi usare solo gli .ogg.
in Windows invece si:
http://msdn.microsoft.com/en-us/library/ms712879.aspx
:Prrr:
Lo so, questo perché il sound server su Linux/Unix non è parte integrante del kernel.
tomminno
04-11-2008, 08:42
Ci sara' anche un motivo per cui i giochi sotto Linux non sono molto diffusi.
Sotto Windows, in C#
SoundPlayer sp = new SoundPlayer(@"C:\WINDOWS\Media\tada.wav");
sp.Play();
OT per OT scriveresti un software per riprodurre musica usando un wrapper del PlaySound?
Io credo proprio di no.
Ad esempio su linux se dovessi fare un player utilizzerei libsox. Apro un file (il bello è che supporta molti formati), estraggo i campioni PCM e poi lo butto su /dev/dsp.
Praticamente si riesce a fare un player audio multiformato in 20 linee di codice.
christiantric
04-11-2008, 09:15
Mmmm...:confused: ...da questa vostra piccola discussione dovrei ricavare la soluzione del mio problema??
Nessuno che abbia usato ste libsndfile per riprodurre un file audio?
Mi state per caso suggerendo qualche via alternativa?
Le proposte windowsniane sono molto allettanti ma io mi trovo sotto Linux e qui DEVO rimanere...:help:
tomminno
04-11-2008, 09:28
Mmmm...:confused: ...da questa vostra piccola discussione dovrei ricavare la soluzione del mio problema??
Il "non va" è troppo generico. Cosa esattamente non ti funziona?
christiantric
04-11-2008, 09:52
Il "non va" è troppo generico. Cosa esattamente non ti funziona?
Praticamente il problema è sempre lo stesso, riesco a passare i dati a dev/dsp con quel codice ma viene riprodotto sempre un suono stridulo, un rumore praticamente.
Ho letto tutta la documentazione di libsndfile ma non trovo nulla (apparentemente) riguardante l'estrazione della sola codifica pcm dell'audio o l'isolamento dell'header ecc ecc come mi avevi tu stesso suggerito.
Allora pensando che lo facesse in automatico ho scritto quel codice che ho postato...ma nada de nada!!
Il suggerimento era appunto di usare libsox, aprire il file in lettura, ottenere il buffer in formato PCM e buttarlo su /dev/dsp
Altra alternativa usare il comando play o aplay per far suonare i file audio.
OT per OT scriveresti un software per riprodurre musica usando un wrapper del PlaySound?
Io credo proprio di no. io credo proprio che una classe o funzione o altro sistema per far sentire uno straccio di file audio sia ben lontano dall'essere inutile :rolleyes:
(vedi resto del thread)
io credo proprio che una classe o funzione o altro sistema per far sentire uno straccio di file audio sia ben lontano dall'essere inutile :rolleyes:
(vedi resto del thread)
In tutte le librerie di alto livello c'è già una classe o funzione per far suonare file audio !!! Sia su KDE che su Gnome.
christiantric
04-11-2008, 10:32
Altra alternativa usare il comando play o aplay per far suonare i file audio.
Quindi se io sono dentro al codice c richiamo semplicemente la funzione play()? o aplay()?
Devo importare qualche libreria particolare?
Ho notato che sono comandi bash ma io sto scrivendo codice c. Si possono quindi richiamare da codice comandi di sistema?
Scusa l'ignoranza ma sono completamente nuovo di linux/unix e sono ancora mooolto spaesato!!:muro:
tomminno
04-11-2008, 10:50
Praticamente il problema è sempre lo stesso, riesco a passare i dati a dev/dsp con quel codice ma viene riprodotto sempre un suono stridulo, un rumore praticamente.
Ho letto tutta la documentazione di libsndfile ma non trovo nulla (apparentemente) riguardante l'estrazione della sola codifica pcm dell'audio o l'isolamento dell'header ecc ecc come mi avevi tu stesso suggerito.
Allora pensando che lo facesse in automatico ho scritto quel codice che ho postato...ma nada de nada!!
Ora è un pò che non uso direttamente quella libreria, ma hai almeno letto la documentazione?
When opening a file for read, the format field should be set to zero before calling sf_open().
la struttura sf_info quando leggi non hai bisogno di riempirla eccetto per il campo format che deve valere 0, te invece lo assegni, potrebbe essere questo il problema o magari no.
Poi non so esattamente cosa faccia questa chiamata:
sf_command (sf_fd, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
Io la toglierei, non vorrei che inviasse gli header al device.
[EDIT] Come non detto SFC_UPDATE_HEADER_XXX serve per scrivere un file wav aggiornando gli header, ma te non stai scrivendo un file.
christiantric
04-11-2008, 10:59
Ora è un pò che non uso direttamente quella libreria, ma hai almeno letto la documentazione?
la struttura sf_info quando leggi non hai bisogno di riempirla eccetto per il campo format che deve valere 0, te invece lo assegni, potrebbe essere questo il problema o magari no.
Poi non so esattamente cosa faccia questa chiamata:
sf_command (sf_fd, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
Io la toglierei, non vorrei che inviasse gli header al device.
[EDIT] Come non detto SFC_UPDATE_HEADER_XXX serve per scrivere un file wav aggiornando gli header, ma te non stai scrivendo un file.
Allora tomminno, innanzitutto grazie.
Poi, ho letto tutta la documentazione ed anche più volte ma ovviamente potrebbero essermi sfuggiti dei passaggi visto che non sono molto pratico.
Cmq il file che ho postato è ciò a cui sono giunto dopo innumerevoli tentativi tra cui anche quello di considerare solo il campo format settato a zero.
Ma anche facendo così il risultato non cambiava, poi da qualche raro snippet in rete ho visto che in realtà la struttura SF_INFO puoi anche non riempirla per niente o riempirla a piacere...sembra che in lettura non gliene freghi niente!!
sf_command (sf_fd, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
serve per aggiornare in automatico l'header del file in scrittura e l'avevo messa perchè pensavo che il problema potesse dipendere dal fatto che il file scritto potesse essere incompleto di header...ovviamente togliendola o mettendola non cambia nulla!!
Maledizione!!!:muro:
tomminno
04-11-2008, 11:37
Allora tomminno, innanzitutto grazie.
Poi, ho letto tutta la documentazione ed anche più volte ma ovviamente potrebbero essermi sfuggiti dei passaggi visto che non sono molto pratico.
Cmq il file che ho postato è ciò a cui sono giunto dopo innumerevoli tentativi tra cui anche quello di considerare solo il campo format settato a zero.
Ma anche facendo così il risultato non cambiava, poi da qualche raro snippet in rete ho visto che in realtà la struttura SF_INFO puoi anche non riempirla per niente o riempirla a piacere...sembra che in lettura non gliene freghi niente!!
sf_command (sf_fd, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
serve per aggiornare in automatico l'header del file in scrittura e l'avevo messa perchè pensavo che il problema potesse dipendere dal fatto che il file scritto potesse essere incompleto di header...ovviamente togliendola o mettendola non cambia nulla!!
Maledizione!!!:muro:
Scusa la domanda ma che tipo di dato mandi in uscita?
Degli interi?
Sei sicuro che la tua scheda audio supporti la riproduzione di PCM 32 bit interi?
Io proverei usando gli short, sicuramente è supportato il PCM 16 bit.
christiantric
04-11-2008, 11:43
Scusa la domanda ma che tipo di dato mandi in uscita?
Degli interi?
Sei sicuro che la tua scheda audio supporti la riproduzione di PCM 32 bit interi?
Io proverei usando gli short, sicuramente è supportato il PCM 16 bit.
In effetti la mia inesperienza è venuta a galla quando ho visto che ci sono quattro versioni di read e non sapendo quale usare ho usato quella int.
Cosa cambia tra le quattro?
In realtà non capisco nemmeno come si possa racchiudere il contenuto di un file audio in un vettore di interi o di short o di double...la cosa mi è ignota. E nell'ignoranza ho usato int!!!
Come faccio a sapere quale va bene?
christiantric
04-11-2008, 12:56
Ragazzi tutti,
ho risolto il problema in ben due modi (in realtà molto simili).
Il primo è usando aplay dopo aver scoperto e capito cosa fosse ALSA (si ringrazia cionci per il suggerimento) è bastato:
system("aplay prova_audio.wav");
L'altro è simile ma si richiama la chiamata di sistema play-sound, disponibile dopo aver installato il pacchetto sound-recorder, in questo caso però risulta non supportata la codifica a 32 bit a quanto pare.
Spero che questa discussione possa essere utile a qualcun'altro.
Grazie a tutti.
;)
tomminno
04-11-2008, 13:03
In effetti la mia inesperienza è venuta a galla quando ho visto che ci sono quattro versioni di read e non sapendo quale usare ho usato quella int.
Cosa cambia tra le quattro?
In realtà non capisco nemmeno come si possa racchiudere il contenuto di un file audio in un vettore di interi o di short o di double...la cosa mi è ignota. E nell'ignoranza ho usato int!!!
Come faccio a sapere quale va bene?
Come scritto nella documentazione in caso di lettura libsndfile adatta automaticamente il formato del file a quello del tipo specificato (cioè se leggi uno wav che generalmente è a 16 bit e usi sf_read_float lui converte automaticamente nel formato float normalizzato [0,1]), il tuo problema è che passi il risultato della lettura direttamente al device che quindi deve essere in grado di riprodurre uno stream di interi, cosa che assai probabilmente non è in grado di fare.
Per sapere quale va bene devi conoscere le specifiche della scheda audio. Generalmente sono supportati il PCM a 8,16 e 24 bit a 1 o 2 canali.
Usa sf_read_short e non dovresti avere problemi.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.