/*
===========================================================================
ARX FATALIS GPL Source Code
Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see
.
In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "Athena_Track.h"
#define _CRTDBG_MAP_ALLOC
#include
namespace ATHENA
{
///////////////////////////////////////////////////////////////////////////////
// //
// Key setup //
// //
///////////////////////////////////////////////////////////////////////////////
ATHENAError Track::SetKeyStart(const SLong & k_id, const ULong & start)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
key_l[k_id].start = start;
return ATHENA_OK;
}
ATHENAError Track::SetKeyLoop(const SLong & k_id, const ULong & loop)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
key_l[k_id].loop = loop;
return ATHENA_OK;
}
ATHENAError Track::SetKeyDelay(const SLong & k_id, const ULong & min, const ULong & max)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
key_l[k_id].delay_min = min;
key_l[k_id].delay_max = max;
return ATHENA_OK;
}
ATHENAError Track::SetKeyVolume(const SLong & k_id, const ATHENAKeySetting & setting)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
TrackKey * key = &key_l[k_id];
key->volume.min = setting.min;
key->volume.max = setting.max;
key->volume.interval = setting.interval;
key->volume.flags = setting.flags;
if (flags & (IS_PLAYING | IS_PAUSED) && key_i == ULong(k_id))
{
SLong i_id(GetInstanceID(s_id));
key->volume.cur = (setting.min + setting.max) / 2.0F;
if (_inst.IsValid(i_id)) _inst[i_id]->SetVolume(key->volume.cur);
}
return ATHENA_OK;
}
ATHENAError Track::SetKeyPitch(const SLong & k_id, const ATHENAKeySetting & setting)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
TrackKey * key = &key_l[k_id];
key->pitch.min = setting.min;
key->pitch.max = setting.max;
key->pitch.interval = setting.interval;
key->pitch.flags = setting.flags;
if (flags & (IS_PLAYING | IS_PAUSED) && key_i == ULong(k_id))
{
SLong i_id(GetInstanceID(s_id));
key->pitch.cur = (setting.min + setting.max) / 2.0F;
if (_inst.IsValid(i_id)) _inst[i_id]->SetPitch(key->pitch.cur);
}
return ATHENA_OK;
}
ATHENAError Track::SetKeyPan(const SLong & k_id, const ATHENAKeySetting & setting)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
Track * track = &track_l[t_id];
TrackKey * key = &key_l[k_id];
key->pan.min = setting.min;
key->pan.max = setting.max;
key->pan.interval = setting.interval;
key->pan.flags = setting.flags;
if (flags & (IS_PLAYING | IS_PAUSED) && key_i == ULong(k_id))
{
SLong i_id(GetInstanceID(s_id));
key->pan.cur = (setting.min + setting.max) / 2.0F;
if (_inst.IsValid(i_id)) _inst[i_id]->SetPan(key->pan.cur);
}
return ATHENA_OK;
}
ATHENAError Track::SetKeyPositionX(const SLong & k_id, const ATHENAKeySetting & setting)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
TrackKey * key = &key_l[k_id];
key->x.min = setting.min;
key->x.max = setting.max;
key->x.interval = setting.interval;
key->x.flags = setting.flags;
if (flags & (IS_PLAYING | IS_PAUSED) && key_i == ULong(k_id))
{
SLong i_id(GetInstanceID(s_id));
if (_inst.IsValid(i_id))
{
ATHENAVector position;
_inst[i_id]->GetPosition(position);
position.x = key->x.cur = (setting.min + setting.max) / 2.0F;
_inst[i_id]->SetPosition(position);
}
}
return ATHENA_OK;
}
ATHENAError Track::SetKeyPositionY(const SLong & k_id, const ATHENAKeySetting & setting)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
Track * track = &track_l[t_id];
TrackKey * key = &key_l[k_id];
key->y.min = setting.min;
key->y.max = setting.max;
key->y.interval = setting.interval;
key->y.flags = setting.flags;
if (flags & (IS_PLAYING | IS_PAUSED) && key_i == ULong(k_id))
{
SLong i_id(GetInstanceID(s_id));
if (_inst.IsValid(i_id))
{
ATHENAVector position;
_inst[i_id]->GetPosition(position);
position.y = key->y.cur = (setting.min + setting.max) / 2.0F;
_inst[i_id]->SetPosition(position);
}
}
return ATHENA_OK;
}
ATHENAError Track::SetKeyPositionZ(const SLong & k_id, const ATHENAKeySetting & setting)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
TrackKey * key = &key_l[k_id];
key->z.min = setting.min;
key->z.max = setting.max;
key->z.interval = setting.interval;
key->z.flags = setting.flags;
if (flags & (IS_PLAYING | IS_PAUSED) && key_i == ULong(k_id))
{
SLong i_id(GetInstanceID(s_id));
if (_inst.IsValid(i_id))
{
ATHENAVector position;
_inst[i_id]->GetPosition(position);
position.z = key->z.cur = (setting.min + setting.max) / 2.0F;
_inst[i_id]->SetPosition(position);
}
}
return ATHENA_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Key status //
// //
///////////////////////////////////////////////////////////////////////////////
ATHENAError Track::GetKeyStart(const SLong & k_id, ULong & start)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
start = key_l[k_id].start;
return ATHENA_OK;
}
ATHENAError Track::GetKeyLoop(const SLong & k_id, ULong & loop)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
loop = key_l[k_id].loop;
return ATHENA_OK;
}
ATHENAError Track::GetKeyDelay(const SLong & k_id, ULong & min, ULong & max)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
TrackKey * key = &key_l[k_id];
min = key->delay_min;
max = key->delay_max;
return ATHENA_OK;
}
ATHENAError Track::GetKeyVolume(const SLong & k_id, ATHENAKeySetting & setting)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
TrackKey * key = &key_l[k_id];
setting.min = key->volume.min;
setting.max = key->volume.max;
setting.interval = key->volume.interval;
setting.flags = key->volume.flags;
return ATHENA_OK;
}
ATHENAError Track::GetKeyPitch(const SLong & k_id, ATHENAKeySetting & setting)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
TrackKey * key = &key_l[k_id];
setting.min = key->pitch.min;
setting.max = key->pitch.max;
setting.interval = key->pitch.interval;
setting.flags = key->pitch.flags;
return ATHENA_OK;
}
ATHENAError Track::GetKeyPan(const SLong & k_id, ATHENAKeySetting & setting)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
TrackKey * key = &key_l[k_id];
setting.min = key->pan.min;
setting.max = key->pan.max;
setting.interval = key->pan.interval;
setting.flags = key->pan.flags;
return ATHENA_OK;
}
ATHENAError Track::GetKeyPositionX(const SLong & k_id, ATHENAKeySetting & setting)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
TrackKey * key = &key_l[k_id];
setting.min = key->x.min;
setting.max = key->x.max;
setting.interval = key->x.interval;
setting.flags = key->x.flags;
return ATHENA_OK;
}
ATHENAError Track::GetKeyPositionY(const SLong & k_id, ATHENAKeySetting & setting)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
TrackKey * key = &key_l[k_id];
setting.min = key->y.min;
setting.max = key->y.max;
setting.interval = key->y.interval;
setting.flags = key->y.flags;
return ATHENA_OK;
}
ATHENAError Track::GetKeyPositionZ(const SLong & k_id, ATHENAKeySetting & setting)
{
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
TrackKey * key = &key_l[k_id];
setting.min = key->z.min;
setting.max = key->z.max;
setting.interval = key->z.interval;
setting.flags = key->z.flags;
return ATHENA_OK;
}
ATHENAError Track::GetKeyLength(const SLong & k_id, ULong & length)
{
Float f_lgt(0.0F);
SLong s_id;
Sample * sample;
if (ULong(k_id) >= key_c) return ATHENA_ERROR_HANDLE;
s_id = GetSampleID(s_id);
if (_sample.IsNotValid(s_id))
{
length = 0;
return ATHENA_OK;
}
sample = _sample[s_id];
TrackKey * key = &key_l[k_id];
if (key->pitch.interval)
{
Float min, max, cur;
Float size;
length = sample->length;
size = Float(length) * (key->loop + 1);
min = key->pitch.min * sample->format.frequency * key->pitch.interval * 0.001F;
max = key->pitch.max * sample->format.frequency * key->pitch.interval * 0.001F;
cur = max;
while (size > 0.0F)
{
f_lgt += key->pitch.interval;
size -= cur = cur == min ? max : min;
}
if (size < 0.0F) f_lgt += key->pitch.interval * (size / cur);
f_lgt *= 0.5F;
}
else
{
ULong size, loop;
sample->GetLength(size);
loop = (key->loop + 1) / 2;
f_lgt = (size * loop) * (1.0F / key->pitch.max);
loop = (key->loop + 1) - loop;
f_lgt += (size * loop) * (1.0F / key->pitch.min);
}
length = key->start + (key->loop + 1) * key->delay_max;
length += ULong(f_lgt);
return ATHENA_OK;
}
ATHENAError Track::GetKeyLoopLength(const SLong & k_id, const ULong & loop_i, ULong & length)
{
Float f_lgt(0.0F);
if (ULong(k_id) >= key_c || loop_i > key_l[k_id].loop) return ATHENA_ERROR_HANDLE;
SLong s_id(GetSampleID(s_id));
if (_sample.IsNotValid(s_id))
{
length = 0;
return ATHENA_OK;
}
Sample * sample = _sample[s_id];
TrackKey * key = &key_l[k_id];
if (key->pitch.interval)
{
Float min, max, cur;
Float size;
length = sample->length; //length in bytes
size = Float(length) * (key->loop + 1);
min = key->pitch.min * sample->format.frequency * key->pitch.interval * 0.001F;
max = key->pitch.max * sample->format.frequency * key->pitch.interval * 0.001F;
cur = max;
while (size > 0.0F)
{
f_lgt += key->pitch.interval;
size -= cur = cur == min ? max : min;
}
if (size < 0.0F) f_lgt += key->pitch.interval * (size / cur);
}
else
{
sample->GetLength(length);
length = ULong((loop_i & 0x00000001 ? key->pitch.max : key->pitch.min) * length);
}
return ATHENA_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Track setup //
// //
///////////////////////////////////////////////////////////////////////////////
ATHENAError Track::SetName(const char * _name)
{
Void * ptr;
if (!strlen(_name)) free(name), name = NULL;
else
{
ptr = realloc(name, strlen(_name) + 1);
if (!ptr) return ATHENA_ERROR_MEMORY;
name = (char *)ptr;
strcpy(name, _name);
}
return ATHENA_OK;
}
ATHENAError Track::SetMode(const ULong & _flags)
{
if (_flags & ATHENA_FLAG_POSITION)
flags |= TRACK_3D;
else
flags &= ~TRACK_3D;
if (_flags & ATHENA_FLAG_REVERBERATION)
flags |= TRACK_REVERB;
else
flags &= ~TRACK_REVERB;
return ATHENA_OK;
}
ATHENAError Track::SetSample(const SLong & s_id)
{
if (_sample.IsNotValid(GetSampleID(s_id))) s_id = SFALSE;
else s_id = s_id | 0xffff0000;
return ATHENA_OK;
}
ATHENAError Track::SetKeyCount(const ULong & count)
{
Void * ptr;
if (count == key_c) return ATHENA_OK;
ptr = realloc(key_l, count * sizeof(TrackKey));
if (count && !ptr) return ATHENA_ERROR_MEMORY;
key_l = (TrackKey *)ptr;
if (count > key_c)
{
memset(&key_l[key_c], 0, (count - key_c) * sizeof(TrackKey));
TrackKey * key = &key_l[count];
TrackKey * key_d = &key_l[key_c];
while (key > key_d)
{
--key;
key->volume.min = key->volume.max = key->pitch.min = key->pitch.max = ATHENA_DEFAULT_VOLUME;
}
}
key_c = count;
return ATHENA_OK;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Track status //
// //
///////////////////////////////////////////////////////////////////////////////
ATHENAError Track::GetName(char * _name, const ULong & max_char)
{
if (name) strncpy(_name, name, max_char);
else
{
SLong s_id(GetSampleID(s_id));
if (_sample.IsValid(s_id)) strncpy(_name, _sample[s_id]->name, max_char);
else *_name = 0;
}
return ATHENA_OK;
}
ATHENAError Track::GetMode(ULong & _flags)
{
_flags = 0;
if (flags & TRACK_3D) _flags |= ATHENA_FLAG_POSITION;
if (flags & TRACK_REVERB) _flags |= ATHENA_FLAG_REVERBERATION;
return ATHENA_OK;
}
ATHENAError Track::GetSample(SLong & sample_id)
{
sample_id = s_id | 0xffff0000;
return ATHENA_OK;
}
ATHENAError Track::GetLength(ULong & length)
{
length = 0;
for (ULong i(0); i < key_c; i++)
{
ULong k_lgt;
GetKeyLength(t_id, i, k_lgt);
length += k_lgt;
}
return ATHENA_OK;
}
ATHENAError Track::GetKeyCount(ULong & count)
{
count = key_c;
return ATHENA_OK;
}
}//ATHENA::