VOGONS


Reply 21 of 57, by mcobit

User metadata
Rank Member
Rank
Member

Here are the two python scripts that i use in parallel to drive the logic and the leds.
Unfortunately I don't have access to the bashscripts, that start/restart the synths, but I will post them when I have access to the pi again.
I commented them as good as I can, but if there still are any questions, feel free to ask.

rpimidi.py (main script for handling input, lcd and start/restart actions. I put it into /etc/rc.local to start it automatically when the pi starts):

#!/usr/bin/env python

# We use the RPLCD Python library (https://github.com/dbrgn/RPLCD)
from RPLCD.i2c import CharLCD
# We need the time library for delay
import time
# Glob makes it easier to parse a folder of files
import glob
# We use the OS library to use system commands
import os
# Alsaaudio is used to control the alsamixer from Python
import alsaaudio
# Importing RPi GPIO to check button input on GPIO pins
import RPi.GPIO as GPIO

# Make a control instance of the PCM device from alsaaudio. "PCM" needs to be replaced with the appropriate string for other USB soundcards as the integrated analog out
m = alsaaudio.Mixer("PCM")

# Set up GPIO pins we use for button inputs

# Set the GPIO numbering scheme to use header pin numbering
GPIO.setmode(GPIO.BOARD)

# Set the four used GPIOs as inputs with internal pullup resistors activated, so we just need to pull them to ground by pressing the button for input
GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(12, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(13, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(15, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# Create instance of the RPLCD. In this case an Hitachi 44780 20x2 LCD with a PCF8574 portextender
lcd = CharLCD(i2c_expander='PCF8574', address=0x27, port=1, cols=21, rows=2, dotsize=8, charmap='A02', auto_linebreaks=False, backlight_enabled=True)

# Make sure the LCD is clear
lcd.clear()

# Declare the global lists to store synths and soundfonts we use in this script
global soundfonts
global synths

# Get synths from file and store them in a list called synths. Probably not needed as there are only 3 available for now: Roland CM32L (Munt), Roland MT32 (Munt), General Midi (FluidSynth)
synths = open("synths.dat").readlines()

# Get all the Sondfont names from all the .sf2 files in a directory and store them in a list named soundfonts
soundfonts = glob.glob('/home/pi/sf2/*.sf2')

# Remove paths from the results
soundfonts = [os.path.basename(x) for x in soundfonts]

# Remove sf2 extension from results
soundfonts = [os.path.splitext(x)[0] for x in soundfonts]

# Sort list alphabetically
soundfonts = sorted(soundfonts)

# declare some more variables for navigating the menus and setting edit mode
sfcounter = 0
syncounter = 0
changed = 0

# Write first Synth to the LCD
Show last 167 lines
lcd.cursor_pos = (0, 0)
lcd.write_string(synths[syncounter])
lcd.cursor_pos = (1, 0)
lcd.write_string("Munt Emulator")

# Clear contents of the lcdmessage.txt file. This file is used to to store the sysex messages from the mt32d application to a file so we can read them to the python script
open('/home/pi/lcdmessage.txt', 'w').close()

# Start the first synth via batch script in the background
os.system('/home/pi/cm32lstart.sh &')

# declare more variables for the volume control and lcdmessage for comparison
volume = 0
new_volume = m.getvolume()[0]
oldmessage = ""

# For debugging only: print the current volume
# print m.getvolume()[0]

# Start main loop
while True:

# open the lcdmessage.txt file for reading
lcdfile = open("/home/pi/lcdmessage.txt","r")

# read first line of the file to a variable
lcdmessage = lcdfile.readline()

# if the message is not the same as the last one read, print the new message to the second line of the lcd, then close the file and update the oldmessage variable for comparison with future messages.
if lcdmessage != oldmessage:
lcd.cursor_pos = (1, 0)
lcd.write_string(lcdmessage)
lcdfile.close()
oldmessage = lcdmessage

# Give the main loop a little delay to get cpu usage down to about 17% instead of 100%
time.sleep(0.005)

# If the button on pin 15 is pressed, check every second for 5 seconds, if the button is still pressed and count down the seconds. If the button is released before the 5 seconds are over, reset the current synth. If th button is still pressed after 5 seconds, display a good bye mesage and shut down the Pi
if GPIO.input(15) == 0:
for x in range(0,4):
time.sleep(1)
if GPIO.input(15) == 0:
lcd.cursor_pos = (1, 0)
lcd.write_string("Shutdown in "+str(5-x)+" ")
if GPIO.input(15) == 0:
lcd.cursor_pos = (1, 0)
lcd.write_string("Good Bye ... ")
os.system("sudo shutdown -h now")

# If the button on pin 11 is pressed in the main loop, increase the volume variable by 1
if GPIO.input(11) == 0:
new_volume = volume + 1

# If the button on pin 12 is pressed in the main loop, decrease the volume variable by 1
if GPIO.input(12) == 0:
new_volume = volume - 1

# if the new volume is smaller than 0 or higher than 99, set it to 0 or 99
if int(new_volume) < 0:
new_volume = 0
if int(new_volume) > 99:
new_volume = 99

# If the new volume is different from the current volume, set the volume to the new volume and use the instance of our alsamixercontrol to set it to the new volume
if new_volume != volume:
volume = new_volume
m.setvolume(volume)
time.sleep(0.1)

# write the current volume to the lcd. Ad a whitespace before the volume string if the volume is smaller than 10 to prevent a shift in the lcd columns
lcd.cursor_pos = (0,14)
if int(volume) > 9:
lcd.write_string("Vol:" + str(volume))
else:
lcd.write_string("Vol: " + str(volume))

# If the button on pin 13 is pressed, enter the Edit function by setting the set variable to 1 (True) and write the String "Edit" to the lcd to indicate that we are in edit mode now
if GPIO.input(13) == 0:
set = 1
lcd.cursor_pos = (0,14)
lcd.write_string(" ")
lcd.cursor_pos = (0,15)
lcd.write_string("Edit")
# little delay as a software debounce of the button
time.sleep(0.2)

# enter Edit loop
while set == 1:

# if button on pin 12 is pressed during edit loop, check if we are in General Midi mode (syncounter ==2) and make sure that the value of the sfcounter variable is not higher or lower than the number of soundfonts in the soundfonts list
if GPIO.input(12) == 0:
if syncounter == 2:
if sfcounter == len(soundfonts)-1:
sfcounter = -1

# increase the soundfontcounter by one, clear the lcdline by filling it with whitespaces, then update the current soundfont from the list and writing it to the lcd after cropping it to the max. characters of the lcd
sfcounter = sfcounter + 1
lcd.cursor_pos = (1, 0)
lcd.write_string(" ")
if syncounter == 2:
lcd.cursor_pos = (1, 0)
lcd.write_string(soundfonts[sfcounter][0:19])

# if the current synth is not General Midi, just print Munt Emulator to the second line of the lcd
else:
lcd.cursor_pos = (1,0)
lcd.write_string("Munt Emulator ")

# Only for debug: Print current sfcounter variable
# print(sfcounter)

# little delay for software debounce of the button
time.sleep(0.2)

# If the button on pin 11 is pressed during Edit loop, do the same as with the soundfonts before and update the lcd with current synth an soundfont, if the syncounter is 2 (General Midi)
if GPIO.input(11) == 0:
if syncounter == len(synths)-1:
syncounter = -1
syncounter = syncounter + 1
lcd.cursor_pos = (0, 0)
lcd.write_string(" ")
lcd.cursor_pos = (0, 0)
lcd.write_string(synths[syncounter])
lcd.cursor_pos = (1, 0)
lcd.write_string(" ")
if syncounter == 2:
lcd.cursor_pos = (1, 0)
lcd.write_string(soundfonts[sfcounter][0:19])
else:
lcd.cursor_pos = (1,0)
lcd.write_string("Munt Emulator")
print(syncounter)

# little delay for software debounce of the button
time.sleep(0.2)

# If the button on pin 13 is pressed again, exit the Edit loop by changing set variable to 0 (False) and set the changed variable to 1 to tell the main loop to restart the synth with the parameters set during edit loop
if GPIO.input(13) == 0:
changed = 1
set = 0

# If the edit loop signaled, that something has changed (changed == True), print "Please Wait..." to the lcd while starting the newly selected synth with the newly selected soundfont Then update the lcd with the new values and after that, change the changed variable back to 0 (False)
if changed == 1:
lcd.cursor_pos = (1,0)
lcd.write_string("Please Wait... ")

print(synths[syncounter])
synthname = synths[syncounter]
print(synthname)
if syncounter == 0:
os.system('/home/pi/cm32lstart.sh')
print("cm32l")
if syncounter == 1:
os.system('/home/pi/mt32start.sh')
print("mt32")
if syncounter == 2:
os.system('/home/pi/fluidsynthstart.sh \"'+soundfonts[sfcounter]+'.sf2\"')
lcd.cursor_pos = (1,0)
lcd.write_string(" ")
if syncounter == 2:
lcd.cursor_pos = (1,0)
lcd.write_string(soundfonts[sfcounter][0:19])
else:
lcd.cursor_pos = (1,0)
lcd.write_string("Munt Emulator")
changed = 0

midilight.py (script to listen to the midiport and set the leds accordingly to the messages):

#!/usr/bin/env python

# import sys to exit to shell in case of error
import sys

# import time for delays and stuff
import time

# import the apa102 library to use our APA102 RGB leds (https://github.com/tinue/APA102_Pi)
import apa102

# inport the python rt-midi library (https://github.com/SpotlightKid/python-rtmidi) to open the midi port and monitor midi messages
from rtmidi.midiutil import open_midiinput

# define an instance of the apa102 library to control our ledstrip with 16 leds (Midid has 16 channels per port), brightness of 20% (those leds are REALLY BRIGHT, so low values suffice here), mosi pin 10 and sclk pin of 11. Also the color order of my ledstrip is rgb. May vary with other models.
strip = apa102.APA102(num_led=16, global_brightness=20, mosi = 10, sclk = 11,
order='rgb')

# initialize a variable that counts how many cycles there was no midi input to reset the leds (some tracks or programs don't send note off for all channels when the song ends)
nonecount = 0

# set all pixels to black
for l in range(0, 15):
strip.set_pixel_rgb(l, 0x000000)

# update the strip
strip.show()

# define a little helper function to use as a mapfunction analog to arduino's map function (in python, map has different functionality)
def valmap(x, in_min, in_max, out_min, out_max):
return int((x-in_min) * (out_max-out_min) / (in_max-in_min) + out_min)

# Open a midiport: midiinput(0) refers to first found midiinport, usually 14:0, the systems through port. The USB midiinterface as well as the synths are mapped to this port. This is an easy way to make sure, they always find the right route.
try:
midiin, aplaymidi = open_midiinput(0)
# if that fails, close the program
except (EOFError, KeyboardInterrupt):
sys.exit()

# Enter main loop
while True:

# get a message from the midiport and store it in a list called msg Please refer for the python-rtmidi documentation to see the formatting. It looks like this: [[commandandchannel, note, velocity],sysex and other stuff]
msg = midiin.get_message()

# declare another variable to only get the first list in the list and if the message read is not "none", store the first list in the msg variabel to the list msg0
msg0 = [0,0,0]
if msg != None:
msg0 = msg[0]

# if there is a message we can read, get the chahnnel and check for note on command (144, 159) from the first variable from the list and update the leds, that correspond to the channels with the info for color hue (strip.wheel(valmap(msg0[1], 21, 108, 0, 220))) and velocity (valmap(msg0[2], 0, 127, 0, 15))
if msg:
for x in range(144, 159):
if x in msg[0]:
if len(msg0) > 2:
strip.set_pixel_rgb(15 - (159 - x), strip.wheel(valmap(msg0[1], 21, 108, 0, 220)), valmap(msg0[2], 0, 127, 0, 15))

# if there is no velocity set (len(msg0) <= 2), just set the brightness to 15%
else:
strip.set_pixel_rgb(15 - (159 - x), strip.wheel(valmap(msg0[1], 21, 108, 0, 220)), 15)
Show last 30 lines
				  
# if a note off command is in the list, set the channel's led to black
for y in range(128, 143):
if y in msg[0]:
strip.set_pixel_rgb(15 - (143 - y), 0x000000)

# as we recieved a message, set the count of cycles with no midiinput to 0 again
nonecount = 0

# if there is no message to recieve, rtmidi is non-blocking and will set the message to "None" if no message is present at the midiport, increase the nonecount by 1 and go on
if msg == None:
nonecount = nonecount + 1

# if the nonecount reaches 5000, reset all leds to black (ca. 10 seconds) and start to count again
if nonecount > 5000:
for i in range(0,15):
strip.set_pixel_rgb(i, 0x000000)
nonecount = 0

# show our changes to the strip
strip.show()

#add a delay to tame down cpu usage
time.sleep(0.001)
# if we stop the scipt by ctrl+c or kill command, end the script and close the midi connection, then remove the instance of midiin
finally:
print("Exit.")
midiin.close_port()
del midiin

Reply 22 of 57, by mcobit

User metadata
Rank Member
Rank
Member

I also want to give the self made midi uart interface a second try.

Here is a picture of etching a prototype board in HCl with some H2O2:

20180127_160932.jpg
Filename
20180127_160932.jpg
File size
1.01 MiB
Views
3167 views
File license
Fair use/fair dealing exception

Reply 23 of 57, by mcobit

User metadata
Rank Member
Rank
Member

Here are the scripts to shudown and restart the synths.
I think they are pretty selfexplanatory. TTYmidi is still in there but won't do anything as it is not started.

fluidsynth:

#/bin/bash

if pgrep ttymidi ; then
sudo killall ttymidi
sleep 1
fi

if pgrep -f midilight.py ; then
sudo kill $(pgrep -f midilight.py)
fi

if pgrep mt32d ; then
echo "Killing previous instance of mt32d"
sudo killall mt32d
while pgrep mt32d ; do
sleep 0.1
done
fi

if pgrep fluidsynth ; then
echo "Killing previous instance of fluidsynth"
sudo killall fluidsynth
while pgrep fluidsynth ; do
sleep 0.1
done
fi

while aconnect -l |grep 128 ; do
sleep 0.1
done

sudo LD_PRELOAD=/usr/local/lib/libfluidsynth.so.1.7.0 /usr/local/bin/fluidsynth --server --no-shell --audio-driver=alsa /home/pi/sf2/"$1" &

while ! aconnect -l |grep 128 ; do
sleep 0.1
done

#sudo ttymidi -s /dev/ttyAMA0 -b 38400 &
sleep 1

aconnect 20:0 14:0
aconnect 129:0 14:0
aconnect 14:0 128:0

sleep 1

python /home/pi/APA102_Pi/midilight.py &

cm32l:

#/bin/bash

if pgrep ttymidi ; then
sudo killall ttymidi
sleep 2
fi

if pgrep -f midilight.py ; then
sudo kill $(pgrep -f midilight.py)
fi

if pgrep mt32d ; then
echo "Killing previous instance of mt32d"
sudo killall mt32d
while pgrep mt32d ; do
sleep 1
done

fi

if pgrep fluidsynth ; then
echo "Killing previous instance of fluidsynth"
sudo killall fluidsynth
while pgrep fluidsynth ; do
sleep 1
done
fi

while aconnect -l |grep 128 ; do
sleep 1
done

LD_PRELOAD=/usr/local/lib/libmt32emu.so.2 /usr/local/bin/mt32d -o 1 -i 24&

while ! aconnect -l |grep 128 ; do
sleep 1
done

#sudo ttymidi -s /dev/ttyAMA0 -b 38400 &
sleep 2

aconnect 20:0 14:0
aconnect 129:0 14:0
aconnect 14:0 128:0

sleep 1

python /home/pi/APA102_Pi/midilight.py &

mt32:

#/bin/bash

if pgrep ttymidi ; then
sudo killall ttymidi
sleep 2
fi

if pgrep -f midilight.py ; then
sudo kill $(pgrep -f midilight.py)
fi

if pgrep mt32d ; then
echo "Killing previous instance of mt32d"
sudo killall mt32d
while pgrep mt32d ; do
sleep 1
done
fi

if pgrep fluidsynth ; then
echo "Killing previous instance of fluidsynth"
sudo killall fluidsynth
while pgrep fluidsynth ; do
sleep 1
done
fi

while aconnect -l |grep 128 ; do
sleep 1
done

LD_PRELOAD=/usr/local/lib/libmt32emu.so.2 /usr/local/bin/mt32d -o 2 -i 24&

while ! aconnect -l |grep 128 ; do
sleep 1
done

#sudo ttymidi -s /dev/ttyAMA0 -b 38400 &
sleep 2

aconnect 20:0 14:0
aconnect 129:0 14:0
aconnect 14:0 128:0

sleep 1

python /home/pi/APA102_Pi/midilight.py &

Reply 25 of 57, by gdjacobs

User metadata
Rank l33t++
Rank
l33t++
mcobit wrote:

Right now I am starting/killing processes.
Also helps with hanging notes if a specific synth doesn't get a note off after switching.
Having all synths running seems too resource hungry and more unreliable.

This can be done with a MIDI reset SYSEX. I have the requisite file if you want.

All hail the Great Capacitor Brand Finder

Reply 26 of 57, by mcobit

User metadata
Rank Member
Rank
Member

As said, having all synths running all the time on different ports and having to find out and make sure the ports are the same every start seems a bit more comlicated to me than starting the synth needed. I don't use any gui and want to have it as automated and idiot proof as possible.
Every synth will consume resources that sometimes are needed e.g. when loading big soundfonts or if you have tracks with higher channel count.

Of course I am interested in the file though.

Reply 27 of 57, by gdjacobs

User metadata
Rank l33t++
Rank
l33t++

The Python ALSA API allows you to select internal MIDI routing points by label, but I suspect you're right in terms of making this whole thing straightforward.

I've experimented with using JACK as a sound server (it's actually pretty much required when I have my MIDI/DAC/ADC module plugged in) and I believe hot switching the outputs while maintaining consistent MIDI state in the synthesizers is viable as long as the CPU and RAM holds out. I suspect this is useful only in corner cases like A/B soundfont comparisons and so forth.

All hail the Great Capacitor Brand Finder

Reply 28 of 57, by mcobit

User metadata
Rank Member
Rank
Member

Maybe I will revise the software again later as I also saw some pythonbindings for libfluidsynth...
I want to reduce overhead where possible though. That's why I decided against pulse, jack, portaudio etc.

Reply 29 of 57, by gdjacobs

User metadata
Rank l33t++
Rank
l33t++

Well, IMO Pulseaudio is awful but Jack is pure sex. I've never had any buffer glitching with it and CPU usage is reasonable. If you have a chance to look at it, let me know what you think.

All hail the Great Capacitor Brand Finder

Reply 30 of 57, by DieKatzchen

User metadata
Rank Newbie
Rank
Newbie

A few questions:

How is the midi to uart circuit working? You said you were going to give it another go?

Where did you get your led strips? I'm not seeing any with that tight spacing and that diffused casing.

Would you be willing to share your files for that gorgeous laser cut box?

I'm looking forward to seeing this project unfold.

Reply 32 of 57, by gdjacobs

User metadata
Rank l33t++
Rank
l33t++

It's a standard 0220 lcd module. The 2004 and 1602 modules are quite a bit more common, but you can find the 20x2 ones via the usual suspects. Newhaven Display is probably the most prolific manufacturer and they're available in 2x8 and 1x16 interface pinouts (as well as I2C and SPI).
https://www.digikey.ca/products/en/optoelectr … e=1&pageSize=25

All hail the Great Capacitor Brand Finder

Reply 33 of 57, by ghogan42

User metadata
Rank Newbie
Rank
Newbie

First of all, I'd like to thank mcobit and also gdjacobs for posting info and projects here. It makes it a bunch easier when someone else does something first 😀

I'm just starting a similar project to mcobit's (sound module box with a pi3). I don't even have some of the parts yet. But I've been writing python and bash scripts to control the synths (I'm using a graphic lcd and so I have more stuff to do on the display) and I had a question and maybe a hint or two for other people working on similar projects.

First off, I followed your example and compiled MUNT and FluidSynth with optimized compiler flags. MUNT seems to work just fine so far.

But I did run into a midi file that hit 100% cpu in FluidSynth and made the sound skip. It's the Leisure Suit Larry 6 GM soundtrack (LSL6GM.MID ) from here: http://www.midimusicadventures.com/queststudi … te-soundtracks/

My pi hits 100% cpu during the opening fanfare of the sierra intro and the sound skips using a couple of common soundfonts (others are fine). Arachno is one that skips (maybe chorium skips too). It's not an issue for a reason I'll explain below, but I'm curious if anyone else with a pi3 can play that MIDI file without issues with the Arachno or other larger soundfonts?

Having said that, the reason it's not an issue is because it led me to the fluidsynth docs where I found out that fluidsynth can be started multithreaded. That takes care of any fluidsynth speed issues. If I set it to use 3 cpus (first thing I tried, I'm sure 2 works fine), then I can throw a forearm on my keyboard while the fanfare plays and fluidsynth doesn't miss a beat while topping out at 170% cpu use. 🤣

Here's how mcobit's script starts fluidsynth:

/usr/local/bin/fluidsynth --server --no-shell --audio-driver=alsa /home/pi/sf2/"$1" &

Here's how I start fluidsynth:

/usr/local/bin/fluidsynth --server --no-shell -o synth.cpu-cores=3 -o audio.alsa.device=hw:1 -o audio.period-size=64  --audio-driver=alsa /home/shares/midi_files/soundfonts/"$1" &

You can see the "-o synth.cpu-cores=3" argument to start it up multithreaded.

Another change I made is that I use "-o audio.alsa.device=hw:1" to specify the device (which is my usb sound card) . Without that, fluidsynth tells me that it "requested a period size of 64 but got 940 instead". And latency is terrible that way. According to https://sourceforge.net/p/fluidsynth/wiki/LowLatency/, using the "alsa device layer" is the lowest latency way to use alsa devices. For me it's the difference between good and unusably poor latency. So it's something to try for people that have latency issues with usb sound devices.

I think that's it for now. Once I have something a little closer to a project, I'll make a thread here to post my scripts and whatnot for people. 😎

Reply 35 of 57, by gdjacobs

User metadata
Rank l33t++
Rank
l33t++
ghogan42 wrote:
First of all, I'd like to thank mcobit and also gdjacobs for posting info and projects here. It makes it a bunch easier when so […]
Show full quote

First of all, I'd like to thank mcobit and also gdjacobs for posting info and projects here. It makes it a bunch easier when someone else does something first 😀

I'm just starting a similar project to mcobit's (sound module box with a pi3). I don't even have some of the parts yet. But I've been writing python and bash scripts to control the synths (I'm using a graphic lcd and so I have more stuff to do on the display) and I had a question and maybe a hint or two for other people working on similar projects.

First off, I followed your example and compiled MUNT and FluidSynth with optimized compiler flags. MUNT seems to work just fine so far.

But I did run into a midi file that hit 100% cpu in FluidSynth and made the sound skip. It's the Leisure Suit Larry 6 GM soundtrack (LSL6GM.MID ) from here: http://www.midimusicadventures.com/queststudi … te-soundtracks/

My pi hits 100% cpu during the opening fanfare of the sierra intro and the sound skips using a couple of common soundfonts (others are fine). Arachno is one that skips (maybe chorium skips too). It's not an issue for a reason I'll explain below, but I'm curious if anyone else with a pi3 can play that MIDI file without issues with the Arachno or other larger soundfonts?

Having said that, the reason it's not an issue is because it led me to the fluidsynth docs where I found out that fluidsynth can be started multithreaded. That takes care of any fluidsynth speed issues. If I set it to use 3 cpus (first thing I tried, I'm sure 2 works fine), then I can throw a forearm on my keyboard while the fanfare plays and fluidsynth doesn't miss a beat while topping out at 170% cpu use. 🤣

Here's how mcobit's script starts fluidsynth:

/usr/local/bin/fluidsynth --server --no-shell --audio-driver=alsa /home/pi/sf2/"$1" &

Here's how I start fluidsynth:

/usr/local/bin/fluidsynth --server --no-shell -o synth.cpu-cores=3 -o audio.alsa.device=hw:1 -o audio.period-size=64  --audio-driver=alsa /home/shares/midi_files/soundfonts/"$1" &

You can see the "-o synth.cpu-cores=3" argument to start it up multithreaded.

Another change I made is that I use "-o audio.alsa.device=hw:1" to specify the device (which is my usb sound card) . Without that, fluidsynth tells me that it "requested a period size of 64 but got 940 instead". And latency is terrible that way. According to https://sourceforge.net/p/fluidsynth/wiki/LowLatency/, using the "alsa device layer" is the lowest latency way to use alsa devices. For me it's the difference between good and unusably poor latency. So it's something to try for people that have latency issues with usb sound devices.

I think that's it for now. Once I have something a little closer to a project, I'll make a thread here to post my scripts and whatnot for people. 😎

With default clocks, I found it was necessary to limit polyphony in Fluidsynth along with disabling reverb and chorus..

All hail the Great Capacitor Brand Finder

Reply 36 of 57, by ghogan42

User metadata
Rank Newbie
Rank
Newbie

With default clocks, I found it was necessary to limit polyphony in Fluidsynth along with disabling reverb and chorus..

Ah. So I guess it makes sense that I ran into a bit of trouble with the default settings in Fluidsynth. Out of curiosity, did you try fluidsynth's multithreading? Because I'll lower polyphony or effects if I have to, but I haven't had any problems since I upped the number of cpu cores I gave fluidsynth. I'm a midi noob though, so I'm not sure how to test things properly. I don't suppose you can point me towards some demanding midi files I can try to see if I can make fluidsynth choke? I haven't really looked for anything like that yet.

Reply 37 of 57, by gdjacobs

User metadata
Rank l33t++
Rank
l33t++

I haven't, actually. That would be worth investigating.

As far as testing, I have a selection of MIDI content that comes from Sierra and LucasArts titles. Usually I use QFG4 and Loom for GM and MT32 computational evaluation punctuated by others to check overall sound..

All hail the Great Capacitor Brand Finder

Reply 38 of 57, by dreamblaster

User metadata
Rank Oldbie
Rank
Oldbie

nice project ! 😀

Visit http://www.serdashop.com for retro sound cards, video converters, ...
DreamBlaster X2, S2, S2P, HDD Clicker, ... many projects !
New X2GS SE & X16GS sound card : https://www.serdashop.com/X2GS-SE ,
Thanks for your support !

Reply 39 of 57, by HunterZ

User metadata
Rank l33t++
Rank
l33t++

This is great! Been thinking for a long time that it would be awesome to see Munt's simulated LCD output on a real LCD (which is why I made this: https://youtu.be/ExRFasoLT7o ).

I'm curious why this project only shows SysEx text and not the full MT-32 LCD output though?

I'm also impressed that the rPi CPU is up to the task.