Click here to Skip to main content
15,893,904 members
Articles / Programming Languages / C#

Compose sounds from frequencies and visualize them

Rate me:
Please Sign up or sign in to vote.
4.87/5 (53 votes)
17 Apr 2006CPOL6 min read 191.8K   3.5K   162  
What you never wanted to know about PCM.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WaveMixer
{
    public partial class MainForm : Form
    {
		WaveUtility utility;
        
        public MainForm()
        {
            InitializeComponent();
			utility = new WaveUtility();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
			CreateWave();
        }

        private void btnAddWave_Click(object sender, EventArgs e)
        {
			AddWave();
        }

        private void btnAddRandom_Click(object sender, EventArgs e)
        {
			string message = "Minimum must be less than or equal to maximum.";
			bool canStart = true;

			//remove old error meessage
			errors.SetError(numRandomFrequencyMax, string.Empty);
			errors.SetError(numRandomAmplitudeMax, string.Empty);
			errors.SetError(numRandomOffsetMax, string.Empty);
			errors.SetError(numRandomDurationMax, string.Empty);

			//check values
			if (numRandomFrequencyMin.Value > numRandomFrequencyMax.Value)
			{
				errors.SetError(numRandomFrequencyMax, message);
				canStart = false;
			}
			if (numRandomAmplitudeMin.Value > numRandomAmplitudeMax.Value)
			{
				errors.SetError(numRandomAmplitudeMax, message);
				canStart = false;
			}
			if (numRandomOffsetMin.Value > numRandomOffsetMax.Value)
			{
				errors.SetError(numRandomOffsetMax, message);
				canStart = false;
			}
			if (numRandomDurationMin.Value > numRandomDurationMax.Value)
			{
				errors.SetError(numRandomDurationMax, message);
				canStart = false;
			}

			if (canStart)
			{	//add random waves
				AddRandomWaves();
			}
		}

		private void nunWidth_ValueChanged(object sender, EventArgs e)
		{
			PaintWave();
		}

		private void numHeight_ValueChanged(object sender, EventArgs e)
		{
			PaintWave();
		}

		private void sbWidth_Scroll(object sender, ScrollEventArgs e)
		{
			numWidth.Value = sbWidth.Value;
		}

		private void sbHeight_Scroll(object sender, ScrollEventArgs e)
		{
			numHeight.Value = sbHeight.Value;
		}

		private void tabctlVisualization_Selected(object sender, TabControlEventArgs e)
		{
			if (e.TabPage == tabSynaesthesia)
			{
				PaintWave();
			}
		}

		private void channelColor_CheckChanged(object sender, EventArgs e)
		{
			PaintWave();
		}

		private void btnNewWave_Click(object sender, EventArgs e)
		{
			CreateWave();
		}

		private void btnChangeVolume_Click(object sender, EventArgs e)
		{
			WaveSound waveSound = waveControl.WaveSound;
			utility.ChangeAmplitude(waveSound, waveControl.MaxSampleValue, (short)numChangeVolume.Value);
			DisplayWave();
		}

		private void DisplayWave()
		{
			waveControl.DrawWave();
			if (tabctlVisualization.SelectedTab == tabSynaesthesia)
			{
				PaintWave();
			}
		}

		/// <summary>Adds a specific wave to the current wave.</summary>
		private void AddWave()
		{
			WaveSound waveSound = waveControl.WaveSound;
			WaveUtility utility = new WaveUtility();
			utility.AddWave(waveSound, (float)numFrequency.Value, (float)numOffset.Value, (float)numDuration.Value, (int)numAmplitude.Value);
			
			//display the changed wave
			DisplayWave();
		}

		/// <summary>Adds random waves to the current wave.</summary>
		private void AddRandomWaves()
		{
            this.Cursor = Cursors.WaitCursor;
            try
            {
                WaveSound waveSound = waveControl.WaveSound;

                WaveUtility utility = new WaveUtility();
                Random random = new Random();

                int count = (int)numRandomCount.Value;
                float minFrequency = (float)numRandomFrequencyMin.Value;
                float maxFrequency = (float)numRandomFrequencyMax.Value;
                float scaleFrequency = maxFrequency - minFrequency;

				float minOffset = (float)numRandomOffsetMin.Value;
				float maxOffset = (float)numRandomOffsetMax.Value;
				float scaleOffset = maxOffset - minOffset;

                float minDuration = (float)numRandomDurationMin.Value;
                float maxDuration = (float)numRandomDurationMax.Value;
                float scaleDuration = maxDuration - minDuration;

                int minAmplitude = (int)numRandomAmplitudeMin.Value;
                int maxAmplitude = (int)numRandomAmplitudeMax.Value;

                for (int n = 0; n < count; n++)
                {
                    utility.AddWave(
                        waveSound,
                        (float)random.NextDouble() * scaleFrequency + minFrequency,
						(float)random.NextDouble() * scaleOffset + minOffset,
						(float)random.NextDouble() * scaleDuration + minDuration,
						(int)random.Next(minAmplitude, maxAmplitude));
                }

				//display the changed wave
				DisplayWave();
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
        }

		/// <summary>Paints a bitmap for the current wave.</summary>
		private void PaintWave()
		{
			this.Cursor = Cursors.WaitCursor;
			try
			{
				picSynaesthesia.Width = (int)numWidth.Value;
				picSynaesthesia.Height = (int)numHeight.Value; 
					
				WaveSound waveSound = waveControl.WaveSound;

				ChannelColorFlags firstChannelColors = new ChannelColorFlags();
				firstChannelColors.IsRed = chkStereoLR.Checked;
				firstChannelColors.IsGreen = chkStereoLG.Checked;
				firstChannelColors.IsBlue = chkStereoLB.Checked;

				ChannelColorFlags secondChannelColors = new ChannelColorFlags();
				secondChannelColors.IsRed = chkStereoRR.Checked;
				secondChannelColors.IsGreen = chkStereoRG.Checked;
				secondChannelColors.IsBlue = chkStereoRB.Checked;

				Bitmap waveBitmap = utility.PaintWave(
					waveSound, 
					picSynaesthesia.Width,
					picSynaesthesia.Height, 
					firstChannelColors, 
					secondChannelColors, 
					chkConvertSignedToAbsoluteValues.Checked,
					chkScaleSamplesForPainting.Checked,
					waveControl.MaxSampleValue);
				picSynaesthesia.Image = waveBitmap;
			}
			finally
			{
				this.Cursor = Cursors.Default;
			}
		}

		/// <summary>Starts a new, empty wave.</summary>
		private void CreateWave()
		{
			WaveFormat format = new WaveFormat(44100, 16, 2);
			short[] samples = new short[(int)(format.Channels * format.SamplesPerSec * numNewWave.Value)];
			WaveSound waveSound = new WaveSound(format, samples);
			waveControl.WaveSound = waveSound;

			if (numOffset.Value > numNewWave.Value)
			{
				numOffset.Value = 0;
			}
			if (numRandomOffsetMin.Value > numNewWave.Value)
			{
				numRandomOffsetMin.Value = 0;
			}
			if (numRandomOffsetMax.Value > numNewWave.Value)
			{
				numRandomOffsetMax.Value = numNewWave.Value;
			}
		}
    }
}

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
Germany Germany
Corinna lives in Hanover/Germany and works as a C# developer.

Comments and Discussions