Laden...

8-Bit Sound mit Console.Beep

Erstellt von der-schlingel vor 12 Jahren Letzter Beitrag vor 12 Jahren 13.041 Views
Thema geschlossen
der-schlingel Themenstarter:in
799 Beiträge seit 2007
vor 12 Jahren
8-Bit Sound mit Console.Beep

Hallo Leute,

ich versuche gerade mit Console.Beep(int frequency, int duration) ähnliche Melodien zu erzeugen wie wie in den hier verlinkten Youtube-Videos.

Dazu lasse ich im Moment folgenden Thread im Hintergrund laufen:


            musicThread = new Thread(
                () => {
                    int t = 0;
                    for (; ; t++)
                    {
                        int freq = t | (t >> 9 | t>>7) * t & (t >> 11 | t >> 9);
                         if(freq <= 37 || freq >= 32767) 
                         {
                             continue;
                         }
                         else 
                         {
                             Console.Beep(freq, 100);
                         }
                    }

                }, 
                0);

Ich hab mich schon etwas mit dem Duration-Parameter herumgespielt - musste dann aber doch einsehen, dass es mir hier wohl noch an dem nötigen Basiswissen mangelt wie ich den selben Sound zusammenbringe.

Hat hier irgend jemand Informationen oder sogar ein bisschen Code um mir auf die Sprünge zu helfen?

As a man thinketh in his heart, so he is.

  • Jun Fan
    Es gibt nichts Gutes, außer man tut es.
  • Erich Kästner
    Krawutzi-Kaputzi
  • Kasperl
C
1.214 Beiträge seit 2006
vor 12 Jahren

Ich weiß nicht, inwiefern dir das weiterhilft, aber sowas hab ich paar mal unter Linux verwendet:

Fun with beep

In dem Beispiel ist halbwegs beschrieben, wie das funktioniert, aber ich kann jetzt selber schlecht beurteilen, wie einfach du das übertragen kannst.

1.130 Beiträge seit 2007
vor 12 Jahren

Ich hab einfach mal den code leicht modifiziert, den ich hier schon gepostet hatte im programmier-spiel. Man kann die in dem blog angegebenen formeln 1:1 übernehmen.

    class Program
    {
        const int samplerate = 8000;//8 khz

        private static byte Function(int t)
        {
            return (byte)(t * (((t >> 12) | (t >> 8)) & (63 & (t >> 4))));
        }

        static void Main(string[] args)
        {
            int t=0;

            //Setup OpenAl:
            IntPtr device = ALC.OpenDevice(null);
            IntPtr ctx = ALC.CreateContext(device, null);
            ALC.MakeContextCurrent(ctx);

            uint source = AL.GenSource();
            byte[] samples = new byte[1024];
            uint[] buffers = AL.GenBuffers(10);
            int iCurrentBuffer = 0;
            //Status of sine wave:
            double rotangle = 0, rotangle2 = 0;
            while (true)
            {
                //Get information:
                int numQueued = AL.GetSourcei(source, AlSourceInts.Buffers_Queued);
                int numProcessed = AL.GetSourcei(source, AlSourceInts.Buffers_Processed);
                int numRemaining = numQueued - numProcessed;
                //Take the processed buffers from the queue:
                if (numProcessed > 0) AL.SourceUnqueueBuffers(source, numProcessed);

                if (numRemaining >= buffers.Length)//Nothing to do?
                {
                    System.Threading.Thread.Sleep(5);//Then wait a bit
                    continue;//and try again
                }
                //Calculate the new samples:
                for (int i = 0; i < samples.Length; i++)
                {
                    samples[i] = Function(t++);
                }
                //queue the samples
                AL.BufferData(buffers[iCurrentBuffer], AlAudioFormat.Mono8Bit, samples, sizeof(byte) * samples.Length, samplerate);
                AL.SourceQueueBuffer(source, buffers[iCurrentBuffer]);
                if (++iCurrentBuffer >= buffers.Length) iCurrentBuffer = 0;//increment iBuffer
                //play if the source is not already playing
                if ((AlSourceState)AL.GetSourcei(source, AlSourceInts.Source_State) != AlSourceState.Playing)
                    AL.SourcePlay(source);
            }
        }
    }

Die bindings für openal (welches übrigends installiert sein muss) hatte ich hier gepostet.

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

F
155 Beiträge seit 2009
vor 12 Jahren

Hallo,

ich habe mal den Code von der Seite die Coder007 gepostet hat in C# nachgebildet.

Hörts euch an:


static void Main(string[] args)
        {

            beep(659, 120);
            beep(0, 120);
            beep(622, 120);
            beep(0, 120);

            beep(659, 120);
            beep(0, 120);
            beep(622, 120);
            beep(0, 120);
            beep(659, 120);
            beep(0, 120);
            beep(494, 120);
            beep(0, 120);
            beep(587, 120);
            beep(0, 120);
            beep(523, 120);
            beep(0, 120);

            beep(440, 120);
            beep(0, 140);
            beep(262, 120);
            beep(0, 120);
            beep(330, 120);
            beep(0, 120);
            beep(440, 120);
            beep(0, 120);

            beep(494, 120);
            beep(0, 140);
            beep(330, 120);
            beep(0, 120);
            beep(415, 120);
            beep(0, 120);
            beep(494, 120);
            beep(0, 120);

            beep(523, 120);
            beep(0, 140);
            beep(330, 120);
            beep(0, 120);
            beep(659, 120);
            beep(0, 120);
            beep(622, 120);
            beep(0, 120);

            beep(659, 120);
            beep(0, 120);
            beep(622, 120);
            beep(0, 120);
            beep(659, 120);
            beep(0, 120);
            beep(494, 120);
            beep(0, 120);
            beep(587, 120);
            beep(0, 120);
            beep(523, 120);
            beep(0, 120);

            beep(440, 120);
            beep(0, 140);
            beep(262, 120);
            beep(0, 120);
            beep(330, 120);
            beep(0, 120);
            beep(440, 120);
            beep(0, 120);

            beep(494, 120);
            beep(0, 140);
            beep(330, 120);
            beep(0, 120);
            beep(523, 120);
            beep(0, 120);
            beep(494, 120);
            beep(0, 140);
            beep(440, 120);
        }
        static void beep(int f, int t)
        {
            if (f > 0)
                Console.Beep(f, t);
            else
                System.Threading.Thread.Sleep(t);
        }

fz

"We better hurry up and start coding, there are going to be a lot of bugs to fix."

25 Beiträge seit 2011
vor 12 Jahren

Hallo Leute,

mich hat das Thema irgendwie begeistert und deshalb habe ich mich dran gemacht eine eigene Lösung zu suchen. Ich habe es rein mit .Net Bordmitteln versucht und auch eine passable Lösung gefunden.

Leider läuft meine Lösung nicht als Endlosschleife. Das habe ich leider nicht hin bekommen. Bin halt noch totale Anfänger im C#. Vielleicht hat ja von euch einer ne Idee wie man das noch auch Endlos umbauen kann.


byte[] AudioSize = BitConverter.GetBytes(100000);
byte[] BitsPerSample = BitConverter.GetBytes(8);
byte[] BlockAlign = BitConverter.GetBytes(1);
byte[] ByteRate = BitConverter.GetBytes(8000);
byte[] SampleRate = BitConverter.GetBytes(8000);
byte[] NumChannels = BitConverter.GetBytes(1);
byte[] AudioFormat = BitConverter.GetBytes(1);
byte[] Subchunk1Size = BitConverter.GetBytes(16);
byte[] länge = BitConverter.GetBytes(100036);
//Wave Header zusammen bauen
byte[] header = new byte[] {
	(byte)'R', (byte)'I', (byte)'F', (byte)'F', 
	länge[0], länge[1], länge[2], länge[3], 
	(byte)'W', (byte)'A', (byte)'V', (byte)'E', (byte)'f', (byte)'m', (byte)'t', (byte)' ',
	Subchunk1Size[0], Subchunk1Size[1], Subchunk1Size[2], Subchunk1Size[3],
	AudioFormat[0], AudioFormat[1], NumChannels[0], NumChannels[1], SampleRate[0], SampleRate[1], SampleRate[2], SampleRate[3],
	ByteRate[0], ByteRate[1], ByteRate[2], ByteRate[3], BlockAlign[0], BlockAlign[1], BitsPerSample[0], BitsPerSample[1],
	(byte)'d', (byte)'a', (byte)'t', (byte)'a', AudioSize[0], AudioSize[1], AudioSize[2], AudioSize[3]};

MemoryStream stream = new MemoryStream();
stream.Write(header, 0, 44);

for (int t = 0; t <= 100000; t++)
{
	byte freq = (byte)(t * ((t >> 12 | t >> 8) & 63 & t >> 4));
	stream.WriteByte(freq);
}

stream.Position = 0;
SoundPlayer player = new SoundPlayer(stream);
player.Play();
Console.ReadLine();
player.Dispose();

Gruß
Thomas DaGallier

1.130 Beiträge seit 2007
vor 12 Jahren

Hmm, nette idee.
Zur deiner konkreten umsetzung: Irgendwie habe ich das gefühl, dass du vorher mit c/c++ gearbeitet hast^^
Schau dir mal folgendes an:
BinaryWriter, Encoding.ASCII

Außerdem kann man von der klasse Stream erben, anstatt einen memorystream zu nehmen.

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

25 Beiträge seit 2011
vor 12 Jahren

Hallo Floste,

auf den BinaryWriter hätte ich auch kommen können. Der hätte mir natürlich einiges an Arbeit erspart.

Ich verstehe allerdings im Moment Deine anderen Hinweise nicht?
Was hat dieses "Problem" mit der Zeichencodierung zu tun? Ich will ja nicht unbedingt druckbare Zeichen generieren.

Und wie hätte mir das erben von Stream geholfen? Denkst du da an gleichzeitiges schreiben und lesen? Dafür hätte ich ja erst mal alle Methoden usw. implementieren müssen. Ich glaube das wäre für mich noch zu viel. Ich arbeite noch an meinen Grundlagen!

Mit c/c++ liegst du übrigens daneben. Das hab ich zwar im Studium mal gehabt, aber das wars dann auch schon. Ganz viel früher habe ich mal AMOS BASIC und ein bisschen Assembler (AMIGA) programmiert...

Gruß
Thomas DaGallier

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo DaGallier,

ich vermute mal, du weiß, was der Code macht. Wenn ja, sollte es kein Problem sein, die Stelle zu finden, die den Sound abspielt und die du in die Endlosschleife packen musst. Wenn nicht, sind wir bei [Hinweis] Wie poste ich richtig? Punkt 1.1.1 angelangt.

herbivore

Thema geschlossen