Shop OBEX P1 Docs P2 Docs Learn Events
playing wav file from sd card - part 2 — Parallax Forums

playing wav file from sd card - part 2

shmowshmow Posts: 109
edited 2011-01-26 20:19 in Propeller 1
Hello All,
I've been attempting to replace an EMIC with a SD card/WAV file combination.
Enclosed is the sample code where you can see my pin assignments.
But I don't know why I can't get the "BEEP.WAV" file to play.
I've tried all sorts of different outputs with the command:
wpl.start(sdBasePin, HeadphoneRightPin, HeadphoneLeftPin, @buff, bufferLen)
I'm not sure which pin should correspond with sdBasePin; I assumed it was pin 0.
The HeadphoneRightPin (and ...LeftPin) I've assigned to pin 7.
When I run the chip with this program, I can tell something is happening because there is a click sound
coming out of my speaker - but nothing resembling the file from the SD card.
I'd really appreciate any advice.
Regards,
Shmow

'  Example of waveplayer usage
'
'
'  Propeller Pins                  SD card Pins
'                   3.3v
'                      
'                      10k
'   p0 ───────────┻─┼─┼─┼─────────── do
'   p1 ─────────────┻─┼─┼─────────── clk
'   p2 ───────────────┻─┼─────────── di
'   p3 ─────────────────┻─────────── cs 

'
'─────────────────────────────────────────────────
'
'               
'   p7 ───────────[noparse][[/noparse]20 watt amplifier]───── + [noparse][[/noparse]speaker] - ─────┐ 
'                                                             
'                                                            GND       
'              
con
  _clkmode = xtal1 + pll16x
  _xinfreq = 5_000_000
  bufferLen = 800

obj
  ser : "FullDuplexSerial"
  wpl : "WavePlayerSdAccess"

var                 
  byte buff[noparse][[/noparse]bufferLen]
  long stack[noparse][[/noparse]50]

pub main | sdBasePin, HeadphoneRightPin, HeadphoneLeftPin
  ser.start(31,30,0,19200)

  sdBasePin := 0
  HeadphoneRightPin := 15
  HeadphoneLeftPin := 7
  wpl.start(sdBasePin, HeadphoneRightPin, HeadphoneLeftPin, @buff, bufferLen)

  wpl.playwave(string("BEEP.WAV"))


Comments

  • JonnyMacJonnyMac Posts: 9,234
    edited 2010-07-12 18:20
    In my WAV player (www.efx-tek.com/topics/ap-16.html) I check that the SD card is mounted before doing anything else; perhaps you WavePlayerAccess object isn't doing this for you. If the card is not mounted, nothing else works.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon McPhalen
    Hollywood, CA
  • Oldbitcollector (Jeff)Oldbitcollector (Jeff) Posts: 8,091
    edited 2010-07-12 18:22
    wpl : "WavePlayerSdAccess"

    Without some more of your code, it's hard to tell..

    Any chance you could Archive the project. (Under File in Propeller Tool) and attached it to this thread?
    Drag in your BEEP.WAV for us too..

    OBC

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Propeller Feature Projects: PropellerPowered.com
    Visit the: PROPELLERPOWERED SIG forum kindly hosted by Savage Circuits.
  • shmowshmow Posts: 109
    edited 2010-07-12 18:50
    Hello JohnnyMac,
    when you say mounted, do you mean are the SD card & reader communicating with the prop?
    All I've test for is the connection (which works) by using SD_trainer.spin and PST.

    Hello OBC,
    attached is the archived spin file, the wav file beep.wav and a bin file that's included with the .wav file on the SD card.

    Thanks and regards,
    Shmow
  • David BDavid B Posts: 592
    edited 2010-07-12 20:51
    Something I've found helpful is to trap and display the method return values, especially if a method returns error codes using "abort".

    In your code, main calls wpl.start, which calls sd.mount. But if mount fails, the call will abort, returning a negative valued error code that can be very helpful to debug what's wrong. But your code is not capturing any value, or even checking that the mount succeeded.

    So instead of calling

    wpl.start(sdBasePin, HeadphoneRightPin, HeadphoneLeftPin, @buff, bufferLen)

    you'd capture the return value using the abort trap

    value := \wpl.start(sdBasePin, HeadphoneRightPin, HeadphoneLeftPin, @buff, bufferLen)

    If "value" is negative then the code shouldn't try to play the WAV. Instead, you'd want to display the error code somehow, then use it's value to track down what the problem is.

    I'm not saying that the mount is the problem, but it would be good to verify a successful mount as part of debugging this player.
  • shmowshmow Posts: 109
    edited 2010-07-12 20:58
    Hello David B & JohnnyMac,
    In the code, how do I determine if the card has mounted?
    Shmow
  • shmowshmow Posts: 109
    edited 2010-07-12 21:13
    Hey Guys,
    I included the suggested code you posted and the value I'm displaying is 243 - any significance?
    Shmow
  • shmowshmow Posts: 109
    edited 2010-07-12 22:08
    Hay y'all,
    I finally got the file to play!!!!!
    Attached is the working file - very simple.
    The only problem is the noise in the background.
    It sounds like a nice crackling fire in the background.
    I've put capacitors of all sizes on but no success in diminishing the noise.
    Any suggestions?
    Regards,
    Shmow
  • KyeKye Posts: 2,200
    edited 2010-07-12 23:05
    You should check out the new Full File system driver in the obex under data storage. The demo has a full featured wav player built into it that can handle any standard WAV file.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • JonnyMacJonnyMac Posts: 9,234
    edited 2010-07-13 06:24
    The crackling noise issue is a biggy -- I tried everyone's WAV driver, had this problem, so I wrote my own. And... it was still there. It has to do with the location of the cog vis-a-vis the pin(s) used for the DAC output. No, I didn't figure this out, Chip Gracey (the guy who invented the Propeller) did. He wrote a little routine that takes a stereo sample (in one long), dithers it with noise and outputs it. Note that the output has to be refreshed faster than the normal sample rate to, as Chip puts it, "whiten" the noise and push it up to the point where it is filtered out by the RC circuit on the output.

    Yeah, it seems counter-intuitive but I can tell you it works. Our product has two 20W amps on it so we can hear the difference. Since using Chip's StereoDuty object requires yet another cog, you can help yourself by moving the cog that actually drives the pins to the top of the list (i.e., to cog #1; this helped, but didn't completely clear the noise). There's another thread running where I posted demo code that uses my WAV driver connected to Chip's StereoDuty driver.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon McPhalen
    Hollywood, CA

    Post Edited (JonnyMac) : 7/13/2010 6:40:09 AM GMT
  • Invent-O-DocInvent-O-Doc Posts: 768
    edited 2010-07-13 09:34
    Shmow,
    The recent code you posted looks just like the original code. Do you know what you changed to make things work?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Tom Talbot
    New Market, MD, USA
  • shmowshmow Posts: 109
    edited 2010-07-13 14:00
    Thanks Kye,
    I'll try that out.
    Shmow
  • shmowshmow Posts: 109
    edited 2010-07-13 14:01
    JohnnyMac,
    it's good to hear that. I'll look into Chip's object.
    Regards,
    Shmow
  • lonesocklonesock Posts: 917
    edited 2010-07-13 14:04
    JonnyMac said...
    ...It has to do with the location of the cog vis-a-vis the pin(s) used for the DAC output...Since using Chip's StereoDuty object requires yet another cog, you can help yourself by moving the cog that actually drives the pins to the top of the list (i.e., to cog #1; this helped, but didn't completely clear the noise)...
    There is a chart in the propeller datasheet in section 9.5 showing the "distance" from each cog to each pin. Basically, you draw current every time you switch the state of a pin, and the farther the cog is from the pin (internal circuitry-wise), the more current each transition takes. Your best bets are to drive pins P7 & P8 from cog 0, or pins P23 & P24 from cog 7.

    It should be fairly easy to force the StereoDuty object into cog 0: in your first method, cognew the main startup subroutine, then coginit the StereoDuty object into cog 0.

    (as a side note, in the demo you posted in the other thread, I would recommend switching to the safe_spi.spin block driver from the FSRW 2.6 implementation. For the purposes of reading a WAV file you should not see any speed hit, and it is impervious to this same cog-vs-pin issue we are discussing.)

    Jonathan

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    lonesock
    Piranha are people too.
    (geek humor escalation => "There are 100 types of people: those who understand binary, and those who understand bit masks")
  • shmowshmow Posts: 109
    edited 2010-07-13 14:12
    Hey Tom,
    I boiled my earlier sample code to basic parts (for my understanding).
    I've attached the latest, working code with the objects.
    I assigned pin 15 to HeadphoneRightPin for the sake of expediency; pin 15 doesn't do anything.
    And, here's a snippet of that code:

    
    '  Example of waveplayer usage
    '
    '
    '  Propeller Pins                  SD card Pins
    '                   3.3v
    '                      
    '                      10k
    '   p0 ───────────┻─┼─┼─┼─────────── do
    '   p1 ─────────────┻─┼─┼─────────── clk
    '   p2 ───────────────┻─┼─────────── di
    '   p3 ─────────────────┻─────────── cs 
    
    '
    '─────────────────────────────────────────────────
    '
    '               
    '   p7 ───────────[noparse][[/noparse]20 watt amplifier]───── + [noparse][[/noparse]speaker] - ─────┐ 
    '                                                             
    '                                                            GND       
    '              
    con
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      bufferLen = 800
    
    obj
      ser : "FullDuplexSerial"
      wpl : "WavePlayerSdAccess"
    
    var                 
      byte buff[noparse][[/noparse]bufferLen]
      long stack[noparse][[/noparse]50]
    
    pub main | sdBasePin, HeadphoneRightPin, HeadphoneLeftPin
      ser.start(31,30,0,19200)
    
      sdBasePin := 0
      HeadphoneRightPin := 15
      HeadphoneLeftPin := 7
      wpl.start(sdBasePin, HeadphoneRightPin, HeadphoneLeftPin, @buff, bufferLen)
    
      wpl.playwave(string("BEEP.WAV"))
    
    
    
    



    Regards,
    Shmow
  • vanmunchvanmunch Posts: 568
    edited 2011-01-26 20:19
    Hey thanks for the info on the "sdBasePin." Just wanted to let you know that it helped me get my card working on the FIRST try. That might be the first time, but I guess there's a first time for everything


    first time! (just had to say it once more :) ) Thanks!
Sign In or Register to comment.