/*=============================================================================================== SIMPLE.EXE Copyright (c), Firelight Technologies Pty, Ltd 1999-2004. This example demonstrates some fundamental FMOD usage, including device enumeration, output mode selection, user file I/O callbacks, loading and playing samples and a music file, and calling some runtime manipulation and information functions. ===============================================================================================*/ /** * 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.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import javax.swing.JPanel; import org.jouvieje.Fmod.Fmod; import org.jouvieje.Fmod.Init; import org.jouvieje.Fmod.Callbacks.FMUSIC_CALLBACK; import org.jouvieje.Fmod.Callbacks.FSOUND_ALLOCCALLBACK; import org.jouvieje.Fmod.Callbacks.FSOUND_CLOSECALLBACK; import org.jouvieje.Fmod.Callbacks.FSOUND_FREECALLBACK; import org.jouvieje.Fmod.Callbacks.FSOUND_OPENCALLBACK; import org.jouvieje.Fmod.Callbacks.FSOUND_READCALLBACK; import org.jouvieje.Fmod.Callbacks.FSOUND_REALLOCCALLBACK; import org.jouvieje.Fmod.Callbacks.FSOUND_SEEKCALLBACK; import org.jouvieje.Fmod.Callbacks.FSOUND_TELLCALLBACK; import org.jouvieje.Fmod.Defines.FSOUND_INIT_FLAGS; import org.jouvieje.Fmod.Defines.FSOUND_MISC_VALUES; import org.jouvieje.Fmod.Defines.FSOUND_MODES; 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.Misc.BufferUtils; import org.jouvieje.Fmod.Misc.ObjectPointer; import org.jouvieje.Fmod.Misc.Pointer; import org.jouvieje.Fmod.Structures.FMUSIC_MODULE; import org.jouvieje.Fmod.Structures.FSOUND_SAMPLE; import org.jouvieje.libloader.LibLoader; public class Simple extends ConsoleGUI implements FSOUND_OUTPUTTYPES, FSOUND_INIT_FLAGS, FSOUND_MODES, FSOUND_MISC_VALUES, FSOUND_MIXERTYPES, VERSIONS { private static final long serialVersionUID = 1L; public static void main(String[] args) { new FmodExampleFrame(new Simple()); } private boolean init = false; private boolean deinit = false; private FMUSIC_MODULE mod = null; private ByteBuffer modBuff = null; 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; public Simple() { super(); initFmod(); initialize(); } public JPanel getPanel() { return this; } public String getTitle() { return "FMOD Simple example."; } /* * File callbacks */ private FSOUND_OPENCALLBACK myopen = new FSOUND_OPENCALLBACK(){ RandomAccessFile randomAccessFile; public Pointer FSOUND_OPENCALLBACK(String name) { try { randomAccessFile = new RandomAccessFile(name, "rw"); return ObjectPointer.create(randomAccessFile); } catch(FileNotFoundException e) { print("Failed to open the file " + name + " [" + e.getMessage() + "]\n"); return null; } } }; private FSOUND_CLOSECALLBACK myclose = new FSOUND_CLOSECALLBACK(){ public void FSOUND_CLOSECALLBACK(Pointer handle) { try { ObjectPointer objectPointer = ObjectPointer.createView(handle); RandomAccessFile file = (RandomAccessFile)objectPointer.getObject(); file.close(); objectPointer.release(); //Don't forget to release ObjectPointer ! } catch(Exception e) { print("Failed to close the file [" + e.getMessage() + "]\n"); } } }; private FSOUND_READCALLBACK myread = new FSOUND_READCALLBACK(){ public int FSOUND_READCALLBACK(ByteBuffer buffer, int size, Pointer handle) { try { RandomAccessFile file = (RandomAccessFile)ObjectPointer.createView(handle).getObject(); //read our data byte[] data = new byte[size]; int byteRead = file.read(data); //copy data read into buffer buffer.put(data, 0, byteRead); return byteRead; } catch(IOException e) { print("Error reading file [" + e.getMessage() + "]\n"); return 0; } } }; //Values taken from stdio.h public final static int SEEK_CUR = 1; //Seek from the current position of file pointer public final static int SEEK_END = 2; //Seek from the end of file public final static int SEEK_SET = 0; //Seek from the beginning of file private FSOUND_SEEKCALLBACK myseek = new FSOUND_SEEKCALLBACK(){ public int FSOUND_SEEKCALLBACK(Pointer handle, int pos, byte mode) { try { RandomAccessFile file = (RandomAccessFile)ObjectPointer.createView(handle).getObject(); long position = 0; switch(mode) { case SEEK_CUR: position = file.getFilePointer() + pos; break; case SEEK_END: position = file.length() + pos; break; case SEEK_SET: position = pos; break; } file.seek(position); } catch(IOException e) { print("Error seeking file [" + e.getMessage() + "]\n"); return -1; } return 0; } }; private FSOUND_TELLCALLBACK mytell = new FSOUND_TELLCALLBACK(){ public int FSOUND_TELLCALLBACK(Pointer handle) { try { RandomAccessFile file = (RandomAccessFile)ObjectPointer.createView(handle).getObject(); return (int)file.getFilePointer(); } catch(IOException e) { print("Error in tell method [" + e.getMessage() + "]\n"); return -1; } } }; /* * Memory allocation callbacks */ private FSOUND_ALLOCCALLBACK myalloc = new FSOUND_ALLOCCALLBACK(){ public ByteBuffer FSOUND_ALLOCCALLBACK(int size) { print("FMOD Malloc'ed " + size + " bytes\n"); return BufferUtils.newByteBuffer(size); } }; private FSOUND_REALLOCCALLBACK myrealloc = new FSOUND_REALLOCCALLBACK(){ public ByteBuffer FSOUND_REALLOCCALLBACK(ByteBuffer ptr, int size) { print("FMOD Realloced'ed " + size + " bytes\n"); if(ptr.capacity() < size) { return BufferUtils.newByteBuffer(size); } else { return (ByteBuffer)ptr.limit(size); } } }; private FSOUND_FREECALLBACK myfree = new FSOUND_FREECALLBACK(){ public void FSOUND_FREECALLBACK(ByteBuffer ptr) { print("FMOD freed some memory\n"); //TODO free } }; private FMUSIC_CALLBACK ordercallback = new FMUSIC_CALLBACK(){ public void FMUSIC_CALLBACK(FMUSIC_MODULE mod, short param) { print("\nOrder Callback : param " + param + "\n"); } }; private FMUSIC_CALLBACK instcallback = new FMUSIC_CALLBACK(){ public void FMUSIC_CALLBACK(FMUSIC_MODULE mod, short param) { print("\nInst Callback : param " + param + "\n"); } }; public void initFmod() { /* * NativeFmod Init */ try { Init.loadLibraries(); } catch(InitException e) { printExit("NativeFmod error! " + e.getMessage()); 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 + ")"); 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); return; } init = true; } public void run() { if(!init) { return; } /* * SELECT OUTPUT METHOD */ 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; } /* * Set custom file callbacks? This doesnt have to be done, its just here as an example. * Not MIDI files do not use file callbacks so midi loading will fail. FMUSIC_LoadSongMemory could be used to load the midi. */ if(false) { Fmod.FSOUND_File_SetCallbacks(myopen, myclose, myread, myseek, mytell); } /* * Set custom memory callbacks? This is optional as well of course. */ if(false) { //user callbacks if(!Fmod.FSOUND_SetMemorySystem(null, 0, myalloc, myrealloc, myfree)) { printExit(Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError())); return; } } else { //internal memory management - give it 1 mb and no more mallocs will come from fmod ByteBuffer memoryBuffer = BufferUtils.newByteBuffer(4 * 1024 * 1024); if(!Fmod.FSOUND_SetMemorySystem(memoryBuffer, memoryBuffer.capacity(), null, null, null)) { printExit(Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError())); return; } } /* * SELECT DRIVER */ /* * The following list are the drivers for the output method selected above. */ print("---------------------------------------------------------\n"); 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("---------------------------------------------------------\n"); print("Press a corresponding number\n"); 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) */ /* * INITIALIZE */ if(!Fmod.FSOUND_Init(44100, 32, FSOUND_INIT_USEDEFAULTMIDISYNTH)) { printExit(Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError())); return; } /* * LOAD SONG */ /* * The following list are the drivers for the output method selected above. */ print("---------------------------------------------------------\n"); print(" Select Music Type\n"); print("---------------------------------------------------------\n"); print("1 - MOD\n"); print("2 - MIDI (Using Default Software Synth)\n"); print("---------------------------------------------------------\n"); print("Press a corresponding number\n"); int type = -1; while(type < 1 || type > 2) { try { type = Integer.parseInt("" + getKey()); } catch(NumberFormatException e) { type = -1; } Thread.yield(); } switch(type) { case 1: modBuff = Medias.loadMediaIntoMemory("/Media/invtro94.s3m"); break; case 2: modBuff = Medias.loadMediaIntoMemory("/Media/canyon.mid"); break; } mod = Fmod.FMUSIC_LoadSongEx(modBuff, 0, modBuff.capacity(), FSOUND_LOADMEMORY, (int[])null, 0); if(mod == null) { printExit(Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError())); return; } /* * LOAD SAMPLES */ //PCM,44,100 Hz, 8 Bit, Mono samp1Buff = Medias.loadMediaIntoMemory("/Media/drumloop.wav"); samp1 = Fmod.FSOUND_Sample_Load(FSOUND_UNMANAGED, samp1Buff, FSOUND_NORMAL | FSOUND_HW2D | FSOUND_LOADMEMORY, 0, samp1Buff.capacity()); //hardware? why not, just to show it can be done if(samp1 == null) { printExit(Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError())); return; } Fmod.FSOUND_Sample_SetMode(samp1, FSOUND_LOOP_OFF); //this wav has loop points in it which turns looping on.. turn it off! /* PCM,22,050 Hz, 16 Bit, Mono */ samp2Buff = Medias.loadMediaIntoMemory("/Media/jaguar.wav"); samp2 = Fmod.FSOUND_Sample_Load(FSOUND_UNMANAGED, samp2Buff, FSOUND_NORMAL | FSOUND_LOADMEMORY, 0, samp2Buff .capacity()); if(samp2 == null) { printExit(Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError())); return; } /* PCM,22,050 Hz, 8 Bit, Stereo */ samp3Buff = Medias.loadMediaIntoMemory("/Media/chimes.wav"); samp3 = Fmod.FSOUND_Sample_Load(FSOUND_UNMANAGED, samp3Buff, FSOUND_NORMAL | FSOUND_LOADMEMORY, 0, samp3Buff .capacity()); if(samp3 == null) { printExit(Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError())); return; } /* * DISPLAY HELP */ print("FSOUND Output Method : "); 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("Audio Linux System Audio"); 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 : " + Fmod.FSOUND_GetDriverName(Fmod.FSOUND_GetDriver()) + "\n"); print("=========================================================================\n"); print("Press 1 Play 16bit sound at any time\n"); print(" 2 Play 8bit sound at any time (limited to 3 at a time)\n"); print(" 3 Play 16bit STEREO sound at any time\n"); print(" < Rewind mod back 1 order\n"); print(" > FastForward mod forward 1 order\n"); print(" SPACE Pause/unpause music at any time\n"); print(" e Quit\n"); print("=========================================================================\n"); readInput("Press ENTER to continue..."); print("\n"); print("Playing " + Fmod.FMUSIC_GetName(mod) + "...\n"); for(int count = 0; count < Fmod.FMUSIC_GetNumSamples(mod) && count < 20; count += 2) { String a = Fmod.FSOUND_Sample_GetName(Fmod.FMUSIC_GetSample(mod, count)); String b = Fmod.FSOUND_Sample_GetName(Fmod.FMUSIC_GetSample(mod, count + 1)); if(a == null) { a = ""; } if(b == null) { b = ""; } print(count + " " + a + " " + (count + 1) + " " + b + "\n"); } Fmod.FSOUND_Sample_SetMaxPlaybacks(samp2, 3); /* START PLAYING MUSIC! */ Fmod.FMUSIC_SetOrderCallback(mod, ordercallback, 1); Fmod.FMUSIC_SetInstCallback(mod, instcallback, 5); Fmod.FMUSIC_SetMasterVolume(mod, 192); Fmod.FMUSIC_SetLooping(mod, false); Fmod.FMUSIC_PlaySong(mod); boolean exit = false; do { printr("order = " + Fmod.FMUSIC_GetOrder(mod) + "/" + Fmod.FMUSIC_GetNumOrders(mod) + ", row = " + Fmod.FMUSIC_GetRow(mod) + "/" + Fmod.FMUSIC_GetPatternLength(mod, Fmod.FMUSIC_GetOrder(mod)) + " time = " + (Fmod.FMUSIC_GetTime(mod) / 1000) + "." + (Fmod.FMUSIC_GetTime(mod) % 1000 / 10) + " finished " + Fmod.FMUSIC_IsFinished(mod) + " channels = " + Fmod.FSOUND_GetChannelsPlaying() + " cpu = " + Fmod.FSOUND_GetCPUUsage() + "%"); int channel; switch(getKey()) { case ' ': Fmod.FMUSIC_SetPaused(mod, !Fmod.FMUSIC_GetPaused(mod)); break; case '1': Fmod.FSOUND_PlaySound(FSOUND_FREE, samp1); break; case '2': channel = Fmod.FSOUND_PlaySoundEx(FSOUND_FREE, samp2, null, true); Fmod.FSOUND_SetCurrentPosition(channel, Fmod.FSOUND_Sample_GetLength(samp2) - 1); Fmod.FSOUND_SetFrequency(channel, -22050); //Play it backwards! Fmod.FSOUND_SetVolume(channel, 255); Fmod.FSOUND_SetPan(channel, 255); //pan it all the way to the right Fmod.FSOUND_SetPaused(channel, false); break; case '3': channel = Fmod.FSOUND_PlaySoundEx(FSOUND_FREE, samp3, null, true); Fmod.FSOUND_SetPaused(channel, false); break; case '>': Fmod.FMUSIC_SetOrder(mod, Fmod.FMUSIC_GetOrder(mod) + 1); break; case '<': Fmod.FMUSIC_SetOrder(mod, Fmod.FMUSIC_GetOrder(mod) - 1); break; case 'e': case 'E': exit = true; break; } resetInput(); try { Thread.sleep(100); } catch(InterruptedException e) {} } while(!exit && !deinit); stop(); } public void stop() { if(!init || deinit) { return; } deinit = true; print("\n"); /* CLEANUP AND SHUTDOWN */ if(mod != null && !mod.isNull()) Fmod.FMUSIC_StopSong(mod); modBuff = null; 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; if(mod != null && !mod.isNull()) Fmod.FMUSIC_FreeSong(mod); print("Shutdown FMOD\n"); Fmod.FSOUND_Close(); } }