Click or drag to resize

Song Class

Allows creation of a synthesized musical score storing the resultant song in an in-memory wave file for play back or saving music to disk.
Inheritance Hierarchy
SystemObject
  GSF.MediaWaveFile
    GSF.Media.MusicSong

Namespace: GSF.Media.Music
Assembly: GSF.Media (in GSF.Media.dll) Version: 2.4.218-beta
Syntax
public class Song : WaveFile
View Source

The Song type exposes the following members.

Constructors
 NameDescription
Public methodSong Creates a new song with a 3/4 measure size, a tempo of 240 quarter-notes per minute, mezzo-forte prevailing dynamic level, using a basic note timbre and standard CD-quality settings for the underlying sound file.
Public methodSong(SampleRate, BitsPerSample, DataChannels) Creates a new song with a 3/4 measure size, a tempo of 240 quarter-notes per minute, mezzo-forte prevailing dynamic level, using a basic note timbre and the specified audio format settings.
Top
Properties
 NameDescription
Public propertyAmplitudeScalar Returns the amplitude scalar for the given bits per sample of the WaveFile (i.e., maximum value for given BitsPerSample).
(Inherited from WaveFile)
Public propertyAudioFormat Gets or sets audio format used by the WaveFile.
(Inherited from WaveFile)
Public propertyAudioLength Gets calculated audio length.
(Inherited from WaveFile)
Public propertyBeatTime Returns the time for a single beat.
Public propertyBitsPerSample Gets or sets number of bits-per-sample in the WaveFile.
(Inherited from WaveFile)
Public propertyBlockAlignment Gets or sets the block size of a complete sample of data (i.e., samples for all channels of data at one instant in time).
(Inherited from WaveFile)
Public propertyByteRate Gets or sets the byte rate used for buffer estimation.
(Inherited from WaveFile)
Public propertyChannels Gets or sets number of audio channels in the WaveFile.
(Inherited from WaveFile)
Public propertyDamping Gets or sets the default damping function used to lower the sound volume of the added notes over time. This damping function will be used if no other function is specified when adding notes.
Public propertyDataChunk Gets or sets the WaveDataChunk of this WaveFile.
(Inherited from WaveFile)
Public propertyDynamic Gets or sets the prevailing dynamic (i.e., volume) expressed as percentage in the range of 0 to 1 for the song. Individual notes can choose to override this dynamic.
Public propertyExtraParameters Gets or sets any extra parameters defined in the format header of the WaveFile.
(Inherited from WaveFile)
Public propertyExtraParametersSize Gets the size of the ExtraParameters buffer, if defined.
(Inherited from WaveFile)
Public propertyFormatChunk Gets or sets the WaveFormatChunk of this WaveFile.
(Inherited from WaveFile)
Public propertyHeaderChunk Gets or sets the RiffHeaderChunk of this WaveFile.
(Inherited from WaveFile)
Public propertyInfoChunk Gets the ListInfoChunk of this WaveFile.
(Inherited from WaveFile)
Public propertyInfoStrings Gets list of info strings available in this WaveFile if any were available during load; otherwise an empty dictionary.
(Inherited from WaveFile)
Public propertyInterNoteDelayInjects specified rest time, in seconds, between notes.
Public propertyMeasureSize Gets current measure size or defines a new measure size for the song.
Public propertyNamedDynamic Gets or sets the prevailing named dynamic (i.e., volume) for the song. Individual notes can choose to override this dynamic.
Public propertySampleBlocks Accesses each individual block of sample data indexed by time.
(Inherited from WaveFile)
Public propertySampleRate Gets or sets the sample rate (i.e., the number of samples per second) defined in the WaveFile.
(Inherited from WaveFile)
Public propertyTempo Gets current tempo or defines a new tempo for the song.
Public propertyTimbre Gets or sets the default tibre function used to synthesize the sounds of the added notes (i.e., the instrument). This timbre function will be used if no other function is specified when adding notes.
Top
Methods
 NameDescription
Public methodAddNotes Add a series of notes to the song.
Public methodAddPhrase Add a predefined phrase of notes to the song.
Public methodAddRest(Double) Add a rest for the given length for the current beat.
Public methodAddRest(NoteValue) Add a rest for the given length for the current beat.
Public methodAddRest(NoteValueBritish) Add a rest for the given length for the current beat.
Public methodAddRest(NoteValue, Int32) Add a rest for the given length for the current beat.
Public methodAddRest(NoteValueBritish, Int32) Add a rest for the given length for the current beat.
Public methodAddSample Add the sample to the wave file.
(Inherited from WaveFile)
Public methodAddSampleBlock Adds a block of samples in native format to the wave file (e.g., if BitsPerSample = 16, parameters need to be Int16 values). Note that LittleBinaryValue parameter type is implicitly castable to common native types, including floating points.
(Inherited from WaveFile)
Public methodAddSamples Adds a series of samples, one per channel, to the wave file.
(Inherited from WaveFile)
Public methodCastSample Casts sample value to its equivalent native type based on defined BitsPerSample and AudioFormat.
(Inherited from WaveFile)
Public methodClone Creates a deeply cloned copy of the WaveFile.
(Inherited from WaveFile)
Public methodEqualsDetermines whether the specified object is equal to the current object.
(Inherited from Object)
Protected methodFinalizeAllows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.
(Inherited from Object)
Public methodFinish Called when there are no more notes to add.
Public methodGetHashCodeServes as the default hash function.
(Inherited from Object)
Public methodGetSampleTypeCode Determines sample data type code based on defined BitsPerSample and AudioFormat.
(Inherited from WaveFile)
Public methodGetTypeGets the Type of the current instance.
(Inherited from Object)
Protected methodMemberwiseCloneCreates a shallow copy of the current Object.
(Inherited from Object)
Public methodPlay Plays the wave file using SoundPlayer.
(Inherited from WaveFile)
Public methodReverse Reverses the data samples in the wave file.
(Inherited from WaveFile)
Public methodSave(Stream) Saves wave file to the specified stream.
(Inherited from WaveFile)
Public methodSave(String) Saves wave file to the specified file name.
(Inherited from WaveFile)
Public methodSetCrescendoDynamic Starts crescendo dynamic over the range of the specified number of beats.
Public methodSetDiminuendoDynamic Starts diminuendo dynamic over the range of the specified number of beats.
Public methodToStringReturns a string that represents the current object.
(Inherited from Object)
Top
Extension Methods
 NameDescription
Public Extension MethodGetEnumValueOrDefault Gets the enumeration constant for value, if defined in the enumeration, or a default value.
(Defined by EnumExtensions)
Public Extension MethodGetEnumValueOrDefaultT Gets the enumeration constant for this value, if defined in the enumeration, or a default value.
(Defined by EnumExtensions)
Top
Example
This example generates a multi-instrument chord:
C#
using System;
using GSF.Media;
using GSF.Media.Music;

static class Program
{
    static void Main()
    {
        Song song = new Song { Damping = Damping.Linear };

        Console.WriteLine("Generating multi-instrument chord...");

        song.AddNotes
        (
            new Note { Frequency = Note.C4, Value = 4, Timbre = Timbre.EvenHarmonicSeries },
            new Note { Frequency = Note.C4, Value = 4, Timbre = Timbre.Clarinet },
            new Note { Frequency = Note.C4, Value = 4, Timbre = Timbre.Organ },
            new Note { Frequency = Note.E4, Value = 4, Timbre = Timbre.EvenHarmonicSeries },
            new Note { Frequency = Note.E4, Value = 4, Timbre = Timbre.Clarinet },
            new Note { Frequency = Note.E4, Value = 4, Timbre = Timbre.Organ },
            new Note { Frequency = Note.G4, Value = 4, Timbre = Timbre.EvenHarmonicSeries },
            new Note { Frequency = Note.G4, Value = 4, Timbre = Timbre.SimulatedClarinet },
            new Note { Frequency = Note.G4, Value = 4, Timbre = Timbre.SimulatedOrgan }
        );

        song.Finish();

        Console.WriteLine("Saving chord to disk...");
        song.Save("MajorTriad.wav");

        Console.WriteLine("Playing chord...");
        song.Play();

        Console.ReadKey();
    }
}
This example generates a familiar tune, plays the song and saves it to disk:
C#
// Add reference to System.Speech
using System;
using System.IO;
using GSF.Media;
using GSF.Media.Music;
using System.Speech;
using System.Speech.Synthesis;
using System.Speech.AudioFormat;

static class Program
{
    static void Main()
    {
        Console.WriteLine("Synthesizing speech...");
        WaveFile speech = CreateSynthesizedVoiceOver();

        Console.WriteLine("Synthesizing song at tempo for use with speech...");

        // Define all the notes of jingle bells as a single phrase of music
        Phrase score = CreateJingleBellsScore();

        // Create one song at a slower tempo to help with speech synchronization
        Song speechTempSong = new Song { Tempo = new Tempo(160, NoteValue.Quarter) };

        // Make sure audio specifications for song and speech match
        speechTempSong.SampleRate = speech.SampleRate;
        speechTempSong.BitsPerSample = speech.BitsPerSample;
        speechTempSong.Channels = speech.Channels;

        // Add all the notes to the song
        speechTempSong.AddPhrase(score);
        speechTempSong.Finish();

        Console.WriteLine("Synthesizing song by itself at normal tempo...");

        // Create one song at a slower tempo to help with speech synchronization
        Song normalTempoSong = new Song();

        // Add all the notes to the song
        normalTempoSong.AddPhrase(score);
        normalTempoSong.Finish();

        Console.WriteLine("Saving normal tempo song to disk as \"JingleBells.wav\"...");
        normalTempoSong.Save("JingleBells.wav");

        Console.WriteLine("Combining speech with song...");
        WaveFile combined = WaveFile.Combine(speech, speechTempSong);

        Console.WriteLine("Saving combined work to disk as \"SingingComputer.wav\"...");
        combined.Save("SingingComputer.wav");

        Console.WriteLine("Playing combined work...");
        combined.Play();

        Console.ReadKey();
    }

    private static WaveFile CreateSynthesizedVoiceOver()
    {
        SpeechSynthesizer synthesizer = new SpeechSynthesizer();
        MemoryStream speechStream = new MemoryStream();
        PromptBuilder songText = new PromptBuilder();

        synthesizer.SelectVoice("Microsoft Sam");
        synthesizer.Rate = 5; // Range = -10 to +10
        synthesizer.SetOutputToWaveStream(speechStream);

        songText.AppendText("Jin - gull bells!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(3000000));
        songText.AppendText("Jin - gull bells!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(3000000));
        songText.AppendText("Jin - gull - all, theuh - way!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(12000000));
        songText.AppendText("Oh - what - fun!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(1000000));
        songText.AppendText("It - is!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(500000));
        songText.AppendText("To - ride!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(500000));
        songText.AppendText("a - one - horse!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(500000));
        songText.AppendText("Open!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(500000));
        songText.AppendText("Sleigh!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(1000000));
        songText.AppendText("A!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(2500000));
        songText.AppendText("Jin - gull bells!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(3000000));
        songText.AppendText("Jin - gull bells!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(3000000));
        songText.AppendText("Jin - gull - all, theuh - way!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(12000000));
        songText.AppendText("Oh - what - fun!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(1000000));
        songText.AppendText("It - is!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(500000));
        songText.AppendText("To - ride!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(500000));
        songText.AppendText("a - one - horse!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(500000));
        songText.AppendText("Open!", PromptEmphasis.Strong);
        songText.AppendBreak(new TimeSpan(500000));
        songText.AppendText("Sleigh.", PromptEmphasis.Reduced);

        synthesizer.Speak(songText);
        speechStream.Position = 0;
        return WaveFile.Load(speechStream);
    }

    private static Phrase CreateJingleBellsScore()
    {
        Phrase score = new Phrase();
        Phrase passage = new Phrase();

        // Define the repeating phrase of the song
        passage.AddNotes
        (
            new Note { Frequency = Note.B3, NamedValue = NoteValue.Quarter },
            new Note { Frequency = Note.C3, NamedValue = NoteValue.Whole }
        );
        passage.AddNotes(new Note { Frequency = Note.B3, NamedValue = NoteValue.Quarter });
        passage.AddNotes(new Note { Frequency = Note.B3, NamedValue = NoteValue.Half });

        passage.AddNotes
        (
            new Note { Frequency = Note.B3, NamedValue = NoteValue.Quarter },
            new Note { Frequency = Note.G3, NamedValue = NoteValue.Whole }
        );
        passage.AddNotes(new Note { Frequency = Note.B3, NamedValue = NoteValue.Quarter });
        passage.AddNotes(new Note { Frequency = Note.B3, NamedValue = NoteValue.Half });

        passage.AddNotes
        (
            new Note { Frequency = Note.B3, NamedValue = NoteValue.Quarter },
            new Note { Frequency = Note.C3, NamedValue = NoteValue.Whole }
        );
        passage.AddNotes(new Note { Frequency = Note.D4, NamedValue = NoteValue.Quarter });
        passage.AddNotes(new Note { Frequency = Note.G3, NamedValue = NoteValue.Quarter });
        passage.AddNotes(new Note { Frequency = Note.A3, NamedValue = NoteValue.Quarter });

        passage.AddNotes
        (
            new Note { Frequency = Note.B3, NamedValue = NoteValue.Whole },
            new Note { Frequency = Note.G3, NamedValue = NoteValue.Whole }
        );

        passage.AddNotes
        (
            new Note { Frequency = Note.C4, NamedValue = NoteValue.Quarter },
            new Note { Frequency = Note.D3, NamedValue = NoteValue.Whole }
        );
        passage.AddNotes(new Note { Frequency = Note.C4, NamedValue = NoteValue.Quarter });
        passage.AddNotes(new Note { Frequency = Note.C4, NamedValue = NoteValue.Quarter });
        passage.AddNotes(new Note { Frequency = Note.C4, NamedValue = NoteValue.Quarter });

        passage.AddNotes
        (
            new Note { Frequency = Note.C4, NamedValue = NoteValue.Quarter },
            new Note { Frequency = Note.G3, NamedValue = NoteValue.Whole }
        );
        passage.AddNotes(new Note { Frequency = Note.B3, NamedValue = NoteValue.Quarter });
        passage.AddNotes(new Note { Frequency = Note.B3, NamedValue = NoteValue.Quarter });
        passage.AddNotes(new Note { Frequency = Note.B3, NamedValue = NoteValue.Quarter });

        score.AddPhrase(passage);

        score.AddNotes
        (
            new Note { Frequency = Note.B3, NamedValue = NoteValue.Quarter },
            new Note { Frequency = Note.F3S, NamedValue = NoteValue.Whole }
        );
        score.AddNotes(new Note { Frequency = Note.A3, NamedValue = NoteValue.Quarter });
        score.AddNotes(new Note { Frequency = Note.A3, NamedValue = NoteValue.Quarter });
        score.AddNotes(new Note { Frequency = Note.B3, NamedValue = NoteValue.Quarter });

        score.AddNotes
        (
            new Note { Frequency = Note.A3, NamedValue = NoteValue.Half },
            new Note { Frequency = Note.G3, NamedValue = NoteValue.Whole }
        );
        score.AddNotes(new Note { Frequency = Note.D4, NamedValue = NoteValue.Half });

        score.AddPhrase(passage);

        score.AddNotes
        (
            new Note { Frequency = Note.D4, NamedValue = NoteValue.Quarter },
            new Note { Frequency = Note.G3, NamedValue = NoteValue.Whole },
            new Note { Frequency = Note.F3, NamedValue = NoteValue.Whole }
        );
        score.AddNotes(new Note { Frequency = Note.D4, NamedValue = NoteValue.Quarter });
        score.AddNotes(new Note { Frequency = Note.C4, NamedValue = NoteValue.Quarter });
        score.AddNotes(new Note { Frequency = Note.A3, NamedValue = NoteValue.Quarter });

        score.AddNotes
        (
            new Note { Frequency = Note.G3, NamedValue = NoteValue.Whole },
            new Note { Frequency = Note.E3, NamedValue = NoteValue.Whole }
        );

        return score;
    }
}
See Also