Shop OBEX P1 Docs P2 Docs Learn Events
WAV File Magic — Parallax Forums

WAV File Magic

KyeKye Posts: 2,200
edited 2011-08-30 05:48 in Propeller 1
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!
«1

Comments

  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-07-08 20:51
    Sounds good (pun intended!)

    What sort of hardware do you need for the audio output - a R/C low pass filter?
  • KyeKye Posts: 2,200
    edited 2011-07-09 00:27
    Yep - Demo board setup with SD card socket will work.
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-07-09 11:33
    Kye,

    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.
  • KyeKye Posts: 2,200
    edited 2011-07-10 08:42
    No, no yet. It was asked for by Andy for the PropBOE... its gonna be one of the kill app things for the Prop BOE.

    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,
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-07-10 09:08
    I was talking to chip and he said that the dithering might not be running at a high enough frequency.

    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.
  • KyeKye Posts: 2,200
    edited 2011-07-11 09:45
    I think this problem has more todo with the choice of your RC network... 100 Ohm R and 1uF C work great for me. IDK
  • Ahle2Ahle2 Posts: 1,179
    edited 2011-07-11 10:10
    Kye, that gives a cut off frequency of just 1.6 kHz; That isn't anyway near good enough for CD quality audio.
    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
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-07-11 10:47
    I think this problem has more todo with the choice of your RC network

    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.
  • KyeKye Posts: 2,200
    edited 2011-07-11 15:42
    We just did some testing for this issue at parallax. At least on the demo board the audio sounds picture perfect. You can still hear the noise but you must put your ear right up next to speaker.

    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.
  • Ahle2Ahle2 Posts: 1,179
    edited 2011-07-11 16:01
    Kye, listen to my audio clip from the thread named " Listen up C3 owners".
    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
  • KyeKye Posts: 2,200
    edited 2011-07-11 16:08
    Yeah, I see. Wasn't having that problem using my setup. Maybe its my speaker? It's pretty good. IDK. My test files were "Yeah" by usher. "Billie Jean" my Micheal Jackson and a few other files. Standard CD audio quality. I guess you'd have to be over here to see what I am talking about. They sounded really good. Coworkers agreeded. Again... YMMV.
  • Mark_TMark_T Posts: 1,981
    edited 2011-07-11 17:52
    Ahle2 wrote: »
    Kye, listen to my audio clip from the thread named " Listen up C3 owners".
    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".
    That simple RC filter doesn't get rid of the high frequencies, only drops them 6dB/octave, which is not that aggressive - very little information exists above 10kHz anyway so the effect of the filter won't be as bad as you think. It won't be hifi, but it won't be horrible - the high-hats will be a little quieter and not very brilliant but they will be audible. An LC filter or an active multi-pole RC filter with a sharper knee at 10kHz or so would be much better though...
  • PerryPerry Posts: 253
    edited 2011-07-11 20:28
    CD quality depends on the mastering. Madonna's first CD had excellent audio quality, but the following ones were disappointing. Any of "Credence Clearwater Revival" CDs are also excellent, they were recorded on 32 track Ampex equipment way before CD's existed.

    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.
  • Ahle2Ahle2 Posts: 1,179
    edited 2011-07-12 09:52
    Mark_T wrote: »
    That simple RC filter doesn't get rid of the high frequencies, only drops them 6dB/octave, which is not that aggressive - very little information exists above 10kHz anyway so the effect of the filter won't be as bad as you think.
    I never said anything about a "brick wall filter". (I have one in my home studio though)

    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.
    Mark_T wrote: »
    It won't be hifi, but it won't be horrible - the high-hats will be a little quieter and not very brilliant but they will be audible
    .
    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.
    main_chart.jpg

    Btw, did you listen to the clip I mentioned? It's not a exaggeration to say that the hi-hats almost disappears!
  • Mark_TMark_T Posts: 1,981
    edited 2011-07-12 18:19
    Ahle2 wrote: »

    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".
    Well I would, my hearing is logarithmic in intensity perception with a 100dB dynamic range or so.
    The way human hearing works, higher frequencies will be masked out due to the much higher amplitude at lower frequencies.
    I always thought the masking effect was stronger the nearer the competing frequencies were? A single high-pitched mobile phone ringtone can disrupt a performance for instance and a referee's whistle is audible above a stadium-full of chanting fans.

    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!
    I listened to it and yes that is the perception, but then I listened again, but reversed the order in which I heard the two samples - LPF'd first, then full spectrum - the high hat is perfectly audible, its just a bit quieter and duller - when you drop the level suddenly our brains give the illusion of it vanishing, but that's just the standard neurological response of being highly sensitive to change rather than absolute level. (compare going into the shade from bright sun)

    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.
  • Toby SeckshundToby Seckshund Posts: 2,027
    edited 2011-07-13 01:50
    Is there any way that the noise could be generated on its own and then with level adjustments and anti-phasing perhaps it could be balanced out. I have done this with the PWM bits on AVRs.
  • Ahle2Ahle2 Posts: 1,179
    edited 2011-07-13 08:44
    @Mark_T
    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
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-07-13 08:52
    Again, the noise issue is a function of the internal architecture of the Propeller -- Chip Gracey says so. I spent a long time trying to code around the issue before calling him. The final straw for me was generating a pure sine tone using Audacity (so I knew the file would be clean) and playing it. What should have been clean and pure was full of crackles, especially low frequency tones. When I chatted with Chip about his he was not surprised and solved the issue with his StereoDuty object.
  • KyeKye Posts: 2,200
    edited 2011-07-13 09:03
    Has anyone actually used the WAV player I made and played a tune or two?
  • Ahle2Ahle2 Posts: 1,179
    edited 2011-07-13 09:05
    Yes and it works GREAT!!
    You have done a good job as always. Very efficient code and well commented!
  • KyeKye Posts: 2,200
    edited 2011-07-14 12:26
    Cool =)

    Thanks,
  • kuronekokuroneko Posts: 3,623
    edited 2011-07-16 17:58
    Kye wrote: »
    Has anyone actually used the WAV player I made and played a tune or two?
    Yes. I suggest you have another look to resolve the following issues:
    • Just starting the DAC engine will result in artificial noise after about 35 sec (@80MHz). This is due to the LFSR additions which - as JonnyMac pointed out - should really occur with a higher frequency, i.e. in a different cog.
    • You might want to have another look at the following two lines:
      outerLoop              rdlong  playerMode,         samplePositionAddress
                             tjz     playerMode,         #skipLoop
      
      In case the sample has finished playing you fall back to signed-16bit/2 channels which - having just played a unsigned-8bit mono sample - will result in rather noisy distortion (note that the DAC engine is always running even without a file being played). As a quick solution removing the tjz worked for me (playerMode is kept up-to-date with what's in the sample buffer). It'd probably be better to stop the player if nothing needs to be played.
  • KyeKye Posts: 2,200
    edited 2011-07-17 10:18
    So... it doesn't fall back to signed 16-bit samples. It only reloads settings when it has data to play. So, it shouldn't have problems with point two. It also deletes samples as they are played so it never will play a sample twice. All this is also synced with the buffering in the SPIN cog as to prevent issues. It puts center level where samples were so when it plays them over again (as it is always running) it will play center level using the settings it loaded previously.
    As a quick solution removing the tjz worked for me (playerMode is kept up-to-date with what's in the sample buffer). It'd probably be better to stop the player if nothing needs to be played.

    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.
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-07-17 10:35
    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.
  • kuronekokuroneko Posts: 3,623
    edited 2011-07-17 14:20
    Kye wrote: »
    So... it doesn't fall back to signed 16-bit samples. It only reloads settings when it has data to play.
    Then please explain this to me.
    outerLoop               [COLOR="red"]rdlong  playerMode,         samplePositionAddress[/COLOR]
                            [COLOR="red"]tjz     playerMode,         #skipLoop[/color]
    
                            rdword  buffer,             numberOfChannelsAddress
                            cmp     buffer,             #1 wz
                            muxz    playerMode,         #1
    
                            rdword  buffer,             bitsPerSampleAddress
                            cmp     buffer,             #8 wz
                            muxz    playerMode,         #2
    
    skipLoop                mov     counter,            #128
                            [COLOR="red"]test    playerMode,         #1 wc[/COLOR]
    if_c                    shl     counter,            #1
                            [COLOR="red"]test    playerMode,         #2 wc[/COLOR]
    if_c                    shl     counter,            #1
    
    Once my unsigned 8 bit mono sample (playerMode == %11) has finished samplePositionAddress holds 0. The outerLoop keeps going but with playerMode now being 0 it skips channel and sample evaluation which is equivalent of channels not being 1 (i.e. 2) and bits per sample not being 8 (i.e. 16). I even dumped the sample buffer (before being filled by the FS) and I can actually see the switch between 16bit/stereo and 8bit/mono (and I can hear the distortions caused by that). What am I missing here?

    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.
  • KyeKye Posts: 2,200
    edited 2011-07-17 19:06
    Oh, your right. It should not do that. Thanks!

    (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.
  • KyeKye Posts: 2,200
    edited 2011-07-17 19:13
    Here's something else that was cooked up. Its a WAV voice recorder for the demo board. It works really good and me and Andy were able to record an hour of conversation no problem.

    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.
  • KyeKye Posts: 2,200
    edited 2011-07-19 18:42
    Okay, Here's a new version with everyone's input added.

    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! =)
  • Cluso99Cluso99 Posts: 18,069
    edited 2011-07-20 04:57
    So Kye, what series cap are you using? (eg, 100R, then 0.1uF to gnd, followed by series cap to output usually around 4.7uF-10uF)

    I had been planning on 680R and 10nF (~20KHz) followed by 10uF mono, not electro (because they come in 0805 smt).
  • KyeKye Posts: 2,200
    edited 2011-07-20 09:49
    Was using the demo board. So... this stuff works just fine for it.
Sign In or Register to comment.