Laden...

Beep über Soundkarte ausgeben

Erstellt von klausm vor 15 Jahren Letzter Beitrag vor 13 Jahren 6.567 Views
K
klausm Themenstarter:in
3 Beiträge seit 2008
vor 15 Jahren
Beep über Soundkarte ausgeben

Hallo,
ich will Töne anhand der Frequenz und der Dauer erstellen. Console.Beep erledigt das ja schon mal ganz schön. Allerdings will ich die Töne nicht über den Systemlautsprecher ausgeben lassen, sondern über die Soundkarte/externen Lautsprecher. Kann mir da vielleicht jemand weiterhelfen?
Danke.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo klausm,

das Thema wurde schon einige Male besprochen. Bitte benutze die Forumssuche und poste die besten Treffer hier. Vielen Dank!

herbivore

K
klausm Themenstarter:in
3 Beiträge seit 2008
vor 15 Jahren

ok, ich hab zwar gesucht aber einfach zu durchschauendes gefunden, sondern nur ellenlange codestücke. aber dann halt so und umständlicher....

Ich habs mit dem Code von hier versucht und Teile davon verwendet. Vielleicht sagen einigen ja 5-Ton-Folgen was, wird zur Alarmierung von Rettungsdienst etc. verwendet. Dabei werden 5 Töne hintereinander abgespielt, je nach "Schleife". Die setzt sich eben aus 5 Zahlen zusammen, jede Zahl ist ein Ton der 70ms dauert, danach folgt der nächste bis eben alle 5 durch sind, und das 2x hintereinander mit einer Unterbrechung von 600ms.

Das klappt zwar alles, allerdings "hängt" das abspielen irgendwie. Vielleicht liegt's an Vista oder an meiner Soundkarte (Realtek AC'97).

hier mein code


private static int[] Hertz = { 2600, 1060, 1160, 1270, 1400, 1530, 1670, 1830, 2000, 2200, 2400 };

		public static void play5Ton( int tonfolge, System.Windows.Forms.Form f )
		{
			/*
			 * 2 gleiche Töne folgen -> 2400 abspielen an 2. Stelle
			 * wenn dann wieder der gleiche Ton -> wieder normaler Ton
			*/
			bool folgen = false;
			List<int> hertztoene = new List<int>();
			for ( int i = 0; i < 5; i++ )
			{
				char c = tonfolge.ToString()[i];
				int ton = 0;
				if ( i > 0 && c.Equals(tonfolge.ToString()[i-1]) && !folgen)
				{
					ton = 10;
					folgen = true;
				}
				else
				{
					switch ( c )
					{
						case '1':
							ton = 1; break;
						case '2':
							ton = 2; break;
						case '3':
							ton = 3; break;
						case '4':
							ton = 4; break;
						case '5':
							ton = 5; break;
						case '6':
							ton = 6; break;
						case '7':
							ton = 7; break;
						case '8':
							ton = 8; break;
						case '9':
							ton = 9; break;
					}
					folgen = false;
				}
				hertztoene.Add( Hertz[ton] );
			}
			SoundGen sg = new SoundGen( f );
			for ( int j = 0; j < 2; j++ )
			{
				foreach ( int ton in hertztoene )
				{
					sg.Beep( ton, 70 );
					//Console.Beep( ton, 70 );
				}
				if ( j == 0)
					Thread.Sleep( 600 );
			}
		}

hier noch der Code für die SoundGenerator Klasse


using Microsoft.DirectX;
using Microsoft.DirectX.DirectSound;

namespace SG
{
	public class SoundGen
	{
		private struct Osc
		{
			public double dphi;     // frequency
			public double phase;    // phase accumulator
			public int duration;    // duration in msec.
		}

		#region constants
		/// <summary>
		/// 10 ms in bytes
		/// </summary>
		public const int NotifySize = 160 * 2 * 2;

		/// <summary>
		/// Number of Record notifications
		/// </summary>
		private const int RecordNotifications = 4;

		/// <summary>
		/// buffer size in bytes
		/// </summary>
		public const int OutputBufferSize = NotifySize * RecordNotifications;

		/// <summary>
		/// Final buffer size
		/// 220 ms
		/// </summary>
		private const int BufferLength = 320 * 2;//*220 msec.
		#endregion

		#region fields
		private SecondaryBuffer buffer = null;
		private Device device = null;
		private BufferDescription description = null;
		private WaveFormat format;

		private bool squareWave = false;

		private bool playing = false;

		Osc osc = new Osc();
		#endregion

		#region Properties
		public bool SquareWave
		{
			get
			{
				return squareWave;
			}
			set
			{
				if ( squareWave != value )
					squareWave = value;
			}
		}
		public SecondaryBuffer Buffer
		{
			get
			{
				return buffer;
			}
		}
		#endregion

		#region Constructor
		/// <summary>
		/// Constructor
		/// </summary>
		public SoundGen(Control control)
			: base()
		{
			try
			{
				device = new Device();
				device.SetCooperativeLevel( control, CooperativeLevel.Normal );
			}
			catch
			{
			}

			format = new WaveFormat();
			format.BlockAlign = 2 * 2;
			format.AverageBytesPerSecond = 16000 * 2;
			format.FormatTag = WaveFormatTag.Pcm;
			format.Channels = 1 * 2; // stereo
			format.BitsPerSample = 16;
			format.SamplesPerSecond = 8000;

			description = new BufferDescription( format );
			description.BufferBytes = OutputBufferSize;
			description.ControlVolume = true;
			description.CanGetCurrentPosition = true;

			buffer = new SecondaryBuffer( description, device );
			buffer.Volume = -1500;

			Clear();
		}
		#endregion


		#region Beep
		public void Beep( int frequency, int duration )
		{
			if ( playing )
				return;

			osc.duration = duration;
			osc.dphi = frequency * 1.25e-4;
			osc.phase = 0;

			playing = true;
			int time = 0;
			int lockSize;
			int playPos;
			int offset = 0;

			buffer.Play( 0, BufferPlayFlags.Looping );
			Generate( offset );

			while ( playing )
			{
				playPos = buffer.PlayPosition;

				lockSize = playPos - offset;

				if ( lockSize < 0 )
					lockSize += OutputBufferSize;

				lockSize -= ( lockSize % BufferLength );
				if ( lockSize == 0 )
				{ }
				else
				{
					offset += Generate( offset );

					offset %= OutputBufferSize;

					time += 20;

					if ( time >= duration )
						playing = false;
				}
			}

			//Hier fällt auf, wenn ich hier stoppe, gibt er keinen Ton von sich!
			buffer.Stop();
		}
		#endregion

		private int Generate( int offset )
		{
			byte[] data = new byte[BufferLength];
			Int32 outword;

			for ( int i = 0; i < BufferLength; )
			{
				if ( !squareWave )
					// Sine
					outword = (Int32)( Math.Sin( osc.phase ) * ( 32767 ) );
				else
				{
					// Square
					if ( Math.Sin( osc.phase ) >= 0 )
						outword = 0x7fff;
					else
						outword = 0x8000;
				}

				osc.phase += 2 * Math.PI * osc.dphi;
				if ( osc.phase > Math.PI * 2 )
					osc.phase -= Math.PI * 2;

				data[i++] = (System.Byte)( outword & 0xff );//lsb
				data[i++] = (System.Byte)( ( outword >> 8 ) & 0xff );//msb
				data[i++] = (System.Byte)( outword & 0xff );//lsb
				data[i++] = (System.Byte)( ( outword >> 8 ) & 0xff );//msb
			}

			buffer.Write( offset, data, LockFlag.None );

			return data.Length;
		}

		private void Zero( int offset )
		{
			byte[] data = new byte[BufferLength];
			osc.phase = 0;

			for ( int i = 0; i < BufferLength; )
			{
				data[i++] = (System.Byte)( 0 & 0xff );//lsb
				data[i++] = (System.Byte)( ( 0 >> 8 ) & 0xff );//msb
				data[i++] = (System.Byte)( 0 & 0xff );//lsb
				data[i++] = (System.Byte)( ( 0 >> 8 ) & 0xff );//msb
			}

			buffer.Write( offset, data, LockFlag.None );
		}

		private void Clear()
		{
			Zero( 0 );
			buffer.SetCurrentPosition( BufferLength );
			Zero( BufferLength );
			buffer.SetCurrentPosition( BufferLength * 2 );
			Zero( BufferLength * 2 );
			buffer.SetCurrentPosition( BufferLength * 3 );
			Zero( BufferLength * 3 );
			buffer.SetCurrentPosition( 0 );
		}
	}
}

K
klausm Themenstarter:in
3 Beiträge seit 2008
vor 15 Jahren

keiner?

3.971 Beiträge seit 2006
vor 15 Jahren

Wo an welcher Stelle was "hängt" kannst du nur mit dem Debugger prüfen oder Profilern.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

T
55 Beiträge seit 2009
vor 13 Jahren

Ich weiß alte Karmellen. Wäre aber schon interessant, warum die ersten Töne verzehrt klingen.