0
0

I’m VERY pleased that FMOD supports web streaming right out of the box for files and web radios. But I need to know what settings I can play with in fmod to improve a few things…

1) I figured out you can’t pause a web stream… When you un-pause, it resumes the buffer it has and then you get silence…. Though the position is updated, nothing plays. If I recreate the connection (stop and restart the sound) the connection re-establishes.

2) Sometimes, the sound gets stuck in a loop, playing it’s memory buffer I guess, over and over because it can’t get more information from the broadcaster… Or for other reasons… Again, if I stop and restart the sound it plays normally. Often though, it deadlocks so I can’t stop the channel and restart. I must Kill the Application with task manager

I’ve been listening to radio for hours now… Only a few providers have "flaky" connection (I assume)

All my sounds are created with the stream option…

I would like to see an improvement in

1) the time it takes to create a web streamed sound channel… Well, I don’t care if it takes 20 seconds to start playing… But I do care that the application is deadlocked while it’s connecting.

2) when the channel "looses" it’s connection, I would like to see an improvement in the way it handles it… like go silent while it retries to connect… And retry without deadlocking the application…

I was thinking to add real web radio in games for ambient sound effect like for a city environment… Or turning on a virtual radio in a game.

But the fact that it deadlocks makes me think FMOD is not quite ready for that yet.

Status functions are needed to get various states of the web stream connection… Did I overlook something or am I right to say there is practically nothing (high level) in the API to help me?

This is the FMOD Demo application I’m experimenting with…
http://www.yoyogames.com/games/show/34365

  • You must to post comments
0
0

[quote="brett":2xan8810]Thanks I modified the netstream example to check for channel being valid as well.

One extra thing I did was simply put this extra code in.

[code:2xan8810]
printf("Shutting down.\n");

if (channel)
{
    result = channel->stop();
    ERRCHECK(result);
}

[/code:2xan8810]

The stream simply needs to be stopped. This cancels file reads, and makes openstate say it is finished within a very short time.

You can then release the sound without it stalling at all.[/quote:2xan8810]

Cool.

But I did find that, occasionally, if the sound has been starving for a while/internet gone, though you can stop the channel, you simply cant free the sound whitout causing some odd effect. I can’t replicate it in the demo and it’s kinda hard to tell when it happens.

1) I would detect the starving,
2) when the sound is starving, I mute. -> Does not always work
3) Then, to compensate for the fact that I get the expected FMOD_OPENSTATE_STREAMING condition but never a (half expected FMOD_ERR_HTTP_TIMEOUT on top of that, I added my own timeout variable in the application
4) If starving for more than 10 seconds, I channel->stop() and I sound->release() using the same loop and check as the sample.
5) I reconnect, and back to step 1

But then, the system became unstable (every so often). Either the next sound would start to play (new sound new channel, same resource) and then the application would lock or everything is fine until I exit. Then I deadlock

So, I decided to skip the sound->release() if I am in the timeout condition. That solved it.

Bah, no big deal, I’ve been playing with the application for… OGM 13 hours now… It’s been stable since I found the work arround (15 minutes after the last post), I’ve been adding new things to it and everytime I run it, I start 10-15 stream. It’s pretty stable and I am happy. And the memory does not seem to be growing.

The last test I ran was 30 streams. They all been playing/reconnecting for 3 hours.

The muting does not always work. Some times it does, often it does not… Almost like I’m too late to do it or something. But that only lasts for 10 seconds. Then it’s gone.

Everything looks right but I’m tired. Perhaps it’s something I missed.

I’m going to double check the release code loop (I copied over) in my dll… I also have a timout variable in there… But when my (that) timeout condition is met (yes, the channel has been stopped), I break and proceed with the free (bad).

The reason is the simplyfied use of the FMOD system through my DLL… I can’t have the users’ game freeze for an undetemined amout of time (it was more than 5 secons) in the middle of a game. So I arbitrarely set if to 5 seconds.

I think I’ll skip over the free like I did in the application when it times out. Still they’ll have a 5 second delay when that happens. But I now have a "IN GAME" solution they can use if someone ever notices.

  • You must to post comments
0
0

you’re supposed to use FMOD_NONBLOCKING to open a netstream, thats what the example does.

It does not deadlock.

We’ll look at what happens if it loses the connection.

  • You must to post comments
0
0

[quote="brett":3b3eupc6]you’re supposed to use FMOD_NONBLOCKING to open a netstream, thats what the example does.

It does not deadlock.

We’ll look at what happens if it loses the connection.[/quote:3b3eupc6]

I’m having trouble…

[code:3b3eupc6]
export double FMODSoundAdd(LPCSTR soundfile, double threed, double streamed)
{
if(!inited) {{FMODASSERT(FMOD_ERR_INITIALIZATION);}}
FMOD_SOUND *sound = NULL;

DWORD flags = FMOD_LOOP_OFF | FMOD_2D | FMOD_SOFTWARE;
if(threed)
{
    //MessageBoxA(GetActiveWindow(),soundfile,(LPCSTR)"3d",MB_ICONINFORMATION);
    flags = FMOD_LOOP_OFF | FMOD_3D | FMOD_SOFTWARE | FMOD_3D_LINEARROLLOFF;
}
else
{
    //      MessageBoxA(GetActiveWindow(),soundfile,(LPCSTR)"2D",MB_ICONINFORMATION);
}
if(streamed)
{
    //FMODASSERT(FMOD_System_CreateStream(mainsystem, soundfile, flags, 0, &sound));
    FMODASSERT(FMOD_System_CreateSound(mainsystem, soundfile, flags| FMOD_CREATESTREAM | FMOD_NONBLOCKING, 0, &sound));
//char t[] = "123456789";
//wsprintf( t, "%ld", (int)sound);

// MessageBoxA(GetActiveWindow(),t,"",0);

}
else
{
    FMODASSERT(FMOD_System_CreateSound(mainsystem, soundfile, flags, 0, &sound));
}
FMODASSERT(FMOD_System_Update(mainsystem));

if(sound == NULL) {{FMODASSERT(FMOD_ERR_INVALID_HANDLE);}}
//MessageBoxA(GetActiveWindow(),"2","",0);

myinfo *mi = (myinfo *)GlobalAllocPtr(GMEM_FIXED|GMEM_ZEROINIT,(sizeof(myinfo)));
//MessageBoxA(GetActiveWindow(),"3","",0);
if(mi == NULL) {FMODASSERT(FMOD_ERR_MEMORY);}
mi->maxvolume = 1;
strcpy(mi->file,soundfile);
mi->threed =(threed);
mi->streamed =(streamed);
//all other members set by GMEM_ZEROINIT
//MessageBoxA(GetActiveWindow(),"4","",0);

FMODASSERT(FMOD_Sound_SetUserData(sound, (void *)mi));
MessageBoxA(GetActiveWindow(),"5","",0);

return (double) (DWORD) sound;

}
[/code:3b3eupc6]

My function returns 0… Failed…

If I enable the message boxes, I get a valid sound.

Looks like I can’t SetUserData on it
Any ideas?

  • You must to post comments
0
0

Bug Confirmed.

Cant SetUserData on a sound initialized with FMOD_NONBLOCKING while it’s "Not ready"

I need my user data LOL…

Are there any other sound or channel related functions that will fail if the FMOD_NONBLOCKING is set?

  • You must to post comments
0
0

You are saying things are bugs when they are not, please refer to the documentation more closely.

To set the userdata on a nonblocking sound, use FMOD_CREATESOUNDEXINFO ‘userdata’ member when creating your sound.

Nothing succeeds with a nonblocking sound except getOpenState, because if you create a nonblocking sound if you call something straight after createSound, the sound hasnt even been created yet.

  • You must to post comments
0
0

[quote="brett":1w5gvswa]You are saying things are bugs when they are not, please refer to the documentation more closely.

To set the userdata on a nonblocking sound, use FMOD_CREATESOUNDEXINFO ‘userdata’ member when creating your sound.

Nothing succeeds with a nonblocking sound except getOpenState, because if you create a nonblocking sound if you call something straight after createSound, the sound hasnt even been created yet.[/quote:1w5gvswa]

That is silly, I have a sound and a channel… I see no reason why I cant set my data to it using that function.

So, basically, for example, I can’t
Sound::set3DMinMaxDistance on the sound
or
Channel::set3DMinMaxDistance
or
Channel::setChannelGroup
or anything???

FMOD_CREATESOUNDEXINFO ‘userdata’ is a work around to the fact tha Sound::setUserData does not work.

If you read Sound::setUserData documentation, nowhere does it state that this function cannot be used if NON BLOCKING is used AND is not ready.

And the non blocking blurb
[quote:1w5gvswa]
FMOD_NONBLOCKING

For opening sounds and getting streamed subsounds (seeking) asyncronously. Use Sound::getOpenState to poll the state of the sound as it opens or retrieves the subsound in the background.
[/quote:1w5gvswa]

Where does it state that I cannot do anything to the sound or its channel until it’s ready!!??

[quote:1w5gvswa]
Remarks

When a sound is opened with FMOD_NONBLOCKING, it is opened and prepared in the background, or asynchronously.
This allows the main application to execute without stalling on audio loads.
This function will describe the state of the asynchronous load routine i.e. whether it has succeeded, failed or is still in progress.

If ‘starving’ is true, then you will most likely hear a stuttering/repeating sound as the decode buffer loops on itself and replays old data.
Now that this variable exists, you can detect buffer underrun and use something like Channel::setMute to keep it quiet until it is not starving any more.
[/quote:1w5gvswa]

Long story short, FMOD gave me a sound, it gave me a channel, I should be able to treat them as I would normally even if it’s still streaming, I should be able to setup it’s properties (sound or channel).

What follows are a few thoughts with minor critisism on the fmod design. don’t take it personally…

If I have to wait for it to be ready then the non blocking feature is 80% worthless (to me) since, yes, it ain’t blocking but now I have to do the waiting myself until it’s ready to set up… You’re basically differing the problem. Passing the ball onto me…

I was not planning of fiddling with the FMOD_CREATESOUNDEXINFO structure either… I hate to switch between two different methods that do the same thing.

Sound::setUserData is used everywhere in my code and getUserData as well.

When the channel starts, I use this data to setup the channel based on properties the user has previously set after loading the sound…. Properties that are only applicable on a channel.

Now I have to wait for it to be ready… That means I have to block and dealock the caller otherwise his setup will not be complete… That is, his 3d settings, his group, his max sound volume…

Same deal when he starts a channel, right after he loaded to sound and then tries to setup the playing channel. I have to block and wait (if I did not do so in the load sound fn)…

Or, I differ everything myself to the callers… Tell them to expect a not ready state and try later…

I guess I cannot support this unless I rewrite everything. Or write a specific web stream load sound version… Yes, that’s most likely the answer.

Having a specific web stream load sound function will FORCE the user to read the documentation on how to use it and so be aware he has to poll the sound before setting it up.

OK. That sounds like the plan.

Thanks brett…

BTW, I disabled the get/setUserData and was able to web stream sounds myself… Even got the tags in!!!

The example helped to setup everything right though it does not work… It fails to create a channel (using the same url I use in my app) and later fails to pause (or is it mute) the null channel.

But, I’m still having dealocks with "skipping record effect" when (looks like) it looses the connection to the stream… I’ll add the starving check and pause the channel… Maybe that will fix it.

Don’t know what else to do about that.

  • You must to post comments
0
0

‘i have a sound and i have a channel’.

You -don’t- have a sound. You dont have a channel. How are you getting a channel if the sound isnt even loaded and playsound hasnt been successfuly called?

You missed that 1 crucial point I wrote, before writing a big comment on how we should change our engine. The sound is not created/opened yet, it is being created in a background thread. You cannot execute functions when a sound has not even been created yet.

The point non blocking is to not block your application, that’s what you asked for. It is not worthless, you can then still access your gui and do other things while it is loading thanks to nonblocking flag. Even winamp displays a ‘buffering’ message, that’s the same as this. You get the chance to display a buffering message (and even the amount buffered), rather than just hang the app. This is what the netstream example does.

  • You must to post comments
0
0

[quote="brett":3gt3f1ah]’i have a sound and i have a channel’.

You -don’t- have a sound. You dont have a channel. How are you getting a channel if the sound isnt even loaded and playsound hasnt been successfuly called?

You missed that 1 crucial point I wrote, before writing a big comment on how we should change our engine. The sound is not created/opened yet, it is being created in a background thread. You cannot execute functions when a sound has not even been created yet.

The point non blocking is to not block your application, that’s what you asked for. It is not worthless, you can then still access your gui and do other things while it is loading thanks to nonblocking flag. Even winamp displays a ‘buffering’ message, that’s the same as this. You get the chance to display a buffering message (and even the amount buffered), rather than just hang the app. This is what the netstream example does.[/quote:3gt3f1ah]

I must be going crazy because I am getting a channel on a streamed sound that is not ready… It’s IsPlaying returns FALSE but I have a pointer.

I add the sound
I instanciate it.
I have a channel and it start to play (10-20 seconds later in some case). Even if SetUserData failed on the sound, I GOT a channel.

I said 80% worthless TO ME… I played with the 20% that was useful TO ME and I now have a proper implementation. I went with the plan I told you about.

And yes, now I can display information related to streaming and it is very useful.

The point I was making, which you missed, from what I can tell, is that FMOD’s design should have made the process seamless to it’s user… Without negating the fact that the information is useful and can be used at a lower level for finer control.

The point is that if I make a game or application and I decide, 2 days before the release to make my sounds non blocking, the original code should work.

Who cares if the sound is not yet a real sound, when it becomes real, it could apply the settings I set it to (while it was not real) like a normal sound. I mean you have to admit it’s not a bad idea. I do that myself using data that I have added to the sound using SetUserData.

Same deal with a channel, creating a channel with a web streamed "not ready sound" and setting it up should be part of normal operations.

Man, it was just a minor suggestion. It was not made to offend you.

I added 3 functions to my interface

sound = FMODSoundAddAsyncStream(url)
ready = FMODSoundAsyncReady(sound)
ok = FMODInstanceAsyncOK(instance)

so now I can deffer the setting up of the sound until it’s ready (my main beef)

So instead of
[code:3gt3f1ah]
sound = FMODSoundAdd(url);
FMODSoundSetMinMaxRange(sound,100,500);
instance = FMODSoundPlay(sound)
[/code:3gt3f1ah]

I use
[code:3gt3f1ah]
sound = FMODSoundAddAsyncStream(url);
instance = 0;
white(1)
{
if(instance == 0)
{
FMODSoundAsyncReady(sound);
if(FMODGetLastError() == FMOD_OK)
{
FMODSoundSetMinMaxRange(sound,100,500);
instance = FMODSoundPlay(sound);
}
}
else
{
if(!FMODInstanceAsyncOK(instance))
{
if(FMODGetLastError() != FMOD_OK)
{
FMODInstanceStop(instance);
FMODSoundFree(sound);
exit(0);
}
FMODInstanceSetMute(instance, true);
}
else
{
FMODInstanceSetMute(instance, false);
}
}
FMODUpdate()
Sleep (16)
}
[/code:3gt3f1ah]

Anyway, I have a solution so thanks.

  • You must to post comments
0
0

OK, I think I have isolated the circumstance of my application hanging using the netstream demo…

I also fixed the demo so it works… Turns out the SetMute was outside the if(channel) condition…

I moved the setmute in the if condition and moved the get open state above the if condition…

You should fix the sample on your side.

[code:3vitnfam]
/*===============================================================================================
NetStream Example
Copyright (c), Firelight Technologies Pty, Ltd 2004-2008.

This example shows how to play streaming audio from the internet
===============================================================================================*/

include <windows.h>

include <stdio.h>

include <conio.h>

include "../../api/inc/fmod.h"

include "../../api/inc/fmod_errors.h"

void ERRCHECK(FMOD_RESULT result)
{
if (result != FMOD_OK)
{
printf("FMOD error! (%d) %s\n", result, FMOD_ErrorString(result));
exit(-1);
}
}

int main(int argc, char *argv[])
{
FMOD_SYSTEM *system;
FMOD_SOUND *sound;
FMOD_CHANNEL *channel = 0;
FMOD_RESULT result;
int key;
unsigned int version;

printf(&quot;===================================================================\n&quot;);
printf(&quot;NetStream Example.  Copyright (c) Firelight Technologies 2004-2008.\n&quot;);
printf(&quot;===================================================================\n\n&quot;);

/*if (argc &lt; 2)
{
    printf(&quot;Usage:   netstream &lt;url&gt;\n&quot;);
    printf(&quot;Example: netstream http://www.fmod.org/stream.mp3\n\n&quot;);
    return -1;
}

/
/

Create a System object and initialize.
*/
result = FMOD_System_Create(&system);
ERRCHECK(result);

result = FMOD_System_GetVersion(system,&amp;version);
ERRCHECK(result);

if (version &lt; FMOD_VERSION)
{
    printf(&quot;Error!  You are using an old version of FMOD %08x.  This program requires %08x\n&quot;, version, FMOD_VERSION);
    return 0;
}

result = FMOD_System_Init(system, 1, FMOD_INIT_NORMAL, 0);
ERRCHECK(result);

/*
    Bump up the file buffer size a little bit for netstreams (to account for lag).
*/
result = FMOD_System_SetStreamBufferSize(system, 64*1024, FMOD_TIMEUNIT_RAWBYTES);
ERRCHECK(result);

result = FMOD_System_CreateSound(system, &quot;http://64.72.118.114:8030&quot;, FMOD_HARDWARE | FMOD_2D | FMOD_CREATESTREAM | FMOD_NONBLOCKING,  0, &amp;sound);
ERRCHECK(result);

printf(&quot;Press space to pause, Esc to quit\n\n&quot;);

/*
    Main loop
*/
do
{
    unsigned int    ms = 0, percent = 0;
    int             playing = FALSE;
    int             paused = FALSE;
    int             starving = FALSE;
    FMOD_OPENSTATE  openstate;



    if (kbhit())
    {
        key = getch();

        switch (key)
        {
            case ' ' :
            {
                if (channel)
                {
                    int paused;
                    FMOD_Channel_GetPaused(channel, &amp;paused);
                    FMOD_Channel_SetPaused(channel, !paused);
                }
                break;
            }
            case 's' :
            {
                if (channel)
                {
                    int paused;
                    FMOD_Channel_Stop(channel);
                    channel = 0;
                }
                break;
            }
            case 'p' :
            {
                if (!channel)
                {
                    result = FMOD_System_PlaySound(system, FMOD_CHANNEL_FREE, sound, FALSE, &amp;channel);
                }
                break;
            }
       }
    }

    FMOD_System_Update(system);

    for (;;)
    {
        FMOD_TAG tag;
        if (FMOD_Sound_GetTag(sound, 0, -1, &amp;tag) != FMOD_OK)
        {
            break;
        }
        if (tag.datatype == FMOD_TAGDATATYPE_STRING)
        {
            printf(&quot;%s = %s (%d bytes)       \n&quot;, tag.name, tag.data, tag.datalen);
        }
    }
    result = FMOD_Sound_GetOpenState(sound, &amp;openstate, &amp;percent, &amp;starving);
    ERRCHECK(result);
    if (openstate != FMOD_OPENSTATE_READY)
    {
        printf(&quot;Open State: %d\n&quot;,openstate);
    }

printf("Open State: %d\n",openstate);
if (channel)
{
result = FMOD_Channel_GetPaused(channel, &paused);
ERRCHECK(result);
result = FMOD_Channel_IsPlaying(channel, &playing);
ERRCHECK(result);
result = FMOD_Channel_GetPosition(channel, &ms, FMOD_TIMEUNIT_MS);
ERRCHECK(result);
result = FMOD_Channel_SetMute(channel, starving);
ERRCHECK(result);
if (starving)
{
printf("Handling Starving \n");
}
}

    printf(&quot;Time %02d:%02d:%02d : %s : (%3d%%%) %s     \r&quot;, ms / 1000 / 60, ms / 1000 % 60, ms / 10 % 100, openstate == FMOD_OPENSTATE_BUFFERING ? &quot;Buffering...&quot; : openstate == FMOD_OPENSTATE_CONNECTING ? &quot;Connecting...&quot; : paused ? &quot;Paused       &quot; : playing ? &quot;Playing      &quot; : &quot;Stopped      &quot;, percent, starving ? &quot;STARVING&quot; : &quot;        &quot;);

    Sleep(10);

} while (key != 27);

printf(&quot;\n&quot;);

printf(&quot;Shutting down.\n&quot;);

/*
    If we pressed escape before it is ready, wait for it to finish opening before we release it.
*/
do
{
    FMOD_OPENSTATE openstate;

    result = FMOD_Sound_GetOpenState(sound, &amp;openstate, 0, 0);
    ERRCHECK(result);

    if (openstate == FMOD_OPENSTATE_READY)
    {
        break;
    }

    printf(&quot;State %d: Waiting for sound to finish opening before trying to release it....\r&quot;,openstate);

    Sleep(10);
} while (1);

/*
    Shut down
*/
result = FMOD_Sound_Release(sound);
ERRCHECK(result);
result = FMOD_System_Close(system);
ERRCHECK(result);
result = FMOD_System_Release(system);
ERRCHECK(result);

return 0;

}
[/code:3vitnfam]

OK you start the demo

You press p to start the channel

Now stop your internet connection

You see, get open state returns FMOD_OK with FMOD_OPENSTATE_STREAMING

It looks like there is no timeout (I waited 5 minutes).

now press escape

in the exit now, waiting… OK, fine re-establish the internet connection
Still nothing…

Even if you have a
FMOD_System_Update(system);
in the wait to free loop, you are stuck.

OK… Terminate the app and restart.

press p
disable your internet connection
starving… FMOD_OK, FMOD_OPENSTATE_STREAMING
enable the internet connection

The sound continues
ESC
It quits. Fine that is normal

So, my problem is having users quit the application while a sound is starved and suck on streaming. The application deadlocks when he quits because that is when I free the sounds… And I added that wait to be free code in there….

Quick question… Can I have multiple channels playing the same net stream?

  • You must to post comments
0
0

Thanks I modified the netstream example to check for channel being valid as well.

One extra thing I did was simply put this extra code in.

[code:39bf2v52]
printf("Shutting down.\n");

if (channel)
{
    result = channel-&gt;stop();
    ERRCHECK(result);
}

[/code:39bf2v52]

The stream simply needs to be stopped. This cancels file reads, and makes openstate say it is finished within a very short time.

You can then release the sound without it stalling at all.

  • You must to post comments
Showing 10 results
Your Answer

Please first to submit.