Certo che puoi, non è banale farlo sembrare "carino".
Non so come farlo in Linux, ma se riesci a riprodurre un buffer PCM, tutto ciò che devi fare è riempirlo con quello che vuoi.
Quindi supponendo che il tuo buffer sia impostato per essere riprodotto in campioni mono a 16 bit con segno, a 44100 campioni al secondo, creare un suono A4 (sinusoidale) puro (440 Hz) è semplice come
int16_t buffer[44100];
float frequency = 440.0f;
float sampling_ratio = 44100.0f;
float amplitude = 0.5f;
float t;
for (int i = 0; i < 44100; i++)
{
float theta = ((float)i / sampling_ratio) * PI;
buffer[i] = (int16_t)(sin(theta * frequency) * 32767.0f * amplitude);
}
Tuttavia, questo suono è probabilmente molto noioso per i tuoi interessi, quindi devi fare alcune cose più complicate. In generale, ci sono due tipi di sintesi sonora: additiva e sottrattiva . Ce ne sono molti altri, ma questi due sono probabilmente i più semplici. Oggi parlerò solo di sintesi additiva.
Per la sintesi additiva, fai la stessa cosa che ho fatto lassù, ma invece di usare solo una frequenza ad un'ampiezza, aggiungi diverse onde insieme. È come premere contemporaneamente più tasti su un piano. Quindi modifichi il tuo codice per assomigliare a questo:
void add_sine_wave(int16_t* buffer, int buffer_length, float frequency, float sampling_ratio, float amplitude)
{
for (int i = 0; i < buffer_length; i++)
{
float theta = ((float)i / sampling_ratio) * M_PI;
// make sure to correct for overflows and underflows
buffer[i] += (int16_t)(sin(theta * frequency) * 32767.0f * amplitude);
}
}
e poi usalo in questo modo:
int16_t buffer[44100];
memset(buffer, 0, sizeof(buffer));
// Create an A Major chord
add_sine_wave(buffer, 44100, 440.0f, 44100.0f, 0.5f);
add_sine_wave(buffer, 44100, 554.37f, 44100.0f, 0.5f);
add_sine_wave(buffer, 44100, 659.26f, 44100.0f, 0.5f);
A proposito, io ricevo la mia frequenze da qui (sto usando temperamento uguale , ma ci sono un sacco di altre accordature disponibili).
Si noti che finora ho usato solo onde sinusoidali, ma i vecchi sintetizzatori supportano anche onde quadrate , triangolari e saw , ognuna con le sue interessanti proprietà sonore. L'implementazione di questi è piuttosto semplice.
Altre cose che puoi fare per aumentare la varietà di suoni che puoi creare sono:
- Modulazione dell'ampiezza : modifica dell'ampiezza dell'onda in tutto il buffer
- Modulazione di frequenza : modifica della frequenza dell'onda in tutto il buffer
- Riverbero : ripetere un campione modificandone la forma e la posizione nel buffer. È un argomento molto complesso.
- Avvolgimento : modifica dell'ampiezza di un campione per dargli più vita
Il punto qui è che le tecniche stesse non sono molto difficili, quindi non hai davvero bisogno di una libreria per astrarle per te. Li sta usando per creare suoni interessanti ciò che è difficile.
Un'ultima nota. Quando si sperimenta un suono del genere, può essere molto utile salvare i dati in file WAV e visualizzarli in alcuni software come Audacity. In questo modo puoi vedere cosa stai facendo più chiaramente.