Sintetizador sonoro que toca redez vouz 4
Publicado por Matth (última atualização em 09/02/2016)
[ Hits: 1.970 ]
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; }
Compartilhando a tela do Computador no Celular via Deskreen
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
Efeito "livro" em arquivos PDF
Como resolver o erro no CUPS: Unable to get list of printer drivers
Flatpak: remover runtimes não usados e pacotes
Mudar o gerenciador de login (GDM para SDDM e vice-versa) - parte 2
Estou com sede em aprender sobre o nosso querido Linux. (1)
big linux sem audio como resolver (2)
Como faz para dar um update-grub por shell script [RESOLVIDO] (3)
[Python] Automação de scan de vulnerabilidades
[Python] Script para analise de superficie de ataque
[Shell Script] Novo script para redimensionar, rotacionar, converter e espelhar arquivos de imagem
[Shell Script] Iniciador de DOOM (DSDA-DOOM, Doom Retro ou Woof!)
[Shell Script] Script para adicionar bordas às imagens de uma pasta