|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: May 2005
Messaggi: 340
|
[Libreria] Audio
Sapete una libreria audio per C che mi consente di creare un suono dandogli dei dati ( lunghezza , ampiezza , ecc ) ???
Pf aiutatemi
|
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Partiamo dall'inizio: tu cosa devi fare di preciso??? Devi "sintetizzare" un'onda sinusoidale conoscendone la sua frequenza e ampiezza??
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Quote:
EDIT: mmmh, forse non fa al caso tuo, se la necessità è solo quella di generare un suono.
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson Ultima modifica di -fidel- : 09-10-2006 alle 16:11. |
|
|
|
|
|
|
#4 | |
|
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
Quote:
questo è il progetto free [tool di sviluppo visual studio net 2003]: http://www.twork.it/public/oki/guetbook.asp questo è l'help online http://www.twork.it/public/oki/oki.htm è la mia libreria del sound, o meglio, per creare il proprio engine del sound, fatta sopratutto per i videogame, ma è utile per fare qualsiasi cosa. Da come scrivi penso ti sia utile anche per quello che vuoi fare tu. Devi aver installate le directx Il codice è free (per scopi non commerciali) E' anche incluso nella firma. Questo è l'articolo messo su codeproject: http://www.codeproject.com/useritems/Oki.asp In inglese |
|
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Il problema della riproduzione di una onda sonora (dati i suoi parametri) si può suddividere in due parti:
- calcolo dei campioni audio - invio dei campioni ad un dispositivo audio per la riproduzione Il primo punto lo si risolve con delle semplici operazioni matematiche. Il secondo punto lo si risolve utilizzando delle apposite librerie o API di sistema per riprodurre campioni audio. Vediamo il primo punto in dettaglio. Per calcolare i campioni si può usare la nota funzione trigonometrica del seno: f(x) = A * sin (omega * x + phi) dove omega è 2*pi*f ovvero la pulsazione. (nel post non si riesce a mettere i simboli speciali, ma si dovrebbe capire) Visto che non sono un matematico, traduciamo questa cruda formula in un codice "C": nell'esempio verranno generati i primi 1000 campioni a 16 bit di un'onda sinusoidale di frequenza 440 Hz (il "La") usando una frequenza di campionamento di 44100 Hz. Codice:
#include <math.h>
...
double freq = 440;
double sampling = 44100;
double omega;
unsigned short campione;
int x;
omega = 2 * M_PI * freq / sampling;
for (x=0; x<1000; x++)
{
campione = (unsigned short) 32768 + 32767 * sin (omega * x);
....
}
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Feb 2002
Messaggi: 906
|
Quote:
Se vuoi generare un onda puoi fare i calcoli aiutandoti con questa chiamata: frequenza vale per default 22050 hz settalo a 100 lVolumeSound va da 0 a -10000 lBalance va da -10000 a 10000 0 il sound è riprodotto al centro delle casse long TUO_maxRPM=18000; //fino a 200000 frequency xp SoundPlay_Sound(n, true, lVolumeSound, ((frequenza* hz)/(long)TUO_maxRPM), lBalance); ora con lVolumeSound, frequenza* hz, lBalance con questi valori, modificabili da te puoi ottenere i dati da usare nel tuo grafico per generare le onde (inoltre con le chiamate 3D sound puoi generare altri tipi di onde tipo il passaggio da una cassa all'altra o il sound che sale o scende su uno specifico altoparlante ). Tutto questo usando la lib che ti genera i sounds (in quanto la funzione chiamata (come quella sopra l'ho fatta void e non ritorna nessun valore)). Se invece hai programmato routine con il sound fatto da te allora usa ciò che ti ha detto andbin. Ultima modifica di okay : 09-10-2006 alle 19:50. |
|
|
|
|
|
|
#7 | |
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Sempre che lo scopo sia di lavorare con l'audio, se invece ci si accontenta di una banale riproduzione un semplicissimo cast va più che bene. |
|
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Riprendendo il discorso fatto da andbin, normalmente per emettere un suono ti basta riempire un buffer contenente i valori campionati dell'onda da riprodurre (i campioni appunto) ed inviare tale buffer al driver della scheda audio.
Facendo l'esempio di linux, il cui classico driver OSS prevede l'uso del device /dev/dsp come un normale file su cui fare una "write" (o una read), ti basterà fare questo (l'algoritmo è simile a quello postato da andbin, ma con qualche importante correzione per generare un'onda sinusoidale senza distorsioni): Codice:
#define SAMPLE_RATE 48000
int fd_out;
...
void write_sine (void)
{
short buf[SAMPLE_RATE];
unsigned short ampiezza;
double frequenza = 220; /* Nota: La */
double omega; /* Pulsazione */
int x;
omega = 2 * M_PI * frequenza / SAMPLE_RATE;
ampiezza = 20000;
for (x = 0; x < SAMPLE_RATE ; x++)
{
buf[x] = (short)(ampiezza * (sin (omega * x)));
}
if (write (fd_out, buf, sizeof (buf)) != sizeof (buf))
{
perror ("Errore in scrittura sul dispositivo");
exit (-1);
}
}
Nel caso di linux, usando il driver OSS (ALSA è compatibile al 100% con questo driver), basta aprire il dispositivo /dev/dsp con una classica open: Codice:
fd_out = open ("/dev/dsp", O_WRONLY, 0);
Nel caso di Windows, i passaggi sono gli stessi per campionare l'onda, poi per scrivere il buffer sulla scheda audio devi ottenerne l'handle, appoggiandoti all'API che astrae il driver, ma sostanzialmente l'output è simile al caso linux (le funzioni per aprire un device come la scheda audio penso le trovi su MSDN). EDIT: Ho calcolato i campioni uno ad uno con la funzione sin(), ma normalmente, per ragioni di efficienza, si usa una "wave table", ossia un buffer con valori precalcolati di un'onda ad una data frequenza, e si riempe il buffer di destinazione leggendo la wave table ed inserendo nel buffer di destinazione tali valori (in base al sampling rate ovviamente).
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson Ultima modifica di -fidel- : 10-10-2006 alle 13:02. |
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Il codice che ho postato io non è certamente perfetto. Avrei dovuto ad esempio mettere le parentesi
campione = (unsigned short) (32768 + 32767 * sin (omega * x)); anche se non era comunque questo il problema maggiore e non avrebbe cambiato il calcolo. Non sono esperto (magari ....) della teoria dei segnali. Comunque è risaputo che la quantizzazione di un segnale porta inevitabilmente ad avere un errore di quantizzazione. Si ha cioè una distorsione del segnale. Il segnale generato dal mio programma quindi non è più composto solo da una unica frequenza fondamentale di 440 Hz ma contiene anche delle armoniche superiori dovute all'errore di quantizzazione. Le soluzioni per ridurre l'errore di quantizzazione, ci sono. Un metodo ad esempio è il dithering, accennato da tomminno. Se ben ricordo (ma dovrei documentarmi meglio) consiste nell'aggiungere al segnale un rumore casuale, tale per cui sulla media si riesce a correggere, in parte, l'errore (se non è corretto, non sparatemi Comunque, qui si va nella parte un po' più complessa della teoria dei segnali ... e che purtroppo non conosco molto bene o affatto. Quote:
L'errore di quantizzazione non lo risolvi cambiando nomi alle variabili o aggiungendo qualche parentesi al mio codice.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Quote:
Ovviamente ho provato il tuo codice, ma il segnale generato non era continuo, bensì molto distorto. EDIT: E' importante che il buffer che contiene i campioni debba essere grande quanto il sampling scelto, per evitare che i gruppi di campioni nel tempo T non siano tra loro "allineati". EDIT: Seguendo sempre il codice postato prima, si possono fare interessanti esperimenti. Ad esempio, se non si predispone un buffer per i campioni di dimensioni almeno doppie della frequenza dell'onda, si potrà apprezzare il cosiddetto fenomeno di aliasing (dal momento che in questo modo risulta che la frequenza di campionamento non è almeno il doppio della banda del segnale - per quanto la banda di un segnale sinusoidale è formato da due impulsi - e si viola quindi il criterio di Nyqist del campionamento per segnali a banda limitata). Provate ad esempio a settare la frequenza a 880 e SAMPLE_RATE a 300: l'aliasing sarà ben udibile.
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson Ultima modifica di -fidel- : 10-10-2006 alle 16:17. |
|
|
|
|
|
|
#11 | ||||
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Quote:
Quote:
Quote:
Nel mio sorgente c'è una variabile 'x' che indica il campione da generare. Se la frequenza di campionamento è 44100 e tu usi un buffer di 44100 campioni mi sta bene ma se poi finito il buffer ricominci rimettendo la x a 0, no! In pratica la 'x' deve sempre andare avanti. L'indice nel buffer può, ovviamente, ripartire da 0. Ma in quel caso non ci fregherebbe nulla che il buffer sia grande quanto il sampling scelto!!
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||||
|
|
|
|
|
#12 | |||
|
Senior Member
Iscritto dal: Jan 2006
Messaggi: 2722
|
Quote:
Quote:
Quote:
EDIT: mi sembra importante indicare che, mandando direttamente i campioni alla scheda (un buffer uguale a 1 insomma) non si sente alcun suono, per i motivi detti prima. La prova sul tuo codice che mi chiedevi prima l'ho fatta sempre con il programma C di cui parlavo, ma sempre considerando un buffer.
__________________
- Spesso gli errori sono solo i passi intermedi che portano al fallimento totale. - A volte penso che la prova piu' sicura che esiste da qualche parte una forma di vita intelligente e' il fatto che non ha mai tentato di mettersi in contatto con noi. -- Bill Watterson Ultima modifica di -fidel- : 10-10-2006 alle 16:29. |
|||
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 14:20.



















