Caso d'uso è quello di generare un'onda sinusoidale per la sintesi digitale, in modo, abbiamo bisogno di calcolare tutti i valori del peccato (dt) dove:Come calcolare un'onda sinusoidale con precisione nel tempo
t è un numero intero numero, che rappresenta il numero del campione. Questo è variabile. La gamma va da 0 a 158.760.000 per un suono di un'ora di qualità CD.
d è doppio, rappresenta il delta dell'angolo. Questo è costante. E l'intervallo è: maggiore di 0, minore di pi.
obiettivo è di ottenere un'elevata precisione con tradizionali int e doppie tipi di dati. Le prestazioni non sono importanti.
Naive implementazione è:
double next()
{
t++;
return sin(((double) t) * (d));
}
Ma, il problema è quando t aumenta, la precisione si riduce a causa grandi numeri forniti alla funzione "peccato".
Una versione migliorata è la seguente:
double next()
{
d_sum += d;
if (d_sum >= (M_PI*2)) d_sum -= (M_PI*2);
return sin(d_sum);
}
Ecco, faccio in modo di fornire i numeri nella gamma da 0 a 2 * pi alla funzione di "peccato".
Ma, ora, il problema è quando d è piccolo, ci sono molte piccole aggiunte che diminuiscono la precisione ogni volta.
La domanda qui è come migliorare la precisione.
Appendice 1
"precisione viene ridotto perché i grandi numeri forniti a "" funzione" peccato:
#include <stdio.h>
#include <math.h>
#define TEST (300000006.7846112)
#define TEST_MOD (0.0463259891528704262050786960234519968548937998410258872449766)
#define SIN_TEST (0.0463094209176730795999323058165987662490610492247070175523420)
int main()
{
double a = sin(TEST);
double b = sin(TEST_MOD);
printf("a=%0.20f \n" , a);
printf("diff=%0.20f \n" , a - SIN_TEST);
printf("b=%0.20f \n" , b);
printf("diff=%0.20f \n" , b - SIN_TEST);
return 0;
}
uscita:
a=0.04630944601888796475
diff=0.00000002510121488442
b=0.04630942091767308033
diff=0.00000000000000000000
perché non si può calcolare prima (doppia) (t) * D e quindi sottrarre abbastanza 2 * pi ' s per rendere il risultato inferiore a 2 * pi. –
vedere [È possibile realizzare simulazioni realistiche di sistemi solari n-body in termini di dimensioni e massa?] (Http://stackoverflow.com/a/28020934/2521214) Nella parte inferiore di questa risposta (ultima modifica) è semplice tecnica che vuoi – Spektre
La frequenza dell'onda sinusoidale è un numero intero di Hz? Se è così puoi semplicemente azzerare d_sum a zero ogni 44100 campioni – samgak