/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.open2jam.sound;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jouvieje.fmodex.Channel;
import org.jouvieje.fmodex.ChannelGroup;
import org.jouvieje.fmodex.DSP;
import org.jouvieje.fmodex.FmodEx;
import org.jouvieje.fmodex.Init;
import org.jouvieje.fmodex.Sound;
import org.jouvieje.fmodex.SoundGroup;
import org.jouvieje.fmodex.defines.FMOD_INITFLAGS;
import org.jouvieje.fmodex.defines.FMOD_MODE;
import org.jouvieje.fmodex.enumerations.FMOD_CHANNELINDEX;
import org.jouvieje.fmodex.enumerations.FMOD_DSP_PITCHSHIFT;
import org.jouvieje.fmodex.enumerations.FMOD_DSP_TYPE;
import org.jouvieje.fmodex.enumerations.FMOD_RESULT;
import org.jouvieje.fmodex.enumerations.FMOD_SOUND_FORMAT;
import org.jouvieje.fmodex.exceptions.InitException;
import org.jouvieje.fmodex.structures.FMOD_CREATESOUNDEXINFO;
import org.open2jam.parsers.utils.ByteHelper;
import org.open2jam.parsers.utils.SampleData;
/**
*
* @author dttvb
*/
public class FmodExSoundSystem implements SoundSystem {
private org.jouvieje.fmodex.System system;
private SoundGroup masterSoundGroup = new SoundGroup();
private ChannelGroup masterChannelGroup = new ChannelGroup();
private ChannelGroup bgmGroup = new ChannelGroup();
private ChannelGroup keyGroup = new ChannelGroup();
private DSP dsp = new DSP();
private int nextChannelID = 0;
public FmodExSoundSystem(int bufferSize) throws SoundSystemException {
try
{
Init.loadLibraries();
}
catch(InitException e)
{
throw new SoundSystemInitException(e);
}
system = new org.jouvieje.fmodex.System();
errorCheck(FmodEx.System_Create(system));
errorCheck(system.setDSPBufferSize(bufferSize, 2));
errorCheck(system.setSoftwareChannels(512));
errorCheck(system.init(512, FMOD_INITFLAGS.FMOD_INIT_NORMAL, null));
errorCheck(system.getMasterSoundGroup(masterSoundGroup));
errorCheck(system.createChannelGroup("BGM", bgmGroup));
errorCheck(system.createChannelGroup("KEY", keyGroup));
errorCheck(system.getMasterChannelGroup(masterChannelGroup));
// errorCheck(system.createDSPByType(FMOD_DSP_TYPE.FMOD_DSP_TYPE_PITCHSHIFT, dsp));
// errorCheck(bgmGroup.addDSP(dsp, null));
// dsp.setParameter(FMOD_DSP_PITCHSHIFT.FMOD_DSP_PITCHSHIFT_FFTSIZE.asInt(), 1024);
SoundGroup soundGroup = new SoundGroup();
errorCheck(system.getMasterSoundGroup(soundGroup));
errorCheck(soundGroup.setMaxAudible(-1));
System.out.println("Audio engine : FMOD Sound System by Firelight Technologies");
}
private void errorCheck(FMOD_RESULT result) throws SoundSystemException {
if (result != FMOD_RESULT.FMOD_OK) {
throw new SoundSystemException(FmodEx.FMOD_ErrorString(result));
}
}
public void release() {
system.release();
}
@Override
public org.open2jam.sound.Sound load(SampleData data) throws SoundSystemException {
ByteArrayOutputStream out = new ByteArrayOutputStream(ByteHelper.tmp_buffer.length);
try {
data.copyTo(out);
} catch (IOException ex) {
Logger.getLogger(FmodExSoundSystem.class.getName()).log(Level.SEVERE, "{0}", ex);
return null;
}
ByteBuffer buffer = ByteBuffer.allocateDirect(out.size());
buffer.put(out.toByteArray());
buffer.flip();
return new FmodSound(buffer);
}
@Override
public void setBGMVolume(float factor) {
bgmGroup.setVolume(factor);
}
@Override
public void setKeyVolume(float factor) {
keyGroup.setVolume(factor);
}
@Override
public void setMasterVolume(float factor) {
masterSoundGroup.setVolume(factor);
}
@Override
public void update() {
system.update();
}
@Override
public void setSpeed(float factor) {
keyGroup.setPitch(factor);
bgmGroup.setPitch(factor);
// dsp.setParameter(FMOD_DSP_PITCHSHIFT.FMOD_DSP_PITCHSHIFT_PITCH.asInt(), 1.0f / factor);
}
class FmodSound implements org.open2jam.sound.Sound {
private Sound sound;
public FmodSound(ByteBuffer buffer) throws SoundSystemException {
sound = new Sound();
FMOD_CREATESOUNDEXINFO exinfo = FMOD_CREATESOUNDEXINFO.allocate();
exinfo.setLength(buffer.capacity());
errorCheck(system.createSound(buffer, FMOD_MODE.FMOD_SOFTWARE | FMOD_MODE.FMOD_OPENMEMORY, exinfo, sound));
}
@Override
public SoundInstance play(SoundChannel soundChannel, float volume, float pan) throws SoundSystemException {
Channel channel = new Channel();
errorCheck(system.playSound(FMOD_CHANNELINDEX.FMOD_CHANNEL_FREE, sound, true, channel));
errorCheck(channel.setVolume(Math.min(1, volume)));
errorCheck(channel.setPan(pan));
errorCheck(channel.setPaused(false));
errorCheck(channel.setLoopCount(0));
errorCheck(channel.setChannelGroup(soundChannel == SoundChannel.BGM ? bgmGroup : keyGroup));
system.update();
if (channel.isNull()) return null;
return new FmodSoundInstance(channel);
}
}
class FmodSoundInstance implements SoundInstance {
private final Channel channel;
private FmodSoundInstance(Channel channel) {
this.channel = channel;
}
@Override
public void stop() {
channel.stop();
}
}
}