collapse

* Posts Recentes

Amplificador - Rockboard HA 1 In-Ear por almamater
[Ontem às 19:13]


O que é isto ? por KammutierSpule
[26 de Março de 2024, 19:35]


Bateria - Portátil por almamater
[25 de Março de 2024, 22:14]


Emulador NES em ESP32 por dropes
[13 de Março de 2024, 21:19]


Escolher Osciloscópio por jm_araujo
[06 de Fevereiro de 2024, 23:07]


TP4056 - Dúvida por dropes
[31 de Janeiro de 2024, 14:13]


Leitura de dados por Porta Serie por jm_araujo
[22 de Janeiro de 2024, 14:00]


Distancia Cabo por jm_araujo
[08 de Janeiro de 2024, 16:30]


Meu novo robô por josecarlos
[06 de Janeiro de 2024, 16:46]


Laser Engraver - Alguém tem? por almamater
[16 de Dezembro de 2023, 14:23]

Autor Tópico: Desafio: State Variable Filter  (Lida 17511 vezes)

0 Membros e 2 Visitantes estão a ver este tópico.

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: Desafio: State Variable Filter
« Responder #15 em: 23 de Junho de 2015, 14:16 »
Fica aqui um referência muito interessante. Tem código de matlab mas ignorem isso, o sumo está na na explicação dos vários efeitos tipicamente usados para guitarra eléctrica:

http://www.cs.cf.ac.uk/Dave/CM0268/PDF/10_CM0268_Audio_FX.pdf
« Última modificação: 26 de Junho de 2015, 01:27 por Njay »

Offline MAntunes

  • Mini Robot
  • *
  • Mensagens: 75
Re: Desafio: State Variable Filter
« Responder #16 em: 26 de Junho de 2015, 00:36 »
Boas pessoal, desde que tive Eletrónica I e Sinais e Sistemas que fiquei interessado nisto dos filtros, mas sempre mais nos filtros analógicos.. Depois em Processamento de Sinal falamos sobre os filtros digitais, mas tudo demasiado teorico, quase sem exemplos praticos.. Alguém tem alguma literatura sobre a implementação de filtros em C/C++, apenas sobre o básico??
Cumprimentos :)

Offline msr

  • Mini Robot
  • *
  • Mensagens: 798
Re: Desafio: State Variable Filter
« Responder #17 em: 26 de Junho de 2015, 22:42 »
Boas pessoal, desde que tive Eletrónica I e Sinais e Sistemas que fiquei interessado nisto dos filtros, mas sempre mais nos filtros analógicos.. Depois em Processamento de Sinal falamos sobre os filtros digitais, mas tudo demasiado teorico, quase sem exemplos praticos.. Alguém tem alguma literatura sobre a implementação de filtros em C/C++, apenas sobre o básico??
Cumprimentos :)

Tenho na calha uns "blog posts" para escrever sobre isso mesmo! Há medida que forem saindo venho aqui ao forum avisar.
Entretanto, tens aqui código C com a implementação de alguns filtros (MA, EMA, FIR e IIR):
https://github.com/qkthings/qkdsp
O repositorio inclui um projecto no Code::Blocks e exemplos (para já só do MA e EMA), por isso é muito fácil de usar e experimentar.

De um ponto de vista muito prático, aquilo que precisas de saber para implementar filtros digitais em microcontroladores sem FPU (floating-point unit) é isto:
1) Como representar números de virgula flutuante (floating-point, ie, variaveis do tipo "float" ou "double") em virgula fixa (fixed-point, ie, "int"), e perceber os truques da "fixed-point arithmetic" (multiplicações e adições)
2) Como calcular coeficientes (no caso dos filtros FIR e IIR) tendo em conta as especificações do filtro que pretendes realizar. Para isso podes usar o Octave ou usar SciPy (Python), basta chamares uma função com os parâmetros que queres e ele dá-te os coeficientes

Googla sobre isto.

Desconhecia no entanto este "state variable filter" que me parece muito interessante também. É claramente um candidato a entrar na QkDSP. Alguem se quer voluntariar com um Pull-Request? :D
(mais tarde ou mais cedo, se não houver voluntários tenciono fazê-lo)


« Última modificação: 26 de Junho de 2015, 22:46 por msr »

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: Desafio: State Variable Filter
« Responder #18 em: 27 de Junho de 2015, 17:32 »
Venham de lá esses posts! Quanto ao pull request, vamos ver :)

A representação de números em ponto fixo é uma técnica extremamente simples e intuitiva, que eu inventei quando tinha uns 20 e andava a brincar com demos gráficas em PC - claro que eu não inventei nada :D , já existia, e vim depois mais tarde a descobrir que se chamava ponto fixo.

Como é que se representa um número real, por exemplo 1.25, com números inteiros? Multiplicando por uma constante, digamos 1000, e ficando assim 1250, que é nitidamente um número inteiro. Se quisermos "recuperar" o número original, só temos que o dividir pela mesma constante: 1250 / 1000 = 1.25. Como se vê, não tem nada de especial :)

1250 é uma representação em ponto fixo do número 1.25 quando usamos 1000 como a "unidade": 1000, nesta representação, é 1.000 (.000 para evidenciar qtas casas decimais podemos representar), a unidade. Podemos chamar U (de Unidade) ao 1000, dizer que 1000 é a nossa unidade, nesta representação. Com uma unidade de 1000, o valor real mais pequeno que podemos representar com um inteiro é 0.001 .

O que fazer se o número real tem mais casas decimais do que consigo representar com a unidade escolhida, neste caso 1000? Arredondar. Por exemplo, 0.44584. Ao multiplicar por 1000 ficamos com 445.84 mas como temos que ficar com um inteiro, arredondamos para o inteiro mais próximo e ficamos com 446. Aqui estamos a criar um pequeno erro na representação; "quanto erro" é tolerável só depende da nossa aplicação. Aqui o nosso erro é inferior a +/-0.001, que equivale a 1 em ponto fixo no nosso exemplo de U = 1000; se precisarmos de um erro menor, teremos que usar um U maior, por exemplo U = 10000.

Como é que se somam 2 números em ponto fixo com U = 1000 ("PF1000", para simplicidade)?
Se começar com 1.25 e 0.25, tenho que os converter para PF1000: 1.25 = 1.25 x 1000 = 1250 e 0.25 x 1000 = 250.
Podemos ver que basta adicioná-los como inteiros, não é preciso nada de especial: 1250 + 250 = 1500. Convertendo 1500, que é um PF1000, para real, vemos que o resultado está certo: 1500 / 1000 = 1.5 (= 1.25 + 0.25)
Subtrair é igualmente fácil e a mesma coisa que somar, pois subtrair é somar um número negativo.

A multiplicação é que já é um pouco diferente, mas é muito fácil perceber porquê. Vamos pegar outra vez no 1.25 e 0.25 e multiplicá-los em ponto fixo com unidade 1000 (PF1000):

1.25 -> 1250
0.25 -> 250
1250 x 250 = 312500


Se convertermos 312500 "de volta" para real, ficamos com 312.5, quando o resultado deveria ser 1.25 x 0.25 = 0.3125. O que é que aconteceu? O que aconteceu foi que pelo caminho criámos um resultado em PF1000000! Para mostrar como, em vez de usar 1250 e 250 para representar os números em PF1000, vou usar (1.25 x U) e (0.25 x U), e então fica evidente:

(1.25 x U) x (0.25 x U)
= 1.25 x U x 0.25 x U
= 1.25 x 0.25 x U x U
= 0.3125 x U x U


ou seja acabámos com o resultado (0.3125) multiplicado pelo quadrado da unidade, U x U, e não pela unidade U como se quer. Como resolver isto? Muito simples, basta dividir o resultado por U, e voltamos a ter o número em PF1000

0.3125 x U x U
--------------- = 0.3125 x U = 0.3125 x 1000 = 312.5 -> 313 (arredondado)
       U


Portanto para multiplicar 2 números que estão em ponto fixo temos que multiplicá-los e dividir o resultado pela unidade U da representação.

Na divisão de numeros em PF ocorre um "problema" semelhante ao que acontece na multiplicação. Se fizermos 1250 / 250 ficamos com 5, quando o resultado em PF1000 deveria ser (1.25 / 0.25) x 1000 = 5000. O que aconteceu foi que, na divisão, dividimos a Unidade por ela própria, eliminando-a:

 1.25 x U     1.25
---------- = ------ = 5
 0.25 x U     0.25


Para resolver isto, temos que multiplicar o dividendo pela unidade U, antes de fazer a divisão:

 1.25 x U x U     1.25 x U
-------------- = ---------- = 5 x U = 5 x 1000 = 5000
   0.25 x U         0.25


Espero que se entenda :) . Se alguém quiser discutir sou todo ouvidos.

Há ainda 3 detalhes práticos, sobre melhorar a precisão nas divisões (a divisão inteira dos CPUs é uma divisão por defeito, o que faz com que o resultado não seja sempre o número inteiro mais próximo do número real), velocidade de cálculo (dividir/multiplicar por 1000 é relativamente lento num CPU, mas e se for por uma potência de 2?) e tamanho da representação intermédia (quando dividimos números em PF temos um valor intermédio que tem U2, e isso ocupa muito "espaço", bits, que não precisamos para as representações finais em PF), mas por agora já me alonguei mais do que queria :)
« Última modificação: 28 de Junho de 2015, 14:08 por Njay »

Offline MAntunes

  • Mini Robot
  • *
  • Mensagens: 75
Re: Desafio: State Variable Filter
« Responder #19 em: 28 de Junho de 2015, 13:56 »
Obrigado aos dois pelo esclarecimento!
Fico à espera desses "blog posts", msr :)
Cumprimentos!

Offline msr

  • Mini Robot
  • *
  • Mensagens: 798
Re: Desafio: State Variable Filter
« Responder #20 em: 01 de Julho de 2015, 11:23 »
Aqui está o post sobre representação de números e aritmética em virgula-fixa: http://theramblingness.com/2015/07/01/the-art-of-representing-floating-point-numbers-as-integers/

Espero que o inglês não seja problema :P Qualquer dúvida, erro que detectem ou melhoria que queiram sugerir, mandem vir que será muito apreciada.

No próximo post vou escrever sobre alguns tipos de filtros digitais e como os dimensionar.




Offline msr

  • Mini Robot
  • *
  • Mensagens: 798
Re: Desafio: State Variable Filter
« Responder #21 em: 09 de Julho de 2015, 02:01 »
Então malta anda tudo sem tempo para ler coisas sobre "fixed-point representation"? :P

Nas próximas semanas tenciono publicar um post sobre implementação de filtros. Desta vez vai ser menos extenso e vai incluir imagens com cores ;)

Alguem tentou implementar o state variable filter em C ?

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: Desafio: State Variable Filter
« Responder #22 em: 10 de Julho de 2015, 14:15 »
Aqui está o post sobre representação de números e aritmética em virgula-fixa: http://theramblingness.com/2015/07/01/the-art-of-representing-floating-point-numbers-as-integers/
Boa, bem explicadinho com rigor matemático e bom Inglês ;)

Não falta qualquer coisa ao limite inferior?

-2m-1 <= value <= 2m-1 - 2-n

É que o limite negativo também cresce, em - (1 - 2-n), certo?

Eu tenho o filtro implementado em C, mas eu não conto :D
« Última modificação: 10 de Julho de 2015, 14:21 por Njay »

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: Desafio: State Variable Filter
« Responder #23 em: 12 de Julho de 2015, 14:48 »
Ontem implementei também um "overdrive" (distorção), que deu uma "investigação" interessante, com arctan à mistura, mas tem que ficar para outro tópico. A matemática é mesmo uma coisa tann bunita :D
« Última modificação: 12 de Julho de 2015, 14:50 por Njay »

Offline msr

  • Mini Robot
  • *
  • Mensagens: 798
Re: Desafio: State Variable Filter
« Responder #24 em: 16 de Julho de 2015, 03:46 »
Aqui está o post sobre representação de números e aritmética em virgula-fixa: http://theramblingness.com/2015/07/01/the-art-of-representing-floating-point-numbers-as-integers/

Não falta qualquer coisa ao limite inferior?

-2m-1 <= value <= 2m-1 - 2-n

É que o limite negativo também cresce, em - (1 - 2-n), certo?

Realmente tenho aí um erro, deveria ser: -2m <= value <= 2m - 2-n (já editei no post)

O limite é mesmo este, como tens um bit para sinal, quando tens todos os outros bits a zero, o valor minimo que se consegue representar, em complemento para dois, é -(2^m). Por exemplo, se m=0, o valor minimo que se consegue representar é -1 (corresponde a ter apenas o bit de sinal a um) e máximo, com n=15, será 0.9997.


Quanto ao overdrive, partilha aí os resultados! :D

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: Desafio: State Variable Filter
« Responder #25 em: 17 de Julho de 2015, 20:17 »
Citar
Qm.n

Where m corresponds to the bits available to represent the integer part of and n corresponds to the bits available to represent the fractional part.

com o bit de sinal à parte (reparei agora que na imagem tens o n e o m trocados, e o "of" tá a mais).

Reservar 1 bit para sinal não é exactamente a mesma coisa que complemento para 2, pois a 1ª permite ter -0 e +0 enquanto que a 2ª usa o -0 para estender o limite negativo... Se vais definir matematicamente, tens que ser rigoroso, e a tua definição diz que o limite negativo é o bit de sinal a negar a soma do maior número positivo em m bits de inteiro com o maior de n bits de fraccionário (ambos só com representação positiva, já que o sinal é à parte).

Já iremos ao overdrive.
« Última modificação: 17 de Julho de 2015, 20:24 por Njay »

Offline msr

  • Mini Robot
  • *
  • Mensagens: 798
Re: Desafio: State Variable Filter
« Responder #26 em: 21 de Julho de 2015, 00:41 »
É isso. Quando refiro esse bit de sinal assumi sempre representação em complemento para dois sem deixar isso claro por escrito, porque de facto pode estar lá o bit de sinal e o resto nao estar em complemento para dois.
A imagem foi reaproveitada de outro texto, obrigado pelo alerta, tenho de lhe dar um jeito também.

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: Desafio: State Variable Filter
« Responder #27 em: 22 de Setembro de 2015, 02:35 »
Em relação ao overdrive/distorção cá fica:

http://lusorobotica.com/index.php?topic=8324.0

Ainda queria fazer uns testes com mais rigor (ainda não meti o scope, mas de qq maneira soa bem) e sacar uns WAV, mas é melhor publicar já senão não sai :)