Granular synthesis

jMusic can be used to create sound textures based on granular synthesis techniques. Granular synthesis is a synthesis technique whereby new sonic textures are formed by breaking down existing sound samples into small (circa 20-50ms) sound granules and then using these granules to build new sounds For more information on granular synthesis just go to http://zor.org/synthesis - there is an entire online resource there.

jMusic supports both real-time and non-real-time granular synthesis. Following are examples of both.  Let's first take a quick look at non-real-time granular synthesis. You will need an audio file called "song1.au" and the GranularInst instrument to run this first example.

Source Code

import jm.JMC;
import jm.music.data.*;
import jm.audio.*;
import jm.util.*;
  /** * @author Timothy Opie * Updated 24/06/2002 * * Non-real-time demo of granular synthesis */ public final class GranulatorTest implements JMC{ public static void main(String[] args){ Score score = new Score("JMDemo - Audio test"); Part part = new Part("wave", 0); Phrase phr = new Phrase(0.0); int sampleRate = 44100; int bufferSize = sampleRate/4;   // All you need to do is set a sound file (in .au format), // and a buffersize! GranularInst inst = new GranularInst("song1.au", bufferSize);   Note note = new Note(A4, 4.0); //about 44O Hz phr.addNote(note); part.addPhrase(phr); score.addPart(part); Write.au(score, "GranularTest.au", inst); } }

OK, that was kind of boring. Lets look at real-time granular synthesis:

This consists of 2 files. A main file, and an RTLine file.

You will need an audio file called "song1.au" and the GranularInstRT instrument to run this second example.

Lets look at the main file first:

Source Code

// This example uses Java Sliders to control the granular process.
import jm.JMC;
import jm.music.data.*;
import jm.audio.*;
import jm.audio.synth.Granulator;
import jm.util.*;
import jm.audio.RTMixer;
import jm.music.rt.RTLine;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.*;
 
/**
 * Real-time Granulator sample
 * Made using JSliders.
 *
 * A more complex version of this instrument has been written using
 * MIDI control. It was used for the Poseidon - a Granular Texture Controlling Fish -
 * in the REV concert at the Brisbane Powerhouse. More information on this, and on
 * Granular Synthesis can be obtained at: http://zor.org/synthesis
 *
 * This file is used in conjunction with RTSliderGrainLine  
 *
 * Author: Timothy Opie
 * Latest Update: 24/06/2002
 * Designed to function with jMusic designed by
 * Andrew Sorensen and Andrew Brown
 */
 
 
public final class RTSliderGrainmaker implements JMC,ChangeListener,ActionListener {
    private RTMixer mixer;
    private RTSliderGrainLine grain;
    private JSlider duration, density, volume;
    private JToggleButton asyn;
    private int sampleRate = 44100;
    
    public static void main(String[] args){
        new RTSliderGrainmaker();
    }
    
    private GranularInst rtGranularInst;
    
    public RTSliderGrainmaker(){
        
        int channels = 2;
        double controlRate = 0.25;
        int bufferSize = (int)((sampleRate*channels) *controlRate);
        
        Instrument[] instArray = new Instrument[1];
        for(int i=0;i<instArray.length;i++){
            instArray[i] = new GranularInst("song1.au",bufferSize);
        }
        rtGranularInst = (GranularInst) instArray[0];
        grain = new RTSliderGrainLine(instArray, controlRate, bufferSize);
        RTLine[] lineArray = {grain};
        mixer = new RTMixer(lineArray, bufferSize, sampleRate, channels, controlRate);
        mixer.begin();
        makeGUI();
    }
 
// this is where the sliders are set up!
 
    private void makeGUI(){
        JFrame f = new JFrame("Granular Synthesis");
        f.setSize(370, 180);
        JPanel pan = new JPanel();
        f.getContentPane().add(pan);
        //grainduration
        duration = new JSlider(0,10,60,30);
        duration.addChangeListener(this);
        pan.add(duration);
        JLabel val=new JLabel("Grain Duration");
        pan.add(val);
        
        // Grain Density
        density = new JSlider(0,5,120,60);
        density.addChangeListener(this);
        pan.add(density);
        JLabel val2=new JLabel("Grains per second");
        pan.add(val2);
        
        // Grain Volume
        volume = new JSlider(0,0,20,10);
        volume.addChangeListener(this);
        pan.add(volume);
        JLabel val3=new JLabel("Grain Volume");
        pan.add(val3);
        
        asyn = new JToggleButton("A/Syncronicity toggle");
        asyn.addActionListener(this);
        pan.add(asyn);
        
        f.setVisible(true);
    }
    
// This section sends the values of the sliders to the RTLine
 
    public void stateChanged(ChangeEvent e){
        if(e.getSource() == duration) {
            mixer.actionLines(duration, 1);
        }
        if(e.getSource() == density) {
            mixer.actionLines(density, 2);
        }
        if(e.getSource() == volume) {
            mixer.actionLines(volume, 3);
        }
    }
    public void actionPerformed(ActionEvent e){
        if(e.getSource() == asyn){
            mixer.actionLines(asyn, 4);
        }
    }
}

Now lets look at the RTLine file:

Source Code

/**
* Real-time Granulator Line
* Author: Timothy Opie
* Latest Update: 24/06/2002
* Designed to function with jMusic designed by
* Andrew Sorensen and Andrew Brown
*/
  import jm.music.rt.RTLine; import jm.audio.Instrument; import jm.music.data.Note; import javax.swing.*;   public class RTSliderGrainLine extends RTLine { private Note n = new Note(72, 1000.0); private int pitch = 72; private int dynamic = 100; private GranularInst[] inst; private boolean asyn = false; // Constructor public RTSliderGrainLine(Instrument[] instArray,
double controlRate, int bufferSize) {
super(instArray, controlRate, bufferSize);
inst = new GranularInst[instArray.length];
for (int i=0; i<instArray.length; i++) {
inst[i] = (GranularInst)instArray[i];
}
}

public synchronized Note getNote(){
n.setPitch(pitch);
n.setDynamic(dynamic);
return n;
}

// added for control change
//This is the section that converts the JSlider information into numbers that
//can be understood by the Granulator Audio Object.
public synchronized void externalAction(Object obj, int actionNumber){ if(actionNumber == 1){ // grain duration JSlider slider = (JSlider)obj; int duration = (slider.getValue()* (44100/1000)); // propgate to all instruments for(int i=0;i<inst.length;i++){ inst[i].setGrainDuration(duration); } } if(actionNumber == 2){ // Grain Density JSlider slider = (JSlider)obj; int length = slider.getValue(); // propgate to all instruments for(int i=0;i<inst.length;i++){ inst[i].setGrainsPerSecond(length); } } if(actionNumber == 3){ // Grain Volume JSlider slider = (JSlider)obj; float vol = (float)slider.getValue(); // propgate to all instruments for(int i=0;i<inst.length;i++){ inst[i].setVolume(vol); } } if(actionNumber == 4){ //toggle A/Syncronicity if(asyn == true) asyn=false; else asyn=true; for(int i=0;i<inst.length;i++){ inst[i].setRandomIndex(asyn); } } } }

Enjoy :)

 


jMusic Tutorial Index


© 2002 Tim Opie