/** * Copyright (c) 2005 - Bob Lang (http://www.cems.uwe.ac.uk/~lrlang/) * * 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.contrib.boblang; /** Stores the details of a note that presently being played by the synthesizer @author Bob Lang @version 22 Mar 2003 */ public class BezierPlayingNote { // Various working values private int underSampling, // Undersampling rate midiPitch, // The pitch of the note index, // Index position [stepped by undersampling rate] releaseIndex; // Number of samples since release // Various flags private boolean isReleased; // True if released // Links to other objects and classes private BezierSynth bezierSynth; // Which generates sound sample values private BezierEnvelopeShaper shaper; // Envelope shaper /** Constructor for this class. */ public BezierPlayingNote (BezierSynth inBezierSynth, BezierEnvelopeShaper inShaper, int inMidiPitch, int inUnderSampling) { // Save the sound buffer data bezierSynth = inBezierSynth; shaper = inShaper; midiPitch = inMidiPitch; underSampling = inUnderSampling; // Start playback from the start index = 0; // Note hasn't been released yet isReleased = false; releaseIndex = 0; } // BezierPlayingNote () /** Set the release status for this note, recording the index number where the release happened. */ public void setRelease () { isReleased = true; releaseIndex = index; } // setRelease () /** Get the release status for this loop */ public boolean isReleased () { return isReleased; } // isReleased () /** Has the note finished yet? */ public boolean isFinished () { if (!isReleased) { return false; } else { return shaper.isNoteFinished (index, releaseIndex); } } // isFinished () /** Get the pitch of this note */ public int getPitch () { return midiPitch; } // getPitch () /** Get the next buffer of data from the sound buffer. This method performs the undersampling necessary to convert from the internal sample rate (say 196000) to the output rate (say 48000). This is achieved by incrementing the index by the undersampling rate each time. */ public void getBuffer (short [] buffer, int count) { // Special action if note is released or not if (!isReleased) { for (int i=0; i<count; i++) { // Get the sample and the envelope factor int sample = bezierSynth.getSample (index); double factor = shaper.getFactor (index); // Perform envelope shaping sample = (int) (sample * factor); buffer [i] = (short) sample; // Increment the index number for the whole note index += underSampling; } // for } // if else { // Released note - different version of shaping factor for (int i=0; i<count; i++) { // Get the sample and the envelope factor int sample = bezierSynth.getSample (index); double factor = shaper.getRelFactor (index, releaseIndex); // Perform envelope shaping sample = (int) (sample * factor); buffer [i] = (short) sample; // Increment the index number for the whole note index += underSampling; } // for } // else } // getBuffer () /** Get the next buffer of data from the sound buffer. This method performs the undersampling necessary to convert from the internal sample rate (say 196000) to the output rate (say 48000). This is achieved by incrementing the index by the undersampling rate each time. Adjustments for Frinika 32 bit floating point version startBuffer and endBufferPos - for realtime parameter modifications Add (mix) new samples to the buffer instead of replace. @author Bob Lang @author Peter Johan Salomonsen */ public void getBuffer (float [] buffer, int startBufferPos, int endBufferPos) { // Special action if note is released or not if (!isReleased) { for (int i=startBufferPos; i<endBufferPos;) { // Get the sample and the envelope factor double sample = bezierSynth.getSample (index); double factor = shaper.getFactor (index); // Perform envelope shaping sample = (sample * factor) / 32768f; // Assume 16 bit and convert to range -1.0 to 1.0 buffer [i++] += sample; buffer [i++] -= sample; // Simple stereo effect // Increment the index number for the whole note index += underSampling; } // for } // if else { // Released note - different version of shaping factor for (int i=startBufferPos; i<endBufferPos; ) { // Get the sample and the envelope factor double sample = bezierSynth.getSample (index); double factor = shaper.getRelFactor (index, releaseIndex); // Perform envelope shaping sample = (sample * factor) / 32768f; // Assume 16 bit and convert to range -1.0 to 1.0 buffer [i++] += sample; buffer [i++] -= sample; // Simple stereo effect // Increment the index number for the whole note index += underSampling; } // for } // else } // getBuffer () } // BezierPlayingNote