Re: 5.4 C++ Play sound

#11
Here is the sample component that will allow you to play sdl mixer sound by its name.

EntityAudioComponent.h

Code: Select all

#pragma once

#include <CryAudio/IAudioInterfacesCommonData.h>
#include <CrySerialization/Forward.h>
#include <CrySchematyc/Reflection/TypeDesc.h>
#include <CrySchematyc/Env/IEnvRegistrar.h>
#include <CryString/CryString.h>

struct SEntityAudioComponent final : public IEntityComponent
{
public:
SEntityAudioComponent::SEntityAudioComponent(){}
virtual ~SEntityAudioComponent() {}
virtual void Initialize() override;
inline void ReflectType(Schematyc::CTypeDesc<SEntityAudioComponent>& desc)
{
desc.SetGUID("{924B2A79-B026-4592-B215-1CBFB1BC8169}"_cry_guid);
}
void PlayByName(string sSoundName);
void StopByName(string sSoundName);
IEntityAudioComponent *pAudioComponent = nullptr;
CryAudio::AuxObjectId auxObjectId = CryAudio::InvalidAuxObjectId;
};
EntityAudioComponent.cpp

Code: Select all

#include "StdAfx.h"
#include "EntityAudioComponent.h"

void SEntityAudioComponent::Initialize()
{
pAudioComponent = m_pEntity->CreateComponent<IEntityAudioComponent>();
CRY_ASSERT(auxObjectId == CryAudio::InvalidAuxObjectId);
auxObjectId = CryAudio::DefaultAuxObjectId;
}

void SEntityAudioComponent::PlayByName(string sSoundName)
{
CryAudio::ControlId audioControlId = CryAudio::StringToId(sSoundName);
if (pAudioComponent != nullptr && audioControlId != CryAudio::InvalidControlId)
{
CryAudio::SRequestUserData const userData(CryAudio::ERequestFlags::DoneCallbackOnExternalThread | CryAudio::ERequestFlags::DoneCallbackOnExternalThread, this);
pAudioComponent->ExecuteTrigger(audioControlId, auxObjectId, userData);
}
}

void SEntityAudioComponent::StopByName(string sSoundName)
{
CryAudio::ControlId audioControlId = CryAudio::StringToId(sSoundName);
if (pAudioComponent != nullptr && audioControlId != CryAudio::InvalidControlId)
{
CryAudio::SRequestUserData const userData(CryAudio::ERequestFlags::DoneCallbackOnExternalThread | CryAudio::ERequestFlags::DoneCallbackOnExternalThread, this);
pAudioComponent->StopTrigger(audioControlId, auxObjectId, userData);
}
}
Cryengine tutorial videos on my Youtube channel! Check it out !
https://www.youtube.com/user/MusicForLifePL20

Re: 5.4 C++ Play sound

#12
Oh, at the moment I just want to play a sound when a press a button, either from a file or one created with the Audio Controls Editor. I thought I can use an engine function for that,

1. Last few times tried with the ISO template c++ (will the solution be different if I use the FP or TP template?!)
2. until yesterday I even really didn't know what a middleware is. But since I use the sound from the bullet the comes with the templates, it should be sdl_mixer. Have to look more on this topic, interesting!
3. Yes, I try this with c++
4. Cry::Audio::DefaultComponents::CTriggerComponent

Thanks for fast reply
Charalampos :-)
Hi,
1. No, the solution is the same, it just gives me a better understanding of the available data set.
2. That's great, yes CRYENGINE currently and officially supports those three audio middlewares. The code/level design work is independent of the underlying audio middleware being used.
3. Got ya
4. That component is not meant to be used from code but Schematyc rather.

Depending on what you want to achieve I recommend to keep things simple at first and use audio triggers created in the ACE as it offers the greater flexibility down the road. If you just want to execute an audio trigger use this code (a bit pseudo and untested so take it with caution). For below examples I'm assuming an audio trigger named explosion exists and some sound file is connected to it that plays at least in the ACE.

For 2D sounds/events use following example.
Note: If a trigger executed via below code starts 3D sounds/events then those will play regardless but positioned at world coordinates 0,0,0 as a position cannot be provided during the call. However, if one wants to verify if the sounds/events at least play they would have to place the listener at or near the world coordinates 0,0,0 depending on designed falloff of spawned sounds/events. For properly handling 3D sounds/events take a look at the second example.

Code: Select all

// for performance reasons cache the data inside the "cachethis" block during initialization
// cachethis
CryAudio::ControlId const id = CryAudio::StringToId("explosion");
// ~cachethis

if (myEventHappened && !myEventHandled)
{
gEnv->pAudioSystem->ExecuteTrigger(id);
myEventHandled = true;
}
else if (!myEventHappened)
{
// if the sound/event requires manual stopping call this (stops all instances of the sounds/events spawned by the trigger)
gEnv->pAudioSystem->StopTrigger(id);
myEventHandled = false;
}
For 3D sounds/events use following example.
Note1: Below code can only be used in fire-and-forget type scenarios! Sounds/events played via this approach that require manual stopping need to be handled differently.

Note2: If a trigger executed via below code starts 2D sounds/events then those will play regardless. Just be aware of that being a waste of resources and a misuse of an otherwise 3D specific pipeline. For properly handling 2D sounds/events take a look at the first example.

Code: Select all

// for performance reasons cache the data inside the "cachethis" block during initialization (only if the SExecuteTriggerData doesn't need to change between trigger executions)
// cachethis
char const* const szControlName = "explosion";
CryAudio::ControlId const id = CryAudio::StringToId(szControlName);
Vec3 const position(ZERO); // position properly if the sound needs to play at a given position in the world
CryAudio::SExecuteTriggerData const data(id, szControlName, CryAudio::EOcclusionType::Ignore, position, INVALID_ENTITYID, true);
// ~cachethis

if (myEventHappened && !myEventHandled)
{
gEnv->pAudioSystem->ExecuteTriggerEx(data);
myEventHandled = true;
}
else if (!myEventHappened)
{
myEventHandled = false;
}
These are the most simple ways of executing 2D/3D type audio triggers via C++ code. The other two ways include doing that via explicitly retrieving an audio object and doing it on an IEntity via retrieving the audio component (not the one you mentioned as that's purely Schematyc and with that controlled via UI) which then also allows handling of Sounds/Events that require manual stopping.
Let me know if you need anything else.

Re: 5.4 C++ Play sound

#13
Wow, a lot of infos. Unfortunatelly I don't have much time today to test everything.

One thing I've tested and have partial success is the 2D solution from cry-thomas. When I start the game (debug from VS2017 or launch the game with right mouse on "Game.cryproject") and I press the key (I bound a small funtion to key 'T') than I get the sound. When I once move the player, I don't hear anything any more.

Strange, this is similar to something that happens all the time but I thought it is not important for now: I've created a new project, iso template with c++. When I start tha game and press the spacebar BEFORE I move the player, then I hear nothing. When I move the player just a little then it works as it should. I have to test with other templates or a new Iso to try reproduce this or see if it is just on my current project.

Have tried to use the EntityAudioComponent but I have to find the correct way. I will try it tomorrow again.

Anyway, thanks both for helping!
Charalampos :-)

Re: 5.4 C++ Play sound

#15
EntityAudioComponent I proposed is not one of Crytek's default components. It's based on it, but not the same. So check that out definitely.
Finally I've found a little time to look at that. But how to implement this? I've tried to define and declare similar I do it with the Crytek's default components but I get some "null" errors.

For example, I want to play a sound when I press a key.
I define in my player.h:

Code: Select all

SEntityAudioComponent* m_pAudioComponent = nullptr;
In the Initialize() of the player.cpp I put one, both or none of these (tried all combinations):

Code: Select all

m_pAudioComponent = m_pEntity->GetOrCreateComponent<SEntityAudioComponent>(); m_pAudioComponent->Initialize();
And I bind a small funktion PlaySound() to a key, say 'r':

Code: Select all

void CPlayerComponent::PlaySound() { m_pAudioComponent->PlayByName("bullet_impact"); }
Is this the right way or I understand something wrong? Maybe a small hint will help.

Thanks anyway for you help. Not only here, for your nice tutorials and so on as well!
Charalampos :-)

Re: 5.4 C++ Play sound

#16
What if you try just this?

Code: Select all

void CPlayerComponent::PlaySound()
{
static constexpr char* szControlName = "bullet_impact";
static constexpr char* szAudioObjectName = "AudioObjectNameUsedForDebuggingAndProfilingWhichIsOmittedInReleaseBuilds";
CryAudio::ControlId const id = CryAudio::StringToId(szControlName );
Vec3 const position(ZERO); // position the sound where you want it to play in the world
CryAudio::SExecuteTriggerData const data(id, szAudioObjectName , CryAudio::EOcclusionType::Ignore, position, INVALID_ENTITYID, true);
gEnv->pAudioSystem->ExecuteTriggerEx(data);
}
Last edited by cry-thomas on Fri Jan 19, 2018 7:41 am, edited 1 time in total.

Re: 5.4 C++ Play sound

#17
What if you try just this?

Code: Select all

void CPlayerComponent::PlaySound()
{
static constexpr char* szControlName = "bullet_impact";
CryAudio::ControlId const id = CryAudio::StringToId(szControlName );
Vec3 const position(ZERO); // position the sound where you want it to play in the world
CryAudio::SExecuteTriggerData const data(id, szControlName, CryAudio::EOcclusionType::Ignore, position, INVALID_ENTITYID, true);
gEnv->pAudioSystem->ExecuteTriggerEx(data);
}
Of course I've found time to try your solution as well! But when I've started to write a comment about, I've got a phone call. So a little bit late but here I am ;-)

It works both. The 2D solution is ok just for testing as you mention.
The 3D works fine and with a small trick, it is always hearable if someone want it. I just bind the position to entity's position!
And I have to change the order of the parameters (name, occlusionType, transformation, SetCurrentEnvironments, control_id).

Code: Select all

CryAudio::ControlId const id = CryAudio::StringToId("explosion"); CryAudio::SExecuteTriggerData data("boom", CryAudio::EOcclusionType::Ignore, m_pEntity->GetPos(), true, id); gEnv->pAudioSystem->ExecuteTriggerEx(data);
But I am still curious about the component solution from fury22uk *g

Thank you
Charalampos :-)

Re: 5.4 C++ Play sound

#19
The reason why your components get null is because u used wrong method to attach them to your entity. You used GetOrCreateComponent. This method only works with cryteks components. With your custom component you go GetOrCreateComponentClass
Once again, I've learned something new. It works!

Cheers
Charalampos :-)

Re: 5.4 C++ Play sound

#20
The reason why your components get null is because u used wrong method to attach them to your entity. You used GetOrCreateComponent. This method only works with cryteks components. With your custom component you go GetOrCreateComponentClass
As I understand, GetOrCreateComponent works, if you register your component for editor like this (and not only with CryTek's standard components):

Code: Select all

static void RegisterYourComponent(Schematyc::IEnvRegistrar& registrar)
{
Schematyc::CEnvRegistrationScope scope = registrar.Scope(IEntity::GetEntityScopeGUID());
{
Schematyc::CEnvRegistrationScope componentScope = scope.Register(SCHEMATYC_MAKE_ENV_COMPONENT(YourComponent));
// Functions
{
}
}
}

CRY_STATIC_AUTO_REGISTER_FUNCTION(&RegisterYourComponent);
Without doing this, you can attach your component only via GetOrCreateComponentClass.

Who is online

Users browsing this forum: No registered users and 1 guest