www.mikrocontroller.net

Forum: PC-Programmierung Synthesizer programmieren


Autor: Sam .. (sam1994)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Ich versuche gerade einen Synthesizer für einen Tiny/Mega (je nach dem 
wie groß der am Ende wird) zu programmieren. Um das zu testen hab ich 
das erstmal am PC probiert. Bisher kann man bis zu 255 Kanäle nutzen. 
Töne hab ich bisher noch nicht definiert. Man kann nur eine Frequenz 
einstellen (44100 / x).

Problem ist nur die Lautstärke. Sobald die Lautstärken unterschiedlich 
sind oder auch bei bestimmten einstellungen, hört man ein Knarren.

Der ganze Code ist im Anhang. Alleg44.dll braucht man um die Exe 
auszuführen.
struct Tone
{
    unsigned char pwm;
    unsigned char max;
    unsigned char volume;
    unsigned short len;
};

struct Stream
{
    Tone* stream;
    unsigned char len;
    unsigned char streampos;
    unsigned char tonepwmpos;
    unsigned short tonepos;
};

struct PolyStream
{
    Stream* stream;
    unsigned char len;
    unsigned char loglen;   
};

unsigned char GetPWM(PolyStream* stream)
{
    unsigned char i = stream->len - 1;
    unsigned short pwm = 0;
    do
    {
        pwm += GetTone(&(stream->stream[i]));
    }
    while(i--);
    pwm >> stream->loglen;
    return (unsigned char)pwm;
}

unsigned char GetTone(Stream* stream)
{
    if(++stream->tonepos == stream->stream[stream->streampos].len) //Ton zu Ende?
    {
        stream->tonepos = 0;    //Werte zurücksetzen
        stream->tonepwmpos = 0;
        stream->streampos++;   //nächster Ton
    }
    if(stream->streampos >= stream->len)
        return 128;
    if(stream->stream[stream->streampos].pwm > ++stream->tonepwmpos)
    {
        return stream->stream[stream->streampos].volume;
    }
    else
        if(stream->tonepwmpos == stream->stream[stream->streampos].max)
        {
            stream->tonepos++;
            stream->tonepwmpos = 0;
        }
    return 255 - stream->stream[stream->streampos].volume;
}
Das ist der Synthesizer abschnitt. Hier müsste der Fehler sein, den ich 
nicht finde.

Es ist doch nichts anderes als, Frequenzen erzeugen und Mittelwert 
bilden?

Anmerkung zum Code: Ich habe extra unsigned char und ushort genutzt, da 
ich das am Ende auf dem µC auch machen muss.

EDIT:
Ist gelöst. Es lag am schieben. Ich habe keine Zuweisung beim schieben 
gemacht.

Autor: Sam .. (sam1994)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Läuft jetzt ganz gut. Obwohl es nur 8 bit sind hört es sich ganz gut an. 
Hab noch einen Konverter geschrieben, so schlecht ist die Quali gar 
nicht.

Ich würde noch gerne ein paar Drums dazumachen, aber wie soll ich das 
anstellen? Ich hab ja gar keine Samples dafür. Lässt sich das vielleicht 
auch "synthetisch" herstellen. Also mit irgendeiner besonderen 
Schwingung?

Ein bessere Midi-Eingabemöglichkeit möchte ich noch programmieren, das 
jetzige ist nur zum testen. Der Konverter soll am Ende nur ein Array 
erstellen. Das wird wahrscheinlich auch das nächste was ich machen 
werde, denn das Kompilieren dauert ewig.

Das einzige brauchbare Projekt zum Midi einlesen, das ich auf die 
Schnelle fand war das hier: 
http://www.codeproject.com/KB/audio-video/MIDIToolkit.aspx

Leider muss man da die Midi-Datei einmal abspielen um sie zu 
konvertieren. Und da das ganze gar nicht dafür gadacht ist, muss man 
Zeitmessungen machen um die Zeiten zu bekommen (sehr ineffizient). Wenn 
jemand eine bessere Lib kennt, wäre mir sehr geholfen.

Eine Hörprobe hab ich mal hochgeladen. Immernoch diesselbe 
Rechteckschwingung, diesmal aber mit Tönen und mit einer konvertierten 
Midi-Datei.

Die Töne sind zum Teil schief, da die Steuerung nicht genau genug ist. 
Da müsste man sich was einfallen lassen.

Eine Frage hätte ich dann noch:
Was heißt das : _mcleanup tos overflow
Das steht bei mir in der Console nach dem Beenden des Programms

Autor: Sam .. (sam1994)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier noch mein bescheidener Konverter.

Autor: Sam .. (sam1994)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Samuel K. schrieb:
> Hier noch mein bescheidener Konverter.

Mit ein Haufen kleiner Bugs. Diese Version kann endlich ohne Probleme 
konvertieren.
Leider erstellt der Konverter bei manchen Stücken >1000 Kanäle was total 
unsinnig ist und deshalb nicht funktioniert.

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Samuel K. schrieb:
> Ich würde noch gerne ein paar Drums dazumachen, aber wie soll ich das
> anstellen? Ich hab ja gar keine Samples dafür. Lässt sich das vielleicht
> auch "synthetisch" herstellen. Also mit irgendeiner besonderen
> Schwingung?

Z.B. weißes Rauschen als Ausgangsmaterial und dann ein (Tiefpass- etc.) 
Filter drauf (subtraktive Synthese).

http://de.wikipedia.org/wiki/Subtraktive_Synthese

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sound on Sound ( http://www.soundonsound.com ) hatte mal eine Serie von 
Artikeln über Synthese verschiedener Instrumente. Such da mal nach 
"Synth Secrets", sind auch Drums und Percussion dabei.

Irgendwann wollte ich sowas auch noch mal umsetzen, aber man kommt ja zu 
nichts...

Mirko

Autor: Sam .. (sam1994)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Links. Ich muss mich da mal einlesen.

Das andere Eingabeformat hab ich jetzt programmiert.

Auszug aus meinem Konverter, der leider noch nicht richtig funktioniert:
             * HEADER
             * Anzahl Kanäle (1 - 255)
             * Anzahl der Noten/Befehle von Kanal 1-x (1 - 65535)
             * 
             * DATA
             * Alle Noten/Befehls - Byte von Kanal 1-x
             * 
             * 
             * Beispiel
             * 2 Kanäle
             * 3 Noten/Befehle im 1. Kanal
             * 1 Noten/Befehle im 2. Kanal
             * a 1. Note/Befehl des 1. Kanals
             * b 2. Note/Befehl
             * c 3. Note/Befehl
             * d 1. Note/Befehl des 2. Kanals
             * 
             * entspricht {2,3,1,a,b,c,d}

Mein Konverter baut gerade völligen Mist, deshalb sind im MidiTest nur 
12 Töne aus Handarbeit. Gibt es eingentlich ein 
Opensource-Midiconverter/Analyser?

Wie viel Kanäle haltet ihr auf einem Attiny für realistisch? Ich finde 
das wird schon ein bisschen knapp: Mit einem Bauratenquarz mit 22.12Mhz 
kommt man auf 22.12Mhz / 44100 = ~500 Takte
Da kann man den PWM-Channel 2 mal durchlaufenlassen. In 500 Takten muss 
man dann das hier für alle Kanäle neuberechnet haben:
unsigned char GetChannel(unsigned char i)
{
    if(channel[i].pos >= channel[i].len)
        return 128;
    if(++channel[i].tonepos >= channel[i].tonelen)
    {
        channel[i].tonepos = 0;
        channel[i].freqpos = 0;
        //Neuer Ton
        unsigned char value;
        while(!IsTone(value = array[++channel[i].pos]))
        {
            switch(value & 0xC0)
            {
                case 0xC0: channel[i].tonelen = (1 << (7 - (value & 0x07))) * 44100 / 128 * 2;
                    printf("Channel %d (%d / %d): New Tone-Len: %d\n",i,channel[i].pos, channel[i].len, channel[i].tonelen);
                    break;
                default: printf("Channel %d (%d / %d): Error: Unknown command: %d\n",i,channel[i].pos, channel[i].len, value & 0xC0);
            };
        }
        
        channel[i].freq = Freq[array[channel[i].pos]];
        printf("Channel %d (%d / %d): New Tone: %d\n", i,channel[i].pos, channel[i].len,array[channel[i].pos]);
    }
    if(++channel[i].freqpos >= channel[i].freq)
        channel[i].freqpos = 0;
    else
    {
        if(channel[i].freqpos > channel[i].freq / 2)
            return 255 - channel[i].tonevol;
        return channel[i].tonevol;
    }
}

Für den µC werd ich natürlich versuchen es noch ein bisschen zu 
optimieren. Wahrscheinlich muss man es am Ende sowieso in Asm umsetzen.

Autor: Sam .. (sam1994)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Verdammt, schon wieder den ,Anhang vergessen.

Autor: Christoph H. (mc-entwickler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier ein paar Tipps.

Atmega Töne in Assembler:
http://www.linusakesson.net/scene/craft/index.php
( 4 Kanäle )
Hier gibt es eine schöne Link-Liste:
http://www.mikrocontroller.net/articles/Klangerzeugung

3 Kanäle in C:
http://www.arduino.cc/playground/Main/SID-shield

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.