Hi folks. It's been a while since I had a chance to fiddle with hifi, and it's been even longer since I posted anything on pfm. About time to change that, I think.
The back story is that I've been listening to all-digital music for years now, mostly Spotify. I built my system around a single digital source: USB audio (more on that in a minute). I've been feeling the vinyl itch for years and finally took the plunge a couple of weeks ago with a Fluance RT-85 (https://www.fluance.com/rt85t-reference-high-fidelity-vinyl-turntable-black-gloss). It's lovely, sounds great. Integrating it into a digital-only system has been fun and I figure there's a few folk might be interested in the details of how it's put together.
Core parts
My system has two sources: Spotify and vinyl. This is what makes it tick:
There's a lot to unpack. Let's start at the top.
Fluance RT-85
I'm really pleased with it - good looking, feels pleasingly solid and tactile to use, easy to setup, runs on 12VDC. The motor and electronics are apparently good (I haven't looked yet), but I'll yeet the factory-supplied wallwart in favor of a homebrew linear supply first chance I get. The Fluance arm is fitted with an Ortofon 2M Blue MM cart as standard (https://www.ortofon.com/ortofon-2m-blue-p-333).
Music Hall pa2.2 phono preamp]
It's a phono -> USB (analog -> digital) preamp. I like the small size and that it's MM/MC. I particularly like the 24-bit 96kHz ADC and USB audio output. It's also got a line-level preamp, volume control, etc., but I don't use any of that. Just the phono -> ADC -> 24/96 USB audio feature.
What I don't love about the pa2.2 is the underwhelming power arrangements: it comes with a 24VDC wallwart and internally it splits that 24V into -12V / 0V / +12V rails using a virtual ground IC, a TLE2426. There's a bit of filtering with an inductor/cap arrangement. The analog circuitry is a bunch of NE5532s sharing +/-12V power with the digital ADC/USB ICs, no voltage regulators, and some of the decoupling could be refined. Not great, but mostly easy to improve. First thing I'll do is cut the PCB power traces to the MM section and recycle a couple of old ALWSRs (https://alw-audio.co.uk/wp-content/uploads/simple-file-list/ALWSR-rev2.9-rev009a.pdf) to give the MM NE5532 a well-fettled isolated +/-12V supply.
The pa2.2 is connected by USB cable to the Intel NUC miniature PC, which sees the pa2.2 as a USB audio source from which raw 24/96 PCM audio streams can be captured.
Intel NUC PC
This is a miniature 64-bit Intel PC running Ubuntu Linux:
The pa2.2 phono preamp connects to one of the NUC's USB ports and is recognized in Linux as a 24/96 PCM audio capture source. The WaveIO in the preamp/DAC/thing connects to the second USB port on the NUC and is recognized as a 32/96 USB audio playback device in Linux. One capture source, one playback device. I use a shell script to create a FIFO and pass incoming 24-bit 96kHz PCM audio from the phono amp to the WaveIO, losslessly upsampling to 32/96 on-the-fly using ALSA's libsamplerate "best" setting. Here's the code that keeps this process running:
The script monitors the state of arecord/aplay to make sure that PCM audio is always being piped from the turntable to the DAC. The keen-eyed will notice $SPOTIFYLOCK. This is a lockfile set by the Spotify Connect daemon (https://github.com/librespot-org/librespot) whenever Spotify playback starts or stops. It works like this: on my iPad I select a playback device called "Livingroom" (the librespot daemon running on the NUC) and hit "play". This signals the librespot daemon on the NUC to start streaming the requested song from the internet and play it back through the WaveIO USB audio device.
Before this can happen, however, the arecord/aplay phono passthrough has to be stopped in order to relinquish control of the WaveIO so that librespot can send audio to it. Fortunately, librespot has a feature that allows you to trigger a script that runs whenever a Spotify event (such as play, stop, next track, etc) occurs. This is how I run librespot to trigger those events:
So whenever I press play or stop, /local/bin/alsa_toggle_sink.sh runs first. It's responsible for handling the lock file, killing arecord/aplay, etc:
All of that together makes the transition from phono to Spotify to phono and back again completely automatic and seamless - no interaction required. The logic is simple: if Spotify is playing, phono is inactive. If Spotify is idle, phono is active.
Preamp/DAC/DSP/thing
This thing is a bit of a beast. At its core it's just a DAC preamp that takes digital USB audio and turns it into line-level analog outputs suitable for a power amp. Here she is:
It's orchestrated and controlled by an Arduino Mega 2560. The digital audio input is the WaveIO XMOS-based USB -> I2S converter, an amazing piece of hardware that outputs an isolated I2S signal:
The WaveIO's output is connected to the input of a MiniSHARC DSP:
The SHARC is configured to do all DSP operations at 24/96 (it can do 16/48 or 24/96). Eventually the DSP will act as a 4-way digital crossover (stereo channels of sub, bass, mid, treble), but for now it's configured to ouput a full-range stereo signal plus LFE subwoofer output crossed @ 56Hz with 48dB/octave Linkwitz-Reilly.
The MiniSHARC's outputs are I2S and are consumed by a pair of Twisted Pear Buffalo III DACs (this is the latest one, mine are older: http://www.twistedpearaudio.com/digital/buffalosep.aspx), the analog outputs of which are connected to a total of four Ivy III I/V modules (http://www.twistedpearaudio.com/linestages/ivy.aspx).
The whole shebang gives the preamp 3 stereo pairs of balanced+unbalanced outputs, plus a balanced mono subwoofer output.
Power for the analog side of the house comes courtesy of one of Terry's lovely audio-specced toroidal transformers:
Digial power is a bog-standard encapsulated toroid:
Clean power comes from Twisted Pair Placid HD shunt regs (http://www.twistedpearaudio.com/power/placidbp.aspx):
The display is an old obsolete version of the 4D Systems uOLED-96 (https://4dsystems.com.au/products/4...le-kits/microoled-arduino-kits/uoled-96-g2-ar):
The volume control is my favorite part. It's built from a Chinese rotary encoder that has no detents and spins freely in either direction; the action is fantastically smooth with very high quality bearings inside. When attached to a heavy aluminium knob you can set it spinning and it'll keep rotating smoothly under its own steam for quite some time. It feels fantastic! I made a video to show what I mean:
https://i.imgur.com/8qBtUJT.mp4
The actual volume attenuation is done digitally in the MiniSHARC's DSP. The volume level is tracked by the Arduino, which reads the signals from the rotary encoder and tells the MiniSHARC to raise/lower/mute the volume. How exactly does the Arduino communicate with the MiniSHARC? That's a long story! The short version is: I reverse engineered the I2C protocol used by the MiniSHARC when communicating with the "official" MiniSHARC volume controller and then wrote a C++ library for the Arduino to emulate the official controller. There's a thread about it here: https://www.minidsp.com/forum/opendrc-series-support/10826-readout-of-volume?start=30#25239
You can get the code here: https://github.com/h4gg1s/MiniSHARC-Arduino
And that's that! The output from the preamp goes to the KJF MA-01 power amplifier (which is an outstanding piece of gear) and from there to the passive crossovers in the Ergo speakers.
I hope this was interesting or helpful to some folks. It's been a fun journey getting it all running smooth and stable. Not only that, but it sounds fantastic to boot.
Don't flame me too hard for taking a perfectly good analog vinyl signal and ruining it with ADCs, DSPs, DACs, and class D amplification ;-)
Cheers,
H.
The back story is that I've been listening to all-digital music for years now, mostly Spotify. I built my system around a single digital source: USB audio (more on that in a minute). I've been feeling the vinyl itch for years and finally took the plunge a couple of weeks ago with a Fluance RT-85 (https://www.fluance.com/rt85t-reference-high-fidelity-vinyl-turntable-black-gloss). It's lovely, sounds great. Integrating it into a digital-only system has been fun and I figure there's a few folk might be interested in the details of how it's put together.
Core parts
My system has two sources: Spotify and vinyl. This is what makes it tick:
- Source 1: An Intel NUC mini PC running Spotify Connect and some custom scripts. It streams digital audio to a preamp/DAC/thing (more about that in a sec) via USB. It receives digital audio, also via USB, from a phono->USB preamp.
- Source 2: Fluance RT-85 record deck into:
- Phono->USB pre: Music Hall pa2.2 (https://musichallaudio.com/product/pa2-2-phono-amplifier/). It has a simple MM phono stage and a rather good 24/96 ADC that converts the analog vinyl signal into digital audio that streams via USB to the Intel NUC.
- Preamp: A homemade digital preamp/DAC/DSP/thing. Takes USB digital audio, processes it in a DSP, and outputs line-level analog audio suitable for connecting to a power amp.
- Power amp: A KJF Audio (OrangeArt) MA-01 6-channel Hypex N-Core power amp (https://kjfaudio.com/product/ma-01-flexible-amplifier/#slot-1)
- Speakers: A homemade pair (https://pinkfishmedia.net/forum/threads/ergo-e-iiir-build.93477/) of James' Ergo E-IIIRs. They're 3-way floorstanders with 15W/8530K-01 woofers, M15CH001 mids, and Hiqufon OW1 tweeters.
- Sub: Rythmik F15HP 15" sealed sub (https://www.rythmikaudio.com/F15HP_specs.html)
There's a lot to unpack. Let's start at the top.
Fluance RT-85
I'm really pleased with it - good looking, feels pleasingly solid and tactile to use, easy to setup, runs on 12VDC. The motor and electronics are apparently good (I haven't looked yet), but I'll yeet the factory-supplied wallwart in favor of a homebrew linear supply first chance I get. The Fluance arm is fitted with an Ortofon 2M Blue MM cart as standard (https://www.ortofon.com/ortofon-2m-blue-p-333).
Music Hall pa2.2 phono preamp]
It's a phono -> USB (analog -> digital) preamp. I like the small size and that it's MM/MC. I particularly like the 24-bit 96kHz ADC and USB audio output. It's also got a line-level preamp, volume control, etc., but I don't use any of that. Just the phono -> ADC -> 24/96 USB audio feature.
What I don't love about the pa2.2 is the underwhelming power arrangements: it comes with a 24VDC wallwart and internally it splits that 24V into -12V / 0V / +12V rails using a virtual ground IC, a TLE2426. There's a bit of filtering with an inductor/cap arrangement. The analog circuitry is a bunch of NE5532s sharing +/-12V power with the digital ADC/USB ICs, no voltage regulators, and some of the decoupling could be refined. Not great, but mostly easy to improve. First thing I'll do is cut the PCB power traces to the MM section and recycle a couple of old ALWSRs (https://alw-audio.co.uk/wp-content/uploads/simple-file-list/ALWSR-rev2.9-rev009a.pdf) to give the MM NE5532 a well-fettled isolated +/-12V supply.
The pa2.2 is connected by USB cable to the Intel NUC miniature PC, which sees the pa2.2 as a USB audio source from which raw 24/96 PCM audio streams can be captured.
Intel NUC PC
This is a miniature 64-bit Intel PC running Ubuntu Linux:
The pa2.2 phono preamp connects to one of the NUC's USB ports and is recognized in Linux as a 24/96 PCM audio capture source. The WaveIO in the preamp/DAC/thing connects to the second USB port on the NUC and is recognized as a 32/96 USB audio playback device in Linux. One capture source, one playback device. I use a shell script to create a FIFO and pass incoming 24-bit 96kHz PCM audio from the phono amp to the WaveIO, losslessly upsampling to 32/96 on-the-fly using ALSA's libsamplerate "best" setting. Here's the code that keeps this process running:
Code:
#!/bin/bash
SPOTIFYLOCK=/tmp/.___spotify_lock_file____
setup_fifo () {
echo 67108864 > /proc/sys/fs/pipe-max-size
rm -f /tmp/.phono
mkfifo /tmp/.phono
}
is_phono_running () {
pgrep arecord || return 0
pgrep aplay || return 0
return 1
}
start_phono () {
setup_fifo
(nice -n -19 arecord -t raw --disable-softvol --disable-resample -r 96000 -D plughw:1,0 -c 2 -f S32_LE /tmp/.phono >> /tmp/arecord.log 2>&1 ; echo "$?" >> /tmp/arecord.log)&
(nice -n -19 aplay -t raw -f S32_LE --disable-softvol --disable-resample --disable-channels --disable-format -D hw:0,0 -r 96000 -c 2 /tmp/.phono >> /tmp/aplay.log 2>&1 ; echo "$?" >> /tmp/aplay.log)&
}
stop_phono () {
killall aplay
killall arecord
killall -9 arecord
cat /tmp/.phono > /dev/null 2>&1
}
while [ 1 ]; do
is_phono_running > /dev/null
isRunning=$?
if [ $isRunning == 1 ]; then
if [ -f $SPOTIFYLOCK ]; then
stop_phono
fi
elif [ $isRunning == 0 ]; then
if [ ! -f $SPOTIFYLOCK ]; then
start_phono
fi
fi
sync
sleep 3
done
The script monitors the state of arecord/aplay to make sure that PCM audio is always being piped from the turntable to the DAC. The keen-eyed will notice $SPOTIFYLOCK. This is a lockfile set by the Spotify Connect daemon (https://github.com/librespot-org/librespot) whenever Spotify playback starts or stops. It works like this: on my iPad I select a playback device called "Livingroom" (the librespot daemon running on the NUC) and hit "play". This signals the librespot daemon on the NUC to start streaming the requested song from the internet and play it back through the WaveIO USB audio device.
Before this can happen, however, the arecord/aplay phono passthrough has to be stopped in order to relinquish control of the WaveIO so that librespot can send audio to it. Fortunately, librespot has a feature that allows you to trigger a script that runs whenever a Spotify event (such as play, stop, next track, etc) occurs. This is how I run librespot to trigger those events:
Code:
/path/to/librespot --name Livingroom --dither none --format S32 --mixer alsa --device-type speaker --backend alsa --bitrate 320 --disable-audio-cache --initial-volume=100 --volume-ctrl fixed --device plughw:0,0 --onevent /usr/local/bin/alsa_toggle_sink.sh --emit-sink-events --username xxx --password xxx
So whenever I press play or stop, /local/bin/alsa_toggle_sink.sh runs first. It's responsible for handling the lock file, killing arecord/aplay, etc:
Code:
#!/bin/bash
SPOTIFY_LOCK_FILE="/tmp/.spotify_active"
# $LINK_STATUS is set in the environment by librespot
if [ "$SINK_STATUS" == "running" ]; then
touch "$SPOTIFY_LOCK_FILE"
killall aplay
killall arecord
# if we don't pause, librespot will barf because
# audio devices haven't been relinquised yet
sleep 0.5
elif [ "$SINK_STATUS" == "closed" ]; then
rm -f "$SPOTIFY_LOCK_FILE" # this will trigger arecord/aplay to start
fi
All of that together makes the transition from phono to Spotify to phono and back again completely automatic and seamless - no interaction required. The logic is simple: if Spotify is playing, phono is inactive. If Spotify is idle, phono is active.
Preamp/DAC/DSP/thing
This thing is a bit of a beast. At its core it's just a DAC preamp that takes digital USB audio and turns it into line-level analog outputs suitable for a power amp. Here she is:
It's orchestrated and controlled by an Arduino Mega 2560. The digital audio input is the WaveIO XMOS-based USB -> I2S converter, an amazing piece of hardware that outputs an isolated I2S signal:
The WaveIO's output is connected to the input of a MiniSHARC DSP:
The SHARC is configured to do all DSP operations at 24/96 (it can do 16/48 or 24/96). Eventually the DSP will act as a 4-way digital crossover (stereo channels of sub, bass, mid, treble), but for now it's configured to ouput a full-range stereo signal plus LFE subwoofer output crossed @ 56Hz with 48dB/octave Linkwitz-Reilly.
The MiniSHARC's outputs are I2S and are consumed by a pair of Twisted Pear Buffalo III DACs (this is the latest one, mine are older: http://www.twistedpearaudio.com/digital/buffalosep.aspx), the analog outputs of which are connected to a total of four Ivy III I/V modules (http://www.twistedpearaudio.com/linestages/ivy.aspx).
The whole shebang gives the preamp 3 stereo pairs of balanced+unbalanced outputs, plus a balanced mono subwoofer output.
Power for the analog side of the house comes courtesy of one of Terry's lovely audio-specced toroidal transformers:
Digial power is a bog-standard encapsulated toroid:
Clean power comes from Twisted Pair Placid HD shunt regs (http://www.twistedpearaudio.com/power/placidbp.aspx):
The display is an old obsolete version of the 4D Systems uOLED-96 (https://4dsystems.com.au/products/4...le-kits/microoled-arduino-kits/uoled-96-g2-ar):
The volume control is my favorite part. It's built from a Chinese rotary encoder that has no detents and spins freely in either direction; the action is fantastically smooth with very high quality bearings inside. When attached to a heavy aluminium knob you can set it spinning and it'll keep rotating smoothly under its own steam for quite some time. It feels fantastic! I made a video to show what I mean:
https://i.imgur.com/8qBtUJT.mp4
The actual volume attenuation is done digitally in the MiniSHARC's DSP. The volume level is tracked by the Arduino, which reads the signals from the rotary encoder and tells the MiniSHARC to raise/lower/mute the volume. How exactly does the Arduino communicate with the MiniSHARC? That's a long story! The short version is: I reverse engineered the I2C protocol used by the MiniSHARC when communicating with the "official" MiniSHARC volume controller and then wrote a C++ library for the Arduino to emulate the official controller. There's a thread about it here: https://www.minidsp.com/forum/opendrc-series-support/10826-readout-of-volume?start=30#25239
You can get the code here: https://github.com/h4gg1s/MiniSHARC-Arduino
And that's that! The output from the preamp goes to the KJF MA-01 power amplifier (which is an outstanding piece of gear) and from there to the passive crossovers in the Ergo speakers.
I hope this was interesting or helpful to some folks. It's been a fun journey getting it all running smooth and stable. Not only that, but it sounds fantastic to boot.
Don't flame me too hard for taking a perfectly good analog vinyl signal and ruining it with ADCs, DSPs, DACs, and class D amplification ;-)
Cheers,
H.