Sintetizador sonoro que toca redez vouz 4
Publicado por Matth (última atualização em 09/02/2016)
[ Hits: 2.307 ]
Recentemente obtive ajuda do grande Paulo no tópico:
https://www.vivaolinux.com.br/topico/C-C++/Alguma-forma-de-criar-equivalentes-ao-sound-da-conioh-com...
Então, para divulgar a ideia de se usar as bibliotecas ao.h para gerar saída de áudio, decidi melhorar um pouco as coisas já que pretendo ainda escrever uma biblioteca para um sintetizador mais aprimorado.
Enquanto não crio coragem para isso, trago aqui um script em C que toca, ou pelo menos tenta, Render Vous 4(Jarre).
Experimentem brincar com as constantes no início do código e verão que o timbre pode ser modificado de várias maneiras. Não coloquem valores muito grandes em nenhuma das amplitudes, a menos que desejem ficar surdos.
#include <ao/ao.h>
#include <math.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
//*constantes e variáveis globais para sintetizar a onda, modifique a vontade para ver o que acontece(não coloque valores muito altos >(5) nas amplitudes de cada onda):
const double s1=2, s2=0, s3=0; //Constantes que aplicam sobre os senos
const double c1=0, c2=0, c3=0; // Constantes ' ' ' ' ' ' cossenos
const double sa=0, sd=0.33333333; //modulam senóides em defasagem
const double ca=1, cd=0.66666666; //ca=amplitude, cd=defazagem de 0 (0) até 1 (2pi)
const double sq=0.5; // amplitude da onda quadrada
double m1=-0.0005; //modificador de frequência diminuindo-a se negativo e dando acréscimo se positivo
const double t1=1, t2=0; //onda triangular, t1 está a 90 graus de defazagem com t2 (que são suas amplitudes)
const double r1=0.5, r2=0; //constante para ondas rampa defasadas 90 similarmente
double fi=1; //fade in para entrada da nota, o quão suavemente a nota chega
double fo=2.5; //fade out para nota.
double tr=0, tf=0; //amplitude de tremulação e sua frequencia(não está em hertz)
double A=80; //amplitude
//*************************************************
// ---
double square(double wt){ ///Gera onda de pulso quadrado | | |
// ----
int n=0;
while(wt-n*2*M_PI>0){n++;}//calculando o resto de wt/2pi
double r=(wt-(n-1)*(2*M_PI))/(2*M_PI);//resto
if (r<=0.5){
return 1;
}else{
return -1;
}
}
// /\ */
double triang(double wt){ //função para gerar ondas triangulares / \ */
// ----
int n=0;
while(wt-n*2*M_PI>0){n++;}//calculando o resto de wt/2pi
double r=(wt-(n-1)*(2*M_PI))/(2*M_PI);//resto
if(r>=0 && r<=0.5){ return (4*r-1)*0.5;}
else{ return (-4*r+3)*0.5;}
}
double ramp(double wt){ //função para gerar ondas na forma rampa(dente de serra) (/| /)
// / |/ ----
int n=0;
while(wt-n*2*M_PI>0){n++;}//calculando o resto de wt/2pi
double r=(wt-(n-1)*(2*M_PI))/(2*M_PI);//resto
return (4*r-1)*0.25;
}
static ao_device *sound_dev=NULL;
/*
Uso: sound(frequencia, duracao); // frequencia em Hz, duracao em segundos
Equivalente ao seguinte código feito com funções declaradas em conio.h e dos.h:
sound(frequencia);
delay(duracao*1000); // duracao em milissegundos
nosound();
*/
void sound(double freq, double duration){
static ao_sample_format format;
static double sample_period;
double w=2*M_PI*freq;
if(!sound_dev){
int default_driver;
ao_initialize();
default_driver = ao_default_driver_id();
memset(&format, 0, sizeof(format));
format.bits = 16;
format.channels = 2;
format.rate = 44100;
format.byte_format = AO_FMT_BIG;
sound_dev = ao_open_live(default_driver, &format, NULL);
if(!sound_dev){
fprintf(stderr, "Error opening sound device.\n");
exit(1);
}
sample_period=1./(double)format.rate;
}
size_t n_frames=(size_t)(duration*format.rate);
uint16_t *wave=malloc(format.channels*n_frames*sizeof *wave);
double a=A;
double traux=tr*tf/10000;
for(size_t i=0; i<n_frames; i++){
double wt=w*i*sample_period;
//Função de modulação: ******************************************
if(fi!=0 || fo!=0 ){ //modula a amplitude
a=(1-pow(2,-fi*i/10000))*pow(2,-fo*i/10000)*A;
}
if(tr!=0){ //tremulação
wt+=traux;
}
int16_t sample=(int16_t)(a*((s1*sin(wt)+c1*cos(wt)+c2*cos(2*wt)+s2*sin(3*wt)+c3*cos(4*wt)+s3*sin(5*wt) + sa*sin(wt+sd*2*M_PI)+ca*cos(wt+cd*2*M_PI)) + 10*(t1*triang(wt) + t2*triang(wt+M_PI) + r1*ramp(wt)+r2*ramp(wt+M_PI)) + sq*square(wt)));
if (m1!=0){ w+=m1; }
if(tr!=0){ //tremulação
if(traux<tr && traux > -tr){
traux+=tf;
}else if(traux>tr || traux < -tr){
traux-=tf;
}
}
//fim da modulação; ********************************************8
for(int channel=0; channel<format.channels; channel++)
wave[i*format.channels+channel]=sample;
}
ao_play(sound_dev, (char *)wave, format.channels*n_frames*sizeof *wave);
free(wave);
}
double getnf(char n){
/* Uso: getnf("c" ) retorna a frequência da primeira nota Dó. Para utilizar oitavas superiores pasta multiplicar a saída da função pelo número, por exemplo: queremos a nota D2, basta fazer 2*getnf('d').
Para notas sustenidas, basta escrever o maiúsculo da nota correspondente, por exemplo, getnf("C") representa dó sustenido
*/
int b;
switch(n){
case 'c':
b=0;
break;
case 'C':
b=1;
break;
case 'd':
b=2;
break;
case 'D':
b=3;
break;
case 'e':
b=4;
break;
case 'E':
b=5;
break;
case 'f':
b=5;
break;
case 'F':
b=6;
break;
case 'g':
b=7;
break;
case 'G':
b=8;
break;
case 'a':
b=9;
break;
case 'A':
b=10;
break;
case 'b':
b=11;
break;
case 'B':
b=12;
break;
}
double freq=2.72525*b+32.703; //Frequecia do primeiro dó mais b vezes saltos de 2.72 que é a medida de um dozeavo do intervalo entre C1 e C2
return freq;
}
int main(){
int cord=0; //para coordenara música programada a la espagueti.
int end=1; //0 significa ultima vez
goto test;
intro:
sound(7*getnf('c'), 0.8);//C
sound(7*getnf('f'), 0.4);//F
sound(7*getnf('a'), 0.8);//A
sound(7*getnf('c'), 0.4);//C
sound(7*getnf('A'), 0.6);//A#
sound(7*getnf('a'), 0.3);//A
sound(7*getnf('c'), 0.8);//C
usleep(500000);
sound(7*getnf('f'), 0.3);//C
sound(7*getnf('A'), 0.6);//A#
sound(7*getnf('a'), 0.3);//A
sound(7*getnf('c'), 0.8);//C
fo=4;
sound(7*getnf('a'), 0.3);//A
usleep(100000);
fo=2.5;
sound(7*getnf('a'), 0.8);//A
fo=1.0;
fi=0.5;
sound(7*getnf('g'), 2);//G
fo=2.5;
fi=1;
if(cord==0 || cord==3){ cord++; goto intro; }
reflex:
cord++;
fo=3;
sound(7*getnf('c'), 0.4);
fo=1.0;
fi=0.5;
sound(7*getnf('f'), 1.8);
fi=1;
fo=2.5;
usleep(500000);
if(cord==2 || cord==5){ goto reflex; }
if(cord==3){ goto intro; }
climax1:
sound(7*getnf('e'), 0.4);//E
sound(7*getnf('f'), 0.4);//F
sound(7*getnf('e'), 0.4);//E
sound(7*getnf('f'), 0.4);//F
fo=2.0;
sound(7*getnf('d'), 1);//C
fo=2.5;
if(cord==6){ cord++; goto climax1; }
//transição
sound(7*getnf('e'), 0.4);//E
sound(7*getnf('f'), 0.4);//F
sound(7*getnf('e'), 0.4);//E
sound(7*getnf('f'), 0.4);//F
sound(7*getnf('A'), 0.6);
sound(7*getnf('a'), 0.6);
sound(7*getnf('g'), 0.6);
sound(7*getnf('f'), 0.6);
fo=2.0;
sound(7*getnf('e'), 1.2);
fo=2.5;
ending:
cord++;
fo=2.0;
sound(7*getnf('f'), 1.2);
fo=2.5;
end:
sound(7*getnf('g'), 0.4);
sound(7*getnf('a'), 0.4);
sound(7*getnf('A'), 0.4);
sound(7*getnf('a'), 0.4);
sound(7*getnf('g'), 0.4);
sound(7*getnf('a'), 0.4);
if(cord<10){goto ending;}
cord++;
sound(7*getnf('f'), 0.6);
sound(7*getnf('A'), 0.4);
sound(7*getnf('a'), 0.5);
sound(7*getnf('A'), 0.4);
sound(7*getnf('a'), 0.4);
if(cord<=13){goto end;}
fo=2.0;
sound(7*getnf('f'), 1.2);
fo=2.5;
if (cord==14 && end){cord=0; end=0; goto intro;}
test:
m1=-0.01;
fo=0.2;
fi=1.5;
sound(7*getnf('c'), 1);
fo=1.5;
fi=3;
m1=0.0001;
sound(7*getnf('f'), 1.5);
fo=2.5;
return 0;
}
Programa que Exibe centro da tela
Método de Power para calcular o autovelor dominante de uma matriz
Retornar o montante de um capital aplicado a juros compostos
Cirurgia para acelerar o openSUSE em HD externo via USB
Void Server como Domain Control
Modo Simples de Baixar e Usar o bash-completion
Monitorando o Preço do Bitcoin ou sua Cripto Favorita em Tempo Real com um Widget Flutuante
Opções secretas em tema do Cinnamon
Como mapear unidade de rede no Linux
Como quebrar senha usando john the ripper
Não consigo instalar distro antiga no virtualbox nem direto no hd (29)
queria saber como posso alterar a frequencia do meu ryzen 2300u pro (3)









