fix(voz): tira o timbre de sapo; voz aguda, limpa e com brilho metalico
O coaxar vinha do zumbido de 72 Hz, da ressonancia grave (~230 Hz), da oitava de baixo e do FM desalinhado. Agora: ressonancia de lata fina (~850 Hz), FM harmonico leve, realce em 3,2 kHz, oitava de baixo quase nula e tom 25% acima. Bravo vira bipes zangados e pensar vira 'hmm?' com bipinhos; nenhum som tem energia relevante abaixo de 250 Hz. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,45 +9,36 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let ruido = null; // buffer de ruído reaproveitado
|
let ruido = null; // buffer de ruído reaproveitado
|
||||||
|
const TOM = 1.25; // todas as sílabas 25% acima do tom escrito
|
||||||
const saidas = new WeakMap(); // AudioContext → nó de saída (compressor)
|
const saidas = new WeakMap(); // AudioContext → nó de saída (compressor)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cadeia de "garganta metálica" (criada uma vez por AudioContext):
|
* Cadeia de "brilho metálico" (criada uma vez por AudioContext):
|
||||||
* voz → [seca + modulação em anel] → ressonância de lata → degraus digitais → compressor → saída
|
* voz → ressonância de lata fina (agudo, ~850 Hz) → saturação leve → compressor → saída
|
||||||
|
* Nada grave: zumbido e ressonância graves deixavam a voz com cara de sapo.
|
||||||
*/
|
*/
|
||||||
function saida(c) {
|
function saida(c) {
|
||||||
if (saidas.has(c)) return saidas.get(c);
|
if (saidas.has(c)) return saidas.get(c);
|
||||||
const entrada = c.createGain();
|
const entrada = c.createGain();
|
||||||
// modulação em anel: multiplica a voz por um zumbido grave → timbre mecânico
|
const seca = c.createGain(); seca.gain.value = 0.8;
|
||||||
const seca = c.createGain(); seca.gain.value = 0.55;
|
const atraso = c.createDelay(0.05); atraso.delayTime.value = 0.00118;
|
||||||
const anel = c.createGain(); anel.gain.value = 0;
|
const volta = c.createGain(); volta.gain.value = 0.42;
|
||||||
const portadora = c.createOscillator(); portadora.frequency.value = 72;
|
const molhada = c.createGain(); molhada.gain.value = 0.35;
|
||||||
const profundidade = c.createGain(); profundidade.gain.value = 0.9;
|
entrada.connect(seca);
|
||||||
portadora.connect(profundidade); profundidade.connect(anel.gain); portadora.start();
|
entrada.connect(atraso); atraso.connect(volta); volta.connect(atraso); atraso.connect(molhada);
|
||||||
const mixAnel = c.createGain(); mixAnel.gain.value = 0.75;
|
const satura = c.createWaveShaper();
|
||||||
entrada.connect(seca); entrada.connect(anel); anel.connect(mixAnel);
|
const n = 2048, curva = new Float32Array(n);
|
||||||
// ressonância de lata: atraso curtíssimo realimentado (pente de harmônicos)
|
for (let i = 0; i < n; i++) { const x = (i / (n - 1)) * 2 - 1; curva[i] = Math.tanh(x * 1.3); }
|
||||||
const lata = c.createGain();
|
satura.curve = curva;
|
||||||
const atraso = c.createDelay(0.05); atraso.delayTime.value = 0.0043;
|
seca.connect(satura); molhada.connect(satura);
|
||||||
const volta = c.createGain(); volta.gain.value = 0.58;
|
const brilho = c.createBiquadFilter(); // realce leve nos agudos: "metal" limpo
|
||||||
const molhada = c.createGain(); molhada.gain.value = 0.55;
|
brilho.type = 'peaking'; brilho.frequency.value = 3200; brilho.Q.value = 1.2; brilho.gain.value = 4;
|
||||||
seca.connect(lata); mixAnel.connect(lata);
|
|
||||||
lata.connect(atraso); atraso.connect(volta); volta.connect(atraso); atraso.connect(molhada);
|
|
||||||
// degraus digitais leves + saturação suave
|
|
||||||
const degraus = c.createWaveShaper();
|
|
||||||
const n = 2048, curva = new Float32Array(n), niveis = 28;
|
|
||||||
for (let i = 0; i < n; i++) {
|
|
||||||
const x = (i / (n - 1)) * 2 - 1;
|
|
||||||
curva[i] = Math.tanh(Math.round(x * niveis) / niveis * 1.6);
|
|
||||||
}
|
|
||||||
degraus.curve = curva;
|
|
||||||
lata.connect(degraus); molhada.connect(degraus);
|
|
||||||
const comp = c.createDynamicsCompressor();
|
const comp = c.createDynamicsCompressor();
|
||||||
comp.threshold.value = -16; comp.ratio.value = 4; comp.attack.value = 0.003; comp.release.value = 0.15;
|
comp.threshold.value = -16; comp.ratio.value = 4; comp.attack.value = 0.003; comp.release.value = 0.15;
|
||||||
const passaBaixa = c.createBiquadFilter();
|
const passaBaixa = c.createBiquadFilter();
|
||||||
passaBaixa.type = 'lowpass'; passaBaixa.frequency.value = 6500;
|
passaBaixa.type = 'lowpass'; passaBaixa.frequency.value = 8000;
|
||||||
const volume = c.createGain(); volume.gain.value = 0.7; // a cadeia metálica soma energia
|
const volume = c.createGain(); volume.gain.value = 0.8;
|
||||||
degraus.connect(comp); comp.connect(passaBaixa); passaBaixa.connect(volume); volume.connect(c.destination);
|
satura.connect(brilho); brilho.connect(comp); comp.connect(passaBaixa); passaBaixa.connect(volume); volume.connect(c.destination);
|
||||||
saidas.set(c, entrada);
|
saidas.set(c, entrada);
|
||||||
return entrada;
|
return entrada;
|
||||||
}
|
}
|
||||||
@@ -59,6 +50,7 @@
|
|||||||
function silaba(c, t0, dur, de, para, vol, op) {
|
function silaba(c, t0, dur, de, para, vol, op) {
|
||||||
op = op || {};
|
op = op || {};
|
||||||
vol *= 2.4; // compensa a energia que o filtro de formante tira
|
vol *= 2.4; // compensa a energia que o filtro de formante tira
|
||||||
|
de *= TOM; para *= TOM; // voz de robozinho: aguda
|
||||||
const osc = c.createOscillator();
|
const osc = c.createOscillator();
|
||||||
osc.type = op.forma || 'sawtooth';
|
osc.type = op.forma || 'sawtooth';
|
||||||
osc.frequency.setValueAtTime(de, t0);
|
osc.frequency.setValueAtTime(de, t0);
|
||||||
@@ -69,13 +61,13 @@
|
|||||||
lfo.connect(prof); prof.connect(osc.frequency);
|
lfo.connect(prof); prof.connect(osc.frequency);
|
||||||
lfo.start(t0); lfo.stop(t0 + dur + 0.05);
|
lfo.start(t0); lfo.stop(t0 + dur + 0.05);
|
||||||
}
|
}
|
||||||
// FM com razão não inteira: harmônicos desalinhados soam como metal
|
// FM harmônico e leve: brilho de metal sem aspereza
|
||||||
const mod = c.createOscillator(), modProf = c.createGain();
|
const mod = c.createOscillator(), modProf = c.createGain();
|
||||||
mod.type = 'sine';
|
mod.type = 'sine';
|
||||||
mod.frequency.setValueAtTime(de * 1.41, t0);
|
mod.frequency.setValueAtTime(de * 2, t0);
|
||||||
mod.frequency.exponentialRampToValueAtTime(Math.max(20, para * 1.41), t0 + dur);
|
mod.frequency.exponentialRampToValueAtTime(Math.max(20, para * 2), t0 + dur);
|
||||||
modProf.gain.setValueAtTime(de * (op.metal ?? 0.55), t0);
|
modProf.gain.setValueAtTime(de * (op.metal ?? 0.22), t0);
|
||||||
modProf.gain.exponentialRampToValueAtTime(Math.max(1, para * (op.metal ?? 0.55)), t0 + dur);
|
modProf.gain.exponentialRampToValueAtTime(Math.max(1, para * (op.metal ?? 0.22)), t0 + dur);
|
||||||
mod.connect(modProf); modProf.connect(osc.frequency);
|
mod.connect(modProf); modProf.connect(osc.frequency);
|
||||||
mod.start(t0); mod.stop(t0 + dur + 0.05);
|
mod.start(t0); mod.stop(t0 + dur + 0.05);
|
||||||
// corpo: uma senoide uma oitava abaixo deixa a voz menos "apito"
|
// corpo: uma senoide uma oitava abaixo deixa a voz menos "apito"
|
||||||
@@ -94,7 +86,7 @@
|
|||||||
g.gain.exponentialRampToValueAtTime(vol, t0 + ataque);
|
g.gain.exponentialRampToValueAtTime(vol, t0 + ataque);
|
||||||
g.gain.setValueAtTime(vol, t0 + dur * 0.7);
|
g.gain.setValueAtTime(vol, t0 + dur * 0.7);
|
||||||
g.gain.exponentialRampToValueAtTime(0.0001, t0 + dur);
|
g.gain.exponentialRampToValueAtTime(0.0001, t0 + dur);
|
||||||
gs.gain.value = 0.35;
|
gs.gain.value = 0.12; // pouca oitava de baixo: grave demais vira coaxar
|
||||||
osc.connect(filtro); sub.connect(gs); gs.connect(filtro); filtro.connect(g); g.connect(saida(c));
|
osc.connect(filtro); sub.connect(gs); gs.connect(filtro); filtro.connect(g); g.connect(saida(c));
|
||||||
osc.start(t0); sub.start(t0);
|
osc.start(t0); sub.start(t0);
|
||||||
osc.stop(t0 + dur + 0.05); sub.stop(t0 + dur + 0.05);
|
osc.stop(t0 + dur + 0.05); sub.stop(t0 + dur + 0.05);
|
||||||
@@ -147,14 +139,14 @@
|
|||||||
coracao: (c, t, v) => { silaba(c, t, 0.55, 760, 560, v, { vogal: [800, 1300], vib: [7, 28] }); },
|
coracao: (c, t, v) => { silaba(c, t, 0.55, 760, 560, v, { vogal: [800, 1300], vib: [7, 28] }); },
|
||||||
piscadinha: (c, t, v) => { clique(c, t, v); silaba(c, t + 0.04, 0.08, 1000, 1300, v * 0.6, { forma: 'square', vogal: I }); },
|
piscadinha: (c, t, v) => { clique(c, t, v); silaba(c, t + 0.04, 0.08, 1000, 1300, v * 0.6, { forma: 'square', vogal: I }); },
|
||||||
surpreso: (c, t, v) => { silaba(c, t, 0.22, 260, 1100, v, { vogal: [450, 2000] }); silaba(c, t + 0.22, 0.12, 1100, 820, v * 0.8, { vogal: I }); },
|
surpreso: (c, t, v) => { silaba(c, t, 0.22, 260, 1100, v, { vogal: [450, 2000] }); silaba(c, t + 0.22, 0.12, 1100, 820, v * 0.8, { vogal: I }); },
|
||||||
bravo: (c, t, v) => { silaba(c, t, 0.42, 190, 120, v * 0.9, { forma: 'square', vogal: [500, 380], vib: [18, 22], q: 3 }); },
|
bravo: (c, t, v) => [0, 0.13, 0.26].forEach((d, i) => silaba(c, t + d, 0.1, 480 - i * 30, 380 - i * 30, v * 0.85, { forma: 'square', vogal: [1300, 900] })), // bipes zangados
|
||||||
triste: (c, t, v) => { silaba(c, t, 0.65, 540, 290, v * 0.85, { vogal: [700, 420], vib: [5, 14] }); },
|
triste: (c, t, v) => { silaba(c, t, 0.65, 640, 380, v * 0.85, { vogal: [1200, 750], vib: [5, 14] }); },
|
||||||
dormir: (c, t, v) => { silaba(c, t, 0.35, 380, 640, v * 0.7, { vogal: [500, 1000] }); silaba(c, t + 0.36, 0.75, 640, 210, v * 0.6, { vogal: [1000, 380], vib: [4, 8] }); },
|
dormir: (c, t, v) => { silaba(c, t, 0.35, 460, 760, v * 0.7, { vogal: [900, 1500] }); silaba(c, t + 0.36, 0.75, 760, 340, v * 0.6, { vogal: [1500, 700], vib: [4, 8] }); },
|
||||||
acordar: (c, t, v) => { servo(c, t, 0.25, v * 0.5); [300, 450, 700].forEach((f, i) => silaba(c, t + 0.22 + i * 0.1, 0.1, f, f * 1.2, v * 0.8, { vogal: I, forma: 'square' })); silaba(c, t + 0.56, 0.2, 700, 1050, v, { vogal: [1200, 2200], vib: [8, 15] }); },
|
acordar: (c, t, v) => { servo(c, t, 0.25, v * 0.5); [300, 450, 700].forEach((f, i) => silaba(c, t + 0.22 + i * 0.1, 0.1, f, f * 1.2, v * 0.8, { vogal: I, forma: 'square' })); silaba(c, t + 0.56, 0.2, 700, 1050, v, { vogal: [1200, 2200], vib: [8, 15] }); },
|
||||||
acenar: (c, t, v) => { servo(c, t, 0.3, v * 0.45); silaba(c, t + 0.28, 0.13, 520, 820, v, { vogal: [1000, 1900] }); silaba(c, t + 0.44, 0.2, 760, 1080, v, { vogal: I, vib: [9, 20] }); },
|
acenar: (c, t, v) => { servo(c, t, 0.3, v * 0.45); silaba(c, t + 0.28, 0.13, 520, 820, v, { vogal: [1000, 1900] }); silaba(c, t + 0.44, 0.2, 760, 1080, v, { vogal: I, vib: [9, 20] }); },
|
||||||
esconder: (c, t, v) => { servo(c, t, 0.45, v * 0.5); silaba(c, t + 0.1, 0.08, 950, 1350, v * 0.8, { vogal: I }); for (let i = 0; i < 5; i++) silaba(c, t + 0.6 + i * 0.09, 0.05, 1200 + (i % 2) * 180, 1300, v * 0.35, { forma: 'square', vogal: I }); servo(c, t + 2.05, 0.4, v * 0.45, false); },
|
esconder: (c, t, v) => { servo(c, t, 0.45, v * 0.5); silaba(c, t + 0.1, 0.08, 950, 1350, v * 0.8, { vogal: I }); for (let i = 0; i < 5; i++) silaba(c, t + 0.6 + i * 0.09, 0.05, 1200 + (i % 2) * 180, 1300, v * 0.35, { forma: 'square', vogal: I }); servo(c, t + 2.05, 0.4, v * 0.45, false); },
|
||||||
espiar: (c, t, v) => { servo(c, t, 0.45, v * 0.5); silaba(c, t + 1.0, 0.3, 480, 760, v * 0.9, { vogal: [600, 1700] }); silaba(c, t + 2.0, 0.16, 800, 1150, v, { vogal: I }); },
|
espiar: (c, t, v) => { servo(c, t, 0.45, v * 0.5); silaba(c, t + 1.0, 0.3, 480, 760, v * 0.9, { vogal: [600, 1700] }); silaba(c, t + 2.0, 0.16, 800, 1150, v, { vogal: I }); },
|
||||||
pensar: (c, t, v) => { servo(c, t, 0.35, v * 0.4); silaba(c, t + 0.35, 0.85, 330, 365, v * 0.6, { vogal: U, vib: [4, 6], forma: 'triangle' }); },
|
pensar: (c, t, v) => { servo(c, t, 0.35, v * 0.4); silaba(c, t + 0.35, 0.5, 520, 640, v * 0.7, { vogal: [900, 1600], vib: [5, 10] }); [0.95, 1.12].forEach((d) => silaba(c, t + d, 0.05, 1500, 1600, v * 0.35, { forma: 'square', vogal: I })); }, // "hmm?" e bipinhos
|
||||||
musica: (c, t, v) => [523, 659, 784, 659, 880, 784, 659, 1047].forEach((f, i) => silaba(c, t + i * 0.26, 0.2, f, f * 1.02, v * 0.6, { forma: 'triangle', vogal: A, vib: [6, 5] })),
|
musica: (c, t, v) => [523, 659, 784, 659, 880, 784, 659, 1047].forEach((f, i) => silaba(c, t + i * 0.26, 0.2, f, f * 1.02, v * 0.6, { forma: 'triangle', vogal: A, vib: [6, 5] })),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+31
-39
@@ -9,45 +9,36 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let ruido = null; // buffer de ruído reaproveitado
|
let ruido = null; // buffer de ruído reaproveitado
|
||||||
|
const TOM = 1.25; // todas as sílabas 25% acima do tom escrito
|
||||||
const saidas = new WeakMap(); // AudioContext → nó de saída (compressor)
|
const saidas = new WeakMap(); // AudioContext → nó de saída (compressor)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cadeia de "garganta metálica" (criada uma vez por AudioContext):
|
* Cadeia de "brilho metálico" (criada uma vez por AudioContext):
|
||||||
* voz → [seca + modulação em anel] → ressonância de lata → degraus digitais → compressor → saída
|
* voz → ressonância de lata fina (agudo, ~850 Hz) → saturação leve → compressor → saída
|
||||||
|
* Nada grave: zumbido e ressonância graves deixavam a voz com cara de sapo.
|
||||||
*/
|
*/
|
||||||
function saida(c) {
|
function saida(c) {
|
||||||
if (saidas.has(c)) return saidas.get(c);
|
if (saidas.has(c)) return saidas.get(c);
|
||||||
const entrada = c.createGain();
|
const entrada = c.createGain();
|
||||||
// modulação em anel: multiplica a voz por um zumbido grave → timbre mecânico
|
const seca = c.createGain(); seca.gain.value = 0.8;
|
||||||
const seca = c.createGain(); seca.gain.value = 0.55;
|
const atraso = c.createDelay(0.05); atraso.delayTime.value = 0.00118;
|
||||||
const anel = c.createGain(); anel.gain.value = 0;
|
const volta = c.createGain(); volta.gain.value = 0.42;
|
||||||
const portadora = c.createOscillator(); portadora.frequency.value = 72;
|
const molhada = c.createGain(); molhada.gain.value = 0.35;
|
||||||
const profundidade = c.createGain(); profundidade.gain.value = 0.9;
|
entrada.connect(seca);
|
||||||
portadora.connect(profundidade); profundidade.connect(anel.gain); portadora.start();
|
entrada.connect(atraso); atraso.connect(volta); volta.connect(atraso); atraso.connect(molhada);
|
||||||
const mixAnel = c.createGain(); mixAnel.gain.value = 0.75;
|
const satura = c.createWaveShaper();
|
||||||
entrada.connect(seca); entrada.connect(anel); anel.connect(mixAnel);
|
const n = 2048, curva = new Float32Array(n);
|
||||||
// ressonância de lata: atraso curtíssimo realimentado (pente de harmônicos)
|
for (let i = 0; i < n; i++) { const x = (i / (n - 1)) * 2 - 1; curva[i] = Math.tanh(x * 1.3); }
|
||||||
const lata = c.createGain();
|
satura.curve = curva;
|
||||||
const atraso = c.createDelay(0.05); atraso.delayTime.value = 0.0043;
|
seca.connect(satura); molhada.connect(satura);
|
||||||
const volta = c.createGain(); volta.gain.value = 0.58;
|
const brilho = c.createBiquadFilter(); // realce leve nos agudos: "metal" limpo
|
||||||
const molhada = c.createGain(); molhada.gain.value = 0.55;
|
brilho.type = 'peaking'; brilho.frequency.value = 3200; brilho.Q.value = 1.2; brilho.gain.value = 4;
|
||||||
seca.connect(lata); mixAnel.connect(lata);
|
|
||||||
lata.connect(atraso); atraso.connect(volta); volta.connect(atraso); atraso.connect(molhada);
|
|
||||||
// degraus digitais leves + saturação suave
|
|
||||||
const degraus = c.createWaveShaper();
|
|
||||||
const n = 2048, curva = new Float32Array(n), niveis = 28;
|
|
||||||
for (let i = 0; i < n; i++) {
|
|
||||||
const x = (i / (n - 1)) * 2 - 1;
|
|
||||||
curva[i] = Math.tanh(Math.round(x * niveis) / niveis * 1.6);
|
|
||||||
}
|
|
||||||
degraus.curve = curva;
|
|
||||||
lata.connect(degraus); molhada.connect(degraus);
|
|
||||||
const comp = c.createDynamicsCompressor();
|
const comp = c.createDynamicsCompressor();
|
||||||
comp.threshold.value = -16; comp.ratio.value = 4; comp.attack.value = 0.003; comp.release.value = 0.15;
|
comp.threshold.value = -16; comp.ratio.value = 4; comp.attack.value = 0.003; comp.release.value = 0.15;
|
||||||
const passaBaixa = c.createBiquadFilter();
|
const passaBaixa = c.createBiquadFilter();
|
||||||
passaBaixa.type = 'lowpass'; passaBaixa.frequency.value = 6500;
|
passaBaixa.type = 'lowpass'; passaBaixa.frequency.value = 8000;
|
||||||
const volume = c.createGain(); volume.gain.value = 0.7; // a cadeia metálica soma energia
|
const volume = c.createGain(); volume.gain.value = 0.8;
|
||||||
degraus.connect(comp); comp.connect(passaBaixa); passaBaixa.connect(volume); volume.connect(c.destination);
|
satura.connect(brilho); brilho.connect(comp); comp.connect(passaBaixa); passaBaixa.connect(volume); volume.connect(c.destination);
|
||||||
saidas.set(c, entrada);
|
saidas.set(c, entrada);
|
||||||
return entrada;
|
return entrada;
|
||||||
}
|
}
|
||||||
@@ -59,6 +50,7 @@
|
|||||||
function silaba(c, t0, dur, de, para, vol, op) {
|
function silaba(c, t0, dur, de, para, vol, op) {
|
||||||
op = op || {};
|
op = op || {};
|
||||||
vol *= 2.4; // compensa a energia que o filtro de formante tira
|
vol *= 2.4; // compensa a energia que o filtro de formante tira
|
||||||
|
de *= TOM; para *= TOM; // voz de robozinho: aguda
|
||||||
const osc = c.createOscillator();
|
const osc = c.createOscillator();
|
||||||
osc.type = op.forma || 'sawtooth';
|
osc.type = op.forma || 'sawtooth';
|
||||||
osc.frequency.setValueAtTime(de, t0);
|
osc.frequency.setValueAtTime(de, t0);
|
||||||
@@ -69,13 +61,13 @@
|
|||||||
lfo.connect(prof); prof.connect(osc.frequency);
|
lfo.connect(prof); prof.connect(osc.frequency);
|
||||||
lfo.start(t0); lfo.stop(t0 + dur + 0.05);
|
lfo.start(t0); lfo.stop(t0 + dur + 0.05);
|
||||||
}
|
}
|
||||||
// FM com razão não inteira: harmônicos desalinhados soam como metal
|
// FM harmônico e leve: brilho de metal sem aspereza
|
||||||
const mod = c.createOscillator(), modProf = c.createGain();
|
const mod = c.createOscillator(), modProf = c.createGain();
|
||||||
mod.type = 'sine';
|
mod.type = 'sine';
|
||||||
mod.frequency.setValueAtTime(de * 1.41, t0);
|
mod.frequency.setValueAtTime(de * 2, t0);
|
||||||
mod.frequency.exponentialRampToValueAtTime(Math.max(20, para * 1.41), t0 + dur);
|
mod.frequency.exponentialRampToValueAtTime(Math.max(20, para * 2), t0 + dur);
|
||||||
modProf.gain.setValueAtTime(de * (op.metal ?? 0.55), t0);
|
modProf.gain.setValueAtTime(de * (op.metal ?? 0.22), t0);
|
||||||
modProf.gain.exponentialRampToValueAtTime(Math.max(1, para * (op.metal ?? 0.55)), t0 + dur);
|
modProf.gain.exponentialRampToValueAtTime(Math.max(1, para * (op.metal ?? 0.22)), t0 + dur);
|
||||||
mod.connect(modProf); modProf.connect(osc.frequency);
|
mod.connect(modProf); modProf.connect(osc.frequency);
|
||||||
mod.start(t0); mod.stop(t0 + dur + 0.05);
|
mod.start(t0); mod.stop(t0 + dur + 0.05);
|
||||||
// corpo: uma senoide uma oitava abaixo deixa a voz menos "apito"
|
// corpo: uma senoide uma oitava abaixo deixa a voz menos "apito"
|
||||||
@@ -94,7 +86,7 @@
|
|||||||
g.gain.exponentialRampToValueAtTime(vol, t0 + ataque);
|
g.gain.exponentialRampToValueAtTime(vol, t0 + ataque);
|
||||||
g.gain.setValueAtTime(vol, t0 + dur * 0.7);
|
g.gain.setValueAtTime(vol, t0 + dur * 0.7);
|
||||||
g.gain.exponentialRampToValueAtTime(0.0001, t0 + dur);
|
g.gain.exponentialRampToValueAtTime(0.0001, t0 + dur);
|
||||||
gs.gain.value = 0.35;
|
gs.gain.value = 0.12; // pouca oitava de baixo: grave demais vira coaxar
|
||||||
osc.connect(filtro); sub.connect(gs); gs.connect(filtro); filtro.connect(g); g.connect(saida(c));
|
osc.connect(filtro); sub.connect(gs); gs.connect(filtro); filtro.connect(g); g.connect(saida(c));
|
||||||
osc.start(t0); sub.start(t0);
|
osc.start(t0); sub.start(t0);
|
||||||
osc.stop(t0 + dur + 0.05); sub.stop(t0 + dur + 0.05);
|
osc.stop(t0 + dur + 0.05); sub.stop(t0 + dur + 0.05);
|
||||||
@@ -147,14 +139,14 @@
|
|||||||
coracao: (c, t, v) => { silaba(c, t, 0.55, 760, 560, v, { vogal: [800, 1300], vib: [7, 28] }); },
|
coracao: (c, t, v) => { silaba(c, t, 0.55, 760, 560, v, { vogal: [800, 1300], vib: [7, 28] }); },
|
||||||
piscadinha: (c, t, v) => { clique(c, t, v); silaba(c, t + 0.04, 0.08, 1000, 1300, v * 0.6, { forma: 'square', vogal: I }); },
|
piscadinha: (c, t, v) => { clique(c, t, v); silaba(c, t + 0.04, 0.08, 1000, 1300, v * 0.6, { forma: 'square', vogal: I }); },
|
||||||
surpreso: (c, t, v) => { silaba(c, t, 0.22, 260, 1100, v, { vogal: [450, 2000] }); silaba(c, t + 0.22, 0.12, 1100, 820, v * 0.8, { vogal: I }); },
|
surpreso: (c, t, v) => { silaba(c, t, 0.22, 260, 1100, v, { vogal: [450, 2000] }); silaba(c, t + 0.22, 0.12, 1100, 820, v * 0.8, { vogal: I }); },
|
||||||
bravo: (c, t, v) => { silaba(c, t, 0.42, 190, 120, v * 0.9, { forma: 'square', vogal: [500, 380], vib: [18, 22], q: 3 }); },
|
bravo: (c, t, v) => [0, 0.13, 0.26].forEach((d, i) => silaba(c, t + d, 0.1, 480 - i * 30, 380 - i * 30, v * 0.85, { forma: 'square', vogal: [1300, 900] })), // bipes zangados
|
||||||
triste: (c, t, v) => { silaba(c, t, 0.65, 540, 290, v * 0.85, { vogal: [700, 420], vib: [5, 14] }); },
|
triste: (c, t, v) => { silaba(c, t, 0.65, 640, 380, v * 0.85, { vogal: [1200, 750], vib: [5, 14] }); },
|
||||||
dormir: (c, t, v) => { silaba(c, t, 0.35, 380, 640, v * 0.7, { vogal: [500, 1000] }); silaba(c, t + 0.36, 0.75, 640, 210, v * 0.6, { vogal: [1000, 380], vib: [4, 8] }); },
|
dormir: (c, t, v) => { silaba(c, t, 0.35, 460, 760, v * 0.7, { vogal: [900, 1500] }); silaba(c, t + 0.36, 0.75, 760, 340, v * 0.6, { vogal: [1500, 700], vib: [4, 8] }); },
|
||||||
acordar: (c, t, v) => { servo(c, t, 0.25, v * 0.5); [300, 450, 700].forEach((f, i) => silaba(c, t + 0.22 + i * 0.1, 0.1, f, f * 1.2, v * 0.8, { vogal: I, forma: 'square' })); silaba(c, t + 0.56, 0.2, 700, 1050, v, { vogal: [1200, 2200], vib: [8, 15] }); },
|
acordar: (c, t, v) => { servo(c, t, 0.25, v * 0.5); [300, 450, 700].forEach((f, i) => silaba(c, t + 0.22 + i * 0.1, 0.1, f, f * 1.2, v * 0.8, { vogal: I, forma: 'square' })); silaba(c, t + 0.56, 0.2, 700, 1050, v, { vogal: [1200, 2200], vib: [8, 15] }); },
|
||||||
acenar: (c, t, v) => { servo(c, t, 0.3, v * 0.45); silaba(c, t + 0.28, 0.13, 520, 820, v, { vogal: [1000, 1900] }); silaba(c, t + 0.44, 0.2, 760, 1080, v, { vogal: I, vib: [9, 20] }); },
|
acenar: (c, t, v) => { servo(c, t, 0.3, v * 0.45); silaba(c, t + 0.28, 0.13, 520, 820, v, { vogal: [1000, 1900] }); silaba(c, t + 0.44, 0.2, 760, 1080, v, { vogal: I, vib: [9, 20] }); },
|
||||||
esconder: (c, t, v) => { servo(c, t, 0.45, v * 0.5); silaba(c, t + 0.1, 0.08, 950, 1350, v * 0.8, { vogal: I }); for (let i = 0; i < 5; i++) silaba(c, t + 0.6 + i * 0.09, 0.05, 1200 + (i % 2) * 180, 1300, v * 0.35, { forma: 'square', vogal: I }); servo(c, t + 2.05, 0.4, v * 0.45, false); },
|
esconder: (c, t, v) => { servo(c, t, 0.45, v * 0.5); silaba(c, t + 0.1, 0.08, 950, 1350, v * 0.8, { vogal: I }); for (let i = 0; i < 5; i++) silaba(c, t + 0.6 + i * 0.09, 0.05, 1200 + (i % 2) * 180, 1300, v * 0.35, { forma: 'square', vogal: I }); servo(c, t + 2.05, 0.4, v * 0.45, false); },
|
||||||
espiar: (c, t, v) => { servo(c, t, 0.45, v * 0.5); silaba(c, t + 1.0, 0.3, 480, 760, v * 0.9, { vogal: [600, 1700] }); silaba(c, t + 2.0, 0.16, 800, 1150, v, { vogal: I }); },
|
espiar: (c, t, v) => { servo(c, t, 0.45, v * 0.5); silaba(c, t + 1.0, 0.3, 480, 760, v * 0.9, { vogal: [600, 1700] }); silaba(c, t + 2.0, 0.16, 800, 1150, v, { vogal: I }); },
|
||||||
pensar: (c, t, v) => { servo(c, t, 0.35, v * 0.4); silaba(c, t + 0.35, 0.85, 330, 365, v * 0.6, { vogal: U, vib: [4, 6], forma: 'triangle' }); },
|
pensar: (c, t, v) => { servo(c, t, 0.35, v * 0.4); silaba(c, t + 0.35, 0.5, 520, 640, v * 0.7, { vogal: [900, 1600], vib: [5, 10] }); [0.95, 1.12].forEach((d) => silaba(c, t + d, 0.05, 1500, 1600, v * 0.35, { forma: 'square', vogal: I })); }, // "hmm?" e bipinhos
|
||||||
musica: (c, t, v) => [523, 659, 784, 659, 880, 784, 659, 1047].forEach((f, i) => silaba(c, t + i * 0.26, 0.2, f, f * 1.02, v * 0.6, { forma: 'triangle', vogal: A, vib: [6, 5] })),
|
musica: (c, t, v) => [523, 659, 784, 659, 880, 784, 659, 1047].forEach((f, i) => silaba(c, t + i * 0.26, 0.2, f, f * 1.02, v * 0.6, { forma: 'triangle', vogal: A, vib: [6, 5] })),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user