/*
SoundVoice.java
(c) 2009-2016 Edward Swartz
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
*/
package v9t9.audio.sound;
import ejs.base.settings.ISettingSection;
import ejs.base.sound.ISoundOutput;
import ejs.base.sound.ISoundVoice;
/**
* The base class for sounds. This assumes 255 distinct volume settings
* versus the TMS9919's 15, for possible future expansion.
* @author ejs
*
*/
public abstract class SoundVoice implements ISoundVoice
{
protected static final int MAX_VOLUME = 255;
/** volume, 0 == off, 0xff == loudest */
private int volume;
private final String name;
/** how the left/right channels are balanced; -128 for all left to 127 for all right */
protected byte balance;
static final float[] volumeToMagnitude;
static {
volumeToMagnitude = new float[MAX_VOLUME + 1];
double val = 1.0;
// dB power falls by 10^(dB/20).
// With 15 steps of 2 dB, the ratio is 10^-0.1
// With 255 steps of 1/8 dB, the ratio is 10^-0.1
double mult = Math.pow(10, -(30. / MAX_VOLUME / 20.));
for (int x = MAX_VOLUME; x > 0; x--) {
volumeToMagnitude[x] = (float) val;
//System.out.println(val);
val *= mult;
}
volumeToMagnitude[0] = 0.0f;
}
public SoundVoice(String name) {
this.name = name;
}
@Override
public String toString() {
if (volume == 0)
return name + " [SILENT]";
else
return name + " volume="+volume;
}
/* (non-Javadoc)
* @see ejs.base.sound.ISoundVoice#shouldDispose()
*/
@Override
public boolean shouldDispose() {
return false;
}
@Override
public void setOutput(ISoundOutput output) {
}
public void setBalance(byte balance) {
this.balance = balance;
}
public abstract void setupVoice();
public String getName() {
return name;
}
public void saveState(ISettingSection section) {
// derived
//section.put("Volume", volume);
}
public void loadState(ISettingSection section) {
// derived
//volume = (byte) Utils.readSavedInt(section, "Volume");
}
/** Set volume in range 0 (silence) to {@value #MAX_VOLUME} (maximum) */
public void setVolume(int volume) {
this.volume = volume & MAX_VOLUME;
}
/** Set volume in range 0 (silence) to {@value #MAX_VOLUME} */
public int getVolume() {
return volume;
}
public float getCurrentMagnitude() {
return volumeToMagnitude[volume];
}
public boolean isActive() {
return volume != 0;
}
}