mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-10 07:12:07 +00:00
Merge pull request #722 from 0lvin/gamepad
Sync haptic feedback with sound track
This commit is contained in:
commit
8358e386fc
6 changed files with 361 additions and 232 deletions
|
@ -316,7 +316,10 @@ void Key_ReadConsoleHistory();
|
|||
void Key_WriteConsoleHistory();
|
||||
void Key_SetBinding(int keynum, char *binding);
|
||||
void Key_MarkAllUp(void);
|
||||
void Haptic_Feedback(char *name, int effect_volume, int effect_x, int effect_y, int effect_z);
|
||||
void Haptic_Feedback(char *name, int effect_volume, int effect_duration,
|
||||
int effect_begin, int effect_end,
|
||||
int effect_attack, int effect_fade,
|
||||
int effect_x, int effect_y, int effect_z);
|
||||
int Key_GetMenuKey(int key);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -78,33 +78,13 @@ static cvar_t *windowed_mouse;
|
|||
|
||||
// ----
|
||||
|
||||
/* Haptic feedback types */
|
||||
enum QHARPICTYPES {
|
||||
HAPTIC_EFFECT_UNKNOWN = -1,
|
||||
HAPTIC_EFFECT_BLASTER = 0,
|
||||
HAPTIC_EFFECT_MENY,
|
||||
HAPTIC_EFFECT_HYPER_BLASTER,
|
||||
HAPTIC_EFFECT_MACHINEGUN,
|
||||
HAPTIC_EFFECT_SHOTGUN,
|
||||
HAPTIC_EFFECT_SSHOTGUN,
|
||||
HAPTIC_EFFECT_RAILGUN,
|
||||
HAPTIC_EFFECT_ROCKETGUN,
|
||||
HAPTIC_EFFECT_GRENADE,
|
||||
HAPTIC_EFFECT_BFG,
|
||||
HAPTIC_EFFECT_PALANX,
|
||||
HAPTIC_EFFECT_IONRIPPER,
|
||||
HAPTIC_EFFECT_ETFRIFLE,
|
||||
HAPTIC_EFFECT_SHOTGUN2,
|
||||
HAPTIC_EFFECT_TRACKER,
|
||||
HAPTIC_EFFECT_PAIN,
|
||||
HAPTIC_EFFECT_STEP,
|
||||
HAPTIC_EFFECT_TRAPCOCK,
|
||||
HAPTIC_EFFECT_LAST
|
||||
};
|
||||
|
||||
struct hapric_effects_cache {
|
||||
int effect_type;
|
||||
int effect_volume;
|
||||
int effect_duration;
|
||||
int effect_begin;
|
||||
int effect_end;
|
||||
int effect_attack;
|
||||
int effect_fade;
|
||||
int effect_id;
|
||||
int effect_x;
|
||||
int effect_y;
|
||||
|
@ -117,10 +97,12 @@ static SDL_Haptic *joystick_haptic = NULL;
|
|||
static SDL_Joystick *joystick = NULL;
|
||||
static SDL_GameController *controller = NULL;
|
||||
|
||||
#define HAPTIC_EFFECT_LIST_SIZE 16
|
||||
|
||||
static int last_haptic_volume = 0;
|
||||
static int last_haptic_efffect_size = HAPTIC_EFFECT_LAST;
|
||||
static int last_haptic_efffect_size = HAPTIC_EFFECT_LIST_SIZE;
|
||||
static int last_haptic_efffect_pos = 0;
|
||||
static struct hapric_effects_cache last_haptic_efffect[HAPTIC_EFFECT_LAST];
|
||||
static struct hapric_effects_cache last_haptic_efffect[HAPTIC_EFFECT_LIST_SIZE];
|
||||
|
||||
// Joystick sensitivity
|
||||
cvar_t *joy_yawsensitivity;
|
||||
|
@ -990,17 +972,22 @@ static void IN_Haptic_Shutdown(void);
|
|||
* Init haptic effects
|
||||
*/
|
||||
static int
|
||||
IN_Haptic_Effect_Init(int effect_x, int effect_y, int effect_z, int period, int magnitude, int length, int attack, int fade)
|
||||
IN_Haptic_Effect_Init(int effect_x, int effect_y, int effect_z,
|
||||
int period, int magnitude,
|
||||
int delay, int attack, int fade)
|
||||
{
|
||||
/*
|
||||
* Direction:
|
||||
* North - 0
|
||||
* East - 9000
|
||||
* South - 18000
|
||||
* West - 27000
|
||||
*/
|
||||
static SDL_HapticEffect haptic_effect;
|
||||
|
||||
/* limit magnitude */
|
||||
if (magnitude > SHRT_MAX)
|
||||
{
|
||||
magnitude = SHRT_MAX;
|
||||
}
|
||||
else if (magnitude < 0)
|
||||
{
|
||||
magnitude = 0;
|
||||
}
|
||||
|
||||
SDL_memset(&haptic_effect, 0, sizeof(SDL_HapticEffect)); // 0 is safe default
|
||||
|
||||
haptic_effect.type = SDL_HAPTIC_SINE;
|
||||
|
@ -1010,7 +997,8 @@ IN_Haptic_Effect_Init(int effect_x, int effect_y, int effect_z, int period, int
|
|||
haptic_effect.periodic.direction.dir[2] = effect_z;
|
||||
haptic_effect.periodic.period = period;
|
||||
haptic_effect.periodic.magnitude = magnitude;
|
||||
haptic_effect.periodic.length = length;
|
||||
haptic_effect.periodic.length = period;
|
||||
haptic_effect.periodic.delay = delay;
|
||||
haptic_effect.periodic.attack_length = attack;
|
||||
haptic_effect.periodic.fade_length = fade;
|
||||
|
||||
|
@ -1027,97 +1015,6 @@ IN_Haptic_Effect_Init(int effect_x, int effect_y, int effect_z, int period, int
|
|||
return effect_id;
|
||||
}
|
||||
|
||||
static int
|
||||
IN_Haptic_Effects_To_Id(int haptic_effect, int effect_volume, int effect_x, int effect_y, int effect_z)
|
||||
{
|
||||
if ((SDL_HapticQuery(joystick_haptic) & SDL_HAPTIC_SINE)==0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int hapric_volume = joy_haptic_magnitude->value * effect_volume * 16; // * 128 = 32767 max strength;
|
||||
|
||||
if (hapric_volume > 255)
|
||||
{
|
||||
hapric_volume = 255;
|
||||
}
|
||||
else if (hapric_volume < 0)
|
||||
{
|
||||
hapric_volume = 0;
|
||||
}
|
||||
|
||||
switch(haptic_effect) {
|
||||
case HAPTIC_EFFECT_MENY:
|
||||
case HAPTIC_EFFECT_TRAPCOCK:
|
||||
case HAPTIC_EFFECT_STEP:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 500/* 500 ms*/, hapric_volume * 48,
|
||||
200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
|
||||
100/* Takes 0.1 second to fade away */);
|
||||
case HAPTIC_EFFECT_PAIN:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 700/* 700 ms*/, hapric_volume * 196,
|
||||
300/* 0.3 seconds long */, 200/* Takes 0.2 second to get max strength */,
|
||||
200/* Takes 0.2 second to fade away */);
|
||||
case HAPTIC_EFFECT_BLASTER:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 500/* 500 ms*/, hapric_volume * 64,
|
||||
200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
|
||||
100/* Takes 0.1 second to fade away */);
|
||||
case HAPTIC_EFFECT_HYPER_BLASTER:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 500/* 500 ms*/, hapric_volume * 64,
|
||||
200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
|
||||
100/* Takes 0.1 second to fade away */);
|
||||
case HAPTIC_EFFECT_ETFRIFLE:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 500/* 500 ms*/, hapric_volume * 64,
|
||||
200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
|
||||
100/* Takes 0.1 second to fade away */);
|
||||
case HAPTIC_EFFECT_TRACKER:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 500/* 500 ms*/, hapric_volume * 64,
|
||||
200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
|
||||
100/* Takes 0.1 second to fade away */);
|
||||
case HAPTIC_EFFECT_MACHINEGUN:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 800/* 800 ms*/, hapric_volume * 88,
|
||||
600/* 0.6 seconds long */, 200/* Takes 0.2 second to get max strength */,
|
||||
400/* Takes 0.4 second to fade away */);
|
||||
case HAPTIC_EFFECT_SHOTGUN:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 700/* 700 ms*/, hapric_volume * 100,
|
||||
500/* 0.5 seconds long */, 100/* Takes 0.1 second to get max strength */,
|
||||
200/* Takes 0.2 second to fade away */);
|
||||
case HAPTIC_EFFECT_SHOTGUN2:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 700/* 700 ms*/, hapric_volume * 96,
|
||||
500/* 0.5 seconds long */, 100/* Takes 0.1 second to get max strength */,
|
||||
100/* Takes 0.1 second to fade away */);
|
||||
case HAPTIC_EFFECT_SSHOTGUN:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 700/* 700 ms*/, hapric_volume * 96,
|
||||
500/* 0.5 seconds long */, 100/* Takes 0.1 second to get max strength */,
|
||||
100/* Takes 0.1 second to fade away */);
|
||||
case HAPTIC_EFFECT_RAILGUN:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 700/* 700 ms*/, hapric_volume * 64,
|
||||
400/* 0.4 seconds long */, 100/* Takes 0.1 second to get max strength */,
|
||||
100/* Takes 0.1 second to fade away */);
|
||||
case HAPTIC_EFFECT_ROCKETGUN:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 700/* 700 ms*/, hapric_volume * 128,
|
||||
400/* 0.4 seconds long */, 300/* Takes 0.3 second to get max strength */,
|
||||
100/* Takes 0.1 second to fade away */);
|
||||
case HAPTIC_EFFECT_GRENADE:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 500/* 500 ms*/, hapric_volume * 64,
|
||||
200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
|
||||
100/* Takes 0.1 second to fade away */);
|
||||
case HAPTIC_EFFECT_BFG:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 800/* 800 ms*/, hapric_volume * 100,
|
||||
600/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
|
||||
100/* Takes 0.1 second to fade away */);
|
||||
case HAPTIC_EFFECT_PALANX:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 500/* 500 ms*/, hapric_volume * 64,
|
||||
200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
|
||||
100/* Takes 0.1 second to fade away */);
|
||||
case HAPTIC_EFFECT_IONRIPPER:
|
||||
return IN_Haptic_Effect_Init(effect_x, effect_y, effect_z, 500/* 500 ms*/, hapric_volume * 64,
|
||||
200/* 0.2 seconds long */, 100/* Takes 0.1 second to get max strength */,
|
||||
100/* Takes 0.1 second to fade away */);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
IN_Haptic_Effects_Info(void)
|
||||
{
|
||||
|
@ -1134,16 +1031,20 @@ IN_Haptic_Effects_Init(void)
|
|||
{
|
||||
last_haptic_efffect_size = SDL_HapticNumEffectsPlaying(joystick_haptic);
|
||||
|
||||
if (last_haptic_efffect_size > HAPTIC_EFFECT_LAST)
|
||||
if (last_haptic_efffect_size > HAPTIC_EFFECT_LIST_SIZE)
|
||||
{
|
||||
last_haptic_efffect_size = HAPTIC_EFFECT_LAST;
|
||||
last_haptic_efffect_size = HAPTIC_EFFECT_LIST_SIZE;
|
||||
}
|
||||
|
||||
for (int i=0; i<HAPTIC_EFFECT_LAST; i++)
|
||||
for (int i=0; i<HAPTIC_EFFECT_LIST_SIZE; i++)
|
||||
{
|
||||
last_haptic_efffect[i].effect_type = HAPTIC_EFFECT_UNKNOWN;
|
||||
last_haptic_efffect[i].effect_id = -1;
|
||||
last_haptic_efffect[i].effect_volume = 0;
|
||||
last_haptic_efffect[i].effect_duration = 0;
|
||||
last_haptic_efffect[i].effect_begin = 0;
|
||||
last_haptic_efffect[i].effect_end = 0;
|
||||
last_haptic_efffect[i].effect_attack = 0;
|
||||
last_haptic_efffect[i].effect_fade = 0;
|
||||
last_haptic_efffect[i].effect_x = 0;
|
||||
last_haptic_efffect[i].effect_y = 0;
|
||||
last_haptic_efffect[i].effect_z = 0;
|
||||
|
@ -1172,10 +1073,14 @@ IN_Haptic_Effect_Shutdown(int * effect_id)
|
|||
static void
|
||||
IN_Haptic_Effects_Shutdown(void)
|
||||
{
|
||||
for (int i=0; i<HAPTIC_EFFECT_LAST; i++)
|
||||
for (int i=0; i<HAPTIC_EFFECT_LIST_SIZE; i++)
|
||||
{
|
||||
last_haptic_efffect[i].effect_type = HAPTIC_EFFECT_UNKNOWN;
|
||||
last_haptic_efffect[i].effect_volume = 0;
|
||||
last_haptic_efffect[i].effect_duration = 0;
|
||||
last_haptic_efffect[i].effect_begin = 0;
|
||||
last_haptic_efffect[i].effect_end = 0;
|
||||
last_haptic_efffect[i].effect_attack = 0;
|
||||
last_haptic_efffect[i].effect_fade = 0;
|
||||
last_haptic_efffect[i].effect_x = 0;
|
||||
last_haptic_efffect[i].effect_y = 0;
|
||||
last_haptic_efffect[i].effect_z = 0;
|
||||
|
@ -1186,14 +1091,20 @@ IN_Haptic_Effects_Shutdown(void)
|
|||
|
||||
/*
|
||||
* Haptic Feedback:
|
||||
* effect_volume=0..16
|
||||
* effect_volume=0..SHRT_MAX
|
||||
* effect{x,y,z} - effect direction
|
||||
* name - sound file name
|
||||
*/
|
||||
void
|
||||
Haptic_Feedback(char *name, int effect_volume, int effect_x, int effect_y, int effect_z)
|
||||
Haptic_Feedback(char *name, int effect_volume, int effect_duration,
|
||||
int effect_begin, int effect_end,
|
||||
int effect_attack, int effect_fade,
|
||||
int effect_x, int effect_y, int effect_z)
|
||||
{
|
||||
int effect_type = HAPTIC_EFFECT_UNKNOWN;
|
||||
if (!joystick_haptic)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (joy_haptic_magnitude->value <= 0)
|
||||
{
|
||||
|
@ -1205,7 +1116,7 @@ Haptic_Feedback(char *name, int effect_volume, int effect_x, int effect_y, int e
|
|||
return;
|
||||
}
|
||||
|
||||
if (!joystick_haptic)
|
||||
if (effect_duration <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -1218,105 +1129,63 @@ Haptic_Feedback(char *name, int effect_volume, int effect_x, int effect_y, int e
|
|||
|
||||
last_haptic_volume = joy_haptic_magnitude->value * 255;
|
||||
|
||||
if (strstr(name, "misc/menu"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_MENY;
|
||||
}
|
||||
else if (strstr(name, "weapons/blastf1a"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_BLASTER;
|
||||
}
|
||||
else if (strstr(name, "weapons/hyprbf1a"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_HYPER_BLASTER;
|
||||
}
|
||||
else if (strstr(name, "weapons/machgf"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_MACHINEGUN;
|
||||
}
|
||||
else if (strstr(name, "weapons/shotgf1b"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_SHOTGUN;
|
||||
}
|
||||
else if (strstr(name, "weapons/sshotf1b"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_SSHOTGUN;
|
||||
}
|
||||
else if (strstr(name, "weapons/railgf1a"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_RAILGUN;
|
||||
}
|
||||
else if (strstr(name, "weapons/rocklf1a") ||
|
||||
strstr(name, "weapons/rocklx1a"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_ROCKETGUN;
|
||||
}
|
||||
else if (strstr(name, "weapons/grenlf1a") ||
|
||||
strstr(name, "weapons/grenlx1a") ||
|
||||
strstr(name, "weapons/hgrent1a"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_GRENADE;
|
||||
}
|
||||
else if (strstr(name, "weapons/bfg__f1y"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_BFG;
|
||||
}
|
||||
else if (strstr(name, "weapons/plasshot"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_PALANX;
|
||||
}
|
||||
else if (strstr(name, "weapons/rippfire"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_IONRIPPER;
|
||||
}
|
||||
else if (strstr(name, "weapons/nail1"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_ETFRIFLE;
|
||||
}
|
||||
else if (strstr(name, "weapons/shotg2"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_SHOTGUN2;
|
||||
}
|
||||
else if (strstr(name, "weapons/disint2"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_TRACKER;
|
||||
}
|
||||
else if (strstr(name, "player/male/pain") ||
|
||||
strstr(name, "player/female/pain") ||
|
||||
strstr(name, "players/male/pain") ||
|
||||
strstr(name, "players/female/pain"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_PAIN;
|
||||
}
|
||||
else if (strstr(name, "player/step") ||
|
||||
strstr(name, "player/land"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_STEP;
|
||||
}
|
||||
else if (strstr(name, "weapons/trapcock"))
|
||||
{
|
||||
effect_type = HAPTIC_EFFECT_TRAPCOCK;
|
||||
}
|
||||
|
||||
if (effect_type != HAPTIC_EFFECT_UNKNOWN)
|
||||
if (
|
||||
strstr(name, "misc/menu") ||
|
||||
strstr(name, "weapons/") ||
|
||||
/* detect pain for any player model */
|
||||
((
|
||||
strstr(name, "player/") ||
|
||||
strstr(name, "players/")
|
||||
) && (
|
||||
strstr(name, "/pain")
|
||||
)) ||
|
||||
strstr(name, "player/step") ||
|
||||
strstr(name, "player/land")
|
||||
)
|
||||
{
|
||||
// check last effect for reuse
|
||||
if (last_haptic_efffect[last_haptic_efffect_pos].effect_type != effect_type ||
|
||||
if (
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_volume != effect_volume ||
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_duration != effect_duration ||
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_begin != effect_begin ||
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_end != effect_end ||
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_attack != effect_attack ||
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_fade != effect_fade ||
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_x != effect_x ||
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_y != effect_y ||
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_z != effect_z)
|
||||
{
|
||||
if ((SDL_HapticQuery(joystick_haptic) & SDL_HAPTIC_SINE)==0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int hapric_volume = joy_haptic_magnitude->value * effect_volume; // 32767 max strength;
|
||||
|
||||
if (effect_duration <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Com_Printf("%s: volume %d: %d ms %d:%d:%d ms speed: %.2f\n",
|
||||
name, effect_volume, effect_duration - effect_end,
|
||||
effect_begin, effect_attack, effect_fade,
|
||||
(float)effect_volume / effect_fade);
|
||||
|
||||
// FIFO for effects
|
||||
last_haptic_efffect_pos = (last_haptic_efffect_pos+1) % last_haptic_efffect_size;
|
||||
IN_Haptic_Effect_Shutdown(&last_haptic_efffect[last_haptic_efffect_pos].effect_id);
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_volume = effect_volume;
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_type = effect_type;
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_duration = effect_duration;
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_attack = effect_attack;
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_fade = effect_fade;
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_x = effect_x;
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_y = effect_y;
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_z = effect_z;
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_id = IN_Haptic_Effects_To_Id(
|
||||
effect_type, effect_volume, effect_x, effect_y, effect_z);
|
||||
last_haptic_efffect[last_haptic_efffect_pos].effect_id = IN_Haptic_Effect_Init(
|
||||
effect_x, effect_y, effect_z,
|
||||
effect_duration - effect_end, hapric_volume,
|
||||
effect_begin, effect_attack, effect_fade);
|
||||
}
|
||||
|
||||
SDL_HapticRunEffect(joystick_haptic, last_haptic_efffect[last_haptic_efffect_pos].effect_id, 1);
|
||||
|
|
|
@ -54,6 +54,14 @@ typedef struct
|
|||
int bufnum;
|
||||
#endif
|
||||
int stereo;
|
||||
/* effect length */
|
||||
/* begin<->attack..fade<->end */
|
||||
int begin;
|
||||
int end;
|
||||
int attack;
|
||||
int fade;
|
||||
/* effect volume */
|
||||
short volume;
|
||||
byte data[1];
|
||||
} sfxcache_t;
|
||||
|
||||
|
@ -251,7 +259,9 @@ void SDL_ClearBuffer(void);
|
|||
* Caches an sample for use
|
||||
* the SDL backend
|
||||
*/
|
||||
qboolean SDL_Cache(sfx_t *sfx, wavinfo_t *info, byte *data);
|
||||
qboolean SDL_Cache(sfx_t *sfx, wavinfo_t *info, byte *data, short volume,
|
||||
int begin_length, int end_length,
|
||||
int attack_length, int fade_length);
|
||||
|
||||
/*
|
||||
* Performs all sound calculations
|
||||
|
@ -303,7 +313,9 @@ void AL_Shutdown(void);
|
|||
* Upload ("cache") one sample
|
||||
* into OpenAL
|
||||
*/
|
||||
sfxcache_t *AL_UploadSfx(sfx_t *s, wavinfo_t *s_info, byte *data);
|
||||
sfxcache_t *AL_UploadSfx(sfx_t *s, wavinfo_t *s_info, byte *data, short volume,
|
||||
int begin_length, int end_length,
|
||||
int attack_length, int fade_length);
|
||||
|
||||
/*
|
||||
* Deletes one sample from OpenAL
|
||||
|
|
|
@ -167,7 +167,9 @@ AL_GetFormat(int width, int channels)
|
|||
* frontend to work.
|
||||
*/
|
||||
sfxcache_t *
|
||||
AL_UploadSfx(sfx_t *s, wavinfo_t *s_info, byte *data)
|
||||
AL_UploadSfx(sfx_t *s, wavinfo_t *s_info, byte *data, short volume,
|
||||
int begin_length, int end_length,
|
||||
int attack_length, int fade_length)
|
||||
{
|
||||
sfxcache_t *sc;
|
||||
ALsizei size;
|
||||
|
@ -202,6 +204,11 @@ AL_UploadSfx(sfx_t *s, wavinfo_t *s_info, byte *data)
|
|||
sc->size = size;
|
||||
sc->bufnum = name;
|
||||
sc->stereo = s_info->channels - 1;
|
||||
sc->volume = volume;
|
||||
sc->begin = begin_length * 1000 / s_info->rate;
|
||||
sc->end = end_length * 1000 / s_info->rate;
|
||||
sc->fade = fade_length * 1000 / s_info->rate;
|
||||
sc->attack = attack_length * 1000 / s_info->rate;
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
|
|
@ -910,7 +910,9 @@ SDL_UpdateScaletable(void)
|
|||
* performed.
|
||||
*/
|
||||
qboolean
|
||||
SDL_Cache(sfx_t *sfx, wavinfo_t *info, byte *data)
|
||||
SDL_Cache(sfx_t *sfx, wavinfo_t *info, byte *data, short volume,
|
||||
int begin_length, int end_length,
|
||||
int attack_length, int fade_length)
|
||||
{
|
||||
float stepscale;
|
||||
int i;
|
||||
|
@ -940,6 +942,11 @@ SDL_Cache(sfx_t *sfx, wavinfo_t *info, byte *data)
|
|||
sc->stereo = info->channels - 1;
|
||||
sc->length = (int)(info->samples / stepscale);
|
||||
sc->speed = sound.speed;
|
||||
sc->volume = volume;
|
||||
sc->begin = begin_length * 1000 / info->rate;
|
||||
sc->end = end_length * 1000 / info->rate;
|
||||
sc->fade = fade_length * 1000 / info->rate;
|
||||
sc->attack = attack_length * 1000 / info->rate;
|
||||
|
||||
if ((int)(info->samples / stepscale) == 0)
|
||||
{
|
||||
|
|
|
@ -245,6 +245,195 @@ S_LoadVorbis(const char *path, const char* name, wavinfo_t *info, void **buffer)
|
|||
OGG_LoadAsWav(filename, info, buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
S_GetVolume(const byte *data, int sound_length, int width, double *sound_volume)
|
||||
{
|
||||
/* update sound volume */
|
||||
*sound_volume = 0;
|
||||
if (width == 2)
|
||||
{
|
||||
short *sound_data = (short *)data;
|
||||
short *sound_end = sound_data + sound_length;
|
||||
while (sound_data < sound_end)
|
||||
{
|
||||
short sound_sample = LittleShort(*sound_data);
|
||||
*sound_volume += (sound_sample * sound_sample);
|
||||
sound_data ++;
|
||||
}
|
||||
}
|
||||
else if (width == 1)
|
||||
{
|
||||
byte *sound_data = (byte *)data;
|
||||
byte *sound_end = sound_data + sound_length;
|
||||
while (sound_data < sound_end)
|
||||
{
|
||||
// normilize to 16bit sound;
|
||||
short sound_sample = *sound_data << 8;
|
||||
*sound_volume += (sound_sample * sound_sample);
|
||||
sound_data ++;
|
||||
}
|
||||
}
|
||||
if (sound_length != 0)
|
||||
{
|
||||
*sound_volume /= sound_length;
|
||||
*sound_volume = sqrtf(*sound_volume);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
S_GetStatistics(const byte *data, int sound_length, int width, int channels,
|
||||
double sound_volume, int *begin_length, int *end_length,
|
||||
int *attack_length, int *fade_length)
|
||||
{
|
||||
/* attack length */
|
||||
short sound_max = 0;
|
||||
/* calculate max value*/
|
||||
if (width == 2)
|
||||
{
|
||||
short *sound_data = (short *)data;
|
||||
short *sound_end = sound_data + sound_length;
|
||||
while (sound_data < sound_end)
|
||||
{
|
||||
short sound_sample = LittleShort(*sound_data);
|
||||
if (sound_max < abs(sound_sample))
|
||||
{
|
||||
sound_max = abs(sound_sample);
|
||||
}
|
||||
sound_data ++;
|
||||
}
|
||||
}
|
||||
else if (width == 1)
|
||||
{
|
||||
byte *sound_data = (byte *)data;
|
||||
byte *sound_end = sound_data + sound_length;
|
||||
while (sound_data < sound_end)
|
||||
{
|
||||
// normilize to 16bit sound;
|
||||
short sound_sample = *sound_data << 8;
|
||||
if (sound_max < abs(sound_sample))
|
||||
{
|
||||
sound_max = abs(sound_sample);
|
||||
}
|
||||
sound_data ++;
|
||||
}
|
||||
}
|
||||
|
||||
// use something in middle
|
||||
sound_max = (sound_max + sound_volume) / 2;
|
||||
|
||||
// calculate attack/fade length
|
||||
if (width == 2)
|
||||
{
|
||||
// calculate attack/fade length
|
||||
short *sound_data = (short *)data;
|
||||
short *delay_data = sound_data;
|
||||
short *fade_data = sound_data;
|
||||
short *sound_end = sound_data + sound_length;
|
||||
short sound_sample = 0;
|
||||
short sound_treshold = sound_max / 2;
|
||||
|
||||
/* delay calculate */
|
||||
do
|
||||
{
|
||||
sound_sample = LittleShort(*sound_data);
|
||||
sound_data ++;
|
||||
}
|
||||
while (sound_data < sound_end && abs(sound_sample) < sound_treshold);
|
||||
/* delay_data == (short *)(data + info.dataofs) */
|
||||
*begin_length = (sound_data - delay_data) / channels;
|
||||
delay_data = sound_data;
|
||||
fade_data = sound_data;
|
||||
|
||||
/* attack calculate */
|
||||
do
|
||||
{
|
||||
sound_sample = LittleShort(*sound_data);
|
||||
sound_data ++;
|
||||
}
|
||||
while (sound_data < sound_end && abs(sound_sample) < sound_max);
|
||||
/* fade_data == delay_data */
|
||||
*attack_length = (sound_data - delay_data) / channels;
|
||||
fade_data = sound_data;
|
||||
|
||||
/* end calculate */
|
||||
sound_data = sound_end;
|
||||
do
|
||||
{
|
||||
sound_data --;
|
||||
sound_sample = LittleShort(*sound_data);
|
||||
}
|
||||
while (sound_data > fade_data && abs(sound_sample) < sound_treshold);
|
||||
*end_length = (sound_end - sound_data) / channels;
|
||||
sound_end = sound_data;
|
||||
|
||||
/* fade calculate */
|
||||
do
|
||||
{
|
||||
sound_data --;
|
||||
sound_sample = LittleShort(*sound_data);
|
||||
}
|
||||
while (sound_data > fade_data && abs(sound_sample) < sound_max);
|
||||
*fade_length = (sound_end - sound_data) / channels;
|
||||
}
|
||||
else if (width == 1)
|
||||
{
|
||||
// calculate attack/fade length
|
||||
byte *sound_data = (byte *)data;
|
||||
byte *delay_data = sound_data;
|
||||
byte *fade_data = sound_data;
|
||||
byte *sound_end = sound_data + sound_length;
|
||||
short sound_sample = 0;
|
||||
short sound_treshold = sound_max / 2;
|
||||
|
||||
/* delay calculate */
|
||||
do
|
||||
{
|
||||
// normilize to 16bit sound;
|
||||
sound_sample = *sound_data << 8;
|
||||
sound_data ++;
|
||||
}
|
||||
while (sound_data < sound_end && abs(sound_sample) < sound_treshold);
|
||||
/* delay_data == (short *)(data + info.dataofs) */
|
||||
*begin_length = (sound_data - delay_data) / channels;
|
||||
delay_data = sound_data;
|
||||
fade_data = sound_data;
|
||||
|
||||
/* attack calculate */
|
||||
do
|
||||
{
|
||||
// normilize to 16bit sound;
|
||||
sound_sample = *sound_data << 8;
|
||||
sound_data ++;
|
||||
}
|
||||
while (sound_data < sound_end && abs(sound_sample) < sound_max);
|
||||
/* fade_data == delay_data */
|
||||
*attack_length = (sound_data - delay_data) / channels;
|
||||
fade_data = sound_data;
|
||||
|
||||
/* end calculate */
|
||||
sound_data = sound_end;
|
||||
do
|
||||
{
|
||||
sound_data --;
|
||||
// normilize to 16bit sound;
|
||||
sound_sample = *sound_data << 8;
|
||||
}
|
||||
while (sound_data > fade_data && abs(sound_sample) < sound_treshold);
|
||||
*end_length = (sound_end - sound_data) / channels;
|
||||
sound_end = sound_data;
|
||||
|
||||
/* fade calculate */
|
||||
do
|
||||
{
|
||||
sound_data --;
|
||||
// normilize to 16bit sound;
|
||||
sound_sample = *sound_data << 8;
|
||||
}
|
||||
while (sound_data > fade_data && abs(sound_sample) < sound_max);
|
||||
*fade_length = (sound_end - sound_data) / channels;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads one sample into memory
|
||||
*/
|
||||
|
@ -255,6 +444,11 @@ S_LoadSound(sfx_t *s)
|
|||
byte *data = NULL;
|
||||
wavinfo_t info;
|
||||
sfxcache_t *sc;
|
||||
double sound_volume = 0;
|
||||
int begin_length = 0;
|
||||
int attack_length = 0;
|
||||
int fade_length = 0;
|
||||
int end_length = 0;
|
||||
char *name;
|
||||
|
||||
if (s->name[0] == '*')
|
||||
|
@ -327,17 +521,28 @@ S_LoadSound(sfx_t *s)
|
|||
s->is_silenced_muzzle_flash = true;
|
||||
}
|
||||
|
||||
S_GetVolume(data + info.dataofs, info.samples * info.channels,
|
||||
info.width, &sound_volume);
|
||||
|
||||
S_GetStatistics(data + info.dataofs, info.samples * info.channels,
|
||||
info.width, info.channels, sound_volume, &begin_length, &end_length,
|
||||
&attack_length, &fade_length);
|
||||
|
||||
#if USE_OPENAL
|
||||
if (sound_started == SS_OAL)
|
||||
{
|
||||
sc = AL_UploadSfx(s, &info, data + info.dataofs);
|
||||
sc = AL_UploadSfx(s, &info, data + info.dataofs, sound_volume,
|
||||
begin_length, end_length,
|
||||
attack_length, fade_length);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (sound_started == SS_SDL)
|
||||
{
|
||||
if (!SDL_Cache(s, &info, data + info.dataofs))
|
||||
if (!SDL_Cache(s, &info, data + info.dataofs, sound_volume,
|
||||
begin_length, end_length,
|
||||
attack_length, fade_length))
|
||||
{
|
||||
Com_Printf("Pansen!\n");
|
||||
FS_FreeFile(data);
|
||||
|
@ -870,6 +1075,8 @@ S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx,
|
|||
vec3_t orientation, direction;
|
||||
vec_t distance_direction;
|
||||
int dir_x, dir_y, dir_z;
|
||||
int effect_duration = 0;
|
||||
int effect_volume = -1;
|
||||
|
||||
VectorSubtract(listener_forward, listener_up, orientation);
|
||||
|
||||
|
@ -893,7 +1100,25 @@ S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx,
|
|||
dir_y = 16 * orientation[1] * direction[1];
|
||||
dir_z = 16 * orientation[2] * direction[2];
|
||||
|
||||
Haptic_Feedback(sfx->name, 16 - distance_direction / 32, dir_x, dir_y, dir_z);
|
||||
if (sfx->cache)
|
||||
{
|
||||
effect_duration = sfx->cache->length;
|
||||
|
||||
if (sfx->cache->stereo)
|
||||
{
|
||||
effect_duration /= 2;
|
||||
}
|
||||
|
||||
/* sound near player has 16 points */
|
||||
effect_volume = sfx->cache->volume / 16;
|
||||
}
|
||||
|
||||
Haptic_Feedback(
|
||||
sfx->name, (16 - distance_direction / 32) * effect_volume,
|
||||
effect_duration,
|
||||
sfx->cache->begin, sfx->cache->end,
|
||||
sfx->cache->attack, sfx->cache->fade,
|
||||
dir_x, dir_y, dir_z);
|
||||
}
|
||||
|
||||
ps->entnum = entnum;
|
||||
|
@ -1195,10 +1420,16 @@ S_SoundList(void)
|
|||
{
|
||||
size = sc->length * sc->width * (sc->stereo + 1);
|
||||
total += size;
|
||||
Com_Printf("%s(%2db) %8i(%d ch) : %s\n",
|
||||
Com_Printf("%s(%2db) %8i(%d ch) %s %2.1f dB %.1fs:%.1f..%.1f..%.1f..%.1f\n",
|
||||
sc->loopstart != -1 ? "L" : " ",
|
||||
sc->width * 8, size,
|
||||
(sc->stereo + 1), sfx->name);
|
||||
(sc->stereo + 1), sfx->name,
|
||||
10 * log10((float)sc->volume / (2 << 15)),
|
||||
(float)sc->length / 1000,
|
||||
(float)sc->begin / 1000,
|
||||
(float)sc->attack / 1000,
|
||||
(float)sc->fade / 1000,
|
||||
(float)sc->end / 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue