Tuesday, October 22, 2019

Midi and the Pi

Cleaning out my basement after the last of my daughters got married, I found my 1990's Kawai K4, a 16 bit sampled synth which I enjoyed pushing with Linux and Rosegarden back in the 90's.  A lot of software development has taken place since those days, but the functionality was there in 2000, and only improves with time.  This is the staying power of open source.
I'm now driving the K4 with the raspberry Pi, using ALSA sequencer interface, standard with the distribution, and a Midiman MidiSport 2x2 USB interface, also standard.  20+ year old hardware is working with a modern operating system, no issues, producing great sounds!

For the K4 fans, I'm using the GM1.snd general midi patches and a midi piano tutor called pianobooster.  I know Ardour can handle this beast, and so I have to learn how Midi works with Ardour5.

Saturday, February 16, 2019

Python on Android with Kivy

After wandering around in Android Wonderland with Java, Kotlin, Dart and Flutter; I encountered Kivy, under public development since Feb 2011.  It comes with a recent OSC package called OSCpy which works fine with Ardour if the 'h' 64 bit twos complement integer support is added (parse_long).  I may get around to a pull request for this.

diff --git a/oscpy/parser.py b/oscpy/parser.py
index e080157..7172825 100644
--- a/oscpy/parser.py
+++ b/oscpy/parser.py
@@ -7,6 +7,8 @@ Allowed types are:
     floats -> osc float
     bytes (encoded strings) -> osc strings
     bytearray (raw data) -> osc blob
+    *** added by ssc 2019-01-24
+    64 bit big endian two's complement integer -> osc long

 """
 from struct import Struct, pack, unpack_from, calcsize
@@ -19,6 +21,7 @@ else:
     UNICODE = unicode

 Int = Struct('>i')
+Long = Struct('>l')
 Float = Struct('>f')
 String = Struct('>s')
 TimeTag = Struct('>II')
@@ -42,6 +45,10 @@ def parse_int(value, offset=0, **kwargs):
     """Return an int from offset in value."""
     return Int.unpack_from(value, offset)[0], Int.size

+def parse_long(value, offset=0, **kwargs):
+    """Return an long from offset in value."""
+    return Long.unpack_from(value, offset)[0], Long.size
+

 def parse_float(value, offset=0, **kwargs):
     """Return a float from offset in value."""
@@ -81,6 +88,7 @@ def parse_blob(value, offset=0, **kwargs):

 parsers = {
     b'i': parse_int,
+    b'h': parse_long,
     b'f': parse_float,
     b's': parse_string,
     b'b': parse_blob,
@@ -94,6 +102,7 @@ parsers.update({
 writers = (
     (float, (b'f', b'f')),
     (int, (b'i', b'i')),
+    (int, (b'h', b'h')),
     (bytes, (b's', b'%is')),
     (bytearray, (b'b', b'%ib')),
 )

Kivy can use python 2 or 3 and produce APKs for android so I coded an app based on the ArdOSC layout, available on gitlab at AudioPi_OSC.  I am still developing this, and have stopped working on ArdOSC.

I presented AudioPi and the Kivy OSC app to the NoVALug group on February 9, the slides are online at Audio Pi.pdf.  The YouTube stream is available at "Running AudioPi".

Monday, December 24, 2018

Audio Pi in the field

I put the RPi, battery, mike and android in my bag and took the system into the field for some real world testing.  Using WiFi on the system as an access point with hostapd allowed android to connect to RPi directly, and eliminated the need to use the bluetooth stack on both the RPi and Android.  It's a straightforward setup in alpine linux, with /etc/conf.d/hostapd pointing to /etc/hostapd/hostapd.conf.  That file sets the ssid=audiopi, and /etc/hostapd/hostapd.wpa_psk sets the WPA key.

DHCP is provided for the AP with dhcpd, the file /etc/dhcp/dhcpd.conf has this stanza for the subnet 192.168.4.0.

 subnet 192.168.4.0 netmask 255.255.255.0 {
  option domain-name "audiopi";
 range 192.168.4.10 192.168.4.248;
}

The ArdOsc app is configured to use UDP with the 192.168.4.1 IP address configured in /etc/init.d/setup_hostap.  WiFi range is good enough for local control, and I had no issues with network connectivity or performance.

I pushed the setup_hostap script to my gitlab audiopi repository,
https://gitlab.com/schessman/audiopi

#!/bin/sh
#
# enable cirrus_logic audio
/etc/init.d/audiopi_settings.sh 

# shutdown wlan0 client, switch to hostap
/etc/init.d/wpa_supplicant stop
ifdown wlan0
/etc/init.d/hostapd start
ip addr add 192.168.4.1 dev wlan0
ip route add default dev wlan0

# enable DHCP and access
/etc/init.d/dhcpd start

# conserve power
echo /etc/init.d/usb_power stop

I had good success with recording at a jam session, mic clipped to the bag and placed in the center of the group; and also at a few rehearsals where I clipped the mic to a music stand to bring the vocals to the foreground.  For the best results, taking a stereo line in feed from a mixing board connected to more mikes makes the most sense.  I was satisfied with the results from the Stereo Sony ECMCS3, and burned a couple CDs from the rehearsal sessions.  Ardour is a great tool for mastering, the plugin set is extensive and well worth the effort to make it work.

I also went to a Google Developer Group meetup with the RPi in a pocket and had the only wearable computer (besides all the android phones).   The blinking lights on the RPi combined with the volume bar lights in the ArdOsc app make for a good casual demo.

Next I plan to present this at the Monthly NovaLug meeting on 
Saturday, February 9, 2019.  I'll post the slides from the talk on the gitlab audiopi repository.

Tuesday, November 6, 2018

Darting and Fluttering around Android

Looking for Android tools and libraries has led me to the Flutter UI Framework, which looks to be Google's dice throw for the "next big thing".  I personally like Dart as a language, and anything less verbose and simpler than Java is a plus.

After working with Android Studio a while, I discovered I am more productive with vim and the command line.  Flutter environment supports a lot of development functionality with the flutter command, and so my long term habits of edit -> make -> test fit right in.

Getting up to speed in a new and rapidly changing development environment is always broadening, and I am happy to find many different approaches to design.  It looks like a lot has been learned from the Javascript struggles, and flutter seems to have a decent versioning/packaging/distribution system in place, using git.

So I am further down the rabbit hole, through the looking glass, and learning about Material Design, Reactive Programming for Dart, and the BloC Design pattern.

Once I digest this and become productive, it's back to the ArdOsc Android app to rewrite it in Flutter with Material Design, and try to get it working on the iPad as well.

Saturday, September 1, 2018

Floating point on ARM

What's that "funny clicking noise"?  Floating point denormalization seems to be the culprit.
The RPi3B has hardware floating point which is enabled with the GCC incantation:
    CFLAGS=-mcpu=cortex-a53 -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard -funsafe-math-optimizations

All the above is a bit misleading.  /proc/cpuinfo thinks the CPU is ARMv7 but the feature flags show ARMv8 neon float support.  Hardware float support certainly improves performance, but noise is most unwelcome.  I think it's due to the "unsafe-math-optimizations" which were needed for older versions of the RPi.  The Cortex-A53 does not need this and GCC will use the FPU hardware if told correctly.

    processor       : 0
    model name      : ARMv7 Processor rev 4 (v7l)
    BogoMIPS        : 38.40
    Features        : half thumb fastmult vfp edsp neon vfpv3 tls                          vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 
    CPU implementer : 0x41
    CPU architecture: 7
    CPU variant     : 0x0
    CPU part        : 0xd03
    CPU revision    : 4

The "unsafe-math-optimizations" is the interesting part.  This was necessary for older ARM processors.  Now it is no longer needed, and causes issues.  According to the ARM Cortex-A Series Programmer's Guide (PDF), "Support is provided in AArch64 NEON for double-precision floating-point and full IEEE754 operation including rounding modes, denormalized numbers, and NaN handling."   This means that the unsafe optimizations are not needed.  Time to recompile Ardour without that flag and listen to see if the clicking noise is gone.  GCC 6.4 only needs the -mcpu=cortex-a53 -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard flags.  I am happy to report that ardour is not adding the clicking/popping noise with this setting.

I also recompiled the Calf studio plugins with the same flags.  With the unsafe-math-optimizations, the snapping and popping was noticeable.   Now they are blissfully silent.


Friday, August 10, 2018

Android in Wonderland

Modern software development is a complex task, and having an IDE that guides the developer can make this a bit more directed.  I imported the ardmix github java code into Android Studio 3.2 and converted it to kotlin, just to make life interesting.  The syntax is similar to java, but cleaner, and has a more modern feel.  Android Studio considers this a first class language and I was able to compile and run the app after a bit of tweaking.  I will not miss Java, and suspect Google feels the same.

The source is posted on gitlab ardosc, under the GPL3+ license.  It uses an OSC Library called NetUtil to handle the UDP communication to Ardour.  The java sources for de.sciss.net NetUtil were developed by Hanns Holger Rutz and licensed under LGPL 2.1 or later.  The original sources can be found at https://github.com/Sciss/NetUtil/.

I plan to release this as a free Google Play store app with no strings once I am finished testing, and will be using the app with the RPi3 in the field as part of the tests.  There is more conversion to do from Java idioms to Kotlin, as I begin to be comfortable with the syntax and best practices.  The mechanical conversion compiled and ran but lint finds lots of fluff and I know it can be much cleaner.

Wednesday, August 1, 2018

Controlling Ardour with OSC and Android

Now that I have a stable RPi3 running alpine linux 4.14.52-0-rpi2, jackd2 1.9.10, and ardour 5.12.0, and have the recording and playback operational; it is time to work on the remote control.  The use case I am working on is to have the RPi3 with a battery and a stereo mic in a small bag that can be placed unobtrusively in the center of a jam circle and record the session.  I want to have a small android tablet controlling the mix and transport in hand.  That will operate ardour using the OSC protocol.  

It is easy to enable OSC in Ardour, see the Ardour Manual section here. 
The more complicated part is to acquire a suitable Android app that can deal with Ardour.
Candidates include TouchOSC for Android and iPad, which looks full featured and not very expensive, and a number of other apps in various states of development or abandonment. 

As I prefer free and open source software,  I settled on ardmix, by Detlef Urban, which is a working Android app.  The app has to be built from source so my Android Studio adventure begins.

I installed and built oscchief, a very useful command line osc tool from Sebastian Ruml.  This allows me to emulate both sides of the full system, either ardour or the ardmix app.  I can see the OSC messages being sent, and send appropriate canned messages for testing and debugging.

Android development is a complex and dynamic effort.  I feel like Alice in Wonderland, 
"Now, here, you see, it takes all the running you can do to keep in the same place. If you want to get somewhere else, you must run at least twice as fast as that!"

So my implicit task list has just enlarged while I refresh my Android development skill.
I also want to add the led blinking lights to my list, as the RPi3 has a red and a green LED and I think they should indicate running (green) and recording (red).  That looks like a fun diversion when the android complexities get overwhelming.