Last night my Propeller WAV player played its first flawless performance! A full 50 seconds of smooth, clear audio!
It's still very much under construction but I'd like to present the first working version.
This reads a standard WAV file, by name, from an SD card and plays it. It will directly drive a set of mini headphones, or can be sent to amplified computer speakers for louder sound.
Currently it only plays single channel 8 bit PCM (raw digitized byte) files. I've tested it on 8, 11.25, 16 and 22 kHz, all of which
work. It does play 16 bit files but there is a bug that creates bad static in the audio; still working on that. It should be able to play 2 channel (stereo) but I haven't added a second DAC circuit.
It reads short filenames, only, from the root directory of a FAT16 filesystem. It can read FAT12 files but can't play them. I hope to add the ability to search subdirectories for files but probably won't bother decoding long filenames or FAT12 WAV files.
Architecture - the card Spin object starts an assembly cog that manages the SD card. Spin sends sector read requests to asm and reads filesystem info, searches the FAT16 root directory for requested files by name, reads the header from the located WAV file and decodes WAV parameters. Then Spin requests the card asm to read and export the file data.
The card assembly cog reads sectors of file data and passes the data to hub variables. The assembly does the complete FAT16 file tracking, managing clusters, sectors, reading the FAT table to locate the next cluster of the file, and reads sectors until the end of the file. The card module streams file data to a standard output interface, which could be used for other purposes, such as an ebook text display, something else I'd also like to do someday.
The card Spin then starts the DAC asm cog, passing it the address of the card data transfer variables (and the WAV parameters.) The DAC cog configures itself for the data rate, number of bits, then reads data and plays it via the CTRB FRQ controlled IO bit. From that point on, the card and DAC cogs are running on their own, independently from the calling Spin cog, with one producing data and the other consuming it. The DAC cog plays until no more data is available.
The trickiest part was that the DAC cog has to buffer a large supply of sound samples to bridge the times that the card cog pauses to read another sector, and even worse, when a new cluster is needed, to read both a FAT sector then a data sector. Until the buffering was right, the sound played with a regular series of pops, but now it's soft and smooth!
The reason it won't play FAT12 is that the entire FAT file storage cluster decoding is done in assembly to get the speed needed to deliver data fast enough. I did actually get a FAT12 assembly version working, but it was much trickier than FAT16 and basically took up too much code space, to the point where I was fighting for every available byte. I'm not a coding guru; this is all beginner or intermediate-level coding, and the FAT12 struggle was too much. Besides, only smaller SD cards use FAT12; I'm working with a 1 gig SD card and don't expect to go back to 8 meg FAT12 cards.
I'm thinking of using this to make general purpose talking output, like a voltmeter or frequency counter that speaks what it's measuring, or a telescope positioning board that speaks the direction the scope is pointing. Since this will readily play WAV files created by·the PC sound recorder, it's easy to make new sound modules this can play, so those uses aren't that far away!
The SD card data file data stream may be a good fit for the sound decoder players like in the Hydra project; I'm anxious to see how that project works out.