complicacao fabim!
eu diria que vc tem q definir uma taxa de amostragem fixa e um tamanho fixo para a wave table, dae fechou. chutando por exemplo, uma taxa de amostragem de 44.1KHz e uma wave table de 44100 amostras (para facilitar as contas).
para gerar 1Hz:
- Código: Selecionar todos
for(i=0;;i++) saida = table[i%44100];
a conta eh meio obvia, o valor de i incrementa indefinidamente, mas eh limitado na verdade a um valor entre 0 e 44099. se a tabela contem uma senoide, vc tem 1Hz na saida.
para gerar 2Hz:
- Código: Selecionar todos
for(i;;i++) saida = table[(i*2)%44100];
aqui eh facil ver que ele varre a tabela de 2 em 2 valores, assim a contagem entre 0 e 44099 varre a tabela 2x, gerando entao 2Hz na saida.
e assim vai. provavelmente o limite eh 1/4 da frequencia de amostragem, pq vc precisa gera pelo menos a sequencia 0,+A,0,-A para ter a senoide completa. genericamente temos:
- Código: Selecionar todos
for(i;;i++) saida = table[(i*f)%s];
onde f eh a frequencia e s a taxa de amostragem e tamanho da wave table.
um problema disso eh o rollover de i: quando o valor de i voltar a zero, a divisao nao eh de 44100 redondo e isso gera um segmento truncado. entao na pratica o melhor eh adotar wave tables transparentes a rollover, ou seja, com 256 amostras:
- Código: Selecionar todos
for(i=0;;i++) saida = table[(unsigned char)i];
ou com 65536 amostras:
- Código: Selecionar todos
for(i=0;;i++) saida = table[(unsigned short)i];
de modo que vc nao se preocupa com o rollover da wave table: unsigned char trunca para 8 bits o indice e unsigned short para 16 bits. obviamente, quanto maior a wave table utilizada, maior a qualidade do audio na saida. vc pode inclusive gerar wave tables em qq potencia de 2:
- Código: Selecionar todos
for(i=0;;i++) saida = table[i&(s-1)];
onde s eh o tamanho da wave table.
porem precisa ajustar as frequencias. imaginando o primeiro caso, com 256 entradas, para gerar uma senoide de 1Hz com taxa de amostragem de 44.1KHz temos q repetir cada elemento da tabela umas 172x, o q eh feito com o seguinte algoritmo:
- Código: Selecionar todos
for(i=0;;i++) saida = table[(unsigned char)((i*256)/44100)];
se vc fizer a simulacao disso, vai ver que essa conta faz com que a varredura da tabela varie de 0 a 255 no intervalo de 0 a 44099 amostras. quando entra a amostra 44100 (referente ao proximo segundo de audio), o indice eh zero e portanto a varredura recomeca, gerando exatamente 1Hz.
para gerar 2Hz, basta fazer o mesmo ajuste que fizemos lah em cima:
- Código: Selecionar todos
for(i=0;;i++) saida = table[(unsigned char)((i*256*2)/44100)];
e assim temos genericamente:
- Código: Selecionar todos
for(i=0;;i++) saida = table[(unsigned char)((i*256*f)/s)];
onde s eh a taxa de amostragem fixa do DAC e f a frequencia que vc quer gerar. nesse caso, a wavetable esta com 256 entradas. para 65536 entradas fica:
- Código: Selecionar todos
for(i=0;;i++) saida = table[(unsigned short)((i*65536*f)/s)];
e para uma wavetable generica de tamanho w = 2^n:
- Código: Selecionar todos
for(i=0;;i++) saida = table[((i*w*f)/s)&(w-1)];
isso deduzindo intuitivamente o negocio... detalhe que jah discutimos tudo isso em varios posts anteriores e esta ficando repetitivo o assunto!

lembro que a solucao para fazer o negocio funcionar polifonico (canais de saida[0] a saida[n]), com varias senoides em frequencias diferentes (frequencias f[0] a f[n]), mas mesma taxa de amostragem fixa (44.1KHz, por ex) era:
- Código: Selecionar todos
interrupcao_timer_44k1hz()
{
saida[0] = table[(unsigned char)((i*256*f[0])/44100)];
...
saida[n] = table[(unsigned char)((i*256*f[n])/44100)];
mixer(saida[0], ... , saida[n]);
i++;
}
com isso ae vc sincroniza todas as senoides de f[n] diferentes na mesma taxa de amostragem e com isso vc consegue mixar elas. se forem instrumentos diferentes, eh soh ter tables diferentes para cada saida. outra coisa importante: o algoritmo em si nao encherga problemas com frequencias quebradas, mas isso requer ponto flutuante. por exemplo, se f[n] = 123.45, ele faz i*256*f/44100 tudo em ponto flutuante e no final trunca para inteiro para usar de offset no array... eh uma **** conta e provavelmente nao dah para fazer de saida num pic. eu recomendaria testar isso num PC antes, ver todos os detalhes e limitacoes, otimizar tudo ao maximo e soh entao sair procurar um processador adequado para isso. outro detalhe eh que o problema do rollover retorna (eh soh fazer a contarada que vc percebe o problema). uma solucao eh partir para ponto flutuante ou eliminar a possibilidade usando unsigned long: a 44.1KHz vc pode gerar um timestamp unico para 27 horas continuas de audio sem rollover. se vc precisa de mais, eh soh partir para o long long e com isso vc mantem continuidade por 1 milhao de anos!
tinha tb um post ainda com as discussoes variadas ae do mixer... tem dois tipos de mixagem q funcionam, um ideal para audio (nao tem escala automatica, portanto nao tem distorcao) e outro ideal para teleconferencia (tem escala automatica e gera distorcao).