Voice acting, sound editing, etc.

Discuss the Wing Commander Series and find the latest information on the Wing Commander Universe privateer mod as well as the standalone mod Wasteland Incident project.
Post Reply
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

Ok. I'll try them.

One question though:
Are the distances in holo.h in meters?

I think that, if it's added to the engine, all those things should be configurable in vegastrike.config and well documented (otherwise, people won't have a clue).
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

I'm using inches for the four input parameters. From holo.h,

Code: Select all

//Constant assumptions ;-):
//dimensions in inches unless otherwise noted
#define distance_between_ears 6.0
#define distance_from_monitor 25.0
#define width_of_the_monitor 18.0
#define width_of_a_speaker 4.0
The derivative quantities are non-units specific. From holo.cpp,

Code: Select all

//computed constants:
#define distance_between_speakers ((width_of_the_monitor+width_of_a_speaker))
#define speaker_overwidth  ((distance_between_speakers-distance_between_ears))
#define same_side_lateral  ((0.5*speaker_overwidth))
#define cross_side_lateral ((same_side_lateral+distance_between_ears))
#define square_of(x) ((((x))*((x))))
#define same_side_distsqr  \
  ((square_of(same_side_lateral)+square_of(distance_from_monitor)))
#define cross_side_distsqr  \
  ((square_of(cross_side_lateral)+square_of(distance_from_monitor)))
#define nominal_atenuation ((same_side_distsqr/cross_side_distsqr))
#define same_side_dist ((sqrt(same_side_distsqr)))
#define cross_side_dist ((sqrt(cross_side_distsqr)))
#define distance_diff ((cross_side_dist-same_side_dist))
In the end I'm switching to meters, also in holo.cpp

Code: Select all

//here we switch to meters
#define d_diff_m ((distance_diff*0.0254))
#define speed_of_sound 332.0
#define time_diff_s ((d_diff_m/speed_of_sound))

static const double time_diff_seconds = time_diff_s;
static const double atenuation_factor = nominal_atenuation;
So, super easy to change if need be.
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

Ok, klauss, here's the reflections code, for dashboard mounted switches, buttons, beeps and clicks. Only HUD and window reflections are modeled.
There's a way to specify a flat window model, such as for a Tarsus, and a bubble-top, round dome accoustic type such as for the Centurion.
I haven't tried compiling this yet...

Code: Select all

#ifndef _DASH_H_
#define _DASH_H_

//Constant assumptions ;-):
//dimensions in inches unless otherwise noted
#define dist_between_ears (6.0)
#define meters_per_inch (0.0254)
#define speed_o_sound (332.0)
#define bubble_top_amplification (3.0)
#define sqr(x) ((((x))*((x))))
//note: bubble top is when a round glass bubble cockpit is used, and "amplification" denotes
//the fact that the round top reflects waves re-concentrating them; so, the amplification is
//a number to experiment with; might need to be higher, to really sound like a round, hollow
//chamber.

//key_xy is the structure used for input. It places the key on the dashboard. The idea is to
//have one sound for momentary pushbuttons, a pair of sounds for toggle switches on and off
//and to reuse these sounds for momentary and toggle functions, then to place them on the
//dashboard in x and y, so as to more or less track the key bindings on the keyboard. The view
//function keys may need the recording of one of those types of buttons that cause neighboring
//buttons to be released, such as the speed buttons on many kitchen blenders. Then place them
//across the top row: Say F1 at -5,3; F2 at -4,3; and so on.
struct key_xy //x,y pos of a key on dash (inches)
{
    double    x_;
    double    y_;
    key_xy() : x_(0.0), y_(0.0) {}
    key_xy( double x, double y ) : x_(x), y_(y) {}
};

//reflections is the struct used as output. Direct are the direct path to the ears from the
//switch sound on the dashboard. At least one of direct_left- or -right_ear_time will be
//returned as 0.0, as the first sound to arrive is not treated as a reflection. Both the
//direct and HUD-reflected waves for each ear are low-pass-filtered if they come at an
//angle such that waves must curve around the cheek-bone. Secondary reflections are the side
//window or bubble-top reflections. Bubble-top reflections are amplified but very low-pass-
//-filtered.
struct reflections // times in seconds, amplitudes are multiplying
// factors referenced to a sound coming from a key at (0,0) on dash
{
    double    direct_left_ear_time;
    double    direct_left_ear_ampl;
    double    direct_rite_ear_time;
    double    direct_rite_ear_ampl;
    double    hud_refl_left_ear_time;
    double    hud_refl_left_ear_ampl;
    double    hud_refl_rite_ear_time;
    double    hud_refl_rite_ear_ampl;
    double    dir_and_hud_left_lpfreq;
    double    dir_and_hud_rite_lpfreq;
    double    secondrfl_left_ear_time;
    double    secondrfl_left_ear_ampl;
    double    secondrfl_left_ear_lpfreq;
    double    secondrfl_rite_ear_time;
    double    secondrfl_rite_ear_ampl;
    double    secondrfl_rite_ear_lpfreq;
    reflections(){ memfill(this,0,sizeof(reflections); }
};

//instantiate this class for each cockpit model. Give the left and right
//windows a distance of zero to select bubble dome cockpit model. Give a
//bubble top radius of zero to select left and right flat windows instead.
//If flat windows are used, the roof is considered absorbent.
//Might be good to give HUD reflections a high-pass-filter corner of say
//500 to 700 Hz to make it sound like it's thin, like a thick mylar material.
//"process_new_key_pos(x,y)" is the input function. The output function is
//"presults()", which returns a pointer to a "reflections" struct. Enjoy.
class cockpit_dash
{
    //all distances in inches, angles in radians
    double    forward_dist_to_hud;
    double    vert_dist_hud_to_dash;
    double    dashboard_angle;
    double    dist_to_right_window;
    double    dist_to_left_window;
    double    bubble_top_radius;
    key_xy const * mutable pkey_xy;
    reflections * mutable presult;
    mutable double key_x;
    mutable double key_y;
public:
    cockpit_dash
    (
      double fd2hud,
      double vd2dash,
      double dashang,
      double d2rwind,
      double d2lwind,
      double bubtrad
    )
    : forward_dist_to_hud( fd2hud )
    , vert_dist_hud_to_dash( vd2dash )
    , dashboard_angle( dashang )
    , dist_to_right_window( d2rwind )
    , dist_to_left_window( d2lwind )
    , bubble_top_radius( bubtrad )
    , pkey_xy(0)
    , presult(0)
    {}
    ~cockpit_dash()
    {
    	delete pkey_xy; pkey_xy = 0;
        delete presult; presult = 0;
    }
private:
    cockpit_dash();
public:
    void process_new_key_pos( double x, double y ) const
    {
        delete pkey_xy; pkey_xy = 0;
	pkey_xy = new key_xy( x, y );
        delete presult; presult = 0;
        presult = new reflections();
        recompute_reflections();
    }
    reflections * presults() const { return presult; }
private:
    //common private functions:
    double reference_distance_to_dash() const
    {
        return sqrt( sqr(forward_dist_to_hud) + sqr(vert_dist_hud_to_dash) );
    }
    double fwd_key_offset() const
    {
        assert( pkey_xy );
        return pkey_xy->y_ * cos( dashboard_angle );
    }
    double vert_key_offset() const
    {
        assert( pkey_xy );
        return pkey_xy->y_ * sin( dashboard_angle );
    }
    double side_view_horiz_dist_to_key() const
    {
        return forward_dist_to_hud + fwd_key_offset();
    }
    double side_view_vert_dist_to_key() const
    {
        return vert_dist_hud_to_dash - vert_key_offset();
    }
    double lateral_left_ear_dist_to_key_sqr() const
    {
        assert( pkey_xy );
        return sqr( pkey_xy->x_ + ( 0.5 * dist_between_ears ) );
    }
    double lateral_rite_ear_dist_to_key_sqr() const
    {
        assert( pkey_xy );
        return sqr( pkey_xy->x_ - ( 0.5 * dist_between_ears ) );
    }
    static double time( double inches ){ return (0.0254/332.0)*inches; } //seconds
    //DIRECT path:
    double side_view_diagonal_dist_to_key() const
    {
        return sqrt(
          sqr( side_view_horiz_dist_to_key() ) +
          sqr( side_view_vert_dist_to_key() ) );
    }
    double left_ear_dist_to_key() const
    {
    	return sqrt( lateral_left_ear_dist_to_key_sqr()
		+ sqr( side_view_diagonal_dist_to_key() );
    }
    double rite_ear_dist_to_key() const
    {
    	return sqrt( lateral_rite_ear_dist_to_key_sqr()
		+ sqr( side_view_diagonal_dist_to_key() );
    }
    //HUD reflection:
    double side_view_hud_refl_dist_to_key() const
    {
        return side_view_horiz_dist_to_key() + side_view_vert_dist_to_key();
    }
    double left_ear_hud_reflect_dist() const
    {
        return sqrt( lateral_left_ear_dist_to_key_sqr()
		+ sqr( side_view_hud_refl_dist_to_key() );
    }
    double rite_ear_hud_reflect_dist() const
    {
        return sqrt( lateral_left_ear_dist_to_key_sqr()
		+ sqr( side_view_hud_refl_dist_to_key() );
    }
    //DIRECT & HUD low-pass frequency corner
    double dir_and_hud_left_lpf() const
    {
        if( pkey_xy->x_ > 1.0 )
	{
	    return 20000.0 - 1000 * (pkey_xy->x_ - 1.0);
	}
	else
	{
	    return 20000.0
	}
    }
    double dir_and_hud_rite_lpf() const
    {
        if( pkey_xy->x_ < -1.0 )
	{
	    return 20000.0 - 1000 * (-pkey_xy->x_ + 1.0);
	}
	else
	{
	    return 20000.0
	}
    }
    //LEFT-window:
    double lateral_left_ear_dist_to_window() const
    {
        return dist_to_left_window - ( 0.5 * dist_between_ears );
    }
    double lateral_left_key_dist_to_window() const
    {
        return dist_to_left_window + pkey_xy->x_;
    }
    double lateral_left_window_reflect_dist() const
    {
        return lateral_left_key_dist_to_window() + lateral_left_ear_dist_to_window();
    }
    double left_window_reflect_dist() const
    {
        return sqrt(
		sqr( lateral_left_window_reflect_dist() +
		sqr( side_view_diagonal_dist_to_key() );
    }
    //RITE-window:
    double lateral_rite_ear_dist_to_window() const
    {
        return dist_to_rite_window - ( 0.5 * dist_between_ears );
    }
    double lateral_rite_key_dist_to_window() const
    {
        return dist_to_rite_window - pkey_xy->x_;
    }
    double lateral_rite_window_reflect_dist() const
    {
        return lateral_rite_key_dist_to_window() + lateral_rite_ear_dist_to_window();
    }
    double rite_window_reflect_dist() const
    {
        return sqrt(
		sqr( lateral_left_window_reflect_dist() +
		sqr( side_view_diagonal_dist_to_key() );
    }
    //BUBBLE-top reflections:
    double lateral_ear_dist_to_bubble() const
    {
        return bubble_top_radius - ( 0.5 * dist_between_ears );
    }
    double lateral_left_key_dist_to_bubble() const
    {
        return bubble_top_radius + pkey_xy->x_;
    }
    double lateral_left_bubble_reflect_dist() const
    {
        return lateral_ear_dist_to_bubble() + lateral_left_key_dist_to_bubble();
    }
    double lateral_rite_key_dist_to_bubble() const
    {
        return bubble_top_radius - pkey_xy->x_;
    }
    double lateral_rite_bubble_reflect_dist() const
    {
        return lateral_ear_dist_to_bubble() + lateral_rite_key_dist_to_bubble();
    }
    double left_bubble_reflect_dist() const
    {
        return sqrt(
		sqr( lateral_left_bubble_reflect_dist() +
		sqr( side_view_diagonal_dist_to_key() );
    }
    double rite_bubble_reflect_dist() const
    {
        return sqrt(
		sqr( lateral_rite_bubble_reflect_dist() +
		sqr( side_view_diagonal_dist_to_key() );
    }
    double left_ear_horizontal_misalignment_sqr() const
    {
        return sqr( pkey_xy->x_ - ( 0.5 * dist_between_ears ) );
    }
    double rite_ear_horizontal_misalignment_sqr() const
    {
        return sqr( pkey_xy->x_ + ( 0.5 * dist_between_ears ) );
    }
    double vert_misalignment_sqr() const
    {
        return sqr( 0.5 * side_view_vert_dist_to_key() );
    }
    double left_ear_misalignment_sqr() const
    {
        return left_ear_horizontal_misalignment_sqr() + vert_misalignment_sqr();
    }
    double rite_ear_misalignment_sqr() const
    {
        return rite_ear_horizontal_misalignment_sqr() + vert_misalignment_sqr();
    }
    void recompute_reflections() const
    {
        assert( presult );
        presult->direct_left_ear_time = time( left_ear_dist_to_key() );
	presult->direct_left_ear_ampl = sqr( reference_dist_to_dash() / left_ear_dist_to_key() );
        presult->direct_rite_ear_time = time( rite_ear_dist_to_key() );
	presult->direct_rite_ear_ampl = sqr( reference_dist_to_dash() / rite_ear_dist_to_key() );
        presult->hud_refl_left_ear_time = time( left_ear_hud_reflect_dist() );
	presult->hud_refl_left_ear_ampl = sqr( reference_dist_to_dash() / left_ear_hud_reflect_dist() );
        presult->hud_refl_rite_ear_time = time( rite_ear_hud_reflect_dist() );
	presult->hud_refl_rite_ear_ampl = sqr( reference_dist_to_dash() / rite_ear_hud_reflect_dist() );
	presult->dir_and_hud_left_lpfreq = dir_and_hud_left_lpf();
	presult->dir_and_hud_rite_lpfreq = dir_and_hud_rite_lpf();
	if( bubble_top_radius < dist_to_right_window + dist_to_left_window )
	{
	    //side-windows it is
            presult->secondrfl_left_ear_time = time( left_window_reflect_dist() );
	    presult->secondrfl_left_ear_ampl = sqr( reference_dist_to_dash() / left_window_reflect_dist() );
	    presult->secondrfl_left_ear_lpfreq = 20000.0;
            presult->secondrfl_rite_ear_time = time( rite_window_reflect_dist() );
	    presult->secondrfl_rite_ear_ampl = sqr( reference_dist_to_dash() / rite_window_reflect_dist() );
	    presult->secondrfl_rite_ear_lpfreq = 20000.0;
	}
	else
	{
	    //bubble-top it is
            presult->secondrfl_left_ear_time = time( left_bubble_reflect_dist() );
	    presult->secondrfl_left_ear_ampl = bubble_top_amplification * sqr( reference_dist_to_dash() / left_bubble_reflect_dist() );
	    presult->secondrfl_left_ear_lpfreq = 20000.0 / left_ear_misalignment_sqr();
            presult->secondrfl_rite_ear_time = time( rite_bubble_reflect_dist() );
	    presult->secondrfl_rite_ear_ampl = bubble_top_amplification * sqr( reference_dist_to_dash() / rite_bubble_reflect_dist() );
	    presult->secondrfl_rite_ear_lpfreq = 20000.0 / rite_ear_misalignment_sqr();
	}
	//now reduce all times by the lowest time:
	double smallest_time;
	if( presult->direct_left_ear_time < presult->direct_rite_ear_time )
	{
	    smallest_time = presult->direct_left_ear_time;
	    presult->direct_left_ear_time = 0.0;
	    presult->direct_rite_ear_time -= smallest_time;
	}
	else if( presult->direct_rite_ear_time < presult->direct_left_ear_time )
	{
	    smallest_time = presult->direct_rite_ear_time;
	    presult->direct_rite_ear_time = 0.0;
	    presult->direct_left_ear_time -= smallest_time;
	}
	else
	{
	    smallest_time = presult->direct_left_ear_time;
	    presult->direct_left_ear_time = 0.0;
	    presult->direct_rite_ear_time = 0.0;
	}
	presult->hud_refl_left_ear_time -= smallest_time;
	presult->hud_refl_rite_ear_time -= smallest_time;
	presult->secondrfl_left_ear_time -= smallest_time;
	presult->secondrfl_rite_ear_time -= smallest_time;
};

#include <vector>

typedef struct
{
    float left;
    float rite;
    //I know how to spell "right"!...
    //I just like them to line-up, ok? Sheesh! ;-)
} sample;

typedef std::vector<sample> sv_t;
typedef std::vector<sample>::iterator svi_t;

sv_t *add_reflections
(
  sv_t & vs,
  double const & sampling_rate_Hz,
  double const & level
);


#endif
Example:
cockpit_dash cd_Tarsus(30.0,11.0,0.5,9.0,72.0,0.0);
cockpit_dash cd_Centur(25,0,13.0,1.0,0.0,0.0,22.0);
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

I'll take a look at it. Only not today. I'm tied up with schoolwork ATM. But I guess tomorrow I'll be able to.
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

At your convenience. All reflections are single, which means, I believe, that all their signs should be negative; but you're the expert.
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

It so much more complex than that. But that's an acceptable simplification.
Actually, I never studied this propperly, from books, so my terminology may not be right, but I think longitudinal waves are vectored, so it's about directions and not signs. But it's a common simplification, which is not that deviant from reality usually, that single reflections come in opposite directions to that of direct sound.
So, yes... they're negative.
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
klauss
Elite
Elite
Posts: 7243
Joined: Mon Apr 18, 2005 2:40 pm
Location: LS87, Buenos Aires, República Argentina

Post by klauss »

Good news: I'm uploading the barspeech and commspeech sounds as I type, in the usual place. Actually, it's been uploading for the past two hours. Man, that's taking long. Only for 80Mb.

Oh: the usual place (don't act surprised if I mess the link :) )

PS: And that's how long it'll take: 2.4 hours, at present speed.

PS2: Yeah, I know. It grew from 40Mb to 80Mb. If you want, I can create more compressed alternatives. For instance, barspeech could easily go 22Khz/mono, IMO, without much degradation. But I like quality, what can I say. :P Really. I think giving choinces upon download would be a good thing, for those not concerned with quality. Actually, I would try a higher quality version (yes, higher), at around 160MB, so that comm distortion sounds better (call me fanatic, if you like). But all that will have to wait until I come back. For now, 80Mb will have to do.

Chuck: I didn't do the gun sound processing, since in order to use them we'll have to tweak the engine, to be able to specify different environments for guns. (a gun firing in space, outside your cockpit, gets a sound, while a gun firing from your ship, gets another one, and a gun firing from a turret, probably, yet another one).
Oíd mortales, el grito sagrado...
Call me "Menes, lord of Cats"
Wing Commander Universe
chuck_starchaser
Elite
Elite
Posts: 8014
Joined: Fri Sep 05, 2003 4:03 am
Location: Montreal
Contact:

Post by chuck_starchaser »

Ah, I didn't realize the same sound was used for near and far. Okay, we'll tackle that in due time.
And let it be 80 megs. Why not? ;-)
I'm so glad you got around to upload before your trip!

Hope it's a good one, btw. Make sure you carry plenty of fluids and electrolytes. That's a long trip, even on a car. And wear bright clothing. Safety first!
spiritplumber
Developer
Developer
Posts: 1831
Joined: Mon Mar 07, 2005 10:33 pm
Contact:

Post by spiritplumber »

Rock on and thanks!
My Moral Code:
- The only sin is to treat people as if they were things.
- Rules were made for people, not the other way around.
- Don't deceive. Real life is complicated enough.
- If all else fails, smash stuff.
spiritplumber
Developer
Developer
Posts: 1831
Joined: Mon Mar 07, 2005 10:33 pm
Contact:

Post by spiritplumber »

I found someone who can do a lot of voices and accents who is willing to read lines. If Klauss or anyone else (sound related) want to contact this person (preferrably for WCU but also for PR and VS) the email address is

ianpcorbett]at[hotmail.com

I kinda hired this kitty, so don't worry about taking time, only please start communication quickly ^^;
My Moral Code:
- The only sin is to treat people as if they were things.
- Rules were made for people, not the other way around.
- Don't deceive. Real life is complicated enough.
- If all else fails, smash stuff.
Post Reply