Sintetizador sonoro que toca redez vouz 4
Publicado por Matth (última atualização em 09/02/2016)
[ Hits: 1.826 ]
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; }
Calcular determinante de matrizes
Exibe quantos números perfeitos foram digitados
Melhorando o tempo de boot do Fedora e outras distribuições
Como instalar as extensões Dash To Dock e Hide Top Bar no Gnome 45/46
E a guerra contra bots continua
Tradução do artigo do filósofo Gottfried Wilhelm Leibniz sobre o sistema binário
Conheça o firewall OpenGFW, uma implementação do (Great Firewall of China).
Instalando o FreeOffice no LMDE 6
Anki: Remover Tags de Estilo HTML de Todas as Cartas
Colocando uma opção de redimensionamento de imagem no menu de contexto do KDE
[Shell Script] Script para desinstalar pacotes desnecessários no OpenSuse
[Shell Script] Script para criar certificados de forma automatizada no OpenVpn
[Shell Script] Conversor de vídeo com opção de legenda
[C/C++] BRT - Bulk Renaming Tool
[Shell Script] Criação de Usuarios , Grupo e instalação do servidor de arquivos samba