A new version of Drum8 supporting 8 simultaneous sounds and multi-channel audio output has been released.
When I bought an Apple //e in the mid 80s (replacing a very hacked Apple ][+) it came with a small card with a speaker on it called “SAM – Software Automatic Mouth” which allowed the Apple to talk.
The SAM card was an 8 bit DAC, implemented with a latch, DAC chip and amplifier for the speaker. I’d connected it to my sound system and discovered I could get pretty good crunchy 8 bit sound playback (less noisy than the Mac+ I also had at the time, no dither noise).
Around the time I’d written a drum sequencer that triggered a real 70’s era analogue drum box through the 4 game port annunciator outputs. One of the Mac music programs had some drum samples and I tried playing them using the SAM card. It worked great and in 1987/88 I ended up writing a 16 channel / 4 simultaneous voice mouse driven drum machine for the Apple II+ and //e.
Unfortunately the SAM card got left behind in a move and its a rarity on eBay. Recently after researching a few DACs and even an R-2R ladder option, I found an interesting chip that had promise, the AD558. This is pretty much a one chip solution. Internally calibrated, running on a single 5V supply, direct CPU bus compatibility and with a buffered output, it can be configured for a 0 to 2.8V output, perfect for a line level audio out.
From the AD558 datasheet and Apple II reference manual, I came up with this circuit:
The only additional passive components are:
- 0.1uF power decoupling capacitor – unpolarised greencap, 25V rating would have been enough, the one I had was double that.
- 6.8uF electrolytic capacitor. This blocks the DC offset in the 0-2.8V output, giving a ±1.4V output, which should be plenty as its going into my mixer.
- 20kΩ resistor, this is there to let current charge the blocking capacitor if the output isn’t connected (avoiding a transient on connection), I’d originally thought 10kΩ but settled on it after finding it first, its value is not critical.
I used an Apple II prototyping board which are still available here, an Apple II slot card which includes solder pads yet breaks out all the port pins to a wire wrap header. I initially planned to wire wrap it all, but I hadn’t ordered a wire wrap socket (and the pins might not have easily fit through the plated-through holes anyway), so I used one of the spare 20 pin sockets I’d recently bought to fix my mouse card, carefully ignoring the extra holes as the AD558 has 16 pins!
With the 8 data inputs on the AD558 arranged neatly in a sequence that corresponds to the data bus on the Apple slot connector, I directly soldered them to the connector using stripped wirewrap wire which, being silver plated, is a breeze to solder. For me it involved a lot of bright lights, looking through a number of magnifying glasses and some patient assistance from my wife, Oak.
Keeping the solder from running up the length of the slot connector was not easy, I eventually discovered that gravity can be your friend. For each of the 8 data bus wires I attached the slot end first then stretched the fine wire to its pin on the socket, (which I’d soldered in first) so it was just a case of heating a pin up so its corresponding wire could be slipped next to it, then the remaining wire cut off.
I took these photos as part of inspection, you can see the 8 fiddly data wires at the bottom right. Ignore the solder along the top edge of the board, its just strain reliefs for the line out cable.
On the row opposite the data pins on the AD558 (pins 9-16), a few adjacent pins need to be bridged. I ran a wire across them, trying to avoid touching the board itself as all the slot pin have traces criss-crossing to the wire wrap header (on the right on the photo below). If the thin insulation on the board was breached by solder, things would get unpleasant. I took particular care to keep away from the 12V line (pin 50 on the slot connector) as really bad things happen if that gets into TTL chips. I know from childhood experience.
Looks real classy doesn’t it.
The proto board’s half solder/half wire wrap design is really not ideal for building much on the board itself. I think it was intended to have a daughter board (eg: Arduino) hang off it. I would have preferred either bigger holes just for wirewrapping or a board without the wirewrap header and associated traces across most of its area, other proto boards have little pads for soldering to at the slot connector.
I did use wire wrap and the wire wrap header to connect to the device select, read/write and power lines. I’d bought the tool and wire after all, and wanted to stay away from the slot connector after my experience with the data lines.
Mounting the capacitors and resistor was uneventful and I ran the audio to the shielded audio cable at the top of the board with little consideration for what its crossing along the way, fully expecting I’d deal with noise later, once I’d tested the board.
With the card in slot 5, writing alternating 1, 0, 2, 0, 4, 0, etc to $C0D0 generated progressively louder clicks. Both the SAM software and my drum machine worked perfectly first time.
The audio output is surprisingly quiet given the unshielded wires and cross-crossing bus on the board. Plus I’m running without any special power supply regulation for the DAC, the AD558 has its own internal reference. What a great chip, glad I bought a few as I’ll have to do something for the Arduino with one or two.
The not so new EEE PC was experiencing intermittently stuttery audio when playing a Flash based radio stream. This was strange as it coped fine with MP3 and WMV streams, even with video. It wasn’t a buffering issue. The audio had very short glitches – the kind of thing that happens when a device driver locks the bus too long (he says, having worked on a Linux audio driver a few years back).
The wireless drivers were up to date and the wireless hardware configured to use CAM mode (a problem that plagued the ION HTPC when I first installed XP on it). Power management settings were set for high performance.
I also determined it was no where near running out of CPU, sitting at only 10% when playing the stream. After updating drivers, firmware and minimising the configuration as much as I could, I started thinking it might be network related.
I set up a regular ping of length 8192 bytes from my workstation to the EEE so I could see what network performance was like. I was only half surprised to find that ping times were all over the place, with some peaks in the 100s of ms. With the audio streaming, the high peaks corresponded with glitches in the audio.
With it happening even when close to the WNDR3700 wireless AP, it wasn’t a signal level problem. It was connecting at 130mbit (N speed) on the 2.4GHz band.
I switched the router to limit 2.4GHz to 54mbit and the audio problem went away. Ping times to the EEE became a solid 4ms.
Looks like its a combination of crappy behaviour for the EEE’s wireless driver in “N” mode and the Flash Player using a very short audio buffer, making it easy to underrun audio playback. Fortunately I can handle the slower 2.4GHz network since I run a separate 5GHz network for the HTPC.
As I’ve written, for the last few weeks I’ve been working (mostly part time) with a small team on developing a Linux driver for the Gadgetlabs GL824 sound card. Linux audio is a new world for me but with the help of a few others in the group, I’ve learned a lot about how modules are set up and loaded in the 2.6 kernel and generally how things all hang together in the Linux world.
I’ve put most of my focus in the sound engine, as the performance challenges of shifting up to 48000 samples @ 4 bytes per sample * 8 channels * 2 (in/out) = about 3 megabytes per second really intruiged me.
Given the GL uses an Altera in its sound engine, it brought back a lot of fond memories of the projects I’d been involved with at the Institute for Telecommunications Research, particularly with high speed satellite modems.
Optimistically, I set things up so data is moved in just 64 sample blocks per channel, meaning a theoretical latency of only 1.33ms!
One of the challenges of the project is that ALSA is optimised for use with hardware which can DMA into buffers that the driver sets up. The GL doesn’t work this way; it has its own hardware buffer (mapped into IO space) and ALSA’s promised support for this configuration hasn’t worked as we expected. I’ve ended up doing things by having the interrupt handler simulate DMA in and out of the ALSA buffer. For this to work, ALSA has to be using a buffer configuration that easily maps to the GL’s fixed buffer.
Now the tricky part. I wanted the driver to be able to play 16bit 44.1K stereo as well as 24 bit content, and allow multiple clients to use a subset of the channels from the card simultaneously. Given that each ALSA substream uses one buffer for all the channels being asked of it, vs. the GL’s buffer-per-channel approach, it was difficult coming up with a single ALSA buffer configuration that worked in all the modes.
A fixed 24 bit 8 channel mode is trivial if we wanted to give up.
I ended up coming up with a solution where the driver defines multiple Linux “subdevices” for the card. These can be opened in any combination until all the channels are used up. The different subdevices support configurations including stereo 16 bit, stereo 24 bit, 8 channel 16 bit and of course 8 channel 24 bit. I also included support for 32 bit samples since Jack seems to not care about 24 bit samples.
As long as all the substreams for the card are set at the same sample rate (theres only one sample clock), things can be very flexible. It does make the user have to think a bit though in order to pick the right subdevice for a given desired configuration.
Given the lack of hardware DMA, shifting the data becomes very interesting. I started by writing x86 assembly for the transfer routines (a first for me) but later changed it to C, in the spirit of being cross platform. Because of the card’s architecture, you can only transfer data in short bursts, after which you need to do a read-back. I ended up using unrolled loops for maximum speed/pipelineabiltiy, an old trick I’ve used in the past. This gives pages and pages of gibberish like:
The various combinations of sample format and interleaving mean quite a few combinations of these unrolled loops.
My system seems to cope well with the interrupt rate. The basic data pumping only uses about 1% kernel CPU. However we’ve found that the higher level audio layers (Jack) seem to require more buffers than I’d hoped (at least 10 for me). I’m sure its because I haven’t been able to enable the realtime kernel option in the Jack layer, something isn’t installed, so the Linux scheduler gets in the way.
Apart from the buffers issue, my card is working well with aplay/arecord, Audacious (Winamp clone), Ardour (8 channel record/playback at 24 bits), Hydrogen (drum machine) and even, with a bit of persuasion, making it a default linux sound device. The apps seem to work better going straight to the card than through Jack – need to get my realtime kernel issue sorted out.
I’m currently using Fedora Core 8, with the CCRMA realtime kernel patches. This weekend I gave 64Studio a try, but couldn’t get the kernel module for the card to install, even though it compiled fine with the kernel’s headers. There seems an inconsistency in the published kernel headers and the core sound modules being used. Its possibly because I’m not building within the ALSA framework. Given the age of the kernel in 64Studio, I’ve decided to go back to CCRMA as its really on the bleeding edge and I’m getting used to Fedora, even after being a long time Debian user.
So… basically, its working! Still waiting for more people to confirm performance on different machines. I’m starting to think that 1.4ms latency is overkill and I might halve the interrupt rate. I’ll see how things go with the realtime kernel mode before making that decision.
There’s still some way to go before we’re finished. The card has a 16550 UART for MIDI. Its working but we’ve currently got it running off the audio interrupt in polled mode, which isn’t ideal. We need more validation against incorrect modes for the subdevices. Controls need to be defined for the card’s mute/level/monitoring switches. Then there is the possibility of syncing multiple cards (they can be physically linked to share a clock) and maybe support of the 4 channel variants of the GL824.
Once we’re done, we intend to roll it into the ALSA library, and hopefully have it accepted.
I must mention that one of the reasons that the Linux driver came together so quickly is that we had access to the source of the Win32 driver developed by Waldemar aka. “Mostek”. His redesigned Altera code made things a lot more straightfoward than with the original firmware that the cards shipped with, notwithstanding the very different ways of doing things in the Linux ALSA and the MSWindows WDM/ASIO audio models.
Through my writings on this blog, I was approached by a team working on a Linux driver for the Gadgetlabs GL8x24 8 channel pro audio sound card. I’ve got one in my production PC and the lack of a Linux driver has held me back from switching the host OS for my VMs to Linux.
I joined the project at the end of January and am contributing to developing and testing the driver. In working with a couple of the guys from the team, I’ve learned how the cards realtime sound engine works, how linux audio drivers are structured and how to write x86 assembly code (high speed sample moving/conversion) which is my first foray back into ASM since the Apple ][ days. My past experience with Alteras, UARTs and real time systems is all coming back to be useful again.
We’ve got the driver doing 8 channel full duplex analog loop back at the interrupt level, with 1.4ms latency and MIDI record/playback is now also working. I’ll post more details as we approach an alpha driver release.
Its a testament to the quality and functionality of these cards that even 7 years after the company that made them went under, there is a group of loyal users and dedicated developers who have kept the card going, first by writing new WDM drivers (& Altera firmware) so it would work well in XP, and now – a Linux driver development. I’m really proud to be one of them.
This PC is a combination of old and new as its really an upgrade of an older Pentium 4 system which in turn was an upgrade of a Pentium II system which had some PCI multimedia cards dating from last century that I want to keep going.
The case is an Antec Sonata 2. I chose it because it includes an air filter, a large 12″ case fan and wasn’t too expensive.
The motherboard is an Asus P5PE-VM. This is an odd board that allows use of AGP and traditional PCI cards with newer socket 775 processors. The processor is a Core2 Duo 1.8GHz (Intel 6320). The CPU is cooled by a huge Zalman 7700CNPS cooler which is a bit overkill for the efficient Core2 but it helps keep air moving around the Northbridge and RAM.
I recently upgraded the RAM to 2GB of G-Skill CAS 2.5-3-3-6 which is very attractively packaged but chosen because I want all the speed I can get from this system. The motherboard doesn’t allow overclocking – the chipset is already at its limit with the Core2. There are two Western Digital drives (200GB and 300GB) with the OS and archives on a couple of partitions on the first drive and VMs on the second drive. The case has a nice caddy based mechanism for fitting the drives which helps reduce vibration.
The video card is a Matrox Parhelia 128 AGP; ancient by today’s standards but I like its hardware zoom capabilities and its a reliable performer in timing critical multimedia PCs.
There is a Pinnacle DV500 video capture board (the one with the daughter board). Its pretty old as well but does hardware acceleration of basic video transitions as well as analogue and firewire capture and replay. It integrates with Adobe Premiere 6. Whilst some modern video cards have capture capabilities, many of them rely on the sound card for the audio which can lead to sync problems. The DV500 handles quality stereo sound for input and output.
The oldest relic in the PC is a Gadgetlabs 8 channel 24 bit audio capture card (GL824). The company went bust in 2001 before releasing Win2K WDM drivers. Fortunately, a strong user community formed on the Yahoo forums and WDM drivers were written (thank you so much Mostek!) which got the card working under WinXP with ASIO support. With audio latencies of a few ms, multi channel real time synthesis and effects are fantastic.
There are only 3 PCI slots to play with and given the DV500’s daughterboard and the GL824 being a full length PCI card, it took a bit of juggling to get them in together. Fortunately everything just fit. The GL824 just touches the hard drive bay rail so I’ve slipped a plastic shield over its end. It seems recent motherboards and cases dont assume full length cards and populate the PCI area with jumpers, connectors and batteries.
Software wise, I have Premiere 6, Acid 5 and Sonar 5. It all runs great under XP which is just as well since there is no support for my 3 cards under Linux. While the cards continue kicking, WinXP will be the main OS on this system.
I run VMWare Workstation 6, with a couple of virtual machines including a Win2K VM for work and a Debian VM for web serving and site development. This blog is hosted on the linux VM. VMs are great for multimedia production machines because one can avoid installing a lot of software on the host system. This keeps the machine clean which is important when doing real-time audio.
If you are wondering why I would possibly need so many inputs and outputs on a sound card, here’s a picture of an even older relic, a Mackie SR824 I’ve had since the mid 90’s. Its no modern digital mixing surface, but there is plenty of analogue feel to it 🙂