Hi all,
Ive noticed that when I want to load a piece of music (background music) thats pretty large (1 - 10Mb), a long pause appears which worsens when the larger the file. I know that this is the case because of compiling the audio moving it into ram…etc.
What would solve this problem is streaming. So the file would stream from the HD instead of being in ram.
What do you think of this idea?
And arman, is this feasible with the current infrastructure?
DP
I’m certain that it’s possible, and it’s an excellent idea for jME. I’ve written a streaming Oggg loader before, perhaps I could contribute that to jME? The addition of streaming might require a few small design changes to the sound architechture, though.
I’ll look into it once fragment programs are finalized.
Streaming would be cool. In the meantime, you can always preload your music or load it in a background thread of lower priority (not too low though or it won’t ever load. :))
im currently preloading them. But the loading is a io operation which blocks the current thread. So Im going to have to load in another thread.
DP
Just my .02 here…
I agree that streaming audio would be a great addition… I can think of all kinds of situations that would benefit from this functionality…
- Live audio from a network game (players talking to each other? announcements from the game manager?)
- Handling gaming machines with less-than-ideal amounts of memory and/or generally reducing the memory footprint of a game
- Decreasing the load time for the game and/or levels in the game
- Playing CD-audio from the game CD (or let the player pick his own CD music?)
There are probably other benefits as well… these are just what I thought of off the top of my head.
–K
It can also hurt the speed if the sound is loading from a slow drive. Another problem would be if the program needs exacted timed sound. For these reason I think that streaming should be optional.
streaming will be optional ofcourse. However, solving some of your problems would be to set a buffering stage whereby it writes "some" of the sound data (user configurable) onto the ram so that we can play and the rest streams into ram.
DP
Yes… definitely optional. Good idea to clarify that, Badmi.
I also like your suggestion, DP… Using RAM as a buffer should keep things sounding nice and smooth in most cases.
–K
fwiw the following 3dfx real-time streaming audio poc example uses the NativeFmod swig generated binding to FMOD.
I get a fatal error in the jvm closing the stream, but am not sure where this lies so while I track it down have sent the details to jerome, who is the NativeFmod developer.
//===============================================================================================
//USERSTREAM.EXE
//Copyright (c), Firelight Technologies Pty, Ltd, 1999-2004.
//
//This sample specifically demonstrates the user callback streaming facility, and generates a
//very strange noise! :)
//===============================================================================================
/**
* I've ported the C++ Fmod sample to use it with NativeFmod
*
* @author Jérôme JOUVIE (jouvieje)
*
* WANT TO CONTACT ME ?
* E-mail :
* jouvieje@esstin.uhp-nancy.fr
* My web sites :
* http://topresult.tomato.co.uk/~jerome/
* http://www.esstin.uhp-nancy.fr/~jouvieje/
*/
package Music.NativeFmod.FmodSamples;
import Music.NativeFmod.*;
import Tool.es;
public class userstream3DFX implements PLATFORMS, FSOUND_OUTPUTTYPES, FSOUND_MISC_VALUES, FSOUND_MODES, FSOUND_MIXERTYPES
{
/*
* Callback used to divided the volume by 2
* When this callback is called two times, the sound is divided by 4
*/
static FSOUND_DSPCALLBACK dspcallback = new FSOUND_DSPCALLBACK()
{
public CPointer FSOUND_DSPCALLBACK(CPointer originalbuffer, CPointer newBuffer, int length, CPointer userdata)
{
/*
* newbuffer is a buffer that contains the music. You can consider this as a short array.
* This array contains the right and left channel like that :
*
* | l | r | l | r | l | r | l | r | ...
* The odd index are for the left channel and the even channels are for the right.
*/
CShortArray stereo16bitbuffer = CShortArray.toCShortArray(newBuffer);
//System.out.println("DSP callback ENTRY 1 : ");
//length in SAMPLES that is to say length of the buffer (length of the array)
for(int i = 0; i <= length-1; i++) // >>2 = 16bit stereo (4 bytes per sample)
{
/*
* The >> Operator :
* It is a bit manipulation, it move to the left each bit. (<< is the same operator but move bit to the left)
* Ex:
* short a = 13; //in base 2 = 0000000000001101
* short b = a >> 1 // a >> 1 = 0000000000000110 so in base 10 : 6
* The value of b is 6
*
* >> 1 is equivalent to an integer division by 2, that is for that reason the volume is half of
* the original volume.
* When we call two time this callback, the volume is divided by 2*2=4, so the volume is the quart
* of the original volume
*
* Rem: >> 2 is equivalent to an integer division by 4
*/
/**
* Original C++ code
* *stereo16bitbuffer >>= 1;
* *(stereo16bitbuffer+1) >>= 1;
* stereo16bitbuffer += 2;
* is equivalent to
* *stereo16bitbuffer = *stereo16bitbuffer >> 1; //set the value of the first element
* *(stereo16bitbuffer+1) = *(stereo16bitbuffer+1) >> 1; //set the value of the second element
* stereo16bitbuffer++; //increment the pointer
*/
//First method : C++ traduction
// stereo16bitbuffer.setElement(0, (short)(stereo16bitbuffer.getElement(0) >> 1)); //left
// stereo16bitbuffer.setElement(1, (short)(stereo16bitbuffer.getElement(1) >> 1)); //right
// stereo16bitbuffer.incrementPointer(2);
//System.out.println("DSP callback Pre 2 : " + i);
//Second method : 'Java method'
stereo16bitbuffer.setElement(2*i, (short)(stereo16bitbuffer.getElement(2*i) >> 1)); //left
stereo16bitbuffer.setElement(2*i+1, (short)(stereo16bitbuffer.getElement(2*i+1) >> 1)); //right
//System.out.println("DSP callback3 : " + i);
}
//System.out.println("DSP callback Pre-EXIT : ");
return newBuffer;
}
};
/*
* [DESCRIPTION]
* User streamer callback
*
* [PARAMETERS]
* 'stream' pointer to the stream supplying the callback
* 'buff' pointer to the streamer buffer to fill.
* 'len' length of the data block in BYTES
*
* [REMARKS]
* What a strange noise!!!
* (heh heh)
*/
/*
* This callback 'creates' the sound
*/
static FSOUND_STREAMCALLBACK streamcallback = new FSOUND_STREAMCALLBACK()
{
float t1 = 0, t2 = 0; // time
float v1 = 0, v2 = 0; // velocity
public boolean FSOUND_STREAMCALLBACK(FSOUND_STREAM stream, CPointer buff, int len, CPointer userdata)
{
CShortArray stereo16bitbuffer = CShortArray.toCShortArray(buff);
/*
* len is the length of the buffer in bytes. But we have 4 byte per SAMPLES,
* that is for that reason that we need to divide by 4 (>>2) the length
*/
for(int i = 0; i < (len>>2); i++) // >>2 = 16bit stereo (4 bytes per sample)
{
/**
* This is a pure C++ code
* (If you don't know anything to C++ pointer, you should not understand this code !)
*
* C++ Code
* *stereo16bitbuffer++ = (signed short)(sin(t1) * 32767.0f);
* *stereo16bitbuffer++ = (signed short)(sin(t2) * 32767.0f);
* <=>
* *stereo16bitbuffer = (signed short)(sin(t1) * 32767.0f); //set the value of the first element
* stereo16bitbuffer++; //increment the pointer
* *stereo16bitbuffer = (signed short)(sin(t2) * 32767.0f); //set the value of the first element
* stereo16bitbuffer++; //increment the pointer
*/
//First method : C++ traduction
// stereo16bitbuffer.setElement(0, (short)(Math.sin(t1)*32767.0f)); //left channel
// stereo16bitbuffer.incrementPointer(1);
// stereo16bitbuffer.setElement(0, (short)(Math.sin(t2)*32767.0f)); //right channel
// stereo16bitbuffer.incrementPointer(1);
//Second method : 'Java method'
stereo16bitbuffer.setElement(2*i, (short)(Math.sin(t1)*32767.0f)); //left channel
stereo16bitbuffer.setElement(2*i+1, (short)(Math.sin(t2)*32767.0f)); //right channel
//stereo16bitbuffer.setElement(2*i+1, (short)(0)); //right channel
t1 += 0.01f + v1;
t2 += 0.0142f + v2;
v1 += (float)(Math.sin(t1) * 0.002f);
v2 += (float)(Math.sin(t2) * 0.002f);
}
//System.out.println("callback : buff = "+buff+", len = "+len+", time = "+((float)NativeFmod.FSOUND_Stream_GetTime(stream) / 1000.0f)+" param = "+userdata);
return true;
}
};
/*
* [DESCRIPTION]
* End of stream user callback, initialized with FSOUND_Stream_SetEndCallback or
* FSOUND_Stream_SetSynchCallback
*
* [PARAMETERS]
* 'stream' A pointer to the stream that ended.
* 'buff' This is NULL for end of stream callbacks, or a string for synch callbacks.
* 'len' This is reserved and is always 0 for end and synch callbacks. ignore.
* 'param' This is the value passed to FSOUND_Stream_SetEndCallback or
* FSOUND_Stream_SetSynchCallback as a user data value.
*
* [RETURN_VALUE]
* TRUE or FALSE, the value is ignored.
*/
static FSOUND_STREAMCALLBACK endcallback = new FSOUND_STREAMCALLBACK()
{
public boolean FSOUND_STREAMCALLBACK(FSOUND_STREAM stream, CPointer buff, int len, CPointer userdata)
{
//end of stream callback doesnt have a 'buff' value, if it doesnt it could be a synch point.
System.out.println("");
if(buff != null)
/*
* The call come from FSOUND_Stream_SetEndCallback so here buff is always NULL !
* It can be a synchpoint if the call com from FSOUND_Stream_SetSyncCallback, in this case, buff holds a string
*
* Look at the Fmod sample : stream with the file jbtennis.wav
*/
System.out.println("SYNCHPOINT : "+CString.toCStringPointer(buff));
else
System.out.println("STREAM ENDED!!");
return true;
}
};
static int channel = 1;
public static void main(String[] args)
{
FSOUND_STREAM stream;
FSOUND_DSPUNIT dsp1;
FSOUND_DSPUNIT dsp2;
System.out.println("
");
System.out.println("FSOUND Streamer example.");
System.out.println("Copyright (c) Firelight Technologies Pty, Ltd, 2001-2004.");
System.out.println("
");
System.out.println("
");
System.out.println("Output Type");
System.out.println("
");
if(NativeFmod.PLATFORM == WIN32 || NativeFmod.PLATFORM == WIN64)
{
System.out.println("1 - Direct Sound");
System.out.println("2 - Windows Multimedia Waveout");
System.out.println("3 - ASIO");
}
else if(NativeFmod.PLATFORM == LINUX)
{
System.out.println("1 - OSS - Open Sound System");
System.out.println("2 - ESD - Elightment Sound Daemon");
System.out.println("3 - ALSA 0.9 - Advanced Linux Sound Architecture");
}
else if(NativeFmod.PLATFORM == MAC)
{
System.out.println("1 - Mac SoundManager");
}
else
{
System.out.println("1 - NoSound");
}
System.out.println("
"); // print driver names
System.out.println("Press a corresponding number");
int output;
do
{
output = es.readInt_("Your choice = ");
}
while(output < 1 || output > 4);
if(NativeFmod.PLATFORM == WIN32 || NativeFmod.PLATFORM == WIN64)
{
switch(output)
{
case 1: NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_DSOUND); break;
case 2: NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_WINMM); break;
case 3: NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_ASIO); break;
}
}
else if(NativeFmod.PLATFORM == LINUX)
{
switch(output)
{
case 1: NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_OSS); break;
case 2: NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_ESD); break;
case 3: NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_ALSA); break;
}
}
else if(NativeFmod.PLATFORM == MAC)
{
NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_MAC);
}
else
{
NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_NOSOUND);
}
// ==========================================================================================
// SELECT DRIVER
// ==========================================================================================
// The following list are the drivers for the output method selected above.
System.out.println("
");
output = NativeFmod.FSOUND_GetOutput();
if(output == FSOUND_OUTPUT_NOSOUND)
System.out.print("NoSound");
else if(output == FSOUND_OUTPUT_WINMM)
System.out.print("Windows Multimedia Waveout");
else if(output == FSOUND_OUTPUT_DSOUND)
System.out.print("Direct Sound");
else if(output == FSOUND_OUTPUT_ASIO)
System.out.print("ASIO");
else if(output == FSOUND_OUTPUT_OSS)
System.out.print("Open Sound System");
else if(output == FSOUND_OUTPUT_ESD)
System.out.print("Enlightment Sound Daemon");
else if(output == FSOUND_OUTPUT_ALSA)
System.out.print("Audio Linux System Audio");
else if(output == FSOUND_OUTPUT_MAC)
System.out.print("Mac SoundManager");
System.out.println(" Driver list");
System.out.println("
");
for(int i = 0; i <= NativeFmod.FSOUND_GetNumDrivers()-1; i++)
{
System.out.println(i+" - "+NativeFmod.FSOUND_GetDriverName(i));
}
System.out.println("
"); // print driver names
System.out.println("Press a corresponding number");
int driver = -1;
do
{
driver = es.readInt_("Your choice = ");
}
while(driver < 0 || driver > NativeFmod.FSOUND_GetNumDrivers()-1);
NativeFmod.FSOUND_SetDriver(driver); // Select sound card (0 = default)
// ==========================================================================================
// INITIALIZE
// ==========================================================================================
if(!NativeFmod.FSOUND_Init(44100, 16, 0))
{
System.out.println("Error!");
System.out.println(NativeFmod.FMOD_ErrorString(NativeFmod.FSOUND_GetError()));
System.exit(1);
}
NativeFmod.FSOUND_SetMixer(FSOUND_MIXER_QUALITY_AUTODETECT);
NativeFmod.FSOUND_3D_SetDistanceFactor(1.0f);
NativeFmod.FSOUND_3D_SetRolloffFactor(1.0f);
System.out.println("Finish");
System.out.println("New FSOUND_REVERB_PROPERTIES ");
//FSOUND_REVERB_PROPERTIES cityPresets = new FSOUND_REVERB_PROPERTIES(FSOUND_REVERB_PRESETS.FSOUND_PRESET_CITY);
FSOUND_REVERB_PROPERTIES druggedPresets = new FSOUND_REVERB_PROPERTIES(FSOUND_REVERB_PRESETS.FSOUND_PRESET_DRUGGED);
System.out.println("Finish");
System.out.println("");
System.out.println("Get Room value of this preset (before modification) :");
//System.out.println("Room = "+cityPresets.getRoom());
System.out.println("Room = "+ druggedPresets.getRoom());
System.out.println("");
System.out.print("Set value to 136...");
//cityPresets.setRoom(136);
druggedPresets.setRoom(136);
System.out.println("Finish");
System.out.println("");
// ==========================================================================================
// CREATE USER STREAM
// ==========================================================================================
stream = NativeFmod.FSOUND_Stream_Create(streamcallback, 2*2048, FSOUND_HW3D |FSOUND_FORCEMONO | FSOUND_NORMAL | FSOUND_16BITS , 44100, null);
if(stream == null)
{
System.out.println("Error!");
System.out.println(NativeFmod.FMOD_ErrorString(NativeFmod.FSOUND_GetError()));
System.exit(1);
}
NativeFmod.FSOUND_Stream_SetEndCallback(stream, endcallback, null);
dsp1 = NativeFmod.FSOUND_Stream_CreateDSP(stream, dspcallback, 0, null); // priority 0 = it comes first in dsp chain.
dsp2 = NativeFmod.FSOUND_Stream_CreateDSP(stream, dspcallback, 1, null); // priority 1 = it comes last
System.out.println("Press any key to quit");
System.out.println("=========================================================================");
System.out.println("Playing stream...");
// ==========================================================================================
// PLAY STREAM
// ==========================================================================================
// if(NativeFmod.FSOUND_Stream_Play(FSOUND_FREE, stream) == -1)
// {
// System.out.println("Error!");
// System.out.println(NativeFmod.FMOD_ErrorString(NativeFmod.FSOUND_GetError()));
// System.exit(1);
// }
// System.out.print("Loading the music ...");
// sample = NativeFmod.FSOUND_Sample_Load(
// FSOUND_FREE,
// musicName,
// FSOUND_HW3D | FSOUND_LOADMEMORY ,
// 0,
// 0);
NativeFmod.FSOUND_3D_SetMinMaxDistance(channel, 1.0f, 1000f);
//NativeFmod.FSOUND_Sample_SetMode(NativeFmod.FSOUND_Stream_GetSample(stream), FSOUND_LOOP_NORMAL);
System.out.println("Finish init");
System.out.print("Playing the music ...");
//channel = NativeFmod.FSOUND_PlaySoundEx(FSOUND_FREE, NativeFmod.FSOUND_Stream_GetSample(stream), null, true);
channel = NativeFmod.FSOUND_Stream_Play(FSOUND_FREE, stream);
NativeFmod.FSOUND_3D_SetAttributes(channel,
new float[] {0.0f, 0.0f, 0.0f},
new float[] {0.0f, 0.0f, 0.0f});
NativeFmod.FSOUND_SetVolume(channel, 255);
NativeFmod.FSOUND_SetPaused(channel, false);
System.out.println("Finish Playing");
System.out.println();
es.readString("Press a key to deplace around the music ...");
loop1();
setPosition(0.0f);
System.out.println();
es.readString("Press a key to continue...");
loop2();
es.readString("******* Hit ENTER to active stream DSP unit #1 to halve the stream volume...");
NativeFmod.FSOUND_DSP_SetActive(dsp1, true);
es.readString("******* Now hit ENTER to active stream DSP unit #2 to quarter the stream volume...");
NativeFmod.FSOUND_DSP_SetActive(dsp2, true);
es.readString("******* How hit a ENTER to finish...");
System.out.println("Free dsp's");
NativeFmod.FSOUND_DSP_Free(dsp1);
NativeFmod.FSOUND_DSP_Free(dsp2);
System.out.println("Close Stream");
NativeFmod.FSOUND_Stream_Close(stream);
System.out.println("Close FSound");
NativeFmod.FSOUND_Close();
System.exit(0);
}
private static void loop1()
{
int updates = 0;
final int NB_UPDATES = 80;
final int UPDATE_TIME = 100;
float position = -5.0f;
float lastPosition = 0;
float velocity = 0;
float lastVelocity = 0;
do
{
updates++;
//increase deplacement
position += 0.125f;
// deplacement in units s / time in ms
velocity = (position - lastPosition) * (1000 / UPDATE_TIME);
//save ourposition
lastPosition = position;
System.out.println("Distance from the music = "+position);
NativeFmod.FSOUND_3D_Listener_SetAttributes(
new float[] {position, 0, 0},
new float[] {velocity, 0, 0},
0, 0, 1.0f,
0, 1.0f, 0);
NativeFmod.FSOUND_Update();
try
{
Thread.sleep(UPDATE_TIME);
}
catch(Exception e){}
}
while(updates < NB_UPDATES);
}
private static void loop2()
{
boolean continuer = true;
float position = 0.0f;
while(continuer)
{
System.out.println("");
System.out.println("Menu of choice :");
System.out.println("1 : set distance from the music");
System.out.println("2 : print distance");
System.out.println("0 : exit");
int choice = es.readInt_("Your choice : ");
switch(choice)
{
case 0 : continuer = false; break;
case 1 :
try
{
position = Float.parseFloat(es.readString("Position = "));
setPosition(position);
}
catch(Exception e)
{
System.err.println("Wrong value !!!");
}
break;
case 2 : printInformations(); break;
}
}
}
/**
* Set our position
*/
private static void setPosition(float position)
{
float[] pos = new float[] {position, 0.0f, 0.0f};
float[] vel = new float[] {position, 0.0f, 0.0f};
//update our position (ears position)
NativeFmod.FSOUND_3D_Listener_SetAttributes(
pos, vel,
0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f);
//need to update 3d engine
NativeFmod.FSOUND_Update();
}
/**
* Print our distance from the music
*/
private static void printInformations()
{
float[] jPosition = new float[3];
NativeFmod.FSOUND_3D_Listener_GetAttributes(jPosition, new float[3],
new float[1], new float[1], new float[1],
new float[1], new float[1], new float[1]);
System.out.print("Distance from the music = "+jPosition[0]+"r");
}
}
Hummmmm you should look at lwjgl fmod binding (it doesn’t require LWJGL to run)…
Chman
Chman
Matzon, the fmod binding developer, has replied to my q's on that topic at the end of this post:
http://www.javagaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=xith3d;action=display;num=1101613660
Fixed.
/**
* This exemple is based on Fmod sample : userstream (ported by Jérôme Jouvie) and Sound3D sample (written by Jérôme Jouvie).
*
* @author Paul Cohen
*/
package Music.NativeFmod.Samples;
import Music.NativeFmod.*;
import Tool.es;
public class userstream3DFX implements PLATFORMS, FSOUND_OUTPUTTYPES, FSOUND_MISC_VALUES, FSOUND_MODES
{
/*
* Callback used to divided the volume by 2
* When this callback is called two times, the sound is divided by 4
*/
static FSOUND_DSPCALLBACK dspcallback = new FSOUND_DSPCALLBACK()
{
public CPointer FSOUND_DSPCALLBACK(CPointer originalbuffer, CPointer newBuffer, int length, CPointer userdata)
{
CShortArray stereo16bitbuffer = CShortArray.toCShortArray(newBuffer);
for(int i = 0; i <= length-1; i++)
stereo16bitbuffer.setElement(i, (short)(stereo16bitbuffer.getElement(i) >> 1));
return newBuffer;
}
};
/*
* [DESCRIPTION]
* User streamer callback
*
* [PARAMETERS]
* 'stream' pointer to the stream supplying the callback
* 'buff' pointer to the streamer buffer to fill.
* 'len' length of the data block in BYTES
*
* [REMARKS]
* What a strange noise!!!
* (heh heh)
*/
/*
* This callback 'creates' the sound
*/
static FSOUND_STREAMCALLBACK streamcallback = new FSOUND_STREAMCALLBACK()
{
float t1 = 0, t2 = 0; // time
float v1 = 0, v2 = 0; // velocity
public boolean FSOUND_STREAMCALLBACK(FSOUND_STREAM stream, CPointer buff, int len, CPointer userdata)
{
CShortArray stereo16bitbuffer = CShortArray.toCShortArray(buff);
/*
* len is the length of the buffer in bytes. But we have 4 byte per SAMPLES,
* that is for that reason that we need to divide by 4 (>>2) the length
*/
for(int i = 0; i < (len>>2); i++) // >>2 = 16bit stereo (4 bytes per sample)
{
stereo16bitbuffer.setElement(2*i, (short)(Math.sin(t1)*32767.0f)); //left channel
stereo16bitbuffer.setElement(2*i+1, (short)(Math.sin(t2)*32767.0f)); //right channel
t1 += 0.01f + v1;
t2 += 0.0142f + v2;
v1 += (float)(Math.sin(t1) * 0.002f);
v2 += (float)(Math.sin(t2) * 0.002f);
}
return true;
}
};
/*
* [DESCRIPTION]
* End of stream user callback, initialized with FSOUND_Stream_SetEndCallback or
* FSOUND_Stream_SetSynchCallback
*
* [PARAMETERS]
* 'stream' A pointer to the stream that ended.
* 'buff' This is NULL for end of stream callbacks, or a string for synch callbacks.
* 'len' This is reserved and is always 0 for end and synch callbacks. ignore.
* 'param' This is the value passed to FSOUND_Stream_SetEndCallback or
* FSOUND_Stream_SetSynchCallback as a user data value.
*
* [RETURN_VALUE]
* TRUE or FALSE, the value is ignored.
*/
static FSOUND_STREAMCALLBACK endcallback = new FSOUND_STREAMCALLBACK()
{
public boolean FSOUND_STREAMCALLBACK(FSOUND_STREAM stream, CPointer buff, int len, CPointer userdata)
{
//end of stream callback doesnt have a 'buff' value, if it doesnt it could be a synch point.
System.out.println("");
if(buff != null)
/*
* The call come from FSOUND_Stream_SetEndCallback so here buff is always NULL !
* It can be a synchpoint if the call com from FSOUND_Stream_SetSyncCallback, in this case, buff holds a string
*
* Look at the Fmod sample : stream with the file jbtennis.wav
*/
System.out.println("SYNCHPOINT : "+CString.toCStringPointer(buff));
else
System.out.println("STREAM ENDED!!");
return true;
}
};
public static void main(String[] args)
{
FSOUND_STREAM stream;
FSOUND_DSPUNIT dsp1;
FSOUND_DSPUNIT dsp2;
int channel = -1;
System.out.println("
");
System.out.println("FSOUND Streamer example.");
System.out.println("Copyright (c) Firelight Technologies Pty, Ltd, 2001-2004.");
System.out.println("
");
System.out.println("
");
System.out.println("Output Type");
System.out.println("
");
if(NativeFmod.PLATFORM == WIN32 || NativeFmod.PLATFORM == WIN64)
{
System.out.println("1 - Direct Sound");
System.out.println("2 - Windows Multimedia Waveout");
System.out.println("3 - ASIO");
}
else if(NativeFmod.PLATFORM == LINUX)
{
System.out.println("1 - OSS - Open Sound System");
System.out.println("2 - ESD - Elightment Sound Daemon");
System.out.println("3 - ALSA 0.9 - Advanced Linux Sound Architecture");
}
else if(NativeFmod.PLATFORM == MAC)
{
System.out.println("1 - Mac SoundManager");
}
else
{
System.out.println("1 - NoSound");
}
System.out.println("
"); // print driver names
System.out.println("Press a corresponding number");
int output;
do
{
output = es.readInt_("Your choive = ");
}
while(output < 1 || output > 4);
if(NativeFmod.PLATFORM == WIN32 || NativeFmod.PLATFORM == WIN64)
{
switch(output)
{
case 1: NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_DSOUND); break;
case 2: NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_WINMM); break;
case 3: NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_ASIO); break;
}
}
else if(NativeFmod.PLATFORM == LINUX)
{
switch(output)
{
case 1: NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_OSS); break;
case 2: NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_ESD); break;
case 3: NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_ALSA); break;
}
}
else if(NativeFmod.PLATFORM == MAC)
{
NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_MAC);
}
else
{
NativeFmod.FSOUND_SetOutput(FSOUND_OUTPUT_NOSOUND);
}
// ==========================================================================================
// SELECT DRIVER
// ==========================================================================================
// The following list are the drivers for the output method selected above.
System.out.println("
");
output = NativeFmod.FSOUND_GetOutput();
if(output == FSOUND_OUTPUT_NOSOUND)
System.out.print("NoSound");
else if(output == FSOUND_OUTPUT_WINMM)
System.out.print("Windows Multimedia Waveout");
else if(output == FSOUND_OUTPUT_DSOUND)
System.out.print("Direct Sound");
else if(output == FSOUND_OUTPUT_ASIO)
System.out.print("ASIO");
else if(output == FSOUND_OUTPUT_OSS)
System.out.print("Open Sound System");
else if(output == FSOUND_OUTPUT_ESD)
System.out.print("Enlightment Sound Daemon");
else if(output == FSOUND_OUTPUT_ALSA)
System.out.print("Audio Linux System Audio");
else if(output == FSOUND_OUTPUT_MAC)
System.out.print("Mac SoundManager");
System.out.println(" Driver list");
System.out.println("
");
for(int i = 0; i <= NativeFmod.FSOUND_GetNumDrivers()-1; i++)
{
System.out.println(i+" - "+NativeFmod.FSOUND_GetDriverName(i));
}
System.out.println("
"); // print driver names
System.out.println("Press a corresponding number");
int driver = -1;
do
{
driver = es.readInt_("Your choice = ");
}
while(driver < 0 || driver > NativeFmod.FSOUND_GetNumDrivers()-1);
NativeFmod.FSOUND_SetDriver(driver); // Select sound card (0 = default)
// ==========================================================================================
// INITIALIZE
// ==========================================================================================
if(!NativeFmod.FSOUND_Init(44100, 16, 0))
{
System.out.println("Error!");
System.out.println(NativeFmod.FMOD_ErrorString(NativeFmod.FSOUND_GetError()));
System.exit(1);
}
NativeFmod.FSOUND_3D_SetDistanceFactor(1.0f);
NativeFmod.FSOUND_3D_SetRolloffFactor(1.0f);
System.out.println("Using FSOUND_PRESET_DRUGGED reverb preset.");
FSOUND_REVERB_PROPERTIES druggedPresets = new FSOUND_REVERB_PROPERTIES(FSOUND_REVERB_PRESETS.FSOUND_PRESET_DRUGGED);
System.out.println("");
// ==========================================================================================
// CREATE USER STREAM
// ==========================================================================================
stream = NativeFmod.FSOUND_Stream_Create(streamcallback, 2*2048, FSOUND_HW3D | FSOUND_FORCEMONO | FSOUND_16BITS, 44100, null);
if(stream == null)
{
System.out.println("Error!");
System.out.println(NativeFmod.FMOD_ErrorString(NativeFmod.FSOUND_GetError()));
System.exit(1);
}
NativeFmod.FSOUND_Stream_SetEndCallback(stream, endcallback, null);
dsp1 = NativeFmod.FSOUND_Stream_CreateDSP(stream, dspcallback, 0, null); // priority 0 = it comes first in dsp chain.
dsp2 = NativeFmod.FSOUND_Stream_CreateDSP(stream, dspcallback, 1, null); // priority 1 = it comes last
System.out.println("Press any key to quit");
System.out.println("=========================================================================");
System.out.println("Playing stream...");
// ==========================================================================================
// PLAY STREAM
// ==========================================================================================
channel = NativeFmod.FSOUND_Stream_PlayEx(FSOUND_FREE, stream, null, false);
if(channel == -1)
{
System.out.println("Error!");
System.out.println(NativeFmod.FMOD_ErrorString(NativeFmod.FSOUND_GetError()));
System.exit(1);
}
System.out.println();
es.readString("Press a key to deplace around the music ...");
loop1();
setPosition(0.0f);
System.out.println();
es.readString("Press a key to continue...");
loop2();
System.out.println();
es.readString("******* Hit ENTER to active stream DSP unit #1 to halve the stream volume...");
NativeFmod.FSOUND_DSP_SetActive(dsp1, true);
es.readString("******* Now hit ENTER to active stream DSP unit #2 to quarter the stream volume...");
NativeFmod.FSOUND_DSP_SetActive(dsp2, true);
es.readString("******* How hit a ENTER to finish...");
NativeFmod.FSOUND_DSP_SetActive(dsp1, false);
NativeFmod.FSOUND_DSP_SetActive(dsp2, false);
System.out.println("");
NativeFmod.FSOUND_DSP_Free(dsp1);
NativeFmod.FSOUND_DSP_Free(dsp2);
NativeFmod.FSOUND_Stream_Stop(stream);
NativeFmod.FSOUND_Stream_Close(stream);
NativeFmod.FSOUND_Close();
System.exit(0);
}
private static void loop1()
{
int updates = 0;
final int NB_UPDATES = 80;
final int UPDATE_TIME = 100;
float position = -5.0f;
float lastPosition = 0;
float velocity = 0;
float lastVelocity = 0;
do
{
updates++;
//increase deplacement
position += 0.125f;
// deplacement in units s / time in ms
velocity = (position - lastPosition) * (1000 / UPDATE_TIME);
//save ourposition
lastPosition = position;
System.out.println("Distance from the music = "+position);
NativeFmod.FSOUND_3D_Listener_SetAttributes(
new float[] {position, 0, 0},
new float[] {velocity, 0, 0},
0, 0, 1.0f,
0, 1.0f, 0);
NativeFmod.FSOUND_Update();
try
{
Thread.sleep(UPDATE_TIME);
}
catch(Exception e){}
}
while(updates < NB_UPDATES);
}
private static void loop2()
{
boolean continuer = true;
float position = 0.0f;
while(continuer)
{
System.out.println("");
System.out.println("Menu of choice :");
System.out.println("1 : set distance from the music");
System.out.println("2 : print distance");
System.out.println("0 : exit");
int choice = es.readInt_("Your choice : ");
switch(choice)
{
case 0 : continuer = false; break;
case 1 :
try
{
position = Float.parseFloat(es.readString("Position = "));
setPosition(position);
}
catch(Exception e)
{
System.err.println("Wrong value !!!");
}
break;
case 2 : printInformations(); break;
}
}
}
/**
* Set our position
*/
private static void setPosition(float position)
{
float[] pos = new float[] {position, 0.0f, 0.0f};
float[] vel = new float[] {position, 0.0f, 0.0f};
//update our position (ears position)
NativeFmod.FSOUND_3D_Listener_SetAttributes(
pos, vel,
0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f);
//need to update 3d engine
NativeFmod.FSOUND_Update();
}
/**
* Print our distance from the music
*/
private static void printInformations()
{
float[] jPosition = new float[3];
NativeFmod.FSOUND_3D_Listener_GetAttributes(jPosition, new float[3],
new float[1], new float[1], new float[1],
new float[1], new float[1], new float[1]);
System.out.print("Distance from the music = "+jPosition[0]+"r");
}
}