Hi peoples!
No segundo post sobre nossa jornada pelo processing e universo multimídia vamos brincar um pouco com uma técnica que tem como propósito a implementação de filtros para sons ou imagens. A técnica , que por enquanto vamos explorar em som, chama-se convolução.
Trata-se de um processo de aplicação de efeitos em áudio, onde podemos considerar o som como um vetor de números e vamos alterar esses valores para aplicar um efeito que desejamos. Essa alteração sedá pela multiplicação dos valores do vetor do som por uma matriz que contém uma representação discreta de uma curva gaussiana. A curva gaussiana tem um formato similar ao de um sino e é utilizada em vários campos da matemática, física.. Para saber mais sobre as propriedades dessa entidade matemática sugiro dar uma olhadinha na nossa querida enciclopédia livre:
wikipédia.
Abaixo segue o código do programinha desenvolvido para ilustrar essa tal de convolução:
import ddf.minim.*;
import ddf.minim.analysis.*;
import javax.sound.sampled.*;
Minim minim;
AudioSample audio;
AudioSample filtroPassaBaixa;
AudioSample filtroBox;
AudioSample filtroPassaAlta;
float[] out;
void setup(){
size(500,600);
AudioFormat formatoAudio = new AudioFormat(44100,16,2,true,true);
minim = new Minim(this);
float[] passaAlta = {0.1, 0.8, 1 ,0.8,0.1};
float[] matrizBox = {1, 1, 1 ,1,1};
float[] passaBaixa = {0.9, 0.2, 0 ,0.2, 0.9};
audio = minim.loadSample("/home/gleison/musica.mp3", 1024);
out = audio.getChannel(AudioSample.RIGHT);
float[] outPassaAlta = convolucao(out, passaAlta);
float[] outFiltroBox = convolucao(out, matrizBox);
float[] outPassaBaixa = convolucao(out, passaBaixa);
filtroPassaAlta = minim.createSample(outPassaAlta, formatoAudio);
filtroPassaAlta.trigger();
filtroBox = minim.createSample(outFiltroBox, formatoAudio);
filtroBox.trigger();
filtroPassaBaixa = minim.createSample(outPassaBaixa, formatoAudio);
filtroPassaBaixa.trigger();
}
float[] convolucao(float[] input, float[] matrizConvolucao){
float[] out = new float[input.length];
for(int i = 0; i < input.length - matrizConvolucao.length; i++){
float soma = 0;
for(int j = 0; j < matrizConvolucao.length; j++){
soma += input[i + j] * matrizConvolucao[j];
}
out[i] = soma;
}
return out;
}
void draw(){
background(0);
stroke(255);
for(int i = 0; i < filtroPassaAlta.mix.size() - 1; i++){
line(i, 100 + filtroPassaAlta.mix.get(i)*30, i+1, 100 + filtroPassaAlta.mix.get(i+1)*30);
}
for(int i = 0; i < filtroBox.mix.size() - 1; i++){
line(i, 250 + filtroBox.mix.get(i)*30, i+1, 250 + filtroBox.mix.get(i+1)*30);
}
for(int i = 0; i < filtroPassaBaixa.mix.size() - 1; i++){
line(i, 400 + filtroPassaBaixa.mix.get(i)*30, i+1, 400 + filtroPassaBaixa.mix.get(i+1)*30);
}
}
Bem, acho que o código é relativamente simples de entender, por isso vou focar apenas na função denominada convolução. Ela recebe como parâmetro o vetor que representa o áudio que vamos manipular e a matriz que contém os valores gaussianos. Seu retorno é um vetor onde cada posição contém o valor da somatória do produto dos valores da matriz gaussiana pelo vetor do áudio.
Na função draw fizemos um método simples, pescado da documentação, para mostrar a ocilação do som e fazermos uma comparação.
Abaixo segue um print da aplicação:
E para detalhes sobre a biblioteca minim que utilizamos é ś dar uma olhada na documentação:
http://code.compartmental.net/tools/minim/.
E é isso.
That's all folks!