void KX_SoundActuator::play()
{
	if (m_handle) {
		AUD_Handle_stop(m_handle);
		m_handle = NULL;
	}

	if (!m_sound)
		return;

	// this is the sound that will be played and not deleted afterwards
	AUD_Sound* sound = m_sound;

	bool loop = false;

	switch (m_type)
	{
	case KX_SOUNDACT_LOOPBIDIRECTIONAL:
	case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
		sound = AUD_Sound_pingpong(sound);
		ATTR_FALLTHROUGH;
	case KX_SOUNDACT_LOOPEND:
	case KX_SOUNDACT_LOOPSTOP:
		loop = true;
		break;
	case KX_SOUNDACT_PLAYSTOP:
	case KX_SOUNDACT_PLAYEND:
	default:
		break;
	}

	AUD_Device* device = AUD_Device_getCurrent();
	m_handle = AUD_Device_play(device, sound, false);
	AUD_Device_free(device);

	// in case of pingpong, we have to free the sound
	if (sound != m_sound)
		AUD_Sound_free(sound);

	if (m_handle != NULL) {
		if (m_is3d) {
			AUD_Handle_setRelative(m_handle, true);
			AUD_Handle_setVolumeMaximum(m_handle, m_3d.max_gain);
			AUD_Handle_setVolumeMinimum(m_handle, m_3d.min_gain);
			AUD_Handle_setDistanceReference(m_handle, m_3d.reference_distance);
			AUD_Handle_setDistanceMaximum(m_handle, m_3d.max_distance);
			AUD_Handle_setAttenuation(m_handle, m_3d.rolloff_factor);
			AUD_Handle_setConeAngleInner(m_handle, m_3d.cone_inner_angle);
			AUD_Handle_setConeAngleOuter(m_handle, m_3d.cone_outer_angle);
			AUD_Handle_setConeVolumeOuter(m_handle, m_3d.cone_outer_gain);
		}

		if (loop)
			AUD_Handle_setLoopCount(m_handle, -1);
		AUD_Handle_setPitch(m_handle, m_pitch);
		AUD_Handle_setVolume(m_handle, m_volume);
	}

	m_isplaying = true;
}
Example #2
0
bool KX_SoundActuator::Update(double curtime, bool frame)
{
	if (!frame)
		return true;
	bool result = false;

#ifdef WITH_AUDASPACE
	// do nothing on negative events, otherwise sounds are played twice!
	bool bNegativeEvent = IsNegativeEvent();
	bool bPositiveEvent = m_posevent;
#endif  // WITH_AUDASPACE
	
	RemoveAllEvents();

#ifdef WITH_AUDASPACE
	if (!m_sound)
		return false;

	// actual audio device playing state
	bool isplaying = m_handle ? (AUD_Handle_getStatus(m_handle) == AUD_STATUS_PLAYING) : false;

	if (bNegativeEvent)
	{
		// here must be a check if it is still playing
		if (m_isplaying && isplaying)
		{
			switch (m_type)
			{
			case KX_SOUNDACT_PLAYSTOP:
			case KX_SOUNDACT_LOOPSTOP:
			case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
				{
					// stop immediately
					if (m_handle)
					{
						AUD_Handle_stop(m_handle);
						m_handle = NULL;
					}
					break;
				}
			case KX_SOUNDACT_PLAYEND:
				{
					// do nothing, sound will stop anyway when it's finished
					break;
				}
			case KX_SOUNDACT_LOOPEND:
			case KX_SOUNDACT_LOOPBIDIRECTIONAL:
				{
					// stop the looping so that the sound stops when it finished
					if (m_handle)
						AUD_Handle_setLoopCount(m_handle, 0);
					break;
				}
			default:
				// implement me !!
				break;
			}
		}
		// remember that we tried to stop the actuator
		m_isplaying = false;
	}
	
#if 1
	// Warning: when de-activating the actuator, after a single negative event this runs again with...
	// m_posevent==false && m_posevent==false, in this case IsNegativeEvent() returns false 
	// and assumes this is a positive event.
	// check that we actually have a positive event so as not to play sounds when being disabled.
	else if (bPositiveEvent)  /* <- added since 2.49 */
#else
	else	// <- works in most cases except a loop-end sound will never stop unless
			// the negative pulse is done continuesly
#endif
	{
		if (!m_isplaying)
			play();
	}
	// verify that the sound is still playing
	isplaying = m_handle ? (AUD_Handle_getStatus(m_handle) == AUD_STATUS_PLAYING) : false;

	if (isplaying)
	{
		if (m_is3d)
		{
			KX_Camera* cam = KX_GetActiveScene()->GetActiveCamera();
			if (cam)
			{
				KX_GameObject* obj = (KX_GameObject*)this->GetParent();
				MT_Vector3 p;
				MT_Matrix3x3 Mo;
				float data[4];

				Mo = cam->NodeGetWorldOrientation().inverse();
				p = (obj->NodeGetWorldPosition() - cam->NodeGetWorldPosition());
				p = Mo * p;
				p.getValue(data);
				AUD_Handle_setLocation(m_handle, data);
				p = (obj->GetLinearVelocity() - cam->GetLinearVelocity());
				p = Mo * p;
				p.getValue(data);
				AUD_Handle_setVelocity(m_handle, data);
				(Mo * obj->NodeGetWorldOrientation()).getRotation().getValue(data);
				AUD_Handle_setOrientation(m_handle, data);
			}
		}
		result = true;
	}
	else
	{
		m_isplaying = false;
		result = false;
	}
#endif  // WITH_AUDASPACE

	return result;
}