Projekt:MidiPiSynth: Unterschied zwischen den Versionen

Aus Schaffenburg
Zur Navigation springen Zur Suche springen
(Die Seite wurde neu angelegt: „{{Infobox Projekt |name = MidiPiSynth |status = beta |beschreibung = ein kleiner Synthesizer mit Raspberry Pi |autor = Zoredh…“)
 
KKeine Bearbeitungszusammenfassung
 
(9 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt)
Zeile 16: Zeile 16:
* einfache USB-Soundkarte (hab hier eine billige "Sabrent" für 6,99 Euro verwendet)
* einfache USB-Soundkarte (hab hier eine billige "Sabrent" für 6,99 Euro verwendet)
* ein Paar Boxen mit Klinken-Anschluss
* ein Paar Boxen mit Klinken-Anschluss
* mindestens Midi-Gerät (ich verwendete hier hauptsächlich ein "Akai MPK mini MKII" und manchmal auch einen "Jamstik+")
* mindestens ein Midi-Gerät (ich verwendete hier hauptsächlich ein "Akai MPK mini MKII" und manchmal auch einen "Jamstik+")
* temporär eine USB-Tastatur und Bildschirm mit HDMI-Anschluss (später läuft alles ohne)
* temporär eine USB-Tastatur und Bildschirm mit HDMI-Anschluss (später läuft alles ohne)
* optional LAN-Kabel (oder via raspi-config WLAN einrichten)
* optional LAN-Kabel (oder via raspi-config WLAN einrichten)
Zeile 36: Zeile 36:
Anschließend müssen die Paket-Sourcen aktualisiert werden, damit die noch benötigten Komponenten installiert werden können:
Anschließend müssen die Paket-Sourcen aktualisiert werden, damit die noch benötigten Komponenten installiert werden können:


<nowiki>sudo apt update</nowiki>
sudo apt update


==Weitere Konfiguration==
==Weitere Konfiguration==
Da ich ungerne mit "nano" editiere oder händisch durch Verzeichnisse wusele, installierte ich mir als erstes einen vernünftigen Editor und den allseits beliebten Midnight-Commander:
Da ich ungerne mit "nano" editiere oder händisch durch Verzeichnisse wusele, installierte ich mir als erstes einen vernünftigen Editor und den allseits beliebten Midnight-Commander:


<nowiki>sudo apt install vim mc</nowiki>
sudo apt install vim mc


Anschließend muss die interne Soundkarte unbedingt deaktiviert werden:
Anschließend muss die interne Soundkarte unbedingt deaktiviert werden:
<nowiki>sudo /boot/config.txt</nowiki>
sudo vim /boot/config.txt


Die letzte Zeile muss hier auskommentiert werden:
Die letzte Zeile muss hier auskommentiert werden:
<nowiki>#dtparam=audio=on</nowiki>
#dtparam=audio=on


==Installation der benötigten Software==
==Installation der benötigten Software==


Hier werden das "Jack Audio Connection Kit", "Fluidsynth", ein freier Soundfont und ein ALSA-Plugin installiert:
Hier werden das "Jack Audio Connection Kit", "Fluidsynth", ein freier Soundfont, ein ALSA-Plugin und einen OGG-Player installiert:


sudo apt install jackd fluidsynth fluid-soundfont-gm libasound2-plugins
sudo apt install jackd fluidsynth fluid-soundfont-gm libasound2-plugins vorbis-tools


Dem User pi muss es auch erlaubt sein, sich die Audio-Geräte zu reservieren:
Dem User pi muss es auch erlaubt sein, sich die Audio-Geräte zu reservieren:
Zeile 59: Zeile 59:
Hier wird eine Datei angepasst:
Hier wird eine Datei angepasst:


<nowiki>sudo vim /etc/dbus-1/system.d/org.freedesktop.systemd1.conf</nowiki>
sudo vim /etc/dbus-1/system.d/org.freedesktop.systemd1.conf
oder
oder
<nowiki>sudo nano /etc/dbus-1/system.d/org.freedesktop.systemd1.conf</nowiki>
sudo nano /etc/dbus-1/system.d/org.freedesktop.systemd1.conf
 
Unter dem Block <policy user="root">... </policy> muss folgender Block eingefügt werden:


Unter dem Block <nowiki><policy user="root">... </policy></nowiki> muss folgender Block eingefügt werden:
<nowiki>
         <policy user="pi">
         <policy user="pi">
             <allow own="org.freedesktop.ReserveDevice1.Audio0"/>
             <allow own="org.freedesktop.ReserveDevice1.Audio0"/>
             <allow own="org.freedesktop.ReserveDevice1.Audio1"/>
             <allow own="org.freedesktop.ReserveDevice1.Audio1"/>
         </policy>
         </policy>
</nowiki>
 
==Konfiguration und Skripte==
==Konfiguration und Skripte==
===JACK===
===JACK===


Anlegen der Datei /home/pi/.jackdrc mit folgendem Inhalt:
Anlegen der Datei /home/pi/.jackdrc mit folgendem Inhalt:
<nowiki>/usr/bin/jackd -T -R -P35 -dalsa -dhw:0,0 -r44100 -p256</nowiki>
/usr/bin/jackd -T -R -P35 -dalsa -dhw:0,0 -r44100 -p256


-T nach dem Trennen der letzten Instanz JACK beenden
-T nach dem Trennen der letzten Instanz JACK beenden
-R -P35 Realtime mit der Priorität 35 (mit der Priorität kann man ruhig etwas rumspielen
-R -P35 Realtime mit der Priorität 35 (mit der Priorität kann man ruhig etwas rumspielen
-dalsa -dhw0:0 Als Output die erste Soundkarte via ALSA verwenden
-dalsa -dhw0:0 Als Output die erste Soundkarte via ALSA verwenden
-r44100 Sample-Rate an Fluidsynth anpassen
-r44100 Sample-Rate an Fluidsynth anpassen
-p256 maximale Anzahl der Ports festlegen (256 reichen locker aus)
-p256 maximale Anzahl der Ports festlegen (256 reichen locker aus)


ACHTUNG: -dhw:0,0 kann ggf. auch -dhw:1,0 bzw. -dhw:2,0 sein


===Fluidsynth===
===Fluidsynth===
Zeile 88: Zeile 89:
* Anlegen des Start-Skripts für Fluidsynth "/home/pi/bin/fs"
* Anlegen des Start-Skripts für Fluidsynth "/home/pi/bin/fs"


<nowiki>#!/bin/bash
#!/bin/bash
 
#DBUS-Problem ohne XServer
#DBUS-Problem ohne XServer
export JACK_NO_AUDIO_RESERVATION=1
export JACK_NO_AUDIO_RESERVATION=1
 
#Starte Fluidsyntkript
#Starte Fluidsyntkript
fluidsynth -l -s -a jack -j -i -f /home/pi/bin/fs.cfg /usr/share/sounds/sf2/FluidR3_GM.sf2 &
fluidsynth -l -s -a jack -j -i -f /home/pi/bin/fs.cfg /usr/share/sounds/sf2/FluidR3_GM.sf2 &
 
#Warte bis sich wenigstens ein Gerät verbindet
#Warte bis sich wenigstens ein Gerät verbindet
while ! /home/pi/bin/condev &>/dev/null; do sleep 1;done
while ! /home/pi/bin/condev &>/dev/null; do sleep 1;done
</nowiki>


* Anlegen der Konfigurationsdatei "/home/pi/bin/fs.cfg" (ich habe hier die Lautstärke auf 2 und für den ersten Channel ein Banjo gewählt)
* Anlegen der Konfigurationsdatei "/home/pi/bin/fs.cfg" (ich habe hier die Lautstärke auf 2 und für den ersten Channel ein Banjo gewählt)


<nowiki>gain 2
gain 2
prog 0 105</nowiki>
prog 0 105


===ALSA===
===ALSA===
Da man über ALSA nur einen Sound zur gleichen Zeit abspielen kann, bauen wir eine Brücke zu JACK, so dass die Ausgaben alle via JACK zu ALSA laufen. Dazu legen wir die Datei /home/pi/.asoundrc mit folgendem Inhalt an:
Da man über ALSA nur einen Sound zur gleichen Zeit abspielen kann, bauen wir eine Brücke zu JACK, so dass die Ausgaben alle via JACK zu ALSA laufen. Dazu legen wir die Datei /home/pi/.asoundrc mit folgendem Inhalt an:


<nowiki>pcm.rawjack {
pcm.rawjack {
     type jack
     type jack
     playback_ports {
     playback_ports {
Zeile 118: Zeile 118:
         1 system:capture_2
         1 system:capture_2
     }
     }
}
}
 
pcm.jack {
pcm.jack {
     type plug
     type plug
     slave { pcm "rawjack" }
     slave { pcm "rawjack" }
Zeile 126: Zeile 125:
  description "JACK Audio Connection Kit"
  description "JACK Audio Connection Kit"
     }
     }
}
}
pcm.!default {
pcm.!default {
     type plug
     type plug
     slave { pcm "rawjack" }
     slave { pcm "rawjack" }
}</nowiki>
}


Um nicht jedes Mal mit aconnect schauen zu müssen, welche ID die Midi-Geräte haben, habe ich ein Script angelegt, welches diesen aconnect automatisch macht
Um nicht jedes Mal mit aconnect schauen zu müssen, welche ID die Midi-Geräte haben, habe ich ein Script angelegt, welches diesen aconnect automatisch macht
Zeile 136: Zeile 135:
* Anlegen des Skripts /home/pi/bin/condev (ich gebe mit ogg123 noch einen Sound aus, weil später kein Bildschirm vorhanden sein muss)
* Anlegen des Skripts /home/pi/bin/condev (ich gebe mit ogg123 noch einen Sound aus, weil später kein Bildschirm vorhanden sein muss)


<nowiki>#!/bin/bash
#!/bin/bash
/usr/bin/aconnect -i|/usr/bin/awk '/client.*card=/ {print $2}'| while read INPUT
/usr/bin/aconnect -i|/usr/bin/awk '/client.*card=/ {print $2}'| while read INPUT
do
do
/usr/bin/aconnect ${INPUT}0 128 && /usr/bin/ogg123 -q /home/pi/sound/in.oga
    /usr/bin/aconnect ${INPUT}0 128 && /usr/bin/ogg123 -q /home/pi/sound/in.oga
done
done
exit $?</nowiki>
exit $?


* Ausführbarmachen der Skripte
* Ausführbarmachen der Skripte
<nowiki>chmod -R +x /home/pi/bin/*</nowiki>
chmod -R +x /home/pi/bin/*


==Vorbereitungen für den Betrieb ohne Monitor (headless)==
==Vorbereitungen für den Betrieb ohne Monitor (headless)==
Zeile 152: Zeile 151:
Ganz am Ende folgende Zeile für den Automatischen Start einfügen (der erste Teil  vor den zwei || verhindert das starten bei einer zweiten Shell):
Ganz am Ende folgende Zeile für den Automatischen Start einfügen (der erste Teil  vor den zwei || verhindert das starten bei einer zweiten Shell):


<nowiki>ps-e|grep -q fluid || /home/pi/bin/fs</nowiki>
ps -e|grep -q fluid || /home/pi/bin/fs


===USB-Geräte-Erkennung und Anbindung===
===USB-Geräte-Erkennung und Anbindung===
Die Automatische Erkennung findet über UDEV statt - hierzu braucht man nur folgende die Datei /etc/udev/rules.d/80-mididev.rules mit folgendem Inhalt anzulegen:
Die Automatische Erkennung findet über UDEV statt - hierzu braucht man nur folgende die Datei /etc/udev/rules.d/80-mididev.rules mit folgendem Inhalt anzulegen:


<nowiki>ACTION=="add", SUBSYSTEM=="usb", RUN+="/bin/su - pi /home/pi/bin/condev"</nowiki>
ACTION=="add", SUBSYSTEM=="usb", RUN+="/bin/su - pi /home/pi/bin/condev"


Dadurch wird jetzt immer condev aufgerufen, dass die Geräte via aconnect mit fluidsynth verbindet
Dadurch wird jetzt immer condev aufgerufen, dass die Geräte via aconnect mit fluidsynth verbindet
Zeile 167: Zeile 166:
Ein kleines Pythonscript "/home/pi/bin/shutdown.py" muss mit folgendem Inhalt angelegt werden:
Ein kleines Pythonscript "/home/pi/bin/shutdown.py" muss mit folgendem Inhalt angelegt werden:


<nowiki>#! /usr/bin/env python
#! /usr/bin/env python
import os
import os
import RPi.GPIO as GPIO
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setmode(GPIO.BCM)
# GPIO3 (pin 5) set up as input. It is pulled up to stop false signals
# GPIO3 (pin 5) set up as input. It is pulled up to stop false signals
GPIO.setup(3, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(3, GPIO.IN, pull_up_down=GPIO.PUD_UP)
try:
try:
     while True:
     while True:
         # wait for the pin to be sorted with GND and, if so, halt the system
         # wait for the pin to be sorted with GND and, if so, halt the system
Zeile 179: Zeile 178:
         # shut down the rpi
         # shut down the rpi
         os.system("/sbin/shutdown -h now")
         os.system("/sbin/shutdown -h now")
except:
except:
     GPIO.cleanup()</nowiki>
     GPIO.cleanup()


* Anschließend muss dieses ausführbar gemacht werden mit:
* Anschließend muss dieses ausführbar gemacht werden mit:


<nowiki>chmod +x /home/pi/bin/shutdown.py
chmod +x /home/pi/bin/shutdown.py
</nowiki>
 
Damit der Computer darauf reagieren kann, muss dieses Script beim Start werden. Hierzu editiert man die /etc/crontab:
Damit der Computer darauf reagieren kann, muss dieses Script beim Start werden. Hierzu editiert man die /etc/crontab:


<nowiki>@reboot root /usr/bin/python /home/pi/bin/shutdown.py</nowiki>
@reboot root /usr/bin/python /home/pi/bin/shutdown.py


===Hardware===
===Hardware===

Aktuelle Version vom 19. Oktober 2020, 19:56 Uhr

Crystal Clear action run.png
MidiPiSynth

Status: beta

Midipisynth.jpg
Beschreibung ein kleiner Synthesizer mit Raspberry Pi
Ansprechpartner Zoredh


Projektbeschreibung

Ziel des Projekts ist es, statt teurer Hardware einfach einen Raspberry Pi als Synthesizer zu verwenden. Trotzdem soll hier ein System gebaut werden, das mit wenig Latenz arbeitet.

Hardware-Komponenten

  • Raspberry Pi 3B+ (2B reicht vermutlich auch) mit Netzteil (5V/2,5A)
  • einfache USB-Soundkarte (hab hier eine billige "Sabrent" für 6,99 Euro verwendet)
  • ein Paar Boxen mit Klinken-Anschluss
  • mindestens ein Midi-Gerät (ich verwendete hier hauptsächlich ein "Akai MPK mini MKII" und manchmal auch einen "Jamstik+")
  • temporär eine USB-Tastatur und Bildschirm mit HDMI-Anschluss (später läuft alles ohne)
  • optional LAN-Kabel (oder via raspi-config WLAN einrichten)

Midipisynth.jpg

Software

Installation Betriebssystem

Hier wählte ich ein Raspbian Lite mit PREEMPT-RT-Kernel. Dieser spezielle Realtime-Kernel ist notwendig, da sonst die Latenzen (Zeit zwischen Auslösen des Events und dem hörbaren Ton) zu groß wird. Da ich aber (anders als die meisten hier bei Schaffenburg) ein fauler Hund bin und mir keine 15 Stunden Zeit zum kompilieren des Kernels nehmen wollte, habe ich mir ein fertiges Image runtergeladen: http://unofficialpi.org/Distros/RealtimePi/2018-06-12_2018-04-18-realtimepi-stretch-lite-0.3.zip Dieses Image ist zwar schon ein wenig älter, tut der Sache aber keinen Abbruch. Dieses Image habe ich entzippt und auf die SD-Karte übertragen. An manchen Tagen mag ich eine GUI und so habe ich Etcher gewählt. https://etcher.io

Grundkonfiguration

Als nächstes habe ich alle Komponenten an den Raspberry Pi angeschlossen - USB-Soundkarte Boxen, USB-Keyboard, USB-Midi-Gerät, LAN und als letzes die Stromversorgung. Nach dem ersten Booten mit dieser eben beschriebenen SD-Karte, muss das System noch initial konfiguriert werden. Via "sudo raspi-config" kann man hier, wenn man mag, die Sprache und all die tollen Dinge wie WLAN, SSH-Server usw. konfigurieren. Wichtig ist hier nur der Autologin:

Boot Options -> B1 (Desktop/CLI) -> B2 (Console Autologin)

Anschließend müssen die Paket-Sourcen aktualisiert werden, damit die noch benötigten Komponenten installiert werden können:

sudo apt update

Weitere Konfiguration

Da ich ungerne mit "nano" editiere oder händisch durch Verzeichnisse wusele, installierte ich mir als erstes einen vernünftigen Editor und den allseits beliebten Midnight-Commander:

sudo apt install vim mc

Anschließend muss die interne Soundkarte unbedingt deaktiviert werden:

sudo vim /boot/config.txt

Die letzte Zeile muss hier auskommentiert werden:

#dtparam=audio=on

Installation der benötigten Software

Hier werden das "Jack Audio Connection Kit", "Fluidsynth", ein freier Soundfont, ein ALSA-Plugin und einen OGG-Player installiert:

sudo apt install jackd fluidsynth fluid-soundfont-gm libasound2-plugins vorbis-tools

Dem User pi muss es auch erlaubt sein, sich die Audio-Geräte zu reservieren:

Hier wird eine Datei angepasst:

sudo vim /etc/dbus-1/system.d/org.freedesktop.systemd1.conf

oder

sudo nano /etc/dbus-1/system.d/org.freedesktop.systemd1.conf

Unter dem Block <policy user="root">... </policy> muss folgender Block eingefügt werden:

       <policy user="pi">
            <allow own="org.freedesktop.ReserveDevice1.Audio0"/>
            <allow own="org.freedesktop.ReserveDevice1.Audio1"/>
       </policy>

Konfiguration und Skripte

JACK

Anlegen der Datei /home/pi/.jackdrc mit folgendem Inhalt:

/usr/bin/jackd -T -R -P35 -dalsa -dhw:0,0 -r44100 -p256
-T nach dem Trennen der letzten Instanz JACK beenden
-R -P35 Realtime mit der Priorität 35 (mit der Priorität kann man ruhig etwas rumspielen
-dalsa -dhw0:0 Als Output die erste Soundkarte via ALSA verwenden
-r44100 Sample-Rate an Fluidsynth anpassen
-p256 maximale Anzahl der Ports festlegen (256 reichen locker aus)

ACHTUNG: -dhw:0,0 kann ggf. auch -dhw:1,0 bzw. -dhw:2,0 sein

Fluidsynth

  • Anlegen eines Verzeichnisses /home/pi/bin
  • Anlegen des Start-Skripts für Fluidsynth "/home/pi/bin/fs"
#!/bin/bash

#DBUS-Problem ohne XServer
export JACK_NO_AUDIO_RESERVATION=1

#Starte Fluidsyntkript
fluidsynth -l -s -a jack -j -i -f /home/pi/bin/fs.cfg /usr/share/sounds/sf2/FluidR3_GM.sf2 &

#Warte bis sich wenigstens ein Gerät verbindet
while ! /home/pi/bin/condev &>/dev/null; do sleep 1;done
  • Anlegen der Konfigurationsdatei "/home/pi/bin/fs.cfg" (ich habe hier die Lautstärke auf 2 und für den ersten Channel ein Banjo gewählt)
gain 2
prog 0 105

ALSA

Da man über ALSA nur einen Sound zur gleichen Zeit abspielen kann, bauen wir eine Brücke zu JACK, so dass die Ausgaben alle via JACK zu ALSA laufen. Dazu legen wir die Datei /home/pi/.asoundrc mit folgendem Inhalt an:

pcm.rawjack {
   type jack
   playback_ports {
       0 system:playback_1
       1 system:playback_2
   }
   capture_ports {
       0 system:capture_1
       1 system:capture_2
   }
}
pcm.jack {
   type plug
   slave { pcm "rawjack" }
   hint {
	description "JACK Audio Connection Kit"
   }
}
pcm.!default {
   type plug
   slave { pcm "rawjack" }
}

Um nicht jedes Mal mit aconnect schauen zu müssen, welche ID die Midi-Geräte haben, habe ich ein Script angelegt, welches diesen aconnect automatisch macht

  • Anlegen des Skripts /home/pi/bin/condev (ich gebe mit ogg123 noch einen Sound aus, weil später kein Bildschirm vorhanden sein muss)
#!/bin/bash
/usr/bin/aconnect -i|/usr/bin/awk '/client.*card=/ {print $2}'| while read INPUT
do
    /usr/bin/aconnect ${INPUT}0 128 && /usr/bin/ogg123 -q /home/pi/sound/in.oga
done
exit $?
  • Ausführbarmachen der Skripte
chmod -R +x /home/pi/bin/*

Vorbereitungen für den Betrieb ohne Monitor (headless)

Autostart Fluidsynth & JACK

Ich habe mich hier bewusst für die .bashrc entschieden, weil Fluidsynth hin und wieder Problem mit Sudo hat.

  • Editieren der Datei /home/pi/.bashrc

Ganz am Ende folgende Zeile für den Automatischen Start einfügen (der erste Teil vor den zwei || verhindert das starten bei einer zweiten Shell):

ps -e|grep -q fluid || /home/pi/bin/fs

USB-Geräte-Erkennung und Anbindung

Die Automatische Erkennung findet über UDEV statt - hierzu braucht man nur folgende die Datei /etc/udev/rules.d/80-mididev.rules mit folgendem Inhalt anzulegen:

ACTION=="add", SUBSYSTEM=="usb", RUN+="/bin/su - pi /home/pi/bin/condev"

Dadurch wird jetzt immer condev aufgerufen, dass die Geräte via aconnect mit fluidsynth verbindet

Ein letzter Reboot und alles läuft

Optional sicheres Herunterfahren durch einen Powerbutton

Software

Ein kleines Pythonscript "/home/pi/bin/shutdown.py" muss mit folgendem Inhalt angelegt werden:

#! /usr/bin/env python
import os
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
# GPIO3 (pin 5) set up as input. It is pulled up to stop false signals
GPIO.setup(3, GPIO.IN, pull_up_down=GPIO.PUD_UP)
try:
   while True:
       # wait for the pin to be sorted with GND and, if so, halt the system
       GPIO.wait_for_edge(3, GPIO.FALLING)
       # shut down the rpi
       os.system("/sbin/shutdown -h now")
except:
   GPIO.cleanup()
  • Anschließend muss dieses ausführbar gemacht werden mit:
chmod +x /home/pi/bin/shutdown.py

Damit der Computer darauf reagieren kann, muss dieses Script beim Start werden. Hierzu editiert man die /etc/crontab:

@reboot root /usr/bin/python /home/pi/bin/shutdown.py

Hardware

Hier schließt man einen kleinen Taster an die Pins 3 und 5

Powerbutton1.png

Ausblick & ToDos

  • Vielleicht eine kleine Weboberfläche, damit man remote die Instrumente auswählen kann