plectrum

Plectrum: instrument tuner for Android
Log | Files | Refs | README | LICENSE

EnvelopeFollower.java (4054B)


      1 /*
      2 *      _______                       _____   _____ _____  
      3 *     |__   __|                     |  __ \ / ____|  __ \ 
      4 *        | | __ _ _ __ ___  ___  ___| |  | | (___ | |__) |
      5 *        | |/ _` | '__/ __|/ _ \/ __| |  | |\___ \|  ___/ 
      6 *        | | (_| | |  \__ \ (_) \__ \ |__| |____) | |     
      7 *        |_|\__,_|_|  |___/\___/|___/_____/|_____/|_|     
      8 *                                                         
      9 * -------------------------------------------------------------
     10 *
     11 * TarsosDSP is developed by Joren Six at IPEM, University Ghent
     12 *  
     13 * -------------------------------------------------------------
     14 *
     15 *  Info: http://0110.be/tag/TarsosDSP
     16 *  Github: https://github.com/JorenSix/TarsosDSP
     17 *  Releases: http://0110.be/releases/TarsosDSP/
     18 *  
     19 *  TarsosDSP includes modified source code by various authors,
     20 *  for credits and info, see README.
     21 * 
     22 */
     23 
     24 
     25 package be.tarsos.dsp;
     26 
     27 /**
     28  * An envelope follower follows the envelope of a signal. Sometimes the name
     29  * envelope detector is used. From wikipedia:
     30  *  <blockquote> An envelope detector
     31  * is an electronic circuit that takes a high-frequency signal as input and
     32  * provides an output which is the envelope of the original signal. The
     33  * capacitor in the circuit stores up charge on the rising edge, and releases it
     34  * slowly through the resistor when the signal falls. The diode in series
     35  * rectifies the incoming signal, allowing current flow only when the positive
     36  * input terminal is at a higher potential than the negative input terminal.
     37  * </blockquote>
     38  * 
     39  * The resulting envelope is stored in the buffer in the processed AudioEvent. The class can be used thusly:
     40  * 
     41  * <pre>
     42  * EnvelopeFollower follower = new EnvelopeFollower(44100);
     43  * 		
     44  * AudioDispatcher dispatcher = AudioDispatcher.fromFloatArray(sine, 44100, 1024, 0);
     45  * 	
     46  * 	
     47  * 	dispatcher.addAudioProcessor(follower);
     48  * 	dispatcher.addAudioProcessor(new AudioProcessor() {
     49  * 	
     50  * 		public boolean process(AudioEvent audioEvent) {
     51  * 			//envelope
     52  * 			float buffer[] = audioEvent.getFloatBuffer();
     53  * 			for(int i = 0 ; i < buffer.length ; i++){
     54  * 				System.out.println(buffer[i]);
     55  * 			}
     56  * 			return true;
     57  * 		}
     58  * 			
     59  * 		public void processingFinished() {
     60  *  	}
     61  * 	});
     62  * 	dispatcher.run();
     63  *  </pre>
     64  *  
     65  * 
     66  * @author Joren Six
     67  * 
     68  */
     69 public class EnvelopeFollower implements AudioProcessor {
     70 	
     71 	/**
     72 	 * Defines how fast the envelope raises, defined in seconds.
     73 	 */
     74 	private static final double DEFAULT_ATTACK_TIME =  0.0002;//in seconds
     75 	/**
     76 	 * Defines how fast the envelope goes down, defined in seconds.
     77 	 */
     78 	private static final double DEFAULT_RELEASE_TIME =  0.0004;//in seconds
     79 	
     80 	float gainAttack ;
     81 	float gainRelease;
     82 	float envelopeOut = 0.0f;
     83 	
     84 	/**
     85 	 * Create a new envelope follower, with a certain sample rate.
     86 	 * @param sampleRate The sample rate of the audio signal.
     87 	 */
     88 	public EnvelopeFollower(double sampleRate){
     89 		this(sampleRate,DEFAULT_ATTACK_TIME,DEFAULT_RELEASE_TIME);
     90 	}
     91 	
     92 	/**
     93 	 * Create a new envelope follower, with a certain sample rate.
     94 	 * @param sampleRate The sample rate of the audio signal.
     95 	 * @param attackTime Defines how fast the envelope raises, defined in seconds.
     96 	 * @param releaseTime Defines how fast the envelope goes down, defined in seconds.
     97 	 */
     98 	public EnvelopeFollower(double sampleRate, double attackTime,double releaseTime){
     99 		gainAttack = (float) Math.exp(-1.0/(sampleRate*attackTime));
    100 		gainRelease = (float) Math.exp(-1.0/(sampleRate*releaseTime));
    101 	}
    102 	
    103 	@Override
    104 	public boolean process(AudioEvent audioEvent) {
    105 		float[] buffer = audioEvent.getFloatBuffer();
    106 		calculateEnvelope(buffer);
    107 		return true;
    108 	}
    109 	
    110 	public void calculateEnvelope(float[] buffer){
    111 		for(int i = 0 ; i < buffer.length ; i++){
    112 			float envelopeIn = Math.abs(buffer[i]);
    113 			if(envelopeOut < envelopeIn){
    114 				envelopeOut = envelopeIn + gainAttack * (envelopeOut - envelopeIn);
    115 			} else {
    116 				envelopeOut = envelopeIn + gainRelease * (envelopeOut - envelopeIn);
    117 			}
    118 			buffer[i] = envelopeOut;
    119 		}
    120 	}
    121 
    122 	@Override
    123 	public void processingFinished() {
    124 		
    125 	}
    126 }