jinggle bells SID

Gerade eben experimentiere ich ein wenig mit der SID-Library um darauf Jingle Bells laufen zu lassen, weil das besser klingt als reiner Rechteck Sound.
sid-arduino-lib

Hier habe ich ein Code-Beispiel angepasst:

#include <SID.h>

SID mySid;

#define SLOWATTACK 0xB0
#define FASTATTACK 0x00
#define SLOWDECAY 0x0A
#define FASTDECAY 0x00
#define SUSTAINQUITE 0x00
#define SUSTAINNORM  0xA0
#define SUSTAINLOUD 0xF0
#define SLOWRELEASE 0x09
#define FASTRELEASE 0x00

// https://gist.github.com/elubow/7844436
int speakerPin = 9;
int length = 26;
char notes[] = "eeeeeeegcde fffffeeeeddedg";
int beats[] = { 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2};

int tempo = 150;

void playTone(int tone, int duration) {
    mySid.setFrequency(0,tone/2);
  
  mySid.noteOn(0);
  delay(duration);
  mySid.noteOff(0);
  delay(50); 
  /*
  for (long i = 0; i < duration * 1000L; i += tone * 2) {
    digitalWrite(speakerPin, HIGH);
    delayMicroseconds(tone);
    digitalWrite(speakerPin, LOW);
    delayMicroseconds(tone);
  }*/
}

#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186

void playNote(char note, int duration) {
  char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
  //int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
  int tones[] = { NOTE_C7, NOTE_D7, NOTE_E7, NOTE_F7, NOTE_G7, NOTE_A7, NOTE_B7, NOTE_C8 };
  // play the tone corresponding to the note name
  for (int i = 0; i < 8; i++) {
    if (names[i] == note) {
      playTone(tones[i]/2, duration);
    }
  }
}

void setup() {
  //pinMode(speakerPin, OUTPUT);
    mySid.begin();
  mySid.set_register(ATTACKDECAY+VOICE1,FASTATTACK+SLOWDECAY); 
  mySid.set_register(SUSTAINRELEASE+VOICE1,SUSTAINNORM+5);
  mySid.setWaveForm(0,TRIANGLE);

}

void loop() {
  for (int i = 0; i < length; i++) {
    if (notes[i] == ' ') {
      delay(beats[i] * tempo); // rest
    } else {
      playNote(notes[i], beats[i] * tempo);
    }
    
    // pause between notes
    delay(tempo / 2); 
  }
}

Gibt es noch irgendwo anders Jingle-Bells player oder Weihnachtmusik die ich als Steuerung für den SID nehmen könnte?

ChrisMicro:
Gerade eben experimentiere ich ein wenig mit der SID-Library um darauf Jingle Bells laufen zu lassen, weil das besser klingt als reiner Rechteck Sound.

Wo gibt es denn diese tolle Library, die auf 8-Bit Arduino-Controllern Töne erzeugt, die besser klingen als der Rechtecksound der tone() Funktion? Was da unter dem von Dir geposteten Link liegt, hast Du nicht selbst geschrieben, oder? Un mehr Dokumentation als den Quellcode gibt es nicht?

Tut mir leid, einen C64 Computer habe ich nie besessen, SID-Sounderzeugung sagt mir überhaupt nichts.

Reine Melodien von Weihnachtsliedern und anderem (Pop-Songs und Titelmelodien von Filmen und Fernsehserien der sechziger, siebziger und achtziger Jahre sollten sich mit vertretbarem Aufwand finden lassen, und zwar in der RTTTL Codierung für Nokia-Handies der neuenziger Jahre, als Mobiltelefone noch nicht "smart", sondern strunzdumm waren und Klingeltöne keine MP3 Dateien waren, sondern einfache, monophone Piepstonfolgen aus dem Piezolautsprecher des Handies.

Wenn diese SID-Library so tolle Sounds erzeugt, dann sollte man vielleicht einen der RTTTL-Player für Arduino mal auf diese SID-Tonerzeugung umschreiben.

Siehe auch
iki/Ring_Tones_Text_Transfer_Language

Suchst Du was spezielles?

  • White Christmas
  • Rudolphi the red-nosed rendeer
  • jingle-bell rock
  • stille Nacht, heilige Nacht

ich glaube, irgendwo hätte ich sowas noch auf der Festplatte, und vielleicht könnte ich was finden, wenn ich mir beim Suchen Mühe gebe.

Aber mal zu Deinem Code:

Warum sieht Deine Notenabspielfunktion so aus als wenn sie falsch spielt?

void playTone(int tone, int duration) {
    mySid.setFrequency(0,tone/2);
  
  mySid.noteOn(0);
  delay(duration);
  mySid.noteOff(0);
  delay(50);

Da wird doch beim Aufruf von setFrequency die tonhöhe halbiert, also die Note um genau eine Oktave tiefer gesetzt und dadurch eine Okltave tiefer als vorgegeben gespielt, oder?

Undwdas soll eigentlich dieses delay(50); nach jeder Note?

Die Pause zwischen zwei Noten immer genau gleich lang, egal bei welchem Spieltempo und egal ob ganze, halbe, viertel, achtel oder sechzehntel Noten abgespielt werden?

Ich bin zwar ziemlich unmusikalisch, aber das sieht sogar mir äußerst unpassend aus.

Was da unter dem von Dir geposteten Link liegt, hast Du nicht selbst geschrieben, oder? Un mehr Dokumentation als den Quellcode gibt es nicht?

Im wesentliche schon. Es war eins meiner Projekte um 2007. Ursprünglich war's ein Projekt für den Atmega8. Dann haben ein paar Leute ein Shield für den Arduino gemacht und später hat es jemand vollständig auf den Arduino portiert.

Wo gibt es denn diese tolle Library, die auf 8-Bit Arduino-Controllern Töne erzeugt, die besser klingen als der Rechtecksound der tone() Funktion?

Die Library gibt es unter dem Link oben.
Das Pentatonic Beispiel klingt schon deutlich besser als der reine Rechteck des Originals:
pentatonic

Ich bin zwar ziemlich unmusikalisch, aber das sieht sogar mir äußerst unpassend aus.

Ja, zugegebnermaßen. Ich war aber etwas faul zum richtig nachdenken und hab einfach so lange an den Parametern gedreht, bis es irgendwie am besten klang.

ChrisMicro:
Im wesentliche schon. Es war eins meiner Projekte um 2007. Ursprünglich war's ein Projekt für den Atmega8. Dann haben ein paar Leute ein Shield für den Arduino gemacht und später hat es jemand vollständig auf den Arduino portiert.

Aha, das Projekt ist also schon sehr viel älter als Deine Anmeldung hier im Forum. Und als der Code von jemand anderem auf Arduino portiert wurde hast Du es dann aus den Augen verloren und es gibt keine irgendwie sinnvoll einsetzbare Beispielanwendung?

Was das Melodienspiel betrifft: Am einfachsten ließen sich Weihnachts- und andere Melodien sicher auf Arduino anpassen und abspielen, wenn es für Deine Library Befehle gäbe, die zu den Arduino Funktionen tone() und noTone() wenigstens halbwegs kompatibel sind. Auch wenn man sich die Pins für die Tonerzeugung bei der SID-Library wohl nicht selbst frei aussuchen kann: Wenn es besser klingt, dann müßte man doch die Library doch einfach um Funktionen für "Ton AN" und "Ton AUS" erweitern können, oder nicht?

Meine Idee: Eine Funktion sidTone() als besser klingender Ersatz für tone() und sidNoTome() als Ersatz für noTone().

Zum Beispiel so:

void sidTone(int frequency) 
{
  mySid.setFrequency(0,frequency);
  mySid.noteOn(0);
}

void sidNoTone()
{
  mySid.noteOff(0);
}

Wenn das als Ersatz für tone() und noTone() wenigstens an einem Pin funktionieren würde, könnte man mit wohl sehr geringem Aufwand einen vorhandenen RTTTL-Playercode für Arduino auf die Verwendung der SID-Library umschreiben.

Vielleicht probiere ich nächste Woche mal was und suche mir ein paar weihnachtliche RTTTL-Melodien heraus.

Was würde Dir denn als Beispielanwendung vorschweben, vielleicht sowas:

  • Arduino UNO mit angeschlossenem Piezo-Speaker und einem Tastschalter
  • Und jedesmal beim Drücken des Tasters wird eine zufällige Melodie aus dem Melodien-Repertoire abgespielt?

Ich schau mal, was geht. Piezo-Speaker müßte noch in der Bastelkiste sein.
Und Link zu Deiner SID-Library steht ja oben.
Mal schauen, ob es fehlerfrei kompiliert, ich habe hier Arduino v1.6.5

P.S.: Habe die Compilierung und den Klang Deiner Library mal ausgetestet, das Ergebnis:

  • die Library und Dein Sketch kompilieren einwandfrei
  • Tonausgabe auf Pin-9
    der Ton ist glockenrein und hat einen angenehmen Klang,
  • aber im direkten Vergleich zur Ausgabe mittels tone() Funktion und Rechteckfrequenz auf meinem Piezo nur SEHR LEISE

P.P.S.: Wenn Du Melodien suchst, hier sind auch ein paar weihnachtliche dabei (alles in RTTTL Notation):

http://mines.lumpylumpy.com/Electronics/Computers/Software/Cpp/MFC/RingTones.RTTTL

Gesehen habe ich diese (sind iim englischen Sprachraum wohl populärer als auf Deutsch):

  • Rudolph the Red Nosed Raindeer
  • We Wish you a Merry Christmas
    On the 12th Day of christmas
  • Santa Claus is Coming Tonight
    -Let it snow

Vielen Dank für Deinen ausführlichen Beitrag. Falls sich die Tone Funktionen als praktisch gut einsetzbar erweisen, könnte ich sie in die Library aufnehmen.

Hier noch ein wenig zur Technik des SID:
Er hat 3 Tongeneratoren mit 3 Hüllkurvengeneratoren. ( SID: SID ). Man kann also 3 Töne polyphon gleichzeitig spielen.
In der Arduino-Version fehlen die Filter. Man könnte sie auch noch bauen, allerdings ist das mit einem einigermaßen großen Optimierungsaufwand verbunden.
Ich habe das Projekt damals begonnen, weil die Behauptung im Raum stand, dass man so etwas auf einem AVR gar nicht realisieren kann. Und in der Tat: der Prozessor kommt mit der Berechnung der Töne an seine Leistungsgrenzen. Deshalb war die Entwicklung auch etwas schwierig und konnte nur mit Hilfe des AVR-Simulators und Takte zählen durchgeführt werden. Außerdem wollte ich das Projekt in C machen und nicht in Assembler. Mit Assembler kann man noch deutlich besser optimieren, aber ich wollte das Projekt auch irgendwann auf andere Prozessorarchitekturen portieren können und dazu ist Assembler nicht geeignet.
Heute, knapp 10 Jahre später gibt es natürlich einige Synthesizer auf den AVRs die auch deutlich weiter entwickelt sind als der SID.

P.S.: Habe die Compilierung und den Klang Deiner Library mal ausgetestet, das Ergebnis:

  • die Library und Dein Sketch kompilieren einwandfrei
  • Tonausgabe auf Pin-9
    der Ton ist glockenrein und hat einen angenehmen Klang,
  • aber im direkten Vergleich zur Ausgabe mittels tone() Funktion und Rechteckfrequenz auf meinem Piezo nur SEHR LEISE

Die Tonausgabe ist durch die Hardware auf die Pins 9 und 10 fixiert, weil dort die schnelle PWM-Hardware beim Atmega328 ist. G.Giorgi hat den SID auf Stereo Ausgabe umgestellt, d.h. Voice1 und Voice2 gehen auf verschiedene Kanäle.

Piezos habe das Problem, dass sie im wesentlichen bei einer Frequenz sehr laut klingen. Sie haben eine sehr ungleichmäßigen Frequenzgang. Ein Rechecksignal produziert an den Flanken sehr hohe Frequenzen und regt den Piezo auf seiner Resonanzfrequenz an, dadurch klingt er dann laut.
Lange Rede kurzer Sinn: Die Piezos klingen immer etwas "quäcksig" besser man nimmt einen richtigen Lautsprecher. Bei Polin gab es mal so kleine Mini-Lautsprecher mit 100Ohm, die klingen schon deutlich besser als ein Piezo.
Ich habe hier auf dem Tisch so eine Mini-Soundbar für den PC liegen, dort schließe ich mittels Krokodilklemmen das über einen RC Tiefpass gefilterte Signal ( 1K Ohm, 100nF ) an. Damit klingt der Ton dann richtig gut. Man könnte vielleicht günsige 12 Euro Bluetooth Lautsprecher verwenden, die haben auch meistens einen Audioeingang.

Gibt es eine Möglichkeit, MIDI-Files abzuspielen?