Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#4.0

Grandiose projects 5. Audio support

5.00/5 (2 votes)
3 Feb 2012CPOL8 min read 23.6K   2K  
Audio support for grandiose projects

MainPicture.png

Useful links

1. Introduction

It is clear that Grandiose Projects' software should satisfy following to conditions:

  • (Potential) support all features related to science and engineering;
  • Iteroperability of these features.

Audio support is one of important features. This article is devoted to one implementation of audio support. This implementation is schematically represented below:

AudioScheme.png

External data provides Boolean condition and name of sound file. If condition is equal to true then audio file begins play. For example if imitation model of airplane overpasses height of 60 m, then "Height 60 m.wav" file is played.

2. Elementary samples

2.1 Hello world

"Hello world" sample is presented below:

HelloWorld.png

The Formulae component provides condition and audio information. Properties of this compontent are presented below:

FormulaeProps.png

First formula returns "hello_world" string (italic symbols represent identifiers, no italic ones represent strings). Second formula represents audio condition. This condition means that audio should be played at time = 1. This condition correspond to peak on Chart component. Symbol '_' is token. It means that audio files "hello" and "world" should be sequentially played. The Sound object is audio component. It is connected to Formulae. Its properties are condition (Formulae.Formula_2) and sound file (Formulae.Formula_1) Following code snippet contains implementation of sequential play. Chart contains peak when audio condition is true

/// <summary>
/// Updates object
/// </summary>
void IUpdatableObject.UpdateObject()
{
    if (!test())
    {
        return;
    }
    bool soundCondition = (bool)condition.Parameter();      // Sound condition
    if (soundCondition)
    {
        string currentSound = sound.Parameter() as string;  // Sound file
        Play(currentSound);
    }                                                       // Plays sound
}

/// <summary>
/// Plays sound
/// </summary>
/// <param name="s">String with sound files</param>
void Play(string s)
{
    string[] sounds = s.Split(token); // Sounds
    Action play = () =>   // Play action
    {
        for (int i = 0; i < sounds.Length; i++)
        {
            if (!running)
            {
                return;
            }
            string fn = SoundCollection.SoundDirectory + sounds[i];
            if (!System.IO.File.Exists(fn))
            {
                ("Sound file '" + fn + " do not exist").Show();
                return;
            }
            try
            {
                System.Media.SoundPlayer pl = new System.Media.SoundPlayer();
                pl.SoundLocation = fn;
                pl.PlaySync();
            }
            catch (Exception ex)
            {
                ex.Log();
            }
        }
    };
    // Plays sounds in thread
    System.Threading.ThreadStart ts = new System.Threading.ThreadStart(play);
    System.Threading.Thread t = new System.Threading.Thread(ts);
    t.Start();
}

Formula editor supports constants of arbitrary type. This sample can be also represented by usage of constants. Following picture represents usage of constans.

FormulaePropsConst.png

Here sound file name is equal to s where s="hello_world" is string constant.

See instruction

2.2 Counter

Followning sample represent sequent play of files "0.wav", "1.wav", "2.wav", ..., "20.wav" at times t=0, 1, 2, ..., 20.

Counter.png

Peaks of Chart correspond times of playing. Formulae of codintion and filenames is presented below:

CounterFormulae.png

Formula_1 represent sum of integer number and constant string constant s=".wav". This sum is interpreted as C# sum. Varirable t is current time, meaning of UInt32(t) is evident for C# developers. Formula Formula_2 is true when time is near to integer. Following sample is more complicated

Counter100.png

If time is equal to 21 then this sample sequentially plays files "20.wav" and "1.wav" etc until time = 99. This sample contains following formula of sound files:

Counter100Formula.png

See instruction

2.3 Sound conversion component

Usage of formula editor is not always convenient. So sound conversion component has been developed. Conversion of integer values is only implemented now. However number of types shall be extended by further development. Following snippet represents conversion:
/// <summary>
/// Coversion of object to sound file
/// </summary>
/// <param name="o">Coverted object</param>
/// <returns>Sound filename(s)</returns>
string ConvertDouble(object o)
{
    StringBuilder sb = new StringBuilder();
    double d = (double)o;
    if (d < 0)
    {
        sb.Append("minus.wav_");
        d = -d;
    }
    uint h = (uint)d;
    if (h < 100)
    {
        TwoDigit(h, sb);
    }
    else if (h < 1000)
    {
        uint x = h % 100;
        uint y = (h - x) / 100;
        sb.Append(y);
        sb.Append(".wav_");
        sb.Append("hundred.wav");
        if (x > 0)
        {
            sb.Append("_");
            TwoDigit(x, sb);
        }
    }
    else
    {
        uint x = h % 100;
        uint y = (h - x) / 100;
        TwoDigit(y, sb);
        sb.Append("_");
        TwoDigit(x, sb);
    }
    return sb.ToString();
}

void TwoDigit(uint m, StringBuilder sb)
{
    if (m < 20)
    {
        sb.Append(m);
        sb.Append(".wav");
        return;
    }
    uint x = m % 10;
    uint y = (m - x) / 10;
    if (y > 1)
    {
        sb.Append(y);
        sb.Append("0.wav");
        if (x > 0)
        {
            sb.Append("_");
            sb.Append(x);
            sb.Append(".wav");
        }
    }
    else
    {
        sb.Append(x);
        sb.Append(".wav");
    }
}

Sample of this component application is presented below:

CounterComponent.png

Input of Sound String is Formulae.Formula_1 which is equal to rounded value of time. Output of Sound String is Sound String.Sound_1. This output is used as sound filename(s).

See instruction

3. Advanced samples

3. 1 Automatic Terminal Information Service, ATIS

Logic of ATIS is explained here. Following text contains typical ATIS message

Khabarovsk ATIS. Information Lima. One seven three zero. ILS approach runway two three left. Damp. Covered with wet snow patches seven millimetres. Braking action medium. Departure runway two three right. Wet. Braking action good. Transition level one thousand eight hundred metres. Threshold lights unservicable. Flocks of birds in aerodrome area and on final Wind zero five zero degrees six, maximum one zero metres per second. Visibility eight hundred metres. RVR. Runway two three left one thousand two hundred. Runway two three right one thousand four hundred. Fog. Drizzle. Cloud broken eight zero metres. Overcast four hundred. Temperature seven. Dew point six. Runway two three left QFE niner seven eight or seven three four millimetres. Runway two three right QFE niner eight zero or seven three five millimetres. Caution. Moderate icing between one hundred and one thousand seven hundred metres. Becoming from one eight zero zero, visibility one thousand five hundred metres. Mist. Acknowledge information Lima.

Source of above text

This section contains ATIS like scenario. This scenario is presented below:

ATIS.png

This sample plays ATIS messages and airplane robot messages about velocity and height. Meteorological data is provided by Http Meteo component. This component loads following web page:

MeteoComponentProperties.png

Central component of above form is WebBrowser. Web page comboboxes enable us change region. Parsing of the page provides following parameters:

NParameter nameParameter typeCurrent value of parameter
1Atmospheric pressure, mm mer. coldouble772
2Temperature, °Cdouble-2.6
3Temperature min., °Cdouble-2.4
4Temperature max., °Cdouble-
5CommentsstringSnow strong continuous
6Wind directionstringN-W
7Wind speed, m/sdouble772
1The general nebulosity valuedouble10
9Horizontal visibility, kmdouble1

These parametes do not contain angle of wind direction. However this parameter is useful since motion of airplane depends on this angle. Following code snippet containd rough estimation of this angle by wind direction

/// <summary>
 ///Rough estimation of wind direction angle dictionary
 /// </summary>
 public static readonly Dictionary<string, double> windAngles = new Dictionary<string, double>()
 {
    {"N", 0},
    {"N-E", 0.25 * Math.PI},
    {"E", 0.5 * Math.PI},
    {"S-E", 0.75 * Math.PI},
    {"S", Math.PI},
    {"S-W", 1.25 * Math.PI},
    {"W", 1.5 * Math.PI},
    {"N-W", 1.75 * Math.PI},
  };


/// <summary>
 ///Rough estimation of wind direction angle
 /// </summary>
 void SetWindAngle()
 {
     string d = values[7] + "";
     if (windAngles.ContainsKey(d))
     {
         values[8] = windAngles[d];
     }
 }

So this component also provides angle of wind direction. Usage of wind velocity and wind direction is twofold. First of all these parameters are used in ATIS audio message. Moreover these parameters are used in motion equations. Times of audio messages depend on simulated aircraft motion. ATIS message time depends on distance to airport. Height (resp. velocity) messages are being played in transition of height (resp. velocity) times. All these times correspond to peaks on Chart ATIS component. Red peak corresponds to ATIS message, blue (resp. green) peaks correspond to height (resp.) velocity messages. Here very simplified motion equations are used. Motion is planar (vertical plane). Nominal height depends on distance, nominal velocity depends on height. The Equations component contains differential equations of airplane. As it is noted this equations depends on wind velocity and wind direction. Recursive elements are used for definition of transition times by usage of recursive elements. Let x1, ..., xn be sequence of values of p parameter and transition value is equal to a. Then condition of transition is xi-1 < a < xi. Recursive element provides value xi-1 at ith moment. This scenario contains tables of transition values.

TableOfHeights.png

Column Y of this table contains heights 250, 200, 150, ..., 1 of playing of audofiles "St H 250.wav", "St H 200.wav", "St H 150.wav", ..., "St H 1.wav". Similarly Velocities table is responsible for playing "St V 220.wav", "St V 200.wav", ..., "St V 140.wav" Airplain robot send voice messages (in Russian) about current height and velocity.

See instruction

3.2 Audio + Video

This sample is extesion of previous one by video. All components of previous samlple are aggregated into single container.

Container.png

Checked components are public elements of container. Full scenario of audio + video is presented below:

AudioVideo.png

This scenarion contains Motion + Audio container from prevoius section. Motion parameters are used for 3D visualisation. Also this scenario uses 3D models of airplane and ground. Since file of this scenario exceeds 6 MB this file is uploaded to sourceforge.

See instruction

3.3 Wpf appplication

Universal framework should interoperate with dififferent applications. So it should have low coupling with System.Windows.Forms. So UI libraries (which reference to System.Windows.Forms) are sepatated from libraries which contains business logic. Library WpfInterface. Following table represents this separation.
NFunctionalityBusiness logic librarySystem.Windows.Forms user interface library
1Wpf 3D animationWpfInterface.dllWpfInterface.UI.dll
2Meteo ServiceHttp.Meteo.dllHttp.Meteo.UI.dll

This separation enables usage of framework in applications which do not refernce System.Windows.Forms. Solution Aviation.Wpf3D.Advanced.sln contains Wpf application project Aviation.WpfApplication.csproj. Following scenario is constructed by System.Windows.Forms project.

Audio_Wpf_Scenario.png

Then this scenario is used in following WPF application

Audio_Wpf_Application.png

4. Short instruction

4.1 Installation of audio files

Installation of audio files includes following steps.
Step 1. Unpacking sound archive to any directory

Step 2. Setting directory of unpacked files by following way

SoundsDir.png

4.2 Installation of containes

Unpack Containers.zip file to directory of Aviation.Wpf3D.Advanced.exe file;

Simulation modes

Chart object has two modes of simulation

  • Calculation;
  • Animation.

Following buttons correspond these modes:

SimulationModes.png

Calculation mode provides numerical results represented in charts or texts. Animation mode provides audio and 3D video. CalculationReasonsAttribute is responsible to mode. For example sound component has following value of this attribute:
/// <summary>
/// Multiple sound
/// </summary>
[Serializable()]
[CalculationReasons(new string[]{"Animation"})]
public class MultiSound   : CategoryObject, ISerializable,
    IDataConsumer, IPostSetArrow,
    ITimeMeasureConsumer, IUpdatableObject, IStopped, IStarted
It means that this component is active in animation mode only.

5. Points of interests

I desired to develop audio support at 2002 year. Better late than never.

6. Acknowledgment

I would like to acknowledge ENIcommunications Corp for British English voice prompts

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)