Forum: PC Hard- und Software Software-Synthesizer


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von J. W. (nuernberger)


Lesenswert?

Ich habe die letzten Tage auf Linux/Alsa einen bare-bone Synthesizer 
programmiert.
Mich interessierte eigentlich nur, was mit Alsa oder Jack an Low-Latency 
möglich ist.
Ich war beruflich mit Audio-Entwicklung vor 15 Jahren beschäftigt, 
allerdings mit DSP, insofern kenne ich mich mit der Theorie ganz gut 
aus.

Mich erstaunte die Leistungsfähigkeit sehr, was mich überraschte, da ich 
vorher LinuxSampler, ourorgan(Grandorgue) installierte und enttäuscht 
war.

Im wesentlich habe ich 2 Worker-Threads. Der eine empfängt Midi-Daten 
vom USB-Midi-Keyboard, der andere beschreibt die Audio-Buffer.
1
if ((r=alsaPcmOpen((void**)&pcm_handle,sDevice,
2
  sampleRate,channels, bufsize,2)) < 0) {
3
  printf("alsaPcmOpen error r=%d\n",r);
4
  return NULL;
5
}
6
data= (short *)malloc(p->bufsize);
7
while (1) {
8
  int pcmreturn;
9
10
//beschreiben von data[] mithilfe von Sinus-Tabellen 
11
// im wesentlichen Sinuswellen mit Attack und Release
12
//  (je nach dem welche Töne angeschlagen werden)
13
14
15
  if ((pcmreturn=snd_pcm_writei(pcm_handle, data,
16
    buffSize)) < 0) {
17
    snd_pcm_prepare(pcm_handle);
18
    fprintf(stderr, "<< Buffer Underrun >>\n");
19
    usleep(1000);
20
    //break;
21
  }
22
}

Dabei sind beim normalen Linux-Netbook (Asus 2GB) Buffer bis zu 128 
Samples (512 Byte) möglich und Latenz kaum spürbar.
Alle Berechnungen mache ich mit uint32_t, keine Floats/Doubles.
(die Sinustabelle schon vorher berechnet und die Werte im Bereich 
[-0x7fff,0x7fff] abgespeichert.)

OK, da probierte ich den Raspberry-PI (512MB) mit dem neuesten Raspbian.
Die Performance war schon schlechter, die minimale Buffergröße ist 680 
Samples (2720 Bytes).
Wenn man den Buffer kleiner macht, funktioniert schon eine Stimme nicht 
mehr. Bei 2720 sind 10 stimmen zu je 3 Oszillatoren möglich.
Also durchaus ausbaufähig.

Und da wollte ich fragen, was man noch verbessern kann.
Gibt es eine bessere Distro für diesen Zweck.
Ich habe mal Emlid (Realtime Linux auf Raspbian-Grundlage) installiert,
ohne wesentlichen Verbesserungen.

Ist das Overclocken gefährlich, was zu Zerstörungen führen kann?

Bringt eine schnellere SD-Karte was (class 10 oder was)?
(mein Programm macht aber keine Datei-Zugriffe)

: Bearbeitet durch User
von Hans W. (Firma: Wilhelm.Consulting) (hans-)


Lesenswert?

welche kernel hast du verglichen? 4.05 ist der aktuelle stable kernel.

Das kann ganz schön was ausmachen... vor allem bei ARM

Ggf. den kernel und dein Programm mit "-Ofast -march=native 
-mtune=native" übersetzen und probieren.

Das sollte den Interrupt-Code gehörig beschleunigen und die sonst nicht 
verwendeten Befehlssatzerweiterungen einschalten.

Wie beschreibst du deinen Buffer? memcpy aus der LibC sollte schneller 
sein als einfach nur per for-Schleife  (wobei hier -Ofast ... das 
gehörig aufräumen sollte).

So ein ARM11 ist halt nicht das Speed-Wunder....Das sollte auf dem 
Raspberry2 wesentlich besser laufen... (4 Cores die die Interrupts 
bedienen können, SIMD erweiterung,...)

Deine SD-Karte spielt da keine Rolle...

73

von J. W. (nuernberger)


Lesenswert?

Hans Wilhelm schrieb:
> Wie beschreibst du deinen Buffer? memcpy aus der LibC sollte schneller
> sein als einfach nur per for-Schleife

Da habe ich eine Hauptschleife. Pro angeschlagenen Ton und pro 
Oszillator nehme ich die Phase und hole den Sinus-wert aus der Tabelle. 
Die Werte werden addiert und ggf mit dem Envelop (Falls im Attack oder 
Release) multipliziert.
Alle Phasen müssen dann mit dem jeweiligen Inkrement erhöht werden.
Schon einiges zum Rechnen, aber mit memcpy geht das natürlich nicht.
Aber wie schon geschrieben, bei etwas kleinerem Buffer habe ich schon 
bei einer Taste Knacken (Buffer-Underruns) während bei der 
Mindestbuffergröße 10 Töne (á 3 Oszillatoren) sauber und rund klingen.



> welche kernel hast du verglichen? 4.05 ist der aktuelle stable kernel.
> Das kann ganz schön was ausmachen... vor allem bei ARM
1
pi@raspberrypi ~ $ uname -a
2
Linux raspberrypi 3.18.11+ #781 PREEMPT Tue Apr 21 18:02:18 BST 2015 armv6l GNU/Linux

Da habe ich den Standard Raspian-Kernel vom 5.5.2015.
Seit Kernel 2.4 habe ich keinen mehr kompiliert.
Macht man das als Cross-Compile am PC oder am Raspberry ?


> Das sollte auf dem Raspberry2 wesentlich besser laufen...

Tatsächlich ? Ich hätte gedacht, der Vorteil ist nur im größerem RAM.
Da könnte ich diesen ja bestellen ...
Gibt es andere solche MINI-PCs ?

von Clemens L. (c_l)


Lesenswert?

Ein Realtime-Kernel hilft nur, wenn andere Software deiner in die Quere 
kommt. Gegen schlechte Hardware oder Treiber hilft er nicht.

(Insbesondere Closed-Source-)WLAN-Treiber sind bekannt dafür, mit ihren 
Interrupts die CPU auch mal länger lahm zu legen.

Probier mal, wie gut Jack läuft. Je nach Ergebnis musst du dir dann 
davon etwas abschauen, oder kannst beruhigt sein.

von J. S. (engineer) Benutzerseite


Lesenswert?

Außer dem Rat, alles Unnötige aus dem Kernel rauszuschmeißen, sehe ich 
da wenig Optionen. Und aus Sicht von Klangsynthese Unnötiges 
rauszuschmeißen, heißt genau genommen, so ziemlich alles zu entfernen.

Immer dran denken: Das Multitasking ist der Echtzeit ihr Feind.

Wieviele Stimmequivalente kann der Synthie?

von J. W. (nuernberger)


Lesenswert?

> Wieviele Stimmequivalente kann der Synthie?

Das ist ein bare-bone in ein paar Stunden zusammenprogrammiert.
Der gibt nur Sinus-Töne aus (pro Ton 3 unterschiedliche Oktavlagan)
und hat einen ganz einfachen ADSR-Envelop-Generator.

Ich wollte nur Latenz vergleichen zwischen Windows/ASIO und Linux/Alsa.
Raspberry war ursrünglich gar nicht geplant.

> Außer dem Rat, alles Unnötige aus dem Kernel rauszuschmeißen, sehe ich
> da wenig Optionen.

Ja, das wird nicht einfach. menuconfig bietet bis zu 4000 Optionen?!
Ich habe das vor ein paar Jahren regelmäßig gemacht, um 
Linux-Installationen zu haben, die ganz schnell hochfahren.

von Mark B. (markbrandis)


Lesenswert?

J. Wa. schrieb:
> Ja, das wird nicht einfach. menuconfig bietet bis zu 4000 Optionen?!
> Ich habe das vor ein paar Jahren regelmäßig gemacht, um
> Linux-Installationen zu haben, die ganz schnell hochfahren.

Vielleicht ein Fall für Tiny Core Linux?

http://www.techrepublic.com/blog/diy-it-guy/diy-tiny-core-linux-a-great-kiosk-and-emergency-platform/

von J. S. (engineer) Benutzerseite


Lesenswert?

J. Wa. schrieb:
> Das ist ein bare-bone in ein paar Stunden zusammenprogrammiert.
Ich dachte, das wird jetzt DER Linux-Synth überhaupt :-)

> Ja, das wird nicht einfach. menuconfig bietet bis zu 4000 Optionen?!
Als ich den letzten Linux-Kernel konfiguriert habe, was noch im letzten 
Jahrtausend war!!! - gab es so 40 Optionen, glaube ich :-)

Ich habe irgendwie den Verdacht, dass Linux in all der Zeit nicht 
wirklich schnell geworden sein könnte, eher schon, mächtig Fett 
angesetzt hat. Liege ich richtig?

von J. W. (nuernberger)


Lesenswert?

Mark Brandis schrieb:
> J. Wa. schrieb:
>> Ja, das wird nicht einfach. menuconfig bietet bis zu 4000 Optionen?!
>> Ich habe das vor ein paar Jahren regelmäßig gemacht, um
>> Linux-Installationen zu haben, die ganz schnell hochfahren.
>
> Vielleicht ein Fall für Tiny Core Linux?
>
> http://www.techrepublic.com/blog/diy-it-guy/diy-ti...

Gibt es für den Raspi auch schon zugeschnitten:

http://sourceforge.net/projects/minibian/

Wobei ich nicht glaube, dass mir das viel hilft. Die sind halt im 
Footprint klein gehalten aber nicht in der Schnelligkeit

von J. W. (nuernberger)


Lesenswert?

Ich habe nun meinen neuen Raspi (RPi 2) in Betrieb genommen.
(Ein sehr schönes Gerät mit 4 USB 2.0 Buchsen)

Das Verhalten ist aber unverändert.
Die geringste Buffergröße des normalen Betriebs liegt bei 2640 Bytes 
(660 Samples), das entspricht 14,99 ms.

Ich vermute, dass der Scheduler die Tasks bei 15ms neu zuweist.
Wenn man bei sched.c irgendeine Konstante ändert, könnte es 
funktionieren,
aber ich kenne mich an der Stelle nicht aus.

An mangelnder Rechenleistung liegt es nicht:
Bei 2640 kann ich noch 8-stimmig fehlerfrei spielen, beim nächst 
kleinerem (2560 Bytes) geht 1 Stimme nicht.

Weiß jemand, wie man beim Scheduler die Task-Wechsel-Frequenz hochsetzt 
?

von Clemens L. (c_l)


Lesenswert?

Das hat mit dem Scheduler nichts zu tun.

Die minimale Puffergröße wird vom Treiber bestimmt, und ist 
wahrscheinlich eine Hardware-Beschränkung.

von J. W. (nuernberger)


Lesenswert?

Ich sollte noch sagen, dass das Öffnen des PCM-Devices auch bei 
kleineren Buffergrößen funktioniert, wenn sie durch 80 teilbar sind, 
2640, 2560, 2480 bis ca 1000.
Bei anderen meldet der Treiber einen Fehler (Error setting buffersize).
1120 funktioniert das Öffnen noch, aber snd_pcm_writei() meldet ständig 
Buffer-Underruns, 960 und darunter öffnet das Device gar nicht mehr.

von Rolf M. (rmagnus)


Lesenswert?

J. Wa. schrieb:
> Ich habe mal Emlid (Realtime Linux auf Raspbian-Grundlage) installiert,
> ohne wesentlichen Verbesserungen.

Hast du denn deinen Threads auch Realtime-Prioität gegeben und was sonst 
noch so nötig ist, um die Realtime-Möglichkeiten auch zu nutzen?

von J. W. (nuernberger)


Lesenswert?

"nice -20 ..." und so habe ich schon ausprobiert.
Mit sched_setscheduler(),  /proc/sys/kernel/sched_rr_timeslice_ms  usw 
arbeite ich mich ein.

Wenn natürlich das Limit vom Treiber her kommt, dann hilft das 
wahrscheinlich nichts.

Edit:
Realtime kenne ich nur von Embedded. Beruflich arbeite ich mit Osek-OS, 
Free-RTOS usw.
Mit Linux habe ich in Sachen Realtime noch nichts gemacht.

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

J. Wa. schrieb:
> "nice -20 ..." und so habe ich schon ausprobiert.

Stellt noch nicht auf Realtime-Priorität um, und der Scheduler wird 
nicht angepaßt, aber solange nicht viel anderes läuft, sollte das auch 
schon was bringen.

> Wenn natürlich das Limit vom Treiber her kommt, dann hilft das
> wahrscheinlich nichts.

Allerdings. Ich hab noch nicht soviel mit dem Raspi gemacht, aber der 
eingebaute Sound scheint da auch nicht so besonders gut zu sein. Mit 
einem USB-Audio-Interface hab ich deutlich bessere Ergebnisse erzielt, 
was die Latenzen betrifft.

von J. W. (nuernberger)


Lesenswert?

> eingebaute Sound scheint da auch nicht so besonders gut zu sein.

ja habe ich eben gelesen:
http://computers.tutsplus.com/articles/using-a-usb-audio-device-with-a-raspberry-pi--mac-55876

von J. W. (nuernberger)


Lesenswert?

Bisher habe ich mir um Nyquist-Limits keine Gedanken gemacht.
D.h. ich habe nur Sinus-Wellen ausgegeben.
Beim 61-Tasten Keyboard hat die höchste Note ca 2000Hz (Midi-Note 96),
bei 3 Oktaven drüber liege ich mit 16kHz noch unterhalb der Nyquist 
Frequenz von 22050Hz.

Allerdings dachte ich mir schon, irgendwann andere Wellenformen zu 
spielen, z.B. Dreieck, Sägezahn.
Rechnerisch ist ja das viel einfacher als sin().

Da lese ich in einem Buch, dass man das nicht darf. Alle Wellen müssen 
als Überlagerung von Sinus-Oszillatoren erzeugt werden.
D.h. bei tiefen Tönen kann ein genaueres Rechteck erzeugt werden als bei 
hohen Tönen, wo die Nyquist-Frequenz schon nach wenigen harmonischen 
erreicht wird.

Ich kenne Nyquist nur von der Abtastung her (Tiefpassfilter 
vorschalten), dass bei der synthestischen Wellenerzeugung es auch 
beachtet werden muss, hätte ich nicht daran gedacht.

von J. S. (engineer) Benutzerseite


Lesenswert?

Wieso sollte man nicht auch nichtsinusförmige Wellen überlagern? Bei 
meiner PLD Orgel mache ich das genau so. Das ergibt eben rechteckigere 
Wellen.

J. Wa. schrieb:
> D.h. bei tiefen Tönen kann ein genaueres Rechteck erzeugt werden als bei
> hohen Tönen, wo die Nyquist-Frequenz schon nach wenigen harmonischen
> erreicht wird.

Sagen wir mal so: Die Steilheit ist limitiert und dies für alle 
Rechtecke gleichermaßen.

Du brauchts im Übrigen in der Software keine echten Sinusoszillatoren, 
um die Oberwellen zu machen, sondern nur eine Multiplikation mit 
Offsetkorrektur:

http://www.96khz.org/oldpages/soundsynthesiswithwavemul.htm

: Bearbeitet durch User
von J. W. (nuernberger)


Lesenswert?

Nach einigen Wochen Verzug (Poststreik) habe ich mein 
USB-Audio-Interface erhalten und es am Raspberry eingesteckt.
Jetzt sind Buffer von 512 Bytes (2.9ms @ 44.1kHz) möglich.
Kaum Buffer-Underruns.
Ich vermute, dass die Latenz doch etwas höher ist als beim PC bei der 
gleichen Buffergröße, d.h. dass beim USB-Device noch zusätzliche 
Verzögerungen dazukommen, aber das ist sehr gering.
Die Audio-Qualität ist erheblich besser als das eingebaute Sounddevice.

von J. S. (engineer) Benutzerseite


Lesenswert?

Welche Type?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.