////////////////////////////////////////////////////////////////////////////////
// Copyright 2013 Michael Schmalle - Teoti Graphix, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
//
// Author: Michael Schmalle, Principal Architect
// mschmalle at teotigraphix dot com
////////////////////////////////////////////////////////////////////////////////
package com.teotigraphix.caustk.sound;
import java.util.HashMap;
import java.util.Map;
import com.teotigraphix.caustk.controller.ICaustkController;
import com.teotigraphix.caustk.core.CausticException;
import com.teotigraphix.caustk.core.ICausticEngine;
import com.teotigraphix.caustk.core.IRestore;
import com.teotigraphix.caustk.core.osc.EffectRackMessage;
import com.teotigraphix.caustk.core.osc.MixerMessage;
import com.teotigraphix.caustk.service.ISerialize;
import com.teotigraphix.caustk.sound.effect.EffectType;
import com.teotigraphix.caustk.sound.effect.EffectUtils;
import com.teotigraphix.caustk.utils.ExceptionUtils;
public class SoundMixerChannel implements ISerialize, IRestore {
private transient ICaustkController controller;
private ICausticEngine getEngine() {
return controller;
}
private transient Map<Integer, IEffect> effects = new HashMap<Integer, IEffect>();
public IEffect getEffect(int slot) {
return effects.get(slot);
}
public IEffect addEffect(EffectType type, int slot) throws CausticException {
if (effects.containsKey(slot))
throw new CausticException("Channel already contains slot:" + slot);
IEffect effect = EffectUtils.create(type, slot, getIndex());
EffectRackMessage.CREATE.send(controller, getIndex(), slot, type.getValue());
effects.put(slot, effect);
effect.wakeup(controller);
return effect;
}
public IEffect removeEffect(int slot) {
IEffect effect = effects.remove(slot);
if (effect != null) {
EffectRackMessage.REMOVE.send(controller, getIndex(), slot);
}
return effect;
}
//----------------------------------
// index
//----------------------------------
private int index = -1;
public final int getIndex() {
return index;
}
public final void setIndex(int value) {
index = value;
}
//----------------------------------
// bass
//----------------------------------
private float bass = 0f;
public final float getBass() {
return bass;
}
float getBass(boolean restore) {
return MixerMessage.EQ_BASS.query(getEngine(), index);
}
public final void setBass(float value) {
if (bass == value)
return;
if (value < -1f || value > 1f)
throw newRangeException("bass", "-1.0..1.0", value);
bass = value;
MixerMessage.EQ_BASS.send(getEngine(), getIndex(), value);
}
//----------------------------------
// mid
//----------------------------------
private float mid = 0f;
public float getMid() {
return mid;
}
float getMid(boolean restore) {
return MixerMessage.EQ_MID.query(getEngine(), index);
}
public void setMid(float value) {
if (mid == value)
return;
if (value < -1f || value > 1f)
throw newRangeException("mid", "-1.0..1.0", value);
mid = value;
MixerMessage.EQ_MID.send(getEngine(), getIndex(), value);
}
//----------------------------------
// high
//----------------------------------
private float high = 0f;
public final float getHigh() {
return high;
}
float getHigh(boolean restore) {
return MixerMessage.EQ_HIGH.query(getEngine(), index);
}
public final void setHigh(float value) {
if (high == value)
return;
if (value < -1f || value > 1f)
throw newRangeException("high", "-1.0..1.0", value);
high = value;
MixerMessage.EQ_HIGH.send(getEngine(), getIndex(), value);
}
//----------------------------------
// delaySend
//----------------------------------
private float delaySend = 0f;
public final float getDelaySend() {
return delaySend;
}
float getDelaySend(boolean restore) {
return MixerMessage.DELAY_SEND.query(getEngine(), index);
}
public void setDelaySend(float value) {
if (delaySend == value)
return;
if (value < 0f || value > 1f)
throw newRangeException("delay_send", "0.0..1.0", value);
delaySend = value;
MixerMessage.DELAY_SEND.send(getEngine(), getIndex(), value);
}
//----------------------------------
// reverbSend
//----------------------------------
private float reverbSend = 0f;
public final float getReverbSend() {
return reverbSend;
}
float getReverbSend(boolean restore) {
return MixerMessage.REVERB_SEND.query(getEngine(), index);
}
public void setReverbSend(float value) {
if (reverbSend == value)
return;
if (value < 0f || value > 1f)
throw newRangeException("reverb_send", "0.0..1.0", value);
reverbSend = value;
MixerMessage.REVERB_SEND.send(getEngine(), getIndex(), value);
}
//----------------------------------
// pan
//----------------------------------
private float pan = 0f;
public final float getPan() {
return pan;
}
float getPan(boolean restore) {
return MixerMessage.PAN.query(getEngine(), index);
}
public void setPan(float value) {
if (pan == value)
return;
if (value < -1f || value > 1f)
throw newRangeException("pan", "-1.0..1.0", value);
pan = value;
MixerMessage.PAN.send(getEngine(), index, value);
}
//----------------------------------
// stereoWidth
//----------------------------------
private float stereoWidth = 0f;
public final float getStereoWidth() {
return stereoWidth;
}
float getStereoWidth(boolean restore) {
return MixerMessage.STEREO_WIDTH.query(getEngine(), index);
}
public void setStereoWidth(float value) {
if (stereoWidth == value)
return;
if (value < 0f || value > 1f)
throw newRangeException("stereo_width", "0.0..1.0", value);
stereoWidth = value;
MixerMessage.STEREO_WIDTH.send(getEngine(), index, value);
}
//----------------------------------
// mute
//----------------------------------
private boolean mute = false;
public final boolean isMute() {
return mute;
}
boolean isMute(boolean restore) {
return MixerMessage.MUTE.query(getEngine(), index) != 0f;
}
public void setMute(boolean muted) {
if (mute == muted)
return;
mute = muted;
MixerMessage.MUTE.send(getEngine(), index, muted ? 1 : 0);
}
//----------------------------------
// solo
//----------------------------------
private boolean solo = false;
public final boolean isSolo() {
return solo;
}
boolean isSolo(boolean restore) {
return MixerMessage.SOLO.query(getEngine(), index) != 0f;
}
public void setSolo(boolean soloed) {
if (solo == soloed)
return;
solo = soloed;
MixerMessage.SOLO.send(getEngine(), index, solo ? 1 : 0);
}
//----------------------------------
// volume
//----------------------------------
private float volume = 0f;
public final float getVolume() {
return volume;
}
float getVolume(boolean restore) {
return MixerMessage.VOLUME.query(getEngine(), index);
}
public void setVolume(float value) {
if (volume == value)
return;
if (value < 0f || value > 2f)
throw newRangeException("volume", "0.0..2.0", value);
volume = value;
MixerMessage.VOLUME.send(getEngine(), index, value);
}
//--------------------------------------------------------------------------
// Constructor
//--------------------------------------------------------------------------
public SoundMixerChannel() {
}
public SoundMixerChannel(ICaustkController controller) {
this.controller = controller;
}
//--------------------------------------------------------------------------
// ISerialize API
//--------------------------------------------------------------------------
@Override
public void sleep() {
}
@Override
public void wakeup(ICaustkController controller) {
this.controller = controller;
}
protected final RuntimeException newRangeException(String control, String range, Object value) {
return ExceptionUtils.newRangeException(control, range, value);
}
@Override
public void restore() {
setBass(getBass(true));
setMid(getMid(true));
setHigh(getHigh(true));
setReverbSend(getReverbSend(true));
setDelaySend(getDelaySend(true));
setStereoWidth(getStereoWidth(true));
setPan(getPan(true));
setVolume(getVolume(true));
for (IEffect effect : effects.values()) {
effect.restore();
}
}
public void update() {
MixerMessage.EQ_BASS.send(getEngine(), getIndex(), getBass());
MixerMessage.EQ_MID.send(getEngine(), getIndex(), getMid());
MixerMessage.EQ_HIGH.send(getEngine(), getIndex(), getHigh());
MixerMessage.REVERB_SEND.send(getEngine(), getIndex(), getReverbSend());
MixerMessage.DELAY_SEND.send(getEngine(), getIndex(), getDelaySend());
MixerMessage.STEREO_WIDTH.send(getEngine(), getIndex(), getStereoWidth());
MixerMessage.PAN.send(getEngine(), getIndex(), getPan());
MixerMessage.VOLUME.send(getEngine(), getIndex(), getVolume());
}
}