Shop Learn
Can a WAV file be loaded to and played from EEPROM — Parallax Forums

Can a WAV file be loaded to and played from EEPROM

idbruceidbruce Posts: 6,168
edited 2010-12-28 18:25 in Propeller 1
Hello Everyone

Well the CDROM hack (see my previous post) was a complete success, and my propeller proto board now has sound output capabilities. My next project is to load and play a single WAV file, however, all the WAV file player objects seem to require an SD card. Besides that bad news, I have run out of available pins.

Is it possible to load and play a WAV file from EEPROM?

If not, can it be hardcoded in anyway to make it possible?

Here are the file specs:
Bit Rate - 176 kbps
Audio Sample Size - 8 Bit
Channels - 1(mono)
Audio Sample Rate - 22 kHz
Audio Format - PCM
File Size - 45.8 KB
Your guidance will be greatly appreciated.

Bruce

Comments

  • localrogerlocalroger Posts: 3,439
    edited 2010-12-27 15:47
    Yes. Using a PASM EEPROM interface you can pull 40 Kbytes/sec from standard EEPROM, and up to 100 Kbytes/sec from the 1 MHz chips. I am doing a project with up to 4 128 kbyte Atmel EEPROMs totaling 512K. You should be able to get away with a single Atmel EEPROM (you can just plug it in if your board has an 8-pin socket) or a 64K in addition to a built-on 32 or 64K part.
  • JonnyMacJonnyMac Posts: 7,568
    edited 2010-12-27 16:23
    I wrote a demo that plays a sound out of a DAT table that you can find in this thread:

    -- http://forums.parallax.com/showthread.php?128129-cylon-eye-sound

    If you add I2C access you may be able to make this work without getting into PASM; it will depend on your sample rate.
  • idbruceidbruce Posts: 6,168
    edited 2010-12-27 17:45
    Jon and Roger ->

    You two guys caught my interest here. First off, Jon I tried your code and it worked for me, then of course I had to try and play my file, and of course not enough memory. But I am excited nonetheless because I have sound from a speaker instead of a piezo :smile:

    Alright, as I see it, I have a couple options here:
    1. I could try and find a smaller file similar in size and rate to the files in your demo, however, I have not even begun to get into my main programming yet. As a result, I may run low on memory without the WAV file.
    2. I could try and add more memory. Could you guys please explain an add-on of memory to me. Are the the chips wired in parallel, etc....
  • RaymanRayman Posts: 11,962
    edited 2010-12-27 18:30
    Look for me in OBEX... I've got an 8-bit wav player there that plays files embedded in memory...
  • JonnyMacJonnyMac Posts: 7,568
    edited 2010-12-27 21:16
    @Ray: The demo (link to it) I posted above is a derivative of experiments that you and I have done.

    @idBruce: You could resample your file down to 11 or 8 kHz to conserve space, but the quality will change. Still, it might be enough for the project at hand. The best case is to add an SD card but you've indicated that you don't have the pins for it. To play from EEPROM you'll need to create a player in PASM -- many of us have done that but I don't think you're quite ready for that much programming, at least not yet. And you can't arbitrarily add program or data memory to the Propeller. You can hang extra EEPROMs on the I2C buss, but those require a bit of code for access.
  • idbruceidbruce Posts: 6,168
    edited 2010-12-28 06:48
    Thanks Jon :smile:

    That's exactly what I did. Hopefully I still have enough memory for the rest of the program.

    LOL Read all about it in my next post.

    Bruce
  • MagIO2MagIO2 Posts: 2,241
    edited 2010-12-28 07:00
    @idbruce:
    No free pins left? Adding a SD card is easy and then you no longer have a problem with resampling ..
  • localrogerlocalroger Posts: 3,439
    edited 2010-12-28 16:53
    idbruce, adding EEPROM electrically is very easy; the SDA and SCL (data and clock) pins are wired in parallel, and to use more than one chip you tie two or three pins high or low to set its address. However, you would need a PASM driver for the interface to get enough speed for audio.

    For a simple project SD is heavy overkill because there's a lot of code (even if you don't write it it's there in the object you use to control the SD card, taking up Hub RAM) to navigate the file system. You just need to run a string of bytes out of raw storage and into a D/A converter. There are a couple of PASM I2C examples out there, with a PASM routine to retrieve bytes you could probably get away with using Spin to shovel them to the D/A and do the more complex I2C addressing and setup.
  • idbruceidbruce Posts: 6,168
    edited 2010-12-28 18:25
    Thanks LocalRoger

    I appreciate you getting back to me on the EEPROM, as for the audio, well Jon gave me some good advice and code and it works perfectly for me. I can hear the wav file 35 feet away from a tiny 1 inch speaker :smile:

    However, from here on in, unless it is a simple project, I will add a DIP socket just in case I want to add more EEPROM. In this case, I am simply out of pins. Actually I have one left, but that is like a spare tire, if you get a flat.

    I think I will be in good shape as long as I can get my programming into the EEPROM along with the WAV file.

    Thanks again for getting back to me.

    Bruce
  • Clock LoopClock Loop Posts: 2,056
    edited 2021-04-10 03:12

    @Rayman said:
    Look for me in OBEX... I've got an 8-bit wav player there that plays files embedded in memory...

    Hey @Rayman, I gave your 8-bit player a try and I had problems with specific file names.

    I found that you need the file size in the DAT section set to LONG probably related to file size NAME?.
    Each wav file I load is around 5.25kb
    But some would work, depending on their file NAME with byte, all work with long.

    Thanks for the wav player, I might be using this in my prop railroad engine controller.

    '  SPIN 8-bit WAV Player Ver. 1a  (Plays only mono 8-bit WAV at 8 or 16 ksps)
    '  Copyright 2007 Raymond Allen  See end of file for terms of use.
    '  Settings for Demo Board Audio Output:  Right Pin# = 10, Left Pin# = 11   , VGA base=Pin16, TV base=Pin12
    
    
    CON _clkmode = xtal1 + pll16x
        _xinfreq = 5_000_000       '80 MHz
    
    
    PUB Main|n,i,j
      'Play a WAV File
    Repeat
    
      Player(@WAV1,26,27,3600)
      'waitcnt(40_000_000 + cnt)
    
      Player(@WAV2,26,27,3600)
      'waitcnt(40_000_000 + cnt)
    
      Player(@WAV3,26,27,3600) 
      'waitcnt(40_000_000 + cnt)
    
      Player(@WAV4,26,27,3600)
      'waitcnt(40_000_000 + cnt)
    
    PUB Player(pWav, PinR, PinL, rate1):bOK|n,i,nextCnt,rate,dcnt
      'Play the wav data using counter modules
      'although just mono, using both counters to play the same thing on both left and right pins
    
      'Set pins to output mode
      DIRA[PinR]~~                              'Set Right Pin to output
      DIRA[PinL]~~                              'Set Left Pin to output
    
      'Set up the counters
      CTRA:= %00110 << 26 + 0<<9 + PinR         'NCO/PWM Single-Ended APIN=Pin (BPIN=0 always 0)
      CTRB:= %00110 << 26 + 0<<9 + PinL         'NCO/PWM Single-Ended APIN=Pin (BPIN=0 always 0)
    
      'get length
      n:=long[pWav+40]
      'get rate
      rate:=long[pWav+24]
      case rate
        8000:
          dcnt:=10000
        16000:
          dcnt:=5000
          'dcnt:=2000
        other:
          return false
      'jump over header
      dcnt:=rate1
      pWav+=44   'ignore rest of header (so you better have the right file format!)
    
    
      'Get ready for fast loop
      n--
      i:=0
      NextCnt:=cnt+15000
    
      'Play loop
      repeat i from 0 to n
        NextCnt+=dcnt   ' need this to be 5000 for 16KSPS   @ 80 MHz
        waitcnt(NextCnt)
        FRQA:=(byte[pWav+i])<<24
        FRQB:=FRQA
    
    
          'Easy high-impedance output (e.g., to "line in" input of computer or sound system)
          '
          '              R=100
          ' Prop Pin ────┳──────── Audio Out
           '               C=0.1uF
           '                
           '               Vss
      return true
    
    
    DAT
    
    WAV1 long
    File "c1.wav"           '   <---  put your 8-bit PCM mono 16000 or 8000 sample/second WAV filename here
    
    WAV2 long
    File "c2.wav"           '   <---  put your 8-bit PCM mono 16000 or 8000 sample/second WAV filename here
    
    WAV3 long
    File "c3.wav"           '   <---  put your 8-bit PCM mono 16000 or 8000 sample/second WAV filename here
    
    WAV4 long
    File "c4.wav"           '   <---  put your 8-bit PCM mono 16000 or 8000 sample/second WAV filename here
    
    {{
                                TERMS OF USE: MIT License
    
     Permission is hereby granted, free of charge, to any person obtaining a copy
     of this software and associated documentation files (the "Software"), to deal
     in the Software without restriction, including without limitation the rights
     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     copies of the Software, and to permit persons to whom the Software is
     furnished to do so, subject to the following conditions:
    
     The above copyright notice and this permission notice shall be included in
     all copies or substantial portions of the Software.
    
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING FROM,
     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     THE SOFTWARE.
    }}
    
    

    I was trying to make the playback of the wave vary in speed, but I noticed there is a lower limit, anyway to get it to play lower? (the dcnt variable lower limit is 3600)

  • Peter JakackiPeter Jakacki Posts: 10,191
    edited 2021-04-10 01:55

    If you have I/O to spare then add a footprint for a microSD card anyway. You don't need pullups, just the 4 I/O and 3.3V and a 10uF cap will help. If you end up using EEPROM, then no problem, no loss.

    If though you need to do better then you are already equipped hardware wise to do so. The SD card itself doesn't need much software to work as Flash memory device and the extras that you need to mount FAT32 for finding a file is really minimal. The big advantage of the SD is that you can copy better quality files onto the card with your PC and playback can be a lot better quality. I did this all the time with the P1 (using Tachyon obviously).

    The idea here is not to paint yourself into a corner but to have options, especially when a footprint doesn't add anything to the cost of a pcb.

    EDIT: If you are using EEPROM then you need to sit in a dedicated loop to playback the wav file since you need to read a byte every 45.45us you would do this as an initial read from address operation. After that you can sit in a loop and read in the next sequential byte from I2C an then waitcnt set for 45.45us then output the sample etc. This may require a dedicated cog perhaps (PASM needed anyway). There is a 64kB addressing boundary limit to sequential reading but normally you wouldn't be crossing any boundaries I would think.
    Getting the file onto the EEPROM is another story but you could use a serial hex load as I have done when I load "ROMs" into upper EEPROM from Tachyon.

  • Clock LoopClock Loop Posts: 2,056
    edited 2021-04-10 03:43

    I saw my needs were similar to the ops, wave eeprom loading.

    I switched to eeprom from a sd card because the rotines to run a sd card and the wave player for HQ files was too large to fit WITH my prop program.

    So i switched to a 8-bit player that can load the wav files from eeprom.

    Now I am looking at just using another 32k eeprom, or even two.
    I don't know if that will work I will need to test how fast the file is loaded from the eeprom, to play back.
    John has a program to access the upper 32k.. of a 64k eeprom..
    https://forums.parallax.com/discussion/comment/1218801/#Comment_1218801

    However I may just use another 32k eeprom since its all I have and just use a few more pins.

    Edit: I just noticed raymond's 16-bit stereo player with frsw uses much less eeprom than kyes fancy wave player.
    Gotta test it to see if I can manipulate the playback rate of the wave file realtime.

  • Peter JakackiPeter Jakacki Posts: 10,191
    edited 2021-04-10 03:55

    I am sure that if you wanted minimal routines in PASM for playing wav files from SD that I can provide these. Kye's drivers were always over the top and didn't take into account that to be usable it would have to squeeze into memory rather than push out other software IMO.

    Basic routines required.

    • SPI read and write.
    • SPI sector read.
    • SD CMD (simple)
    • SD INIT

    This will provide all that you need to replace EEPROM and without any practical limit to memory and it is very fast.

    Optional:

    • FAT32 MOUNT

    This is all that is needed since it points to the ROOT directory sector which is so easy to scan for a file name.

    So MOUNT would call SD INIT and use the other routines to read in the partition and INFO sector and you needn't worry about the actual FAT cluster tables really other than translating a file start cluster to a file start sector. It is always made to look complicated but the basics are very easy. When I first looked into it back in 2004 it did look complicated.

  • Clock LoopClock Loop Posts: 2,056
    edited 2021-04-10 04:35

    Once I realized the 8-bit player can do two waves at once by running TWO cogs..... the eeprom method won.
    Multiple eeproms can access the waves faster i suppose than a single eeprom. (like one eeprom per cog wave player)

    My other option is using 4+ sd cards and even then i don't have room for 4 copies of that code etc..

    Truly, the prop has its limits! One day i will venture into the land of p2, but not anytime soon $$$

    The only issue I can see is if I can access the eeprom data fast enough for on the fly 8-bit playback. my chuffs are 5.5kb in size.

  • Peter JakackiPeter Jakacki Posts: 10,191
    edited 2021-04-10 04:42

    No no no no no. One SD card, multiple wav files as easy as that. I can even write a PASM object that fits into a cog that mounts the SD and plays mulitple wav files. btw, I didn't know you were wanting to play multiple files but that isn't really a problem. Four lots of double sector buffers for 4 wave files will require 4kB of RAM. That way while one sector is being played, another can be read in and then that one gets played and vice-versa.

    It is possible to have just one sector read buffer to fill smaller play buffers but the double buffers are better.

  • Clock LoopClock Loop Posts: 2,056
    edited 2021-04-10 04:47

    Lol, I also mean SIMULTANEOUS wave playback (7 waves playing at once at any given time in relation to eachother)

    So a true 7 channel wave simulataneaous player.
    I have tried mixing the outputs of two different wave files playing back on two different pins and it works, so that should work for the 8-bit player.
    I will need to run multiple instances, but perhaps I can objectify that code and use it as an object to save code. (not much)

    I can't believe how small the 8-bit playback code is.

  • Peter JakackiPeter Jakacki Posts: 10,191
    edited 2021-04-10 05:10

    It is trivial to take 8 samples, sum them together and then divide by 8 by shift 3 bits right. SPI Flash is another option because you only need the one chip, they are cheap even for 16MB or more, and they are fast. Once again, 4 lines, so 4 I/O for Flash or SD. A bit-bash SPI read can easily run at 4MHz or more, or 10MHz using the counter.

    EDIT: @"Clock Loop" I didn't realize that i was responding to your needs in the previous post because the OPs needs are different from yours. Perhaps you should start a new thread.

  • Yea I only posted here because I found a problem with the 8-bit player and file names with byte sized variable.

    You can post about the sound playback in my engine controller thread if you want.
    If you have ideas on how to get 7 waves to play back at once with sd card im all ears there..

    My latest talk there has some code posted about the sound.
    https://forums.parallax.com/discussion/comment/1521795/#Comment_1521795

  • @"Clock Loop" - that's ok then. I will cobble together an object that works by sending it a filename. It then responds by playing that file which depends upon the metadata. So you can copy a bunch of wave files onto a card with higher quality settings for instance. If you want multiple files then precede that with a command that will stack the filenames ready to play by sending a PLAY command instead of a filename. It will be super-simple and small. I will make it a weekend project.

  • Clock LoopClock Loop Posts: 2,056
    edited 2021-04-10 10:50

    Perhaps having all the sounds in a single wave file and have the sd driver only retrieve specific gaps of the wave data?, kinda like I do in this whistle extender eeprom player.

    Could the sd driver pick specific bit gaps, like that (it looks like the bit shifter has 24 bits for each access, but it does the loop darn fast?

    I don't know, i barely understand all this, and that 8bit wave code eeprom player as simple as it is, i will still need to look into exactly how it all works.

    This file is a way to make your sound extended or really short if you have parts of the wave that you can skip or gap, etc.

    https://forums.parallax.com/discussion/download/135159/8bitWhistleSustain.zip

    I post it here again, because if the OP wanted to use eeprom waves, like I did, and still get sounds that are much longer than the original wave by having waves with a beginning, middle, and end that can be jumped to.

  • Peter JakackiPeter Jakacki Posts: 10,191
    edited 2021-04-10 12:03

    I just use something like Audacity to process the sound file that I want, normalize the volume etc and save as 16-bit mono 44.1kHz wave files. With that you can even once-off process the files on the Prop itself to generate an interleaved file if that actually helps or just simply have multiple sector buffers which is easy enough too.

    I picked up a stack of 32GB microSD cards today from Officeworks for $6.95. By contrast 1MB of EEPROM will cost you more for 32,000 times less memory. Or put it another way, 32GB of EEPROM would cost more than $222,000.

    The socket needn't cost much either as I use open microSD sockets that only cost 5 cents from LCSC or the fully enclosed ones for 10 cents.

    As a bonus with the SD driver I might even include EEPROM operation too, just for the fun of it, although it will be very limited compared to the SD version.

Sign In or Register to comment.