/*
* Created on Jun 3, 2007
*
* Copyright (c) 2006-2007 P.J.Leonard
*
* http://www.frinika.com
*
* This file is part of Frinika.
*
* Frinika 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
* (at your option) any later version.
* Frinika 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 Frinika; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.frinika.sequencer.model.audio;
import com.frinika.audio.io.*;
import java.io.IOException;
import uk.org.toot.audio.core.AudioBuffer;
import com.frinika.sequencer.model.AudioPart.Envelope;
public class EnvelopedAudioReader extends AudioReader {
protected double gain = 1.0;
protected long attackEnd;
protected long decayStart;
public EnvelopedAudioReader(RandomAccessFileIF fis,float Fs) throws IOException {
super(fis,Fs);
}
public void setEvelope(Envelope e) {
setBoundsInMicros(e.getTOn(),e.getTOff());
gain = e.getGain();
attackEnd = startByte + milliToByte(e.getTRise());
decayStart = endByte - milliToByte(e.getTFall());
if (attackEnd > decayStart) {
long av=(attackEnd+decayStart)/2;
attackEnd=decayStart= (av/(nChannels*2))*nChannels*2;
}
// System.out.println(startByte + "-->" + endByte);
}
protected void processAudioImp(AudioBuffer buffer, int startChunk,
int endChunk) {
// Decode byte data and insert into voiceserver buffer
// TODO duplicate code to save ops if no envelope etc.
long fPtr1 = fPtrBytes + startChunk;
long fPtr2 = fPtrBytes + endChunk;
if (fPtr1 <= decayStart && fPtr2 >= attackEnd) { // all in constant
fillConstantGain(buffer, startChunk, endChunk, gain);
} else if (fPtr1 < attackEnd && fPtr2 >= attackEnd) { // rise constant
// transition
double gainNow = gain * (fPtr1 - startByte)
/ (attackEnd - startByte);
fillLinearInterpolate(buffer, startChunk, endChunk, gainNow, gain);
} else if (fPtr1 < attackEnd) { // all in rise
double gainNow = gain * (fPtr1 - startByte)
/ (attackEnd - startByte);
double gainNext = gain * (fPtr2 - startByte)
/ (attackEnd - startByte);
fillLinearInterpolate(buffer, startChunk, endChunk, gainNow,
gainNext);
} else if (fPtr1 <= decayStart && fPtr2 > decayStart) { // const - decay
double gainNext = gain * (endByte - fPtr2) / (endByte - decayStart);
fillLinearInterpolate(buffer, startChunk, endChunk, gain, gainNext);
} else {
assert (fPtr1 > decayStart);
double gainNow = gain * (endByte - fPtr1) / (endByte - decayStart);
double gainNext = gain * (endByte - fPtr2) / (endByte - decayStart);
fillLinearInterpolate(buffer, startChunk, endChunk, gainNow,
gainNext);
}
}
}