WAV File Magic
Kye
Posts: 2,200
Hey, Everybody!
I think I've made something people will really like. So... if you have and SD card and know how to use it with the prop chip and have some audio output capability try the attached WAV player code. I've worked hard to make it be able to handle all LPCM 8/16-Bit 1/2-Channel WAV files. So, if you were ever having problems before playing audio files your life will now be much easier!
Just download the attached code and edit the pin numbers in the !WAV-Player_Program.spin file... then look for the "folder/wav.wav" string in the code and change it to the name of the WAV file you wish to play.
NOTE: YOU need to FOLLOW 8.3 naming conventions for the file system driver to be able to see the name of your wave file correctly! This means that you should name the file with all upper case characters and only have a name length of 8 character or less. The file extension should also be "WAV" only.
The best part is that all the WAV player functionality is now wrapped all into one object. To use the object just look at how simple the demo code is. (There's some other stuff in the demo code to make the audio file play faster and slower but you can ignore that... in the end all you have todo is call 1 line of code).
Enjoy!
I think I've made something people will really like. So... if you have and SD card and know how to use it with the prop chip and have some audio output capability try the attached WAV player code. I've worked hard to make it be able to handle all LPCM 8/16-Bit 1/2-Channel WAV files. So, if you were ever having problems before playing audio files your life will now be much easier!
Just download the attached code and edit the pin numbers in the !WAV-Player_Program.spin file... then look for the "folder/wav.wav" string in the code and change it to the name of the WAV file you wish to play.
NOTE: YOU need to FOLLOW 8.3 naming conventions for the file system driver to be able to see the name of your wave file correctly! This means that you should name the file with all upper case characters and only have a name length of 8 character or less. The file extension should also be "WAV" only.
The best part is that all the WAV player functionality is now wrapped all into one object. To use the object just look at how simple the demo code is. (There's some other stuff in the demo code to make the audio file play faster and slower but you can ignore that... in the end all you have todo is call 1 line of code).
Enjoy!
Comments
What sort of hardware do you need for the audio output - a R/C low pass filter?
It looks like the DAC driver incorporates Chip's dithering technique to rid remove noise from the playback (noise not in the file, but a result of cog interaction). Have you tried it through something other than PC speakers connected to a demo board? As time permits, I'll run your demo on an AP-16+ with 20w amps to see how it compares to using Chip's Stereo_Duty code in its own cog.
I was talking to chip and he said that the dithering might not be running at a high enough frequency. Not sure if it fixes your problem.
Thanks,
That was my thinking. When I worked through that issue with Chip I suggested putting the dither right into the driver as you have. He said it wouldn't work because the noise added to the signal must be very high frequency in order to get filtered by the RC components of the DAC.
Everything will sound muffled and lo-fi. (like the demo board and C3)
A second order low-pass filter with a cut off frequency of just under 20 kHz will do the trick.
/Johannes
Sorry, Chip identified the noise creation as the result of internal cog interaction with the IO pin drivers, and even made adjustments in the Propeller II design to prevent the same issue there. And then he spent an evening creating the StereoDuty cog to mitigate the situation -- that allowed EFX-TEK to move forward with the AP-16+ (100 ohms / 0.1uF -- and it has worked, we've sold over 750 units and will sell about that many just this summer for the Halloweeners).
I believe you have just been very lucky in which cog is used and the pin selection on a given project, or have been running your audio through small, less-than-quality speakers that mask the issue. For production ready code and real products one cannot rely on luck.
This is what I have found... You audio quality will depend heavily on the circuit you have used and the speaker you are using. We just tested the same software on an engineering prototype and it sounded much worse. But fine on the demo board. The difference in having cheap speakers versus good quality ones seems to only affect the audio ouput quality - not noise issues.
So - on the engineering prototype I heard the same noise that you had a problem with JonnyMac. I now see what you are talking about. With the demo board setup however and a $30 POP-UP Bytech speaker it sounded fine - the noise was still present but too low amplitude. I guess with very high volumes you would see the problem again. (I also tested this with my $500 dollar MM-550 Sennheiser head phones and loved it). The amount of dithering in my driver isn't enough to completely mask the audio at high volume however. So, I guess the AP-16 is different with the 20W speaker amps.
Mmm, YMMY with audio - really an analog world there.
@Ahel2 - That's the same cutoff frequency as the demo board and it sounded fine... I showed this off to several co-workers and they all agreed it sounded really, really good. I guess it can sound better? Probably. It really wasn't bad though with my test setup - as good as my laptop computer speakers with SRS audio enabled (makes them sound ALOT better through software DSP). Wasn't aiming for BOSE quality. Just something nice.
Listen to the last clip with "Dire straits - Money for nothing". And you will hear (even on the cheapest of computer speakers) how the hi-hats almost completely disappears with a cut-off frequency of 1.6 kHz.
Even a bass guitar will produce overtones way beyond 1.6 kHz.
Overtones are extremely important if you want anything to sound "real".
I havn't read a specification to ANY audio device ever stating a frequency range of 0 hz - 1.6 kHz. Not even a device from the 60s!
Btw, did I say i really appreciate your work!
/Johannes
I like to replace the DAC output resistor with a small inductor. Not so much for the rolloff as much as the possibility of driving headphones or even speakers directly.
I wouldn't say that very little information exists above 10 kHz; But I would say that most people above the age of 40 will have a hard time hearing them. For us that can hear them, they do make a great difference.
.
I wouldn't call a drop of 12 dB (25% of the amplitude) for frequencies above 6 kHz "a little quiter".
The way human hearing works, higher frequencies will be masked out due to the much higher amplitude at lower frequencies.
As you can see in the diagram below, most instruments will have overtones above 6 kHz.
Btw, did you listen to the clip I mentioned? It's not a exaggeration to say that the hi-hats almost disappears!
Suggest you listen to the clips again but in the other order.
I'm not condoning the choice of 3dB point, I'm just saying a single RC filter isn't remotely like a brick wall - its possible the values were chosen that low for RFI suppression reasons - a multipole filter would have been been a better solution all round of course, but would add to the BoM.
Yes.. human hearing is logarithmic, but that is taken into account when mixing in the studio. If a hi-hat would have been mixed with the same amplitude as a kick drum, nobody would bare to listen to the final mix. It would sound just awful.
If a mix sounds well balanced and nothing stands out, we could consider it being "linear" in respect to human hearing. (its more complicated than that but well...well... )
If you, when playing back a tune, subtracts information (6 db/octave lowpass filter), you are going to affect the "relative linearity" of the mix. That's all that matters actually.
While human hearing has a 100dB (and even more than that) dynamic range, that doesn't change the fact that loud sounds masks quieter sounds.
Depending on numerous factors, like fundamental tone and composition of overtones compared to the other sounds.. etc etc, a RELATIVE amplitude drop of 12 - 18db for a particular sound in well balanced mix would be enough for a sound to almost vanish in a mix.
This fact is what most lossy audio compression algorithms uses to their advantage.
In real life, however, the brain can compensate for this and "filter out" a quiter sound; This is called the "cocktail party effect".
"I always thought the masking effect was stronger the nearer the competing frequencies were?"
That's true of course.
"when you drop the level suddenly our brains give the illusion of it vanishing"
That's also true.
"Suggest you listen to the clips again but in the other order."
I will.
/Johannes
You have done a good job as always. Very efficient code and well commented!
Thanks,
You get into minor buffering issues and race condition issues with that if you do so. Basically the first block of 512 bytes might be garbled using the simple buffering system I have setup. It works better just to leave it running.
As for point one. Yeah, that is an issue, I just didn't remove it when coding. I plan on remvoing the LFSR and putting it in another cog. I talked about this with Chip and he said that I should make a second cog launch in the background if you want to handle the LFSR issue noise issue.
Chip did this for me with his StereoDuty object -- which is really quite simple once done (I use this in the AP-16+). Instead of writing your volume-adjusted samples to the counter/DACs, you reconstruct a 32-bit word and write it to the hub to be picked up by StereoDuty. This takes care of adding white noise to the sample that is removed by the DAC's RC circuit.
For clarification, I run the demo program which plays a short (about 2 sec) 8bit mono sample in an endless loop.
I agree about the race condition, that's why I suggested stopping/idling the player when no file is active.
Update: I also attach the problematic case for the demoboard using an embedded FS. It contains the player in its original form. After each sample is played there is an audible click due to mode change. For comparison uncomment the tjz (despite being an incomplete fixA) and hear the difference.
A Using buffer instead of playerMode and making playerMode a long 0 (instead of res) should be sufficient here.
(The error you see there is creative... coding... it really shouldn't be doing that...)
Question: You seem to be getting pretty worked up by this. Hehe.
Maybe you can scope out any problems in it. It's a bit more simple than the WAV player so it might not have any.Who knows.
It now has a high speed dither cog. I also fixed any buffer sync issues. They should not occur now.
Thanks for everyone's help!
I had been planning on 680R and 10nF (~20KHz) followed by 10uF mono, not electro (because they come in 0805 smt).