Wave File Player V0.3 (as lib file)

Here is a modified version of the Wave File Player with the following feature:

Sound quality (with proper low-pass filter and amplifier) is almost the quality of FM Radio! :)

LowPassFilter

WavePlayer-v03 <--- Download all files...

Main code: WavePlayer-v0.3.bas
'===============================================================================
' Project:  Wave Audio file player.  (only plays wave riff PCM format)
' Created:  2009-12-10
' Edited:   2009-12-15
' By:       Glen Aidukas
' Description:
' This program will read & play Wave format, RIFF, Mono, 8bit, PCM audio file.
'===============================================================================

'=====[ Compiler Directives ]===================================================
$regfile=   "m644pdef.dat"
$crystal=   18432000          ' 18.432 MHz
$baud=      38400
$hwstack=   100
$swstack=   100
$framesize= 100
'-------------------------------------------------------------------------------

'=====[ Includes ]==============================================================
$include "Config_MMC.bas"              ' Load SD/MMC code and config
$include "Config_AVR-DOS.BAS"          ' Load FAT File system code
$include "WavePlayerib.bas"           ' PlayWaveFile code.
'-------------------------------------------------------------------------------

Dim Btemp1           as byte           ' used by filesystem
Dim Filename         as String * 12    ' Fat Filename

'=====[ Config misc stuff ]=====================================================
Config Serialout = Buffered , Size = 100        ' Serial Buffering
'-------------------------------------------------------------------------------

Enable Interrupts

print
print "Starting... V0.3"

waitms 100

'*******************************************************************************
'*****[ Start of main loop ]****************************************************
'*******************************************************************************

main:

   print "{027}[2J";             ' ansi clear screen...
   print "Starting..."

   print "Initializing file system...";
   waitms 100

   Btemp1 = Initfilesystem(1)       ' Init Partition 1
   if Btemp1 <> 0 Then
      Print "{010}{013}Error: " ; Btemp1 ; " at Init file system!"
      waitms 2000
      end
   endif
   print " ok."
   print

   do
      Filename= Dir("*.wav")
      do
         if FileName <> "" then
            GetWaveFileInfo FileName
               print
               print "Filename      : "; Filename
               Print "BitRate       : "; WP_SampleRate
               Print "Channels      : "; WP_NumChannels
               Print "BitsPerSecond : "; WP_BitsPerSample
               Print "SampleRate    : "; WP_SampleRate
               Print "BlockAlign    : "; WP_BlockAlign
               Print "ChunkSize     : "; WP_ChunkSize
               Print "FileSize      : "; WP_FileSize
            PlayWaveFile Filename
         endif
         Filename= Dir()
         waitms 500
      loop until Filename = ""

      print : print "Done with list. Starting over..."

      waitms 1000

   loop

End 'end program

'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Include File: WavePlayerLib.bas
'===============================================================================
' Project:  Wave Audio file player Lib.  (plays wave riff PCM formated files)
' Created:  2009-12-10
' Edited:   2009-12-15
' By:       Glen Aidukas
' Description:
' This program will read & play Wave format, RIFF, PCM audio file.
' NOTE: Timer1 & Timer2 are used and can not be used for other purposes.
'       Timer0 is available though.
'===============================================================================

Const WP_BufSize=             250      ' Size of each (A&B) buffers

Const WP_StatusNoErrors       = 0      ' No errors
Const WP_StatusBadFile        = 1      ' Not a wave file!
Const WP_StatusBadWavFormat   = 2      ' Bad format (Bits|SampleRate|Other)
Const WP_BufA                 = 0      ' Buffer A
Const WP_BufB                 = 1      ' Buffer B
Const WP_BufEmpty             = 0      ' Buffer status Empty
Const WP_BufFull              = 1      ' Buffer status Full

Dim WP_Btemp1        as Byte           ' Needed for Fat Drivers
Dim WP_Filename      as String * 14    ' Fat Filename
Dim WP_buf           as String *  4    ' misc. text

Dim WP_Buf_A(WP_BufSize)   as byte     ' buffer A for double buffering
Dim WP_Buf_B(WP_BufSize)   as byte     ' buffer B for double buffering
Dim WP_A_Buf_Status        as byte     ' buffer A full (1) or empty (0)
Dim WP_B_Buf_Status        as byte     ' buffer B full (1) or empty (0)
dim WP_ActiveBuffer        as byte     ' Actively playing buffer [0|1]
Dim WP_BufPos              as byte     ' Position in the active buffer
Dim WP_Status              as byte     ' return status

Dim WP_NumChannels         as byte     ' 1 or 2 channels
Dim WP_BitsPerSample       as word     ' 8 or 16 bits (only 8 at the moment)
Dim WP_SampleRate          as word     ' Sample rate (EX: 8k|11K|22k|other)
Dim WP_Byterate            as word     ' Read Bytes per second
Dim WP_Blockalign          as word     '
Dim WP_Chunksize           as long     '
DIM WP_FileSize            as long     ' Size of wave file in bytes

' misc. vars
dim WP_ch                  as byte     '
Dim WP_lx                  as long     '
Declare Sub GetWaveFileInfo(WP_FileName as string)
Declare Sub PlayWaveFile(WP_FileName as string)

''' skip passed the subs so that this file can be included at the beginning of
''' the calling main program file
Goto WP_SkipSubs

' =====[ GetWaveFileInfo ]======================================================
' This sub opens the filename passed to it and reads its WAVE headers.
' This is called by ether the user to get info like Channels and BitRate.
' It is also called by PlaYWaveFile for the needed header info.
Sub GetWaveFileInfo(WP_FileName as string)
   WP_SampleRate=0 : WP_NumChannels=0 : WP_BitsPerSample=0  ' clear old values
   WP_buf= ""

   open WP_Filename For Binary As #10

   ''' Read file format
   get #10, WP_buf , 9, 4         ' should be "WAVE"
   if WP_buf <> "WAVE" then
      close #10
      WP_Status= WP_StatusBadFile
      return
   endif

   get #10, WP_NumChannels, 23      ' Read number of channels (1|2, Mono|Stereo)
   get #10, WP_SampleRate, 25       ' Read Sample rate (EX: 8k|11K|22k|other)
   Get #10, WP_ByteRate, 29         ' Read Bytes per second
   get #10, WP_BitsPerSample, 35    ' Read bits per sample (8|16)
   Get #10, WP_BlockAlign, 33       ' BlockAlignment
   Get #10, WP_ChunkSize, 41        ' ChunkSize
   WP_FileSize= = Lof(#10)          ' Get file size

   close #10
End Sub

' =====[ PlayWaveFile ]=========================================================
' This sub will call GetWaveFileInfo and then play the wave file passed to it.
Sub PlayWaveFile(WP_FileName as string)

   ''' Read file format
   GetWaveFileInfo WP_FileName

   if WP_Status = WP_StatusBadFile then return   ' bad file!

   open WP_Filename For Binary As #10

   ''' Make sure its something we know how to play...
   if WP_NumChannels <> 1 and WP_NumChannels <> 2 then       ' Unknown format!
      WP_Status= WP_StatusBadWavFormat    ' Bad Format
      return
   endif
   if WP_BitsPerSample <> 8 then  ' Unknown format!
      WP_Status= WP_StatusBadWavFormat
      return
   endif

   '=====[ Config Timer2 for PWM audio output ]=================================
   ' This is done by using the PWM out puts on Timer2 (OC2A and OC2B)
   Config Timer2=Pwm, Compare A Pwm= Clear Down, Compare B Pwm= Clear Down, Prescale = 1
   stop timer2

   '=====[ Setup Timer1 for sample pushing isr ]================================
   ' Timer1 is used for setting the rate for pushing the samples to timer2 (PWM)
   Config Timer1= Timer, Prescale= 1, Compare A= Disconnect, Clear Timer= 1
   stop timer1
   On Compare1a WP_Play_isr   ' set up interrupt vector

   ''' setup compare1a reload value to match the SampleRate
   WP_lx= _XTAL / WP_SampleRate        ' CPU Speed / SampleRate of wave file
   Compare1a = WP_lx

   WP_lx= 45 : seek #10, WP_lx         ' seek to start of data at location 45

   ''' start loading buffers
   get #10, WP_Buf_A(1), , WP_BufSize  ' preload buffer A
   WP_A_Buf_Status= WP_BufFull         ' mark buffer A as full
   get #10, WP_Buf_B(1), , WP_bufSize  ' preload buffer B
   WP_B_Buf_Status= WP_BufFull         ' mark buffer B as full
   WP_ActiveBuffer= WP_BufA            ' start with buf 0
   WP_BufPos= 0                        ' Reset the buffer possition

   '======[ start playing file!!! ]============================
   Start Timer1 : Start Timer2
   Enable Compare1a

   ''' Watch the two buffers and fill them up when ether is emty
   while Eof(#10) = 0
      if WP_A_Buf_Status = WP_BufEmpty then
         get #10, WP_Buf_A(1), , WP_BufSize
         WP_A_Buf_Status= WP_BufFull
      elseif WP_B_Buf_Status = WP_BufEmpty then
         get #10, WP_Buf_B(1), , WP_bufSize
         WP_B_Buf_Status= WP_BufFull
      else
         ' Both buffers are full here so this would be a good place to
         ' do some other stuff if needed.  DON'T TAKE TOO LONG THOUGH! ;) 
         WP_ch= inkey()
         if WP_ch= " " then
            WP_lx= LOF(#10) ' skip to end ...
            seek #10, WP_lx
         endif
      endif
   wend
   Disable Compare1a
   Stop Timer1 : Stop Timer2
   close #10

End Sub

'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

'=====[ WP_Play ISR routine ]===================================================
' while Timer1 is active, cycle between buffer A and B and write its data
WP_Play_isr:
   if WP_ActiveBuffer = WP_BufA then               ' buffer A
      incr WP_BufPos                               ' incrment to next byte
      Pwm2a= WP_Buf_A(WP_BufPos)                   ' load sample into pwm2a
      if WP_NumChannels = 2 then incr WP_BufPos    ' if stereo then...
      Pwm2b= WP_Buf_A(WP_BufPos)                   ' load same sample if mono
      if WP_BufPos = WP_BufSize then               ' hit end of buffer A
         WP_BufPos= 0                              ' reset buffer pos to 0
         WP_ActiveBuffer= WP_BufB                  ' Set active buffer to B
         WP_A_Buf_Status= WP_BufEmpty              ' set buffer status empty
      endif
   else                                            ' buffer B
      incr WP_BufPos                               ' incrment to next byte
      Pwm2a= WP_Buf_B(WP_BufPos)                   ' load sample into pwm2a
      if WP_NumChannels = 2 then incr WP_BufPos    ' if stereo then...
      Pwm2b= WP_Buf_B(WP_BufPos)                   ' load same sample if mono
      if WP_BufPos = WP_BufSize then               ' hit end of buffer A
         WP_BufPos= 0                              ' reset buffer pos to 0
         WP_ActiveBuffer= WP_BufA                  ' Set active buffer to B
         WP_B_Buf_Status= WP_BufEmpty              ' set buffer status empty
      endif
   endif
Return
'-------------------------------------------------------------------------------

WP_SkipSubs:      ' this is just used to skip passed the beguning of this code

Leave a Reply

You must be logged in to post a comment.