Streaming internet radio (UE4)

,

Hi,

I need your help. I’m trying to get radio stream working with FMOD 2.01.07 on UE4.25+, based on the examples I found on the internet, but it’s not working. I might be doing something wrong, I don’t know what.

So here’s basically what I’m doing:

  • I set an event with ProgrammerInstrument in FMOD Studio and assigned it to UFMODRadioComponent in UE4.
  • UFMODRadioComponent inherits from UFMODAudioComponent
  • At BeginPlay I’m creating a stream and assign it to ProgrammingSound in the component.

Sidenote: I was following the API docummentation but there was it said about ProgrammerSound in FMODStudio and not ProgrammerInstrument. If I have to make “ProgrammerSound” and not “ProgrammerInstrument”, then I’m not able to make a “ProgrammerSound” in FMODStudio.
Also, stream is working properly in the browser.

I’m working on FMOD 2.01.07, UE4.25+

Here’s what I do:

void UFMODRadioComponent::BeginPlay()
{
	Super::BeginPlay();
	FMOD::Studio::System* System = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime);
	FMOD::System* CoreSystem = nullptr;
	System->getCoreSystem(&CoreSystem);

	// Create sound in memory
	static const int EXAMPLE_SOUND_LEN = 4096;
	float ExampleData[EXAMPLE_SOUND_LEN];
	for (int i = 0; i < EXAMPLE_SOUND_LEN; ++i)
	{
		ExampleData[i] = FMath::Sin((float) i);
	}

	FMOD_CREATESOUNDEXINFO SoundInfo = {0};
	SoundInfo.cbsize = sizeof(SoundInfo);
	SoundInfo.filebuffersize = 1024 * 16;

	FMOD_RESULT Result =
		CoreSystem->createStream("http://144.217.158.59:5120/stream", FMOD_LOOP_NORMAL | FMOD_NONBLOCKING | FMOD_CREATESTREAM, &SoundInfo, &StreamSound); //
	
	if (Result == FMOD_OK)
	{
		this->SetProgrammerSound(StreamSound);
	}
}
//It is called in blueprints.
void UFMODRadioComponent::ToggleRadio()
{
	if (this->IsPlaying())
	{
		this->Stop();
	}
	else
	{
		this->Play();
	}
}

Are you getting any errors or warnings in the console?
If not, you could try changing the logging level to ‘LOG’ and see if any more useful info gets printed.

Hi, thanks for the reply.

First of all, I forgot to put FMOD::Sound* StreamSound = nullptr; before calling createStream method, but it wasn’t the problem.

There are no logs being printed, no warnings, no errors.
I checked if the createStream is being called and yes, it is (I’m debugging it in Visual Studio and the result is FMOD_OK).
It’s not a problem with sound output, because other events are being played correctly.
I have no ideas what else to do, I’m now trying different approach.

PS
The programmer sound works by createSound.
I found out that I don’t have to use this chunk, because it is being used in the programmer sound example:
// Create sound in memory
static const int EXAMPLE_SOUND_LEN = 4096;
float ExampleData[EXAMPLE_SOUND_LEN];
for (int i = 0; i < EXAMPLE_SOUND_LEN; ++i)
{
ExampleData[i] = FMath::Sin((float) i);
}

I’m not sure if it helps, but when I removed FMOD_NONBLOCKING flag, there was a warning in log output:
LogFMOD: Warning: Failed to find FMOD audio entry ‘Radio’

(‘Radio’ is the name of the Programmer Instrument in the Radio event in FMOD.)

Apologies for the delay.

The string ‘Radio’ mentioned in the log should be the name of the sound you want to play from the audio table. If the integration cannot get a good result from Studio::System::getSoundInfo or System::createSound using the ProgrammerSoundName provided then you will get the error you see.

It’s still not the place where it doesn’t work and I still don’t know what I’m doing wrong.
Here’s the full code of my class:
FMODRadio.h:

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "FMODRadio.generated.h"

namespace FMOD
{
    class System;
    class Sound;
    namespace Studio
    {
        class System;
    }
}

class UFMODAudioComponent;

UCLASS()
class TEST425_API AFMODRadio : public AActor
{
    GENERATED_BODY()

public:
    UPROPERTY(EditAnywhere, BlueprintReadWrite)
        UFMODAudioComponent* AudioComp;

protected:
    virtual void BeginPlay() override;
};

FMODRadio.cpp:

#include "FMODRadio.h"

#include "fmod_common.h"
#include "fmod.hpp"
#include "fmod_studio.hpp"
#include "FMODStudioModule.h"
#include "FMODAudioComponent.h"

void AFMODRadio::BeginPlay()
{
    Super::BeginPlay();
    FMOD::Studio::System* System = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime);
    FMOD::System* CoreSystem = nullptr;
    FMOD::Sound* Sound = nullptr;
    System->getCoreSystem(&CoreSystem);

    FMOD_CREATESOUNDEXINFO SoundInfo = { 0 };
    SoundInfo.cbsize = sizeof(SoundInfo);
    SoundInfo.format = FMOD_SOUND_FORMAT_PCMFLOAT;
    SoundInfo.filebuffersize = 1024 * 16;
    SoundInfo.defaultfrequency = 48000;
    SoundInfo.numchannels = 2;

    this->AudioComp->SetProgrammerSoundName("Radio");

    if(CoreSystem->createStream("http://live-radio01.mediahubaustralia.com/2TJW/mp3/", FMOD_CREATESTREAM | FMOD_NONBLOCKING, &SoundInfo, &Sound) == FMOD_OK)
    {
        this->AudioComp->SetProgrammerSound(Sound);
        UE_LOG(LogTemp, Warning, TEXT("Did it.")); //To check if stream creation worked.
    }
    this->AudioComp->Play();
}

Here’s how my FMOD Event looks like:

These are two different ways of doing a similar thing.

When the CreateProgrammerSound callback is triggered, the programmerSound is checked first in the FMODAudioComponent, if this is not null then the Event will use the created sound that has been passed in using SetProgrammerSound.

Otherwise there are two options that can occur from the string passed in from SetProgrammerSoundName.

  1. If the string is a filename then FMOD will attempt to load the file.
    If that fails you will get error “Failed to load programmer sound file…”.

  2. FMOD will attempt to lookup the string in an audio table.
    If that fails you will get error “Failed to load FMOD audio entry…”.

If createStram is failing then it would be worth checking the error code returned.

If you haven’t already, you can change the logging level in the FMOD Plugin settings to LOG to get a lot more detail.

Thanks for the reply.

I changed the logging level and that’s what is appearing in the outputlog when creating the stream and trying to play the FMODAudioComponent:

LogFMOD: e:\jk\workspace\2.1_UE4.25+_Win64\core_api\src\fmod_systemi.cpp(3970) - filename = http://live-radio01.mediahubaustralia.com/2TJW/mp3/ : mode 00010080
LogFMOD: e:\jk\workspace\2.1_UE4.25+_Win64\core_api\src\fmod_systemi.cpp(3974) - FMOD_NONBLOCKING specified.  Putting into queue to be opened asynchronously!
LogFMOD: e:\jk\workspace\2.1_UE4.25+_Win64\core_api\src\fmod_thread.cpp(209) - Init FMOD nonblocking thread (0). Affinity: 0x8000000000000003, Priority: 0xFFFF7FFC, Stack Size: 114688, Semaphore: Yes, Sleep Time: 0, Looping: Yes.
LogFMOD: e:\jk\workspace\2.1_UE4.25+_Win64\core_api\src\fmod_systemi.cpp(4111) - setdata soundi = 00000245A4E8F748 : node = 00000245A5289960
LogFMOD: e:\jk\workspace\2.1_UE4.25+_Win64\core_api\src\fmod_systemi.cpp(4115) - add node to async list : head = 00000245A54098D8.  list count = 0
LogTemp: Warning: Did it. //In this place I checked if CreateStream resulted in FMOD_OK
LogFMOD: e:\jk\workspace\2.1_UE4.25+_Win64\core_api\src\fmod_async.cpp(191) - Starting Asynchronous operation on sound 00000245A4E8F748
LogFMOD: e:\jk\workspace\2.1_UE4.25+_Win64\core_api\src\fmod_systemi_sound.cpp(641) -     Create name='http://live-radio01.mediahubaustralia.com/2TJW/mp3/', mode=0x00010080
LogFMOD: e:\jk\workspace\2.1_UE4.25+_Win64\core_api\src\fmod_systemi_sound.cpp(647) -     exinfo->cbsize             = 224
LogFMOD: e:\jk\workspace\2.1_UE4.25+_Win64\core_api\src\fmod_async.cpp(336) - Finished Asynchronous operation on sound 00000245A4E8F748
PIE: Server logged in
PIE: Play in editor total start time 0,153 seconds.
LogFMOD: Warning: e:\jk\workspace\2.1_UE4.25+_Win64\studio_api\src\fmod_playback_instrument.cpp(1123) - Waveform instance in error state 18

It appears that this is being caused by the integration using the UE4 file system, which is trying to open the url as a regular file. I have created a task to investigate this further to see if there is anything we can do to avoid this.

To work around this you can set a property of the FMOD_CREATESOUNDEXINFO:

SoundInfo.ignoresetfilesystem = true;

Separately you will get an error message if you do not set the SoundInfo.suggestedsoundtype, to MPEG in this case.

Thanks for you patience and help in finding the issue.

Hi,

Thanks a lot! That worked. There’s an issue with delay, the stream being played at wrong time, and stream shutting down after a moment but it’s a different problem and I think I can work on it on my own.

Thanks again!

Ok, so it seems that the stream is working… but partially. It starts with the parameters you said, but it just stops after a few seconds. Do you want me to start another topic with describing this problem or should I wait for you to check the issue with streaming on UE4?

Make sure the programmer instrument is not set to async or use a loop region/sustain point to keep the instrument from being destroyed.

I checked and the programmer instrument is not set to async and doesn’t use loop region or sus point. It’s just empty instrument, even without placeholder sound.

I was testing different parameters in createStream method and found out that the stream starts even without any parameters. However, when I put FMOD_NONBLOCKING parameter, I have a short delay after starting playing the level and have this warning in the output:

LogFMOD: Warning: e:\jk\workspace\2.1_UE4.25+_Win64\studio_api\src\fmod_playback_instrument.cpp(1207) - Loading delay exceeded, sound may play at incorrect time

Aside from that, there’s just no info what’s going on. No info why the sound just stops after a few seconds.

LogFMOD: Warning: e:\jk\workspace\2.1_UE4.25+_Win64\studio_api\src\fmod_playback_instrument.cpp(1207) - Loading delay exceeded, sound may play at incorrect time

You are seeing this warning because you are creating a stream, which can take a lot longer to prepare than a sound, and immediately starting it. To get around this you would need to create the sound/stream manually ahead of time so that it has time to load and prepare for playing.

That is because the sound is ending naturally due to it being synchronous.

My apologies, I misspoke in my previous comment about async. The instrument needs to be set to async for the sound to play out entirely.

It seems that worked (nothing is stopping after a minute)! :smiley:
Thank you very much for your help!