Já cá não escrevo há algum tempo. As sessões em Zoom têm ocupado a maioria do tempo e energia e resta pouca vontade de estar à frente do computador.
Ainda assim, já tinha esta referência para adicionar aos autores e artistas:
Creative Coder – Generative Designer
manoloide.com
La Plata, Argentina
Tem um trabalho absolutamente fantástico.
E, nas últimas aulas, temos desenvolvido técnicas interessantes, como botões que alteram as imagens e sons no seu interior — um dia temos que falar sobre inheritance — propagação de efeitos entre objetos — metrónomos como o do reactable — e o mais interessante, foi um pequeno sketch que grava “todo” o áudio que sai da interação no sketch.
Na realidade, os créditos vão para o Mateus Lima, pois foi ele a descobrir primeiro como resolver o carregamento de um ficheiro de audio com um buffer/sampler object em vez de um AudioFile, bem como da função patch()
Fica aqui o código comentado:
import ddf.minim.*; import ddf.minim.ugens.*; // controlo global de som Minim minim; // variável global de controlo de memória (para gravação) MultiChannelBuffer sampleBuffer; Sampler sampler; // objeto alternativo para "carregar" ficheiros de audio // controlo global do "output" AudioOutput output; // objeto que permite fazer a gravação global do som AudioRecorder recorder; // objetos custom SoundObject s1; SoundObject[] sounds; // no futuro temos que converter isto numa ArrayList // para ativar e desativar a gravação boolean recorded = false; void setup() { size(512, 200); // create Minim and an AudioOutput minim = new Minim(this); output = minim.getLineOut(); // construct a new MultiChannelBuffer with 2 channels and 1024 sample frames. // in our particular case, it doesn't really matter what we choose for these // two values because loadFileIntoBuffer will reconfigure the buffer // to match the channel count and length of the file. sampleBuffer = new MultiChannelBuffer( 1, 1024 ); // we pass the buffer to the method and Minim will reconfigure it to match // the file. if the file doesn't exist, or there is some other problen with // loading it, the function will return 0 as the sample rate. float sampleRate = minim.loadFileIntoBuffer( "groove.mp3", sampleBuffer ); // make sure the file load worked // create a sampler that will use our buffer to generate audio. // we must provide the sample rate of the audio and the number of voices. sampler = new Sampler( sampleBuffer, sampleRate, 1 ); // and finally, connect to the output so we can hear it (when played/triggered) sampler.patch( output ); // create an AudioRecorder that will record from in to the filename specified. // the file will be located in the sketch's main folder. recorder = minim.createRecorder(output, "myrecording.wav"); recorded = false; // create a list of sound playing objects sounds = new SoundObject[10]; // place them on stage and individual sounds into them for (int i = 0; i < 10; i++) { sounds[i] = new SoundObject(random(width), random(height), random(30, 90), "s0.mp3"); } } void draw() { fill(200); if ( recorder.isRecording() ){ text("Now recording, press the r key to stop recording.", 5, 15); } else if ( !recorded ) { text("Press the r key to start recording.", 5, 15); } else { text("Press the s key to save the recording to disk and play it back in the sketch.", 5, 15); } for (int i = 0; i < 10; i++) { sounds[i].update(); sounds[i].display(); } } void keyPressed() { if ( key == ' ' && sampler != null ) { sampler.trigger(); } } void keyReleased() { if ( key == 'r' ) { // to indicate that you want to start or stop capturing audio data, you must call // beginRecord() and endRecord() on the AudioRecorder object. You can start and stop // as many times as you like, the audio data will be appended to the end of the buffer // (in the case of buffered recording) or to the end of the file (in the case of streamed recording). if ( recorder.isRecording() ) { recorder.endRecord(); } else { recorder.beginRecord(); } } if ( key == 's' ) { // we've filled the file out buffer, // now write it to the file we specified in createRecorder // in the case of buffered recording, if the buffer is large, // this will appear to freeze the sketch for sometime // in the case of streamed recording, // it will not freeze as the data is already in the file and all that is being done // is closing the file. // the method returns the recorded audio as an AudioRecording, // see the example AudioRecorder >> RecordAndPlayback for more about that recorder.save(); println("Done saving."); } }
class SoundObject { // objetos/variáveis privadas/locais de cada objeto MultiChannelBuffer mySampleBuffer; // isto vai carregar o ficheiro de audio para cada objeto Sampler mysampler; // isto vai permitir enviar o audio de cada um para o lineout global float x, y; // posição float w; // tamanho color c; // construtor com o "nome" do ficheiro de audio para carregar neste objeto SoundObject(float px, float py, float pw, String ps) { mySampleBuffer = new MultiChannelBuffer( 1, 1024 ); float mySampleRate = minim.loadFileIntoBuffer( ps, mySampleBuffer ); mysampler = new Sampler( mySampleBuffer, mySampleRate, 1 ); mysampler.patch( output ); x = px; y = py; w = pw; c = color(200, 0, 0); } // simple playback when mouseover pressed void update() { if(dist(mouseX, mouseY, x, y) < w/2) { c = color(0, 200, 0); if(mousePressed) { soundPlay(); // fizemos uma função AKA método privado para o objeto para poder fazer playback a partir do prórpio objeto, ou a partir do programa principal } } else { c = color(200, 0, 0); } } void display() { fill(c); noStroke(); ellipse(x, y, w, w); } void soundPlay(){ mysampler.trigger(); // podem colocar outras coisas aqui quando toca o som… modificar cor… forma…? } }