/* This file is part of jpcsp. Jpcsp 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 3 of the License, or (at your option) any later version. Jpcsp 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 Jpcsp. If not, see <http://www.gnu.org/licenses/>. */ package jpcsp.sound; import static jpcsp.HLE.modules.sceSasCore.PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE; import static jpcsp.HLE.modules.sceSasCore.PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE; import static jpcsp.HLE.modules.sceSasCore.PSP_SAS_PITCH_BASE; import static jpcsp.HLE.modules.sceSasCore.getSasADSRCurveTypeName; import static jpcsp.hardware.Audio.PSP_AUDIO_VOLUME_MAX; import jpcsp.HLE.modules.sceAtrac3plus.AtracID; public class SoundVoice { private boolean changed; private int leftVolume; private int rightVolume; private int sampleRate; private int vagAddress; private int vagSize; private AtracID atracId; private int pcmAddress; private int pcmSize; private int loopMode; private int pitch; private int noise; private boolean playing; private boolean paused; private boolean on; private VoiceADSREnvelope envelope; private int playSample; private int index; public class VoiceADSREnvelope { public int AttackRate; public int DecayRate; public int SustainRate; public int ReleaseRate; public int AttackCurveType; public int DecayCurveType; public int SustainCurveType; public int ReleaseCurveType; public int SustainLevel; public int height; public VoiceADSREnvelope() { // Default values (like on PSP) AttackRate = 0; DecayRate = 0; SustainRate = 0; ReleaseRate = 0; AttackCurveType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_INCREASE; DecayCurveType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE; SustainCurveType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE; ReleaseCurveType = PSP_SAS_ADSR_CURVE_MODE_LINEAR_DECREASE; SustainLevel = 0; height = 0; } @Override public String toString() { return String.format("VoiceADSREnvelope[AR 0x%08X(%s), DR 0x%08X(%s), SR 0x%08X(%s, SL 0x%08X), RR 0x%08X(%s)]", AttackRate, getSasADSRCurveTypeName(AttackCurveType), DecayRate, getSasADSRCurveTypeName(DecayCurveType), SustainRate, getSasADSRCurveTypeName(SustainCurveType), SustainLevel, ReleaseRate, getSasADSRCurveTypeName(ReleaseCurveType)); } } public SoundVoice(int index) { this.index = index; changed = true; leftVolume = PSP_AUDIO_VOLUME_MAX; rightVolume = PSP_AUDIO_VOLUME_MAX; vagAddress = 0; vagSize = 0; pcmAddress = 0; pcmSize = 0; loopMode = 0; pitch = PSP_SAS_PITCH_BASE; noise = 0; playing = false; paused = false; on = false; envelope = new VoiceADSREnvelope(); playSample = 0; atracId = null; } public void onVoiceChanged() { changed = true; if (isOn() && !isPlaying()) { // A parameter was changed while the voice was ON but no longer playing. // Restart playing. setPlaying(true); } } public int getLeftVolume() { return leftVolume; } public void setLeftVolume(int leftVolume) { this.leftVolume = leftVolume; } public int getRightVolume() { return rightVolume; } public void setRightVolume(int rightVolume) { this.rightVolume = rightVolume; } public void on() { on = true; setPlaying(true); } public void off() { on = false; } public VoiceADSREnvelope getEnvelope() { return envelope; } public boolean isOn() { return on; } public boolean isPlaying() { return playing; } public void setPlaying(boolean playing) { playSample = 0; if (!playing) { envelope.height = 0; off(); } this.playing = playing; } public boolean isPaused() { return paused; } public void setPaused(boolean paused) { this.paused = paused; } public void setVAG(int address, int size) { vagAddress = address; vagSize = size; atracId = null; pcmAddress = 0; onVoiceChanged(); } public int getVAGAddress() { return vagAddress; } public int getVAGSize() { return vagSize; } public int getLoopMode() { return loopMode; } public void setLoopMode(int loopMode) { if (this.loopMode != loopMode) { this.loopMode = loopMode; onVoiceChanged(); } } public int getPitch() { return pitch; } public void setPitch(int pitch) { this.pitch = pitch; } public int getNoise() { return noise; } public void setNoise(int noise) { if (this.noise != noise) { this.noise = noise; onVoiceChanged(); } } public int getPlaySample() { return playSample; } public void setPlaySample(int playSample) { this.playSample = playSample; } public int getSampleRate() { return sampleRate; } public void setSampleRate(int sampleRate) { this.sampleRate = sampleRate; } public boolean isEnded() { return !isPlaying(); } public boolean isChanged() { return changed; } public void setChanged(boolean changed) { this.changed = changed; } public int getIndex() { return index; } @Override public String toString() { return String.format("SoundVoice #%d", index); } public AtracID getAtracId() { return atracId; } public void setAtracId(AtracID atracId) { this.atracId = atracId; pcmAddress = 0; vagAddress = 0; onVoiceChanged(); } public void setPCM(int address, int size) { pcmAddress = address; pcmSize = size; atracId = null; vagAddress = 0; onVoiceChanged(); } public int getPcmAddress() { return pcmAddress; } public int getPcmSize() { return pcmSize; } }