Sou capaz de escrever um gerador básico de ondas senoidais para áudio, mas quero que seja capaz de fazer a transição sem problemas de uma frequência para outra. Se eu parar de gerar uma frequência e mudar imediatamente para outra, haverá uma descontinuidade no sinal e um "clique" será ouvido.
Minha pergunta é: qual é um bom algoritmo para gerar uma onda que começa em, digamos, 250Hz e depois transita para 300Hz, sem introduzir cliques. Se o algoritmo incluir um tempo opcional de deslizamento / portamento, tanto melhor.
Posso pensar em algumas abordagens possíveis, como a sobre amostragem seguida por um filtro passa-baixo ou talvez usando uma tabela de ondas, mas tenho certeza de que esse é um problema bastante comum e que existe uma maneira padrão de resolvê-la.
Respostas:
Uma abordagem que usei no passado é manter um acumulador de fase que é usado como índice em uma tabela de pesquisa de forma de onda. Um valor delta de fase é adicionado ao acumulador a cada intervalo de amostra:
Para alterar a frequência, você altera o delta de fase que é adicionado ao acumulador de fase em cada amostra, por exemplo
Onde:
Isso garante que a forma de onda de saída seja contínua, mesmo se você mudar phase_delta dinamicamente, por exemplo, para mudanças de frequência, FM, etc.
Para alterações mais suaves na frequência (portamento), é possível aumentar o valor de phase_delta entre seu valor antigo e o novo valor em um número adequado de intervalos de amostras, em vez de apenas alterá-lo instantaneamente.
Note-se que
phase_index
ephase_delta
ambos têm um número inteiro e um componente fraccionada, ou seja, que necessitam de ser ponto ou ponto fixo flutuante. A parte inteira de phase_index (tamanho da tabela de módulo) é usada como um índice na forma de onda LUT, e a parte fracionária pode opcionalmente ser usada para interpolação entre valores LUT adjacentes para obter saída de maior qualidade e / ou tamanho LUT menor.fonte
Uma das melhores maneiras de criar uma onda senoidal é usar um fasor complexo com atualização recursiva. Ou seja,
onde z [n] é a fasor, , com sendo a frequência angular do oscilador em radianos e o índice da amostra. Tanto a parte real quanto a imaginária de são ondas senoidais, estão 90 graus fora de fase. Muito conveniente se você precisar de seno e cosseno. Um cálculo de amostra única requer apenas quatro múltiplos e quatro adições e é MUITO mais barato do que qualquer coisa que contenha sin () cos () ou tabelas de pesquisa. O problema potencial é que a amplitude pode sofrer variações ao longo do tempo devido a problemas de precisão numérica. No entanto, existe um processo bastante simples de reparar isso. Digamos que . Sabemos que deve ter magnitude de unidade, ou seja, ω n z [ n ] z [ n ] = um + j b z [ n ]Ω = exp( j ω ) ω n z[ n ] z[ n ] = a + j b z[ n ]
Assim, podemos verificar de vez em quando se esse ainda é o caso e corrigir de acordo. A correção exata seria
Esse é um cálculo complicado, mas como está muito próximo da unidade, você pode aproximar os termos com uma expansão de Taylor em torno de e obtemos1 / √a ⋅ a + b ⋅ b x=11 / x--√ x = 1
então a correção simplifica para
A aplicação dessa correção simples a cada poucas centenas de amostras manterá o oscilador estável para sempre.
Para variar a frequência continuamente, o multiplicador W precisa ser atualizado de acordo. Mesmo uma mudança não contínua no multiplicador manterá uma função de oscilador contínuo. Se for necessário aumentar a frequência, a atualização pode ser dividida em algumas etapas ou você pode usar o mesmo algoritmo do oscilador para atualizar o próprio multiplicador (já que também é um fasor complexo de ganho de unidade).
fonte
A partir deste site :
Parece que deve funcionar.
(Na verdade, se ambos forem sincronizados no eixo x após a transição, suponho que não seja necessária uma transição gradual.)
fonte
Eu concordo com as sugestões anteriores de usar um acumulador de fase. Essencialmente, a entrada de controle é a quantidade de avanço de fase por etapa ou por período de relógio (ou por interrupção ou o que for), de modo que a alteração desse valor altera a frequência sem uma descontinuidade na fase. A amplitude da onda é então determinada a partir do valor da fase acumulada, via LUT ou apenas computação do pecado (teta) ou cos (teta).
Isso é essencialmente o que é comumente conhecido como oscilador controlado numericamente (NCO) ou sintetizador digital direto (DDS). Fazer uma pesquisa na Web nesses termos provavelmente renderá mais do que você deseja saber sobre a teoria e a prática de fazê-las funcionar bem.
A adição de um acumulador adicional pode permitir transições contínuas entre frequências, como você sugeriu, se desejado, controlando a taxa de variação do valor do avanço de fase. Às vezes, isso é chamado de Digital Differential Analyzer, ou DDA.
fonte
Na 1ª ordem, você deve ajustar a fase inicial do novo sinusóide de frequência para que seja a mesma que seria a fase do sinusóide anterior no primeiro ponto de amostra de transição. Calcule a primeira frequência e use sua fase para a segunda frequência.
A segunda opção pode ser aumentar a d_phase de uma frequência para a seguinte em várias amostras. Isso limpará a continuidade do 1º derivado e proporcionará um deslize.
A terceira opção pode ser usar uma janela de suavização, como um cosseno elevado, na taxa de rampa d_phase.
fonte