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 }