//===============================================================================================
//3D.EXE
//Copyright (c), Firelight Technologies Pty, Ltd, 1999-2004.
//
//This test shows EAX, DS3D and Software all being used together and the simple commands needed
//to set up some 3d audio.
//This application also displays the use of FSOUND_GetDriverCaps to get information on the
//3D capabilities of the selected driver
//===============================================================================================
/**
* I've ported the C++ FMOD example to use it with NativeFmod
*
* @author J�r�me JOUVIE (Jouvieje)
*
* WANT TO CONTACT ME ?
* E-mail :
* jerome.jouvie@gmail.com
* My web sites :
* http://jerome.jouvie.free.fr/
*/
package org.jouvieje.Fmod.Examples;
import java.nio.ByteBuffer;
import javax.swing.JPanel;
import org.jouvieje.Fmod.Fmod;
import org.jouvieje.Fmod.Init;
import org.jouvieje.Fmod.Defines.FSOUND_CAPS;
import org.jouvieje.Fmod.Defines.FSOUND_MISC_VALUES;
import org.jouvieje.Fmod.Defines.FSOUND_MODES;
import org.jouvieje.Fmod.Defines.FSOUND_REVERB_PRESETS;
import org.jouvieje.Fmod.Defines.VERSIONS;
import org.jouvieje.Fmod.Enumerations.FSOUND_MIXERTYPES;
import org.jouvieje.Fmod.Enumerations.FSOUND_OUTPUTTYPES;
import org.jouvieje.Fmod.Examples.Util.ConsoleGUI;
import org.jouvieje.Fmod.Examples.Util.FmodExampleFrame;
import org.jouvieje.Fmod.Examples.Util.Medias;
import org.jouvieje.Fmod.Exceptions.InitException;
import org.jouvieje.Fmod.Structures.FSOUND_REVERB_PROPERTIES;
import org.jouvieje.Fmod.Structures.FSOUND_SAMPLE;
import org.jouvieje.libloader.LibLoader;
public class _3d extends ConsoleGUI implements FSOUND_OUTPUTTYPES, FSOUND_CAPS, FSOUND_MIXERTYPES, FSOUND_MISC_VALUES, FSOUND_MODES, FSOUND_REVERB_PRESETS, VERSIONS {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
new FmodExampleFrame(new _3d());
}
public _3d() {
super();
initFmod();
initialize();
}
public JPanel getPanel() {
return this;
}
public String getTitle() {
return "FMOD 3D example.";
}
private boolean init = false;
private boolean deinit = false;
//samples
private FSOUND_SAMPLE samp1 = null;
private ByteBuffer samp1Buff = null;
private FSOUND_SAMPLE samp2 = null;
private ByteBuffer samp2Buff = null;
private FSOUND_SAMPLE samp3 = null;
private ByteBuffer samp3Buff = null;
//channels
private int channel1 = -1;
private int channel2 = -1;
//50ms update for interface
private final int INTERFACE_UPDATETIME = 50;
private boolean listenerflag = true;
private float[] listenerpos = new float[]{0.f, 0.f, 0.f};
private float t = 0;
private float[] lastpos = {0, 0, 0};
public void initFmod() {
/*
* NativeFmod Init
*/
try {
Init.loadLibraries();
}
catch(InitException e) {
printExit("NativeFmod error! " + e.getMessage() + "\n");
return;
}
/*
* Checking NativeFmodEx version
*/
if(NATIVEFMOD_LIBRARY_VERSION != NATIVEFMOD_JAR_VERSION) {
printExit("Error! NativeFmod library version (" + NATIVEFMOD_LIBRARY_VERSION
+ ") is different to jar version (" + NATIVEFMOD_JAR_VERSION + ")\n");
return;
}
/*==================================================*/
/*
* Checking Fmod version
*/
if(Fmod.FSOUND_GetVersion() < FMOD_VERSION) {
printExit("Error : You are using the wrong DLL version! You should be using FMOD " + FMOD_VERSION + "\n");
return;
}
init = true;
}
public void run() {
if(!init) return;
print("---------------------------------------------------------\n");
print("Output Type\n");
print("---------------------------------------------------------\n");
switch (LibLoader.getPlatform()) {
case LibLoader.PLATFORM_WINDOWS:
print("1 - Direct Sound\n");
print("2 - Windows Multimedia Waveout\n");
print("3 - ASIO\n");
break;
case LibLoader.PLATFORM_LINUX:
print("1 - OSS - Open Sound System\n");
print("2 - ESD - Elightment Sound Daemon\n");
print("3 - ALSA 0.9 - Advanced Linux Sound Architecture\n");
break;
case LibLoader.PLATFORM_MACOSX:
print("1 - Mac SoundManager\n");
break;
default:
print("1 - NoSound\n");
break;
}
print("---------------------------------------------------------\n"); // print driver names
print("Press a corresponding number\n");
int output = -1;
while(output < 1 || output > 4) {
try {
output = Integer.parseInt("" + getKey());
}
catch(NumberFormatException e) {
output = -1;
}
Thread.yield();
}
switch (LibLoader.getPlatform()) {
case LibLoader.PLATFORM_WINDOWS:
switch(output) {
case 1:
Fmod.FSOUND_SetOutput(FSOUND_OUTPUT_DSOUND);
break;
case 2:
Fmod.FSOUND_SetOutput(FSOUND_OUTPUT_WINMM);
break;
case 3:
Fmod.FSOUND_SetOutput(FSOUND_OUTPUT_ASIO);
break;
}
break;
case LibLoader.PLATFORM_LINUX:
switch(output) {
case 1:
Fmod.FSOUND_SetOutput(FSOUND_OUTPUT_OSS);
break;
case 2:
Fmod.FSOUND_SetOutput(FSOUND_OUTPUT_ESD);
break;
case 3:
Fmod.FSOUND_SetOutput(FSOUND_OUTPUT_ALSA);
break;
}
break;
case LibLoader.PLATFORM_MACOSX:
Fmod.FSOUND_SetOutput(FSOUND_OUTPUT_MAC);
break;
default:
Fmod.FSOUND_SetOutput(FSOUND_OUTPUT_NOSOUND);
break;
}
// ==========================================================================================
// SELECT DRIVER
// ==========================================================================================
// The following list are the drivers for the output method selected above.
print("\n---------------------------------------------------------\n");
//switch/case cannot be used because values of the differents FSOUND_OUTPUT_ are not known (by Java) : we have to use if elseif ...
output = Fmod.FSOUND_GetOutput();
if(output == FSOUND_OUTPUT_NOSOUND) print("NoSound");
else if(output == FSOUND_OUTPUT_WINMM) print("Windows Multimedia Waveout");
else if(output == FSOUND_OUTPUT_DSOUND) print("Direct Sound");
else if(output == FSOUND_OUTPUT_ASIO) print("ASIO");
else if(output == FSOUND_OUTPUT_OSS) print("Open Sound System");
else if(output == FSOUND_OUTPUT_ESD) print("Enlightment Sound Daemon");
else if(output == FSOUND_OUTPUT_ALSA) print("Advanced Linux Sound Architecture");
else if(output == FSOUND_OUTPUT_MAC) print("Mac SoundManager");
print(" Driver list\n");
print("---------------------------------------------------------\n");
for(int i = 0; i <= Fmod.FSOUND_GetNumDrivers() - 1; i++) {
print(i + " - " + Fmod.FSOUND_GetDriverName(i) + "\n"); // print driver names
int[] caps = new int[1];
Fmod.FSOUND_GetDriverCaps(i, caps);
if((caps[0] & FSOUND_CAPS_HARDWARE) != 0) print(" * Driver supports hardware 3D sound!\n");
if((caps[0] & FSOUND_CAPS_EAX2) != 0) print(" * Driver supports EAX 2 reverb!\n");
if((caps[0] & FSOUND_CAPS_EAX3) != 0) print(" * Driver supports EAX 3 reverb!\n");
}
print("---------------------------------------------------------\n"); // print driver names
print("Press a corresponding number or E to quit");
int driver = -1;
while(driver < 0 || driver > Fmod.FSOUND_GetNumDrivers() - 1) {
try {
driver = Integer.parseInt("" + getKey());
}
catch(NumberFormatException e) {
driver = -1;
}
Thread.yield();
}
Fmod.FSOUND_SetDriver(driver); // Select sound card (0 = default)
int[] caps = new int[1];
Fmod.FSOUND_GetDriverCaps(Fmod.FSOUND_GetDriver(), caps);
print("\n");
print("---------------------------------------------------------\n");
print("Driver capabilities\n");
print("---------------------------------------------------------\n");
if(caps[0] != 0) print("- This driver will support software mode only.\n It does not properly support 3D sound hardware.\n");
if((caps[0] & FSOUND_CAPS_HARDWARE) != 0) print("- Driver supports hardware 3D sound !\n");
if((caps[0] & FSOUND_CAPS_EAX2) != 0) print("- Driver supports EAX 2 reverb !\n");
if((caps[0] & FSOUND_CAPS_EAX3) != 0) print("- Driver supports EAX 3 reverb !\n");
print("---------------------------------------------------------\n");
Fmod.FSOUND_SetMixer(FSOUND_MIXER_QUALITY_AUTODETECT);
// ==========================================================================================
// INITIALIZE
// ==========================================================================================
if(!Fmod.FSOUND_Init(44100, 32, 0)) {
printExit("Init : " + Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError()));
return;
}
// ==========================================================================================
// LOAD SAMPLES
// ==========================================================================================
// ==========================================================================================
// 3D MONO
// ==========================================================================================
samp1Buff = Medias.loadMediaIntoMemory("/Media/drumloop.wav");
samp1 = Fmod.FSOUND_Sample_Load(FSOUND_FREE, samp1Buff, FSOUND_HW3D | FSOUND_LOADMEMORY, 0, samp1Buff.capacity());
if(samp1 == null) {
printExit("samp1 : " + Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError()));
stop();
return;
}
// increasing mindistnace makes it louder in 3d space
Fmod.FSOUND_Sample_SetMinMaxDistance(samp1, 4.0f, 10000.0f);
Fmod.FSOUND_Sample_SetMode(samp1, FSOUND_LOOP_NORMAL);
// ==========================================================================================
// 3D MONO
// ==========================================================================================
samp2Buff = Medias.loadMediaIntoMemory("/Media/jaguar.wav");
samp2 = Fmod.FSOUND_Sample_Load(FSOUND_UNMANAGED, samp2Buff, FSOUND_HW3D | FSOUND_LOADMEMORY, 0, samp2Buff.capacity());
if(samp2 == null) {
printExit("samp2 : " + Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError()));
stop();
return;
}
// increasing mindistance makes it louder in 3d space
Fmod.FSOUND_Sample_SetMinMaxDistance(samp2, 4.0f, 10000.0f);
Fmod.FSOUND_Sample_SetMode(samp2, FSOUND_LOOP_NORMAL);
// ==========================================================================================
// 2D STEREO
// ==========================================================================================
samp3Buff = Medias.loadMediaIntoMemory("/Media/chimes.wav");
samp3 = Fmod.FSOUND_Sample_Load(FSOUND_UNMANAGED, samp3Buff, FSOUND_HW2D | FSOUND_LOADMEMORY, 0, samp3Buff.capacity());
if(samp3 == null) {
printExit("samp3 : " + Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError()));
stop();
return;
}
// ==========================================================================================
// DISPLAY HELP
// ==========================================================================================
print("FSOUND Output Method : ");
output = Fmod.FSOUND_GetOutput();
if(output == FSOUND_OUTPUT_NOSOUND) print("FSOUND_OUTPUT_NOSOUND");
else if(output == FSOUND_OUTPUT_WINMM) print("FSOUND_OUTPUT_WINMM");
else if(output == FSOUND_OUTPUT_DSOUND) print("FSOUND_OUTPUT_DSOUND");
else if(output == FSOUND_OUTPUT_ASIO) print("FSOUND_OUTPUT_ASIO");
else if(output == FSOUND_OUTPUT_OSS) print("FSOUND_OUTPUT_OSS");
else if(output == FSOUND_OUTPUT_ESD) print("FSOUND_OUTPUT_ESD");
else if(output == FSOUND_OUTPUT_ALSA) print("FSOUND_OUTPUT_ALSA");
print("\nFSOUND Mixer : ");
int mixer = Fmod.FSOUND_GetMixer();
if(mixer == FSOUND_MIXER_QUALITY_FPU) print("FSOUND_MIXER_QUALITY_FPU");
else if(mixer == FSOUND_MIXER_QUALITY_MMXP5) print("FSOUND_MIXER_QUALITY_MMXP5");
else if(mixer == FSOUND_MIXER_QUALITY_MMXP6) print("FSOUND_MIXER_QUALITY_MMXP6");
print("\nFSOUND Driver : ");
print(Fmod.FSOUND_GetDriverName(Fmod.FSOUND_GetDriver()) + "\n");
int[] num2d = new int[2];
int[] num3d = new int[2];
Fmod.FSOUND_GetNumHWChannels(num2d, num3d, null);
print("Hardware 2D channels : " + num2d[0] + "\n");
print("Hardware 3D channels : " + num3d[0] + "\n");
print("=========================================================================\n");
print("Press 1 Pause/Unpause 16bit 3D sound at any time\n");
print(" 2 Pause/Unpause 8bit 3D sound at any time\n");
print(" 3 Play 16bit STEREO 2D sound at any time\n");
print(" 4 Change to EAX Reverb mode CONCERTHALL (DirectSound/SBLive only)\n");
print(" 5 Change to EAX Reverb mode SEWERPIPE (DirectSound/SBLive only)\n");
print(" 6 Change to EAX Reverb mode PSYCHOTIC (DirectSound/SBLive only)\n");
print(" < Move listener left (in still mode)\n");
print(" > Move listener right (in still mode)\n");
print(" SPACE Stop/Start listener automatic movement\n");
print(" e Quit\n");
print("=========================================================================\n");
// ==========================================================================================
// PLAY 2 LOOPING SOUNDS
// ==========================================================================================
//sample 1
float[] pos = new float[]{-10.0f, 0.0f, 0.0f};
float[] vel = new float[]{0.f, 0.f, 0.f};
channel1 = Fmod.FSOUND_PlaySoundEx(FSOUND_FREE, samp1, null, true);
Fmod.FSOUND_3D_SetAttributes(channel1, pos, vel);
if(!Fmod.FSOUND_SetPaused(channel1, false)) {
print(Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError()) + "\n");
}
//sample 2
pos = new float[]{15.0f, 0.0f, 0.0f};
vel = new float[]{0, 0, 0};
channel2 = Fmod.FSOUND_PlaySoundEx(FSOUND_FREE, samp2, null, true);
Fmod.FSOUND_3D_SetAttributes(channel2, pos, vel);
Fmod.FSOUND_SetVolume(channel2, 128);
if(!Fmod.FSOUND_SetPaused(channel2, false)) {
print(Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError()) + "\n");
}
// ==========================================================================================
// MAIN LOOP
// ==========================================================================================
boolean exit = false;
do {
switch(getKey()) {
case '1':
Fmod.FSOUND_SetPaused(channel1, !Fmod.FSOUND_GetPaused(channel1));
break;
case '2':
Fmod.FSOUND_SetPaused(channel2, !Fmod.FSOUND_GetPaused(channel2));
break;
case '3':
Fmod.FSOUND_PlaySound(FSOUND_FREE, samp3);
break;
case '4':
FSOUND_REVERB_PROPERTIES props = FSOUND_REVERB_PROPERTIES.create(FSOUND_PRESET_CONCERTHALL);
Fmod.FSOUND_Reverb_SetProperties(props);
break;
case '5':
props = FSOUND_REVERB_PROPERTIES.create(FSOUND_PRESET_SEWERPIPE);
Fmod.FSOUND_Reverb_SetProperties(props);
break;
case '6':
props = FSOUND_REVERB_PROPERTIES.create(FSOUND_PRESET_PSYCHOTIC);
Fmod.FSOUND_Reverb_SetProperties(props);
break;
case ' ':
listenerflag = !listenerflag;
break;
case '<':
if(!listenerflag) {
listenerpos[0] -= 1.0f;
if(listenerpos[0] < -35) listenerpos[0] = -35;
}
break;
case '>':
if(!listenerflag) {
listenerpos[0] += 1.0f;
if(listenerpos[0] > 30) listenerpos[0] = 30;
}
break;
case 'e':
case 'E':
exit = true;
break;
}
// ==========================================================================================
// UPDATE THE LISTENER
// ==========================================================================================
if(listenerflag) {
listenerpos[0] = ((float)Math.sin(t * 0.05f) * 33.0f); // left right pingpong
}
// ********* NOTE ******* READ NEXT COMMENT!!!!!
// vel = how far we moved last FRAME (m/f), then time compensate it to SECONDS (m/s).
vel[0] = (listenerpos[0] - lastpos[0]) * (1000 / INTERFACE_UPDATETIME);
vel[1] = (listenerpos[1] - lastpos[1]) * (1000 / INTERFACE_UPDATETIME);
vel[2] = (listenerpos[2] - lastpos[2]) * (1000 / INTERFACE_UPDATETIME);
// store pos for next time
lastpos[0] = listenerpos[0];
lastpos[1] = listenerpos[1];
lastpos[2] = listenerpos[2];
Fmod.FSOUND_3D_Listener_SetAttributes(listenerpos, vel, 0.f, 0.f, 1.0f, 0.f, 1.0f, 0.f);
t += (30 * (1.0f / INTERFACE_UPDATETIME)); // t is just a time value .. it increments in 30m/s steps in this example
// print out a small visual display
char[] s = "|.......................<1>......................<2>....................|".toCharArray();
s[(int)(listenerpos[0]) + 35] = 'L';
printr(new String(s));
Fmod.FSOUND_Update();
try {
Thread.sleep(INTERFACE_UPDATETIME - 1); // -1 for time taken for printf etc
}
catch(Exception e) {}
}
while(!exit && !deinit);
stop();
}
public void stop() {
if(!init || deinit) {
return;
}
deinit = true;
print("\n");
// ==========================================================================================
// CLEANUP AND SHUTDOWN
// ==========================================================================================
// you dont need to free samples if you let fsound's sample manager look after samples, as
// it will free them all for you.
if(samp1 != null && !samp1.isNull()) {
Fmod.FSOUND_Sample_Free(samp1);
}
samp1Buff = null;
if(samp2 != null && !samp2.isNull()) {
Fmod.FSOUND_Sample_Free(samp2);
}
samp2Buff = null;
if(samp3 != null && !samp3.isNull()) {
Fmod.FSOUND_Sample_Free(samp3);
}
samp3Buff = null;
print("Shutdown FMOD\n");
Fmod.FSOUND_Close();
}
}