package de.maramuse.soundcomp.generator;
/*
* Copyright 2010 Jan Schmidt-Reinisch
*
* SoundComp - a sound processing library
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; in version 2.1
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* A table driven custom waveform generator.
* Uses UnitySawTooth to generate a phase information and interpolates that
* in a ComplexTable to get a complex "quadrature signal" from the table.
* The phase is linearly projected into the key range of the table.
* The wave form table is a constant, no change at all possible.
* No phase modulation implemented in the current revision, although
* it would be possible and desired.
*/
import de.maramuse.soundcomp.process.NamedSource;
import de.maramuse.soundcomp.process.ProcessElement;
import de.maramuse.soundcomp.process.StandardParameters;
import de.maramuse.soundcomp.process.TableSource;
import de.maramuse.soundcomp.process.TypeMismatchException;
import de.maramuse.soundcomp.process.UnknownConnectionException;
import de.maramuse.soundcomp.process.ValueType;
import de.maramuse.soundcomp.util.ComplexTable;
import de.maramuse.soundcomp.util.NativeObjects;
import de.maramuse.soundcomp.util.ReadOnlyMap;
import de.maramuse.soundcomp.util.ReadOnlyMapImpl;
public class CustomWave extends UnitySawTooth{
private long nativeSpace;
public CustomWave(){
NativeObjects.registerNativeObject(this);
}
CustomWave(boolean s){}
@SuppressWarnings("hiding")
private static final ReadOnlyMapImpl<Integer, ValueType> sourceTypeMap=new ReadOnlyMapImpl<Integer, ValueType>();
static{
sourceTypeMap.put(StandardParameters.OUT.i, ValueType.STREAM);
sourceTypeMap.put(StandardParameters.OUT_IMAG.i, ValueType.STREAM);
}
private static final ReadOnlyMapImpl<Integer, ValueType> destTypeMap=new ReadOnlyMapImpl<Integer, ValueType>();
static{
destTypeMap.put(StandardParameters.FREQUENCY.i, ValueType.STREAM);
destTypeMap.put(StandardParameters.TABLE.i, ValueType.CTABLE);
}
private double value=0d, val_imag=0d, _value, _val_imag;
private String abstractName, instanceName;
@Override
public ReadOnlyMap<Integer, ValueType> getDestinationTypes() {
return destTypeMap;
}
TableSource<Double> table=null;
int tableIndex;
ComplexTable<Double> ct=null;
@SuppressWarnings("unchecked")
@Override
public void setSource(int connectionIndex, NamedSource source,
int sourceIndex) throws UnknownConnectionException,
TypeMismatchException {
if(connectionIndex==StandardParameters.FREQUENCY.i){
if(source==null || (source.getSourceTypes().get(sourceIndex)!=ValueType.DOUBLE &&source.getSourceTypes().get(sourceIndex)!=ValueType.STREAM))
throw new UnknownConnectionException("setting invalid CustomWave frequency source");
super.setSource(connectionIndex, source, sourceIndex);
}else{
if(source==null || (!(source instanceof TableSource<?>)) ||
source.getSourceTypes().get(sourceIndex)!=ValueType.CTABLE)
throw new UnknownConnectionException("setting invalid CustomWave table source");
try{
table=(TableSource<Double>)source;
tableIndex=sourceIndex;
}catch(ClassCastException c){
throw new UnknownConnectionException("setting invalid CustomWave table source type");
}
}
}
@Override
public ReadOnlyMap<Integer, ValueType> getSourceTypes() {
return sourceTypeMap;
}
@Override
public double getValue(int index) {
if(index==StandardParameters.OUT.i)
return value;
else if(index==StandardParameters.OUT_IMAG.i)
return val_imag;
else return Double.NaN;
}
@Override
public void advanceOutput() {
value=_value;
val_imag=_val_imag;
}
@Override
public void advanceState() {
if(ct==null) try{
ct=table.getTable(Double.NaN, tableIndex).getTable();
}catch(UnknownConnectionException ex){
// cannot help it and must not rethrow in this stage
// NB: this may intentionally lead to a huge amount of error messages.
ct=null;
System.err.println(ex.getMessage());
return;
}
super.advanceState();
super.advanceOutput();
double ph=phase*(Double)ct.getMaxIndex()+(1-phase)*(Double)ct.getMinIndex();
_value=ct.getReal(ph);
_val_imag=ct.getImag(ph);
}
@Override
public String getAbstractName() {
return abstractName;
}
@Override
public String getInstanceName() {
return instanceName;
}
@Override
public void setAbstractName(String abstractName) {
this.abstractName=abstractName;
}
@Override
public void setInstanceName(String instanceName) {
this.instanceName=instanceName;
}
@Override
public long getNativeSpace() {
return nativeSpace;
}
/**
* @see ProcessElement#clone()
*/
@Override
public CustomWave clone(){
return new CustomWave();
}
}