Click here to Skip to main content
15,896,348 members
Articles / Programming Languages / C#

Fundamentals of Sound: How to Make Music out of Nothing at All

Rate me:
Please Sign up or sign in to vote.
4.89/5 (106 votes)
30 May 2007CPOL10 min read 237K   3.8K   211  
This article describes the basics of sound waves as well as the PCM WAVE format, and illustrates how to create music by writing your own custom wave form.
using System;
using System.IO;

namespace CPI.Audio
{
    /// <summary>
    /// A class to write 8-bit wave files.
    /// </summary>
    public class WaveWriter8Bit : WaveWriter
    {
        # region Constructors

        /// <summary>
        /// Instatiates a new WaveWriter8Bit object.
        /// </summary>
        /// <param name="output">A Stream object to write the wave to.</param>
        /// <param name="sampleRate">Specifies the sample rate (number of samples per second) of the wave file.</param>
        /// <param name="stereo">Specifies whether this is a mono or stereo wave file.</param>
        /// <remarks>
        /// When this object is disposed, it will close its underlying stream.  To change this default behavior,
        /// you can call an overloaded constructor which takes a closeUnderlyingStream parameter.
        /// </remarks>
        public WaveWriter8Bit(Stream output, int sampleRate, bool stereo)
            : this(output, sampleRate, stereo, true) { }

        /// <summary>
        /// Instatiates a new WaveWriter8Bit object.
        /// </summary>
        /// <param name="output">A Stream object to write the wave to.</param>
        /// <param name="sampleRate">Specifies the sample rate (number of samples per second) of the wave file.</param>
        /// <param name="stereo">Specifies whether this is a mono or stereo wave file.</param>
        /// <param name="closeUnderlyingStream">
        /// Determines whether to close the the stream that the WaveWriter is writing to when the WaveWriter is closed.
        /// </param>
        public WaveWriter8Bit(Stream output, int sampleRate, bool stereo, bool closeUnderlyingStream)
            : base(output, sampleRate, 8, stereo, closeUnderlyingStream) {}

        # endregion

        # region Methods

        /// <summary>
        /// Reads a sample from the wave file.
        /// </summary>
        /// <returns>The data read from the wave file.</returns>
        public Sample8Bit Read()
        {
            ThrowIfDisposed();

            long initialPos = Reader.BaseStream.Position;

            try
            {
                if (Header.Stereo)
                {
                    return new Sample8Bit(Reader.ReadByte(), Reader.ReadByte());
                }
                else
                {
                    return new Sample8Bit(Reader.ReadByte());
                }
            }
            catch
            {
                Reader.BaseStream.Position = initialPos;
                
                throw;
            }
        }

        /// <summary>
        /// Writes a sample to the wave file.
        /// </summary>
        /// <param name="sample">The sample information to write.</param>
        public void Write(Sample8Bit sample)
        {
            ThrowIfDisposed();

            long initialPos = Writer.BaseStream.Position;

            try
            {
                Writer.Write(sample.LeftChannel);

                if (Header.Stereo)
                    Writer.Write(sample.RightChannel);
            }
            catch
            {
                Writer.BaseStream.Position = initialPos;

                throw;
            }
            finally
            {
                if (CurrentSample > Header.NumberOfSamples)
                    Header.NumberOfSamples = CurrentSample;
            }
        }

        # endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Software Developer (Senior)
United States United States
Pete has just recently become a corporate sell-out, working for a wholly-owned subsidiary of "The Man". He counter-balances his soul-crushing professional life by practicing circus acrobatics and watching Phineas and Ferb reruns. Ducky Momo is his friend.

Comments and Discussions