jm.audio.synth.AllFGTR Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jmusic Show documentation
Show all versions of jmusic Show documentation
JMusic - Java Music Library
The newest version!
/*
Copyright (C) 2000 Andrew Sorensen & Andrew Brown
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or any
later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package jm.audio.synth;
import jm.audio.AOException;
import jm.audio.AudioObject;
/**
* The Fast Grain Transform & Resynthesis all in one AO!
*
* @author Timothy Opie
* @version 1.0, Wednesday November 12, 2003
* Last changed:
* Description: This class takes a stream of audio data and reduces
* it to grain information comprising solely of a start and finish
* time band, a top and bottom frequency band and an amplitude.
*/
public final class AllFGTR extends AudioObject {
//----------------------------------------------
// Attributes
//----------------------------------------------
//private float[] grain = new float[buffer.length]; //grain buffer
private float[][] FGTArray = new float[200][7];
private float /*grainDuration,*/ bandwidthTop, bandwidthBottom;
private float frequency, spatial, highestAmp = 0.0f;
// interOnset is the space between the start of each grain
private int grainsPerSecond, interOnset, grainDuration;
private int bCounter = 0, gCounter = 0, dCounter = 0;//This counter keeps track of the buffer
private int grainsPerBuffer = 0, sampleRate = 44100, channels = 2;
// insert filter stuff here, if it will be filtered internally
//----------------------------------------------
// Constructors
//----------------------------------------------
public AllFGTR(AudioObject ao, int gDuration, float bwidthTop, float bwidthBottom, int gps) {
super(ao, "[AllFGTR]");
this.grainDuration = gDuration; //this is in samples
this.bandwidthTop = bwidthTop; //this filter info is purely for data collection puroposes
this.bandwidthBottom = bwidthBottom;
this.grainsPerSecond = gps;
//System.out.println("bandwidthBottom: " + bandwidthBottom);
//System.out.println("bandwidthTop: " + bandwidthTop);
//System.out.println("grainDuration: " + grainDuration);
//System.out.println("grainsPerSecond: " + grainsPerSecond);
}
/**
* --------------------------------------------
* Beginning
* --------------------------------------------
*/
public int work(float[] buffer) throws AOException {
System.out.println("Point 1");
//System.out.println("grainsPerSecond: " + grainsPerSecond);
// Regarding the filter: I am thinking it will be easier to initiate the filter
// as part of the instrument, rather than in this section, so that FGT.java will
// assume it is using a filtered audio buffer. This may change in the future.....
//Filter filterOne = new Filter(buffer, bandwidthBottom, Filter.LOW_PASS);
//Filter filterDone = new Filter(filterOne, bandwidthTop, Filter.HIGH_PASS);
highestAmp = 0.0f;
bCounter = 0;
gCounter = 0;
dCounter = 0;
grainsPerBuffer = (grainsPerSecond * buffer.length) / (sampleRate * channels);
//System.out.println("grainsPerSecond: " + grainsPerSecond + "buffer.length: " + buffer.length + "sampleRate: " + sampleRate + "channels: " + channels + "grainsPerBuffer: " + grainsPerBuffer);
interOnset = buffer.length / grainsPerBuffer;
for (gCounter = 0; gCounter < grainsPerBuffer; gCounter++) {
System.out.println("Point 1.1");
bCounter = gCounter * interOnset;
highestAmp = 0;
System.out.println("gCounter: " + gCounter);
System.out.println("grainDuration1: " + grainDuration);
System.out.println("dCounter: " + dCounter);
for (dCounter = 0; dCounter < grainDuration; dCounter++) {
//System.out.println("Point 1.2");
//System.out.println("grainDuration: " + grainDuration);
float temp = buffer[bCounter] * (float) (Math.sin(Math.PI * ((float) dCounter / (float) grainDuration)));
//System.out.println("temp: " + temp);
//System.out.println("buffer[bCounter]: " + buffer[bCounter]);
//System.out.println("bCounter: " + bCounter);
//System.out.println("dCounter: " + dCounter);
//System.out.println("grainDuration1: " + grainDuration);
//System.out.println("Math.PI: " + Math.PI);
//System.out.println("dCounter/grainDuration: " + (float)dCounter/(float)grainDuration);
float temp2 = temp; //just for bug checking
if (temp < 0.0f) temp = temp * -1;
if (highestAmp < temp) highestAmp = temp;
//System.out.println("Amp:" + temp2 + "Highest:" + highestAmp); //just for bug checking
bCounter++;
}
System.out.println("Point 2");
FGTArray[gCounter][0] = gCounter * interOnset;
FGTArray[gCounter][1] = grainDuration;
FGTArray[gCounter][2] = bandwidthTop;
FGTArray[gCounter][3] = bandwidthBottom;
FGTArray[gCounter][4] = 0.5f; //Stereo placement - will be improved later!
FGTArray[gCounter][5] = highestAmp;
FGTArray[gCounter][6] = grainsPerBuffer;
//System.out.println("gCounter: " + gCounter + "bCounter: " + bCounter);
//System.out.println("gCounter*interOnset2: " + gCounter*interOnset);
//System.out.println("grainDuration2: " + grainDuration);
//System.out.println("bandwidthTop2: " + bandwidthTop);
//System.out.println("bandwidthBottom2: " + bandwidthBottom);
//System.out.println("highestAmp2: " + highestAmp);
//System.out.println("grainsPerBuffer2: " + grainsPerBuffer);
//System.out.println("Point 3");
if ((gCounter + 1) * interOnset + grainDuration > buffer.length) gCounter = grainsPerBuffer; //safety backup
//System.out.println("Point 4");
}
/**
* Transform has been created. Now time to resynthesise!
*/
// First reset all variables, just to be sure :)
System.out.println("Point 5");
grainDuration = 0;
bandwidthTop = 0.0f;
bandwidthBottom = 0.0f;
grainsPerBuffer = 0; //can't reset this - it is important
interOnset = 0;
highestAmp = 0.0f;
bCounter = 0;
gCounter = 0;
dCounter = 0;
for (int counter = 0; counter < buffer.length; counter++) {
buffer[counter] = 0.0f;
}
System.out.println("Point 6");
//Now create new sound file in buffer and return
grainDuration = 1936;//(int) FGTArray[gCounter][1];
grainsPerBuffer = (int) FGTArray[gCounter][6];
System.out.println("grainsPerBuffer6: " + grainsPerBuffer);
System.out.println("grainDuration7: " + grainDuration);
for (gCounter = 0; gCounter < grainsPerBuffer; gCounter++) {
bCounter = (int) FGTArray[gCounter][0];
grainDuration = 1936;//(int) FGTArray[gCounter][1];
bandwidthTop = FGTArray[gCounter][2];
bandwidthBottom = FGTArray[gCounter][3];
spatial = FGTArray[gCounter][4]; //Spatial placement - will be improved later!
highestAmp = FGTArray[gCounter][5];
frequency = (bandwidthTop + bandwidthBottom) * 0.5f; // to be improved later
//System.out.println("Point 7");
//System.out.println("gCounter: " + gCounter + "bCounter: " + bCounter);
//System.out.println("bCounter7: " + bCounter);
//System.out.println("grainDuration7: " + grainDuration);
//System.out.println("bandwidthTop7: " + bandwidthTop);
//System.out.println("bandwidthBottom7: " + bandwidthBottom);
//System.out.println("highestAmp7: " + highestAmp);
for (dCounter = 0; dCounter < grainDuration; dCounter++) {
// This following short equation creates a sine wave and envelopes it at the correct duration
buffer[bCounter] = buffer[bCounter] + (float) ((Math.sin(2 * Math.PI * dCounter * ((frequency * buffer.length) / (sampleRate * channels)))) *
(Math.sin(Math.PI * (dCounter / grainDuration)) * highestAmp));
// Or there is this method which generates a noise band between the specified top and bottom frequency range
// and then envelopes it just like the previous equation.
// buffer[bCounter]=buffer[bCounter]+((bandwidthBottom+Math.random()*(bandwidthTop-bandwidthBottom))*
// (Math.sin(Math.PI*(dCounter/grainDuration))*highestAmp));
bCounter++;
//System.out.println("Point 8");
}
System.out.println("Point 9");
}
System.out.println("Point 10");
return buffer.length;
}
}