ASM WAV Player How can I modify to juke box
bradleyenoy
Posts: 8
I have added the keyboard at the start of the code and I can select my file from the SD card
but how can I replay a wave file after it plays?
It is like the code was written only to play a wave file once..
Please help as losing my hair..
or change this code so I can retrigger from an input pin a wave file to play.
Bradley E Noy
but how can I replay a wave file after it plays?
It is like the code was written only to play a wave file once..
Please help as losing my hair..
or change this code so I can retrigger from an input pin a wave file to play.
Bradley E Noy
Comments
If so then you have to stop reading the file at the end, what might be called closing the file.
Then you have to reopen the file to reload it again at the beginning.
If it's songs, there isn't enough RAM to hold a whole song so the file has to reload directly into the player.
I can't replay any thing else or find out how to end or close or track the buffer
ASM WAV Player Ver. 1b (Plays only stereo, 16-bit PCM WAV files from SD card)
' 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
' Rev.B: 21Dec07 Fixed pin assignment bug.
CON _clkmode = xtal1 + pll16x
_xinfreq = 5_000_000 '80 MHz
buffSize = 100
VAR long parameter1 'to pass @buff1 to ASM
long parameter2 'to pass @buff2 to ASM
long parameter3 'to pass sample rate to ASM
long parameter4 'to pass #samples to ASM
long buff1[noparse][[/noparse]buffSize]
long buff2[noparse][[/noparse]buffSize]
byte Header[noparse][[/noparse]44]
long mem
byte mem1
byte soundname
byte keymem
long m
OBJ
SD : "FSRW"
text : "vga_text" 'For NTSC TV Video: Comment out this line...
'text : "tv_text" 'and un-comment this line (need to change pin parameter for text.start(pin) command below too).
kb : "keyboard"
PUB Main|n,i,j, SampleRate,Samples
'Play a WAV File
'Start up the status display...
text.start(16) 'Start the VGA/TV text driver (uses another cog)
'The parameter (16) is the base pin used by demo and proto boards for VGA output
'Change (16) to (12) when using "tv_text" driver with demo board as it uses pin#12 for video
text.str(STRING("Starting Up",13))
'open the WAV file (NOTE: Only plays stereo, 16-bit PCM WAV Files !!!!!!!!!!!!!)
'access SD card
soundname:=sd.mount(0)
if (i<>0)
repeat
text.str(STRING("SD Card Mounted",13))
'start the keyboard
kb.start(26, 27)
text.str(STRING("Enter sound number",13))
'i:=sd.popen(string("test2.wav"), "r") ' <
Change .wav filename here !!!!!!!!!!!!!!
if (soundname<>0)
text.str(STRING(" no file found",13))
repeat
'ignoring much file header (so you better have the format right!) stereo, 16-bit PCM WAV Files !!!!!!!!!!!!!!!!
'See here for header format: http://ccrma.stanford.edu/CCRMA/Courses/422/projects/WaveFormat/
soundname:=sd.pread(@Header, 44) 'read data words to input stereo buffer
'Get sample rate from header
SampleRate:=Header[noparse][[/noparse]27]<<24+Header[noparse][[/noparse]26]<<16+Header[noparse][[/noparse]25]<<8+Header[noparse][[/noparse]24]
text.dec(SampleRate)
text.out(13)
'get # samples from header
Samples:=Header[noparse][[/noparse]43]<<24+Header[noparse][[/noparse]42]<<16+Header[noparse][[/noparse]41]<<8+Header[noparse][[/noparse]40]
Samples:=Samples>>2
text.dec(Samples)
text.out(13)
'Start ASM player in a new cog
text.str(STRING("Running ASM Player",13))
parameter1:=@buff1[noparse][[/noparse]0]
parameter2:=@buff2[noparse][[/noparse]0]
parameter3:=CLKFREQ/SampleRate '#clocks between samples'1814'for 44100ksps, 5000 'for 16ksps
parameter4:=Samples
COGNEW(@ASMWAV,@parameter1)
'Keep filling buffers until end of file
' note: using alternating buffers to keep data always at the ready...
n:=buffSize-1
j:=buffsize*4 'number of bytes to read
text.str(STRING("n = "))
text.dec(n)
text.out(13)
text.str(STRING("j = "))
text.dec(j)
text.out(13)
m := 0
repeat
'while (j==buffsize*4) 'repeat until end of file
' text.out(@nSamples)
if (buff1[noparse][[/noparse]n]==0)
j:=sd.pread(@buff1, buffSize*4) 'read data words to input stereo buffer
' text.str(STRING("buff1",13))
if (buff2[noparse][[/noparse]n]==0)
j:=sd.pread(@buff2, buffSize*4) 'read data words to input stereo buffer
DAT
ORG 0
ASMWAV
'load input parameters from hub to cog given address in par
'now stop
' COGID thisCog
' COGSTOP thisCog
'JMP #ASMWAV
movd ar,#pData1
mov x,par
mov y,#4 'input 4 parameters
ar rdlong 0,x
add ar,dlsb
add x,#4
djnz y,#ar
setup
'setup output pins
MOV DMaskR,#1
ROL DMaskR,OPinR
OR DIRA, DMaskR
MOV DMaskL,#1
ROL DMaskL,OPinL
OR DIRA, DMaskL
'setup counters
OR CountModeR,OPinR
MOV CTRA,CountModeR
OR CountModeL,OPinL
MOV CTRB,CountModeL
'Wait for SPIN to fill table
MOV WaitCount, CNT
ADD WaitCount,BigWait
WAITCNT WaitCount,#0
'setup loop table
MOV LoopCount,SizeBuff
'ROR LoopCount,#1 'for stereo
MOV pData,pData1
MOV nTable,#1
'setup loop counter
MOV WaitCount, CNT
ADD WaitCount,dRate
MainLoop
SUB nSamples,#1
CMP nSamples,#0 wz
IF_Z JMP #Done
waitcnt WaitCount,dRate
RDLONG Right,pData
ADD Right,twos 'Going to cheat a bit with the LSBs here... Probably shoud fix this!
MOV FRQA,Right
ROL Right,#16 '16 LSBs are left channel...
MOV FRQB,Right
WRLONG Zero,pData
ADD pData,#4
'loop
DJNZ LoopCount,#MainLoop
MOV LoopCount,SizeBuff
'switch table ?
CMP nTable,#1 wz
IF_Z JMP #SwitchToTable2
SwitchToTable1
MOV nTable,#1
MOV pData,pData1
JMP #MainLoop
SwitchToTable2
MOV nTable,#2
MOV pData,pData2
JMP #MainLoop
Done
'now stop
COGID thisCog
COGSTOP thisCog
'JMP #ASMWAV
'Working variables
thisCog long 0
x long 0
y long 0
dlsb long 1 << 9
BigWait long 100000
twos long $8000_8000
'Loop parameters
nTable long 0
WaitCount long 0
pData long 0
LoopCount long 0
SizeBuff long buffsize
'Left long 0
Right long 0
Zero long 0
'setup parameters
DMaskR long 0 'right output mask
OPinR long 10 'right channel output pin # ' <
Change Right pin# here !!!!!!!!!!!!!!
DMaskL long 0 'left output mask
OPinL long 11 'left channel output pin # ' <
Change Left pin# here !!!!!!!!!!!!!!
CountModeR long %00011000_00000000_00000000_00000000
CountModeL long %00011000_00000000_00000000_00000000
'input parameters
pData1 long 0 'Address of first data table
pData2 long 0 'Address of second data table
dRate long 5000 'clocks between samples
nSamples long 2000
The code was only made to play a single file, but it should be easy to modify to play more than one...
FYI: I've recently posted a revised version to the original forum thread... You might want to try that one, but it too is only coded for a single file.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
My Prop Info&Apps: ·http://www.rayslogic.com/propeller/propeller.htm
but maybe you can add a REBOOT command if this program is in eeprom,
unless you probably have it on SD card with femtobasic or propDOS.
Also, keyboard looks initialized too late, and missing parts to type in filename string or use any keys.
It looks like it doesn't work now and I can't fix it but it shouldn't be too hard with an original working version,
except I don't have an SD slot on my protoboard now to test with.
I think if things are initialized without stopping after playing you run out of cogs, but maybe REBOOT can deal with that mess.
I want to make the player fast like play small files and need the speed
I don't like the reboot
Just a few snippets from some code I did a couple of months ago for a WAV player accessed from a numeric keypad. It features instant play and repeat modes as well as jump to track immediate modes etc. I elected to have the code that was feeding the 16-bit signed PCM samples to the sound object as a separate task and simply ask that task to do something different. So the response from the keypad is as I said instant.
The code in PLAY sits in a repeat loop and for my project I get it to increment a track number to go to the next track but all you need to do is not increment it if you just want it to do a track loop. PLAYPAUSE is called from the keypad such as when you hit ENTER.
Make of this what you will, I know it's not everything but should help you along. I'm turning this into a commercial product soon as it has been going really well and I may release the code in a more general form later on. The display is one of my own serial 4 line LCD modules with big digits for the track number. I also read the headers and extract from the chunks the sample rate, bits, size, title etc.
*Peter*
Play task section
P.S. Here's a photo of the prototype
Post Edited (Peter Jakacki) : 9/11/2009 2:45:36 PM GMT
David
Post Edited (Delus) : 9/11/2009 7:10:56 PM GMT
AWG : "Audio Out Gen"
ABG : "Audio Buffer to gen"
David
David
Pretty sure all the necessary files are there this time.
Looks like you put some work into that especially in processing the headers. You could probably do with some string matching though. This code snippet suited my particular implementation and is by no means exhaustive but does illustrate the use of strings.
Maybe we can get a more general method worked out to cover the different formats.
*Peter*
What different formats do you have in mind? My understanding is pretty limited to pcm wav files at this moment. Have been doing quite a bit of work with them in C# and this post was just what I needed to update the wav player i made back in the spring. the wav_decoder was an attempt to generalize but in the end it just ended up stripping the important bits out of the file and leaving you with the data remaining (yes string comparisons would clean that up a bit). It would be nice to have some way of passing the sd object to the wav_decoder as in real oo languages to allow for more seemless integration with other objects.
David
Added: slightly more readable wav_decoder object
Post Edited (Delus) : 9/15/2009 1:41:32 AM GMT
Here's a typical header produced by Audacity. You can see the various tags in ASCII plus the modes and sample-rates etc as per WAV file format specification. I'm using an adapted PCM audio driver for mono 16-bit signed PCM.
I think MACs put their tag info at the end of the file so we need a generalized method for handling most of the common stuff. I imagine that having a method which could be called with a descriptor and return with the data or pointer will be helpful, a bit like wav.readtag(string("INAM")) or sample_rate := wav.sample-rate etc. When I have time to play with it again I will try to clean these methods up a bit instead of the usual Q&Ds
*Peter*
Do you have a description of the wav specifications? The specs I have been using may be incomplete as I have no INFO, INAM sections in my spec. I've been lucky enough so far not to run into any wave files with anything between the WAVE chunk and the data chunk which doesn't have its id immediately followed by its length which is then ignored. But I think I’ve had enough for one night.
David
en.wikipedia.org/wiki/WAV_file
www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
ccrma.stanford.edu/courses/422/projects/WaveFormat/
*Peter*