Autor |
Mensagem |
mjcmello Veterano |
# set/12
· votar
Spiderpoison Estes dias estou tentando descobrir se é possível calcular a frequência de um acorde.
Um exemplo: Dó = 263.63 Mi = 329.63 Sol = 391.99
Só pra dar um pitaco. O próprio instrumento, quando geramos uma nota apenas, gera uma série de harmónicos múltiplos da frequência. É isso que determina o timbre.
Então, cada uma destas notas vai gerar seus respectivos harmônicos e assim compor o acorde. A forma de onda (no que chamamos domínio do tempo) vai ser a sobrbosição de senóides nestas frequências.
Não existe uma frequência resultante. Todas elas estão lá. O alto falante pode "filtrar" algumas delas (diminuir algumas), mas elas continuarão lá.
|
Spiderpoison Veterano |
# set/12
· votar
mjcmello - Pois é, eu consegui entender bem o processo quando realizei testes criando tons em faixas distintas no Audacity e mixando as faixas para formar acordes conhecidos, o resultado foi um encapsulamento das frequencias resultando em uma nova periódica com todas elas lá. Agora estou voltando aos estudos básicos para relembrar um pouco de trigonometria e entender o processo todo de uma forma mais aprofundada.
|
Spiderpoison Veterano |
# set/12
· votar
Galera, para quem está estudando sobre o assunto também eu achei uma ferramenta bem legal criada pelo MIT ... Com ela é possível simular visualmente a somatória das ondas.
http://ocw.mit.edu/ans7870/18/18.06/javademo/FourierSeries/
|
Scrutinizer Veterano |
# set/12
· votar
Spiderpoison Cara, talvez você possa usar uma linguagem específica pra síntese de áudio com o arduino, tipo SuperCollider ou CSound, eles tem as funções para senóides e funções muito mais complexas prontinhas pra você, agora o negócio é achar informações sobre isso, dei uma pesquisada rápida e pelo menos sei que existe essa possibilidade.
|
Spiderpoison Veterano |
# set/12
· votar
Scrutinizer - acho que não vai dar muito trabalho não, eu tinha imaginado mais ou menos como fazer mas mataram a pau no fórum do Arduino.
http://arduino.cc/forum/index.php/topic,121599.15.html
Ainda não testei mas acho que pode funcionar.
|
Luiz_RibeiroSP Veterano |
# set/12
· votar
Spiderpoison Esse programinha em java, feito pelo MIT, é bem legal, mas quanto tentei colocar a equação que passei, o negocio travou 0_o...mas o excel faz isso também. Procura um simulador de circuitos que chama PSpice, vai ajudar.
|
Spiderpoison Veterano |
# set/12
· votar
Pessoal acho que cheguei a uma solução, ainda preciso acertar algumas coisas no projeto acertar a duração das notas, mas basicamente eu consegui misturar as frequências da seguinte forma.
void toca(int n1, int n2, int n3){ for (int i=0;i<100;i++){ digitalWrite(3,HIGH); delayMicroseconds(n1); digitalWrite(3,LOW); delayMicroseconds(n1); digitalWrite(3,HIGH); delayMicroseconds(n2); digitalWrite(3,LOW); delayMicroseconds(n2); digitalWrite(3,HIGH); delayMicroseconds(n3); digitalWrite(3,LOW); delayMicroseconds(n3); } }
void setup(){ pinMode(3,OUTPUT); }
void loop(){ toca(1915,1519,1275); delay(100); toca(1915,1607,1275); delay(1000); }
o 'n', a duracao do pulso pode ser calculado usando essa referência: http://arduino.cc/playground/Portugues/LearningMelody
|
Luiz_RibeiroSP Veterano |
# set/12
· votar
Spiderpoison Mas a saída vai ser uma onda quadrada, que possui vários harmônicos somados, acho que mai do que um acorde com 3 ou 4 notas. Considerando que uma nota é uma senoide, agora não sei se esta consideração é valida. Quado pensei no projeto, imaginei o uso de um falante com bobina(indutivo). o buzzers é piezoeléctrico, acho que ele não reproduz senoides. Preciso pesquisar mais porque não mexi muito com uma aplicação dessas, mas depois gere apenas uma nota e coloca um afinador na saída. se der certo manda reproduzir um acorde. O ideal era usar um analisador de espectros, para poder ver a decomposição do som e analisar os harmônicos separados para saber se esta saindo um acorde. Mas ai ...
|
shoyoninja Veterano |
# set/12 · Editado por: shoyoninja
· votar
O alto falante não vibra com uma frequencia por vez, o cone tem sua posição instantanea determinada pela forma de onda do sinal, que é a soma dos 3 sinais no caso.
Desde de que as 3 notas sejam senóides simples, eh relativamente facil simular.
Aliás eh ridiculo simular. Abra o Reaper, crie 3 tracks com o ReaSynth emitindo uma senóide em cada nas notas que você quer e faça um bounce da mix. Eh só dar um zoom na forma de onda, eh isso que seu alto falante vai fazer.
|
Luiz_RibeiroSP Veterano |
# set/12
· votar
shoyoninja Sim, o cone tem sua posição instantânea determinada pelo valor da somatória dos sinais....mas não sei se um alto falante piezoelétrico faz isso com a mesma precisão de um indutivo.
|
shoyoninja Veterano |
# set/12
· votar
Nem um nem o outro são precisos, vai haver distorção.
|
Spiderpoison Veterano |
# set/12
· votar
pois é o resultado não foi uma onda como a esperada, mas achei uma forma de visualizar a onda gerada pelo microcontrolador, é só gravar em um sampler do som e analisar em um editor de áudio. O que notei é que da forma que eu montei a onda fica uma serra, aprimorando um pouco mais eu consegui achar uma outra forma de escrever a função e talvez corrigir o desenho da curva.
dentro do while estou testando:
int saida= (((sin(3.1415+f1) + sin(2*3.1415+f2) + sin(3*3.1415+f3))*42)+126); digitalWrite(3,HIGH); delayMicroseconds(saida); digitalWrite(3,LOW); delayMicroseconds(saida); digitalWrite(3,HIGH);
confesso que os resultados são interessantes ...
|
shoyoninja Veterano |
# set/12 · Editado por: shoyoninja
· votar
Ok, maninho vc falou em microcontrolador agora hehe. Me conta o que vc está fazendo e como por favor. Esses digital write que vc está fazendo estão controlando o que?
Se agora vc está modulando o delay com o seno de pi somado a f1 que imagino que seja frequencia, o que vc espera que isso faça?
Vc tem uma função tmb que gera uma determinada frequencia sozinha certo? Vc que havia feito ela? Ou eh parte de alguma lib?
|
Spiderpoison Veterano |
# set/12
· votar
shoyoninja - A idéia é um projeto que gere notas e acordes aleatórios para treino de ouvido absoluto. Estou usando o Arduino (www.arduino.cc) Barateei muito o projeto, por isso a qualidade do som é meio limitada. Os digitalWrite estao controlando os pulso da porta PWM.
Neste link tem um exemplo da função que estou usando como modelo para gerar as notas: http://arduino.cc/playground/Portugues/LearningMelody
Para gerar uma frequência no Arduino você pode usra uma função nativa tone(pino,frequencia Hz,duracao ms). Mas também da para simular como o tutorial que passei.
Na minha logica, a cada ciclo do micro ele toca uma das 3 notas do acorde por milésimos de segundo, isso simula uma somatória das notas formando uma onda triangular (isso se eu tiver certo).
|
El_Cabong Veterano |
# set/12
· votar
Um acorde consiste NO MÍNIMO de três ondas senóides de frequências diferentes (que juntas resultam num som "agradável" aos ouvidos). As notas se somam vetorialmente, e isso resulta numa onda complexa.
Se considerar que as notas deste acorde não são senóides simples e sim algo mais complexo cheio de harmônicas (como é o caso real dos instrumentos acústicos) o resultado final só tende a ficar mais complexo.
Eu diria que um acorde, é uma onda contendo inúmeras frequências (não existe A FREQUENCIA do acorde).
|
Spiderpoison Veterano |
# set/12
· votar
El_Cabong - a sim, essa conclusão já ficou para trás quando li sobre a Serie de Fourier, o que resta agora é achar uma forma de somar as senóides para formar o encapsulamento de frequências.
A onda não necessita ser necessariamente uma senóide, pode ser uma onda retangular, dente de serra ou triangular também.
|
Luiz_RibeiroSP Veterano |
# set/12
· votar
Spiderpoison porque colocou um 3 multiplicando no seno? -> sin(3*3.1415+f3) e em outra equação colou sói o pi?
esta usando um conversor D/A na saída?
|
shoyoninja Veterano |
# set/12 · Editado por: shoyoninja
· votar
Ta agora entendi... Nao vai dar certo dessa forma, esse metodo que vc esta usando esta apenas emitindo pulsos em uma determinada frequencia. Pra fazer o que vc quer, vc precisaria usar modulacao pwm, nao eh a mesma coisa. Cada pulso desses tem um monte de harmonicos, gera um sinal assimétrico, muito longe de senoidal.
A função pwm desse modulo usa 500hz como frequencia de base para modulação, Isso eh muito baixo... Vc vai ficar limitado a 200hz e com muita degradação de qualidade.
Vc poderia montar um algoritmo para fazer o pwm usando o digitalwrite, se ele consegue chavear com esse delay de microsegundos. Mas eu acho que nao eh o caso.
Nao vai rolar velhinho. Eh como tentar simular polifonia com uma bexiga, estreitando a ponta.
|
Spiderpoison Veterano |
# set/12
· votar
Luiz_RibeiroSP - Coloquei os números para teste, estou fazendo experimentações para ver os resultados baseados em algumas ideias que tive estudando as teorias. A saída não está usando um conversor digital ... vou ver se se faço um sampler do meu teste e disponibilizo.
|
Spiderpoison Veterano |
# set/12
· votar
shoyoninja - Então eu até consegui gerar os acordes usando o 1 método, mas o som está ruim. Vou voltar a dar uma lida e ver se acho alguma outra forma.
Como está até da para identificar o acorde, mas ainda não vi se está batendo 100%.
|
shoyoninja Veterano |
# set/12
· votar
Então, se vc trabalhar com pulsos esquecer a senoide da pra fazer algo sim.
Quantize tudo usando duração minima que um pulso possa ter, e monte uma função para fazer um stream desses dados parAa a portA de saida.
Da forma que esta, vc esta alternando os pulsos ao inves de gerar todos ao mesmo tempo.
Ou ainda melhor.
Calcule a distancia e monte o padrao de pulsos de uma vez soh, usando soh o desvio de um para o outro.
|
Luiz_RibeiroSP Veterano |
# set/12 · Editado por: Luiz_RibeiroSP
· votar
shoyoninja Mas sem um A/D essa equação que passei não vai ter efeito. A ideia é o arduino calcular o valor instantâneo da função e enviar os valores com 8 bits, para a porta de saída, depois o conversor vai transformar esses números binários em um valor de tensão. O que você esta fazendo é modular em PWM, um sinal na saída, mas pelo que passou da programação, esse sinal não vai variar com a equação
void toca(int n1, int n2, int n3){ for (int i=0;i<100;i++){ // faz essa rotina 100 vezes digitalWrite(3,HIGH); // nivel logico 1(5V) no pino 3 delayMicroseconds(n1); // espera n1 microssegundos digitalWrite(3,LOW); // nivel logico 0 no pino 3 delayMicroseconds(n1); // espera n1 microssegundos
//mesma analogia para o resto do programa digitalWrite(3,HIGH); delayMicroseconds(n2); digitalWrite(3,LOW); delayMicroseconds(n2);
digitalWrite(3,HIGH); delayMicroseconds(n3); digitalWrite(3,LOW); delayMicroseconds(n3); } } Vamos supor de n1=1, n2=2, e n3=3 na saida do pino você vai ter uma onda quadrada assim
--_----__------___ se repetindo 100x 11 2__2__3__3
|
shoyoninja Veterano |
# set/12 · Editado por: shoyoninja
· votar
Huummm nao, nao funciona.
Pensei no seguinte, fazer a funcao (sen(Pi F1 t)+sen(Pi F2 t)+sen(pi f3 t)) em funçao de t, em segundos, e toda a vez que o resultado passar pelo 0, inverter a saída. Quantizando em microsegundos.
Isso vai plotar um cópia, digamos preto e branco, do sinal.
O pwm não seria rápido o suficiente para alimentar o DAC.
Assim vc elimina o elemento supresa de saber o delay de chaveamento do DAC, mas fica com um problema sério de timming, vc precisaria ter acesso a algum tipo de relógio para referenciar o loop principal.
|
Spiderpoison Veterano |
# set/12
· votar
Então Luiz_RibeiroSP, foi exatamente uma das conclusões que cheguei, a única diferença da minha fórmula final é que eu oitavei a terça e a quinta para pegar a frequência harmônica dessa notas. Meu 'i' está sendo calculado pelo ciclo do arduino, sendo assim não precisa do for. Da uma olhada, coloquei link para o audio também.
#define C 1897 #define Ds 1607 #define E 1517 #define G 1276
void toca(int f1, int f2, int f3, int duracao){ duracao=duracao/10; int i=0; while (i<duracao){ digitalWrite(3,HIGH); delayMicroseconds(f1/2); digitalWrite(3,LOW); delayMicroseconds(f1/2); digitalWrite(3,HIGH); delayMicroseconds(((f2+f1)/2)^2); digitalWrite(3,LOW); delayMicroseconds(((f2+f1)/2)^2); digitalWrite(3,HIGH); delayMicroseconds(((f3+f2)/2)^3); digitalWrite(3,LOW); delayMicroseconds(((f3+f2)/2)^3); i++; } }
void setup(){ pinMode(3,OUTPUT); Serial.begin(9600); }
void loop(){ toca(C,E,G,1000); toca(C,Ds,G,1000); }
resultados:
Dó maior - http://flxsys.com.br/do_maior_arduino.mp3 Dó maior e dó menor - http://flxsys.com.br/arduino_teste.mp3 440Hz -referência - http://flxsys.com.br/la_arduino.mp3
esperado: http://flxsys.com.br/do_maior_gerador.mp3
|
shoyoninja Veterano |
# set/12
· votar
Está errado... A soma dos tres sinais nao eh um periodo de cada frequencia depois do outro. A interação dos três leva bem mais do que a soma dos três periodos pra se resolver. Além de não resultar em polifonia, ainda está gerando um sinal com freqüência diferente das 3 iniciais.
|
Spiderpoison Veterano |
# set/12
· votar
shoyoninja - Sim, eu consegui entender isso, que não é um período de cada frequência, mas foi o mais próximo que consegui chegar até o momento, o que eu estou buscando é justamente a formula para juntar estas 3 notas gerando um acorde. Segundo eu entendi a frequência no momento X deve ser a resultante da Serie de Fourier?
|
shoyoninja Veterano |
# set/12
· votar
Eu escrevi a formula ali... eh a soma das funções seno em função do tempo, soh isso.
|
Spiderpoison Veterano |
# set/12
· votar
shoyoninja - Hum, eu via formula (sen(Pi F1 t)+sen(Pi F2 t)+sen(pi f3 t)), até testei, mas acho que o problema é o PWM não ser rápido como você comentou.
|
Spiderpoison Veterano |
# set/12
· votar
Pode ser feito, só vou demorar para entender.
http://www.cs.nott.ac.uk/~jqm/?p=605
|
shoyoninja Veterano |
# set/12
· votar
Tem que dar na mesma....
Vc monta função f(t) = sen(2π•f1•t)+sen(2π•f2•t)+..., detecta se f(t) eh maior que zero, digitalwrite HIGH, senão digitalwrite LOW.
Ou caso isso gere ruído, estabeleça um controle e faça o digitalwrite apenas quando for necessário.
O loop deve ocorrer em um timming específico, seria bom usar um timer.
Se cada iteração tiver um frame de 10microssegundos, t sendo incrementado como contador unitário, adeque a função, sen(2π•f•t÷100000). Entendeu?
Ai basta vc achar um jeito de garantir que cada iteração vai durar exatos 10 microssegundos, se vc tem a função de delay, deve ter acesso a alguma variável de timer também.
|