View previous topic :: View next topic |
Author |
Message |
atmega64
Joined: 23 Feb 2005 Posts: 298 Location: ITALY
|
Posted: Fri May 06, 2016 2:35 pm Post subject: Waveplayer stereo |
|
|
Hi,
I used the example of Glen Aidukas (for the stereo file version) for building a stereo wave file player.
The problem is that on one channel, the audio is ok and on a channel, the audio is disturbed.
I did the test using the same amp once for one channel and then to another, then the circuit is ok.
Something is wrong with the code?
I have attached two audio file to better understand the problem.
It 'a good project would be a shame if I do not solve this problem, help
thank you.
Code: |
'===============================================================================
' Project: Wave Audio file player. (only plays wave riff PCM format)
' Play Wave format, RIFF, Mono max 44KHz/stereo max 22KHz, 8bit, PCM audio file
' Version for stereo wave files
' By: Glen Aidukas
'===============================================================================
'=====[ Compiler Directives ]===================================================
$regfile = "m1284Pdef.dat" '"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 "WavePlayerLib.bas" ' PlayWaveFile code.
'-------------------------------------------------------------------------------
Const Vsw = "2.1"
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)
Dim Btemp1 As Byte ' used by filesystem
Dim Filename As String * 12 ' Fat Filename
Dim Flag_error_sd As Byte
'=====[ Config misc stuff ]=====================================================
Config Serialout = Buffered , Size = 100 ' Serial Buffering
Config Serialin = Buffered , Size = 254
'-------------------------------------------------------------------------------
Enable Interrupts
Print
Print "SW V" ; Vsw
Print "Init. file system SD CARD... ";
Waitms 100
Flag_error_sd = 0
Btemp1 = Initfilesystem(1) ' Init Partition 1
If Btemp1 <> 0 Then
Print "Error: " ; Btemp1
Flag_error_sd = 1
Else
Print "OK"
End If
Filename = Dir( "*.wav")
On Compare1a Wp_play_isr ' set up interrupt vector
Print "Starting..."
Do
Do
If Filename <> "" Then
Getwavefileinfo Filename
Print
Print "Filename : " ; Filename
If Wp_status = Wp_statusbadfile Then
Print "Bad File!"
Goto Sound_error
End If
Open Filename For Binary As # 10
''' Make sure its something we know how to play...
If Wp_numchannels <> 1 And Wp_numchannels <> 2 Then
Wp_status = Wp_statusbadwavformat
Print "Unknown format or Bad Format!"
Goto Sound_error
End If
If Wp_bitspersample <> 8 Then
Wp_status = Wp_statusbadwavformat
Print "Unknown format!"
Goto Sound_error
End If
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
'=====[ 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
End If
End If
Wend
Disable Compare1a
Stop Timer1 : Stop Timer2
Close # 10
End If
Sound_error :
Filename = Dir() 'next wave
Waitms 500
Loop Until Filename = ""
Filename = Dir( "*.wav") 'torna al primo wave
Print : Print "End list"
Waitms 500
Loop
End 'end program
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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
End If
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
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'=====[ 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
End If
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_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_bufa ' Set active buffer to B
Wp_b_buf_status = Wp_bufempty ' set buffer status empty
End If
End If
Return |
(BASCOM-AVR version : 2.0.7.8 ) |
|
Back to top |
|
|
glena
Joined: 25 Jul 2007 Posts: 284 Location: PA near Philly
|
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Sat May 07, 2016 5:20 pm Post subject: |
|
|
Without having closer analyzed the code and only by watching the ISR's natural symmetry, I'd say the one or the other doesn't match.
Quote: | 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
' ...
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_a(wp_bufpos) ' load same sample if mono
' ...
End If
Return |
|
|
Back to top |
|
|
atmega64
Joined: 23 Feb 2005 Posts: 298 Location: ITALY
|
Posted: Mon May 09, 2016 8:40 am Post subject: |
|
|
Sorry if I answer late ...
Thanks Glena short enclose the original wave file ....
however the problem occurs with various wave files, and I am sure that the format is correct: Stereo 22kHz, 8bit, PCM audio files...
Thanks MWS, the anomaly in the code might be the problem ....
the correct code so that's what follows?
Code: |
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
' ...
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
' ...
End If
Return
|
|
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Mon May 09, 2016 7:42 pm Post subject: |
|
|
atmega64 wrote: | the correct code so that's what follows? |
Is this actually a question, or the answer?
If everything fails, you still can do coding by hearing |
|
Back to top |
|
|
atmega64
Joined: 23 Feb 2005 Posts: 298 Location: ITALY
|
Posted: Tue May 10, 2016 7:16 am Post subject: |
|
|
I tried the code and now everything is ok ... |
|
Back to top |
|
|
atmega64
Joined: 23 Feb 2005 Posts: 298 Location: ITALY
|
Posted: Tue May 10, 2016 8:14 am Post subject: |
|
|
one last question,
because when I use a 4gb sd card formatted FAT32 returns me the error 227: Error response at Read Byte Command ???
With an SD card from 2GB okay ... |
|
Back to top |
|
|
laborratte
Joined: 27 Jul 2005 Posts: 299 Location: Berlin
|
Posted: Tue May 10, 2016 11:23 am Post subject: |
|
|
With 4GB you have a SDHC Card, so use the "config_MMCSD_HC.inc" as card driver. For dertails look to the "AVR-DOS File System" help topic and the samples. |
|
Back to top |
|
|
atmega64
Joined: 23 Feb 2005 Posts: 298 Location: ITALY
|
Posted: Wed May 11, 2016 7:19 am Post subject: |
|
|
"config_MMCSD_HC.inc" as card driver works also with ATXMEGA ??? |
|
Back to top |
|
|
Duesentrieb72
Joined: 17 Feb 2006 Posts: 44
|
Posted: Wed May 11, 2016 7:45 am Post subject: |
|
|
"config_MMCSD_HC.inc" as card driver works also with ATXMEGA ???
Yes, it works with ATXmega also.
Here the part of its SPI configuration
' --------- Start of Section for HW-SPI ----------------------------------------
'FOR XMEGA DEVICES
#if _xmega = 1
'portc_pin6ctrl=&B00_011_000 ' MISO pin pull up
'Config Pinc.4 = Output ' define here Pin for CS of MMC/SD Card
'Mmc_cs Alias Portc.4
'Set Mmc_cs
' Define here SS Pin of HW-SPI of the CPU (f.e. Pinb.0 on M128)
'Spi_ss Alias Portc.4
'SPI Configuration for XMEGA
'The MMC-XMEGA.LIB expect SPIC
'If you want to use SPID, SPIE or SPIF you NEED TO CHANGE THE MMC-XMEGA.LIB
'It is documented in MMC-XMEGA.LIB where you need to change the Library
'Config Spic = Hard , Master = Yes , Mode = 0, Clockdiv = Clk2 , Data_order = Msb
Open "SPIC" For Binary As #14
Const _mmc_spi = Spic_ctrl
#else
' define Chip-Select Pin
' Config PinG.5 = Output ' define here Pin for CS of MMC/SD Card
' Mmc_cs Alias PortG.5
' Set Mmc_cs
' ' Define here SS Pin of HW-SPI of the CPU (f.e. Pinb.0 on M128)
' Config Pinb.0 = Output ' define here Pin of SPI SS
' Spi_ss Alias Portb.0
' Set Spi_ss ' Set SPI-SS to Output and High for Proper work of
' ' portb.3=1 'pull up on miso
' ' HW-SPI is configured to highest Speed
' Config Spi = Hard, Interrupt = Off, Data_Order = Msb, Master = Yes, Polarity = Low, Phase = 0, Clockrate = 4, Noss = 1
' SPSR = 1 ' Makes SPI run at 8Mhz instead of 4Mhz
' Spiinit
#endif
' --------- End of Section for HW-SPI ------------------------------------------ |
|
Back to top |
|
|
atmega64
Joined: 23 Feb 2005 Posts: 298 Location: ITALY
|
Posted: Wed May 11, 2016 8:24 am Post subject: |
|
|
thank you...
then works with both, either with atmega that with atmega .... |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|