// Copyright (C) 2012-2015 ChaosForge Ltd // http://chaosforge.org/ // // This file is part of Nova libraries. // For conditions of distribution and use, see copying.txt file in root folder. #include "nv/fmod/fmod_audio.hh" #include "nv/lib/fmod.hh" #include "nv/core/logging.hh" using namespace nv; fmod::audio::audio() { m_system = nullptr; nv::load_fmod_library(); FMOD_RESULT result; FMOD_SYSTEM* system; result = FMOD_System_Create( &system ); if ( result != FMOD_OK ) { NV_LOG_CRITICAL( "Failed to create FMOD System -- ", FMOD_ErrorString( result ) ); return; } result = FMOD_System_Init( system, 64, FMOD_3D | FMOD_INIT_3D_RIGHTHANDED, 0 ); if ( result != FMOD_OK ) { NV_LOG_ERROR( "Failed to initialize FMOD System -- ", FMOD_ErrorString( result ) ); return; } m_system = system; } nv::channel nv::fmod::audio::play_sound( sound a_sound, float volume, float pan /*= 0.0f */ ) { sound_info* info = m_sounds.get( a_sound ); if ( info ) { FMOD_SYSTEM* system = static_cast( m_system ); FMOD_SOUND* sample = static_cast( info->fmod_sound ); FMOD_CHANNEL* channel = nullptr; FMOD_RESULT result = FMOD_System_PlaySound( system, FMOD_CHANNEL_FREE, sample, true, &channel ); if ( result != FMOD_OK ) { NV_LOG_WARNING( "FMOD failed to play sound -- ", FMOD_ErrorString( result ) ); } else { FMOD_Channel_SetVolume( channel, volume ); FMOD_Channel_SetPan( channel, pan ); FMOD_Channel_SetPaused( channel, false ); } } return channel(); } nv::channel nv::fmod::audio::play_sound( sound a_sound, vec3 position ) { sound_info* info = m_sounds.get( a_sound ); if ( info ) { FMOD_SYSTEM* system = static_cast( m_system ); FMOD_SOUND* sample = static_cast( info->fmod_sound ); FMOD_CHANNEL* channel = nullptr; FMOD_RESULT result = FMOD_System_PlaySound( system, FMOD_CHANNEL_FREE, sample, true, &channel ); if ( result != FMOD_OK ) { NV_LOG_WARNING( "FMOD failed to play sound -- ", FMOD_ErrorString( result ) ); } else { FMOD_VECTOR fmod_position; fmod_position.x = position.x; fmod_position.y = position.y; fmod_position.z = position.z; FMOD_Channel_Set3DMinMaxDistance( channel, 1, 100000 ); FMOD_Channel_Set3DAttributes( channel, &fmod_position, 0 ); FMOD_Channel_SetPaused( channel, false ); } } return channel(); } nv::sound fmod::audio::load_sound( const string_view& a_path ) { FMOD_SYSTEM* system = static_cast( m_system ); FMOD_SOUND* sample; FMOD_RESULT fm_result = FMOD_System_CreateSound( system, a_path.data(), FMOD_3D, 0, &sample ); if ( fm_result != FMOD_OK ) { NV_LOG_ERROR( "FMOD failed to load sample '", a_path, "' -- ", FMOD_ErrorString( fm_result ) ); return sound(); } sound result = m_sounds.create(); sound_info* info = m_sounds.get( result ); info->fmod_sound = sample; return result; } void nv::fmod::audio::release( sound a_sound ) { sound_info* info = m_sounds.get( a_sound ); release( info ); m_sounds.destroy( a_sound ); } void nv::fmod::audio::release( sound_info* info ) { if ( info ) FMOD_Sound_Release( static_cast( info->fmod_sound ) ); } void nv::fmod::audio::set_orientation( vec3 forward, vec3 up ) { FMOD_VECTOR fmod_forward; fmod_forward.x = forward.x; fmod_forward.y = forward.y; fmod_forward.z = forward.z; FMOD_VECTOR fmod_up; fmod_up.x = up.x; fmod_up.y = up.y; fmod_up.z = up.z; // TODO: we also need to setup orientation! FMOD_System_Set3DListenerAttributes( static_cast( m_system ), 0, 0, 0, &fmod_forward, &fmod_up ); } void fmod::audio::update( vec3 position ) { m_position = position; FMOD_VECTOR fmod_position; fmod_position.x = position.x; fmod_position.y = position.y; fmod_position.z = position.z; // FMOD_VECTOR fmod_up; // fmod_up.x = 0.0f; // fmod_up.y = 0.0f; // fmod_up.z = 0.0f; // TODO: we also need to setup orientation! FMOD_System_Set3DListenerAttributes( static_cast( m_system ), 0, &fmod_position, 0, 0, 0 ); FMOD_System_Update( static_cast( m_system ) ); } fmod::audio::~audio() { for ( auto& s : m_sounds ) release( &s ); m_sounds.clear(); FMOD_System_Release( static_cast( m_system ) ); }