WAV Player, ASM, some questions
vedderb
Posts: 5
Hi
I got my propeller chip a few days ago, and in order to learn how to use SPIN and PASM i have written a simple wav player. It can play 16-bit stereo, 16-bit mono, 8-bit stereo and 8-bit mono, tested with 44.1 khz with all profiles. (it will most likely work with most usual sample rates)
I got a good first impression with this chip and i like the SPIN syntax (i have written a lot in C for AVR and java for android and swing). I have been using bst (Brad's spin tool) on linux, and i really like it. It would however be nice if parallax could support linux as well.
I am not really experienced with assembly for any platform, but i have read everything i could find about it for the propeller. So, here are some questions regarding the code i have written:
How do i pass byte vectors from SPIN to ASM?
This is what i do now
Another question:
When i play wav files there is a small amount of noise (white noise i think) present when the music is quite quiet. When i change the volume variable in the attached program to something really low like 1000, the noise is almost not present at all (i think it is the same snr in relation to the low music volume). Is this quantization noise? The mode i used for the counter is the same as sigma-delta modulation, right?
I have connected my headphones directly to the pins with capacitor in series to block DC, but nothing else. (see schematic, pin 20 and 21)
Could someone try the code i have written on his or her propeller demo board (or any other board with audio output) and see if there is noise present? Just change the pins accordingly in the spin file and put a few wav files in the root directory of an SD-card (other files are ignore, so no need to format the card) and connect it.
Last question:
The propeller demo board (used as template for the board i made) has no pull-up resistor for the reset pin. Is this not needed, or did they forget it? How many ohms is the internal pull-up (if there is one)?
Schematic
http://dl.dropbox.com/u/1026013/Propeller/Propeller_test.jpg
Code
http://dl.dropbox.com/u/1026013/Propeller/WAW-Player.zip
Thanks
I got my propeller chip a few days ago, and in order to learn how to use SPIN and PASM i have written a simple wav player. It can play 16-bit stereo, 16-bit mono, 8-bit stereo and 8-bit mono, tested with 44.1 khz with all profiles. (it will most likely work with most usual sample rates)
I got a good first impression with this chip and i like the SPIN syntax (i have written a lot in C for AVR and java for android and swing). I have been using bst (Brad's spin tool) on linux, and i really like it. It would however be nice if parallax could support linux as well.
I am not really experienced with assembly for any platform, but i have read everything i could find about it for the propeller. So, here are some questions regarding the code i have written:
How do i pass byte vectors from SPIN to ASM?
This is what i do now
VAR ' Pass these to the asm code long buffer1[_buffer_len / 4] long buffer2[_buffer_len / 4] long clocks_per_sample long bits_per_sample long channels long buffer1_filled long buffer2_filled long l_vol long r_vol ................. cognew(@stream, @buffer1) ................ org 0 stream or dira, diraval ' Setup output mov ctra, ctraval ' Setup counter1 mov ctrb, ctrbval ' Setup counter2 ' Read variables mov index, par mov buffer1_addr, index add index, buffer_len mov buffer2_addr, index add index, buffer_len mov clocks_per_sample_addr, index add index, #4 mov bits_per_sample_addr, index add index, #4 mov channels_addr, index add index, #4 mov buffer1_full_addr, index add index, #4 mov buffer2_full_addr, index add index, #4 mov l_vol_addr, index add index, #4 mov r_vol_addr, index ........and it works. However, if i change the beginning to
VAR ' Pass these to the asm code byte buffer1[_buffer_len] byte buffer2[_buffer_len] long clocks_per_sample long bits_per_sample long channels long buffer1_filled long buffer2_filled long l_vol long r_volit does not work any more. I have not checked the memory content yet because i was hoping someone else has done this before and knows how it works.
Another question:
When i play wav files there is a small amount of noise (white noise i think) present when the music is quite quiet. When i change the volume variable in the attached program to something really low like 1000, the noise is almost not present at all (i think it is the same snr in relation to the low music volume). Is this quantization noise? The mode i used for the counter is the same as sigma-delta modulation, right?
I have connected my headphones directly to the pins with capacitor in series to block DC, but nothing else. (see schematic, pin 20 and 21)
Could someone try the code i have written on his or her propeller demo board (or any other board with audio output) and see if there is noise present? Just change the pins accordingly in the spin file and put a few wav files in the root directory of an SD-card (other files are ignore, so no need to format the card) and connect it.
Last question:
The propeller demo board (used as template for the board i made) has no pull-up resistor for the reset pin. Is this not needed, or did they forget it? How many ohms is the internal pull-up (if there is one)?
Schematic
http://dl.dropbox.com/u/1026013/Propeller/Propeller_test.jpg
Code
http://dl.dropbox.com/u/1026013/Propeller/WAW-Player.zip
Thanks
Comments
BOEn is connected to Vss which means RESn is pulled up internally (see data sheet section 2.2 for details).
I have to get back to you on the noise question unless someone else chimes in for clarification,
Regarding the issue of audio noise, I know that Cog 0 should be specified such that it is reduced to a minimum.
JonnyMac has researched and solved this problem ...
Regards,
T o n y
Edited to add JonnyMac's link:
http://forums.parallax.com/showthread.php?t=123900
Thanks, that really helps. The reason i want to use byte is because the sd driver reads bytes from the sd card. However, spin does not seem to care if i give a long or a byte as parameter as it is the same thing. Java would never let me do this
@ TonyWaite
I have read the thread you pointed out, and it helps. It appears adding dither to the samples helps with noise shaping and gives better results.
The problem is... how do i start the wav sampling code in cog0? Would the following method work:
1. The main method starts another method, and then terminates.
2. The other method waits long enough for the main method to terminate and then starts the wav sequencer in a new cog. Will this new cog be cog0 as the main method already has terminated?
Should i upload my wav player to obex? I have not found other wav players capable of playing stereo and mono with 8 or 16-bit samples using the same code. Maybe it helps someone.
He has also posted an SD file system which has a SD wave player function.
NickL
I have tried to stream 58 khz 16-bit stereo, and with a large buffer i get no underruns at all! That means that the data throughput is 58000 * 4 = 232000 bytes per second, which is impressive for software spi with a filesystem on top.
Here is the current code:
http://dl.dropbox.com/u/1026013/Propeller/WAW-Player.zip
The sd-card is scanned for wav-files with compatible header and they are played based on the parameters in the header. Next/prev buttons, 0-65535 volume for each channel (ASM multiplication), 8bit/16-bit samples, stereo/mono, sample rate up to 58 khz, optional dithering, sample rate and volume can be changed at runtime... When the buffer underruns the asm code waites for the buffers to get filled and updates the channels, bitrate, etc, so when the next wav file on the sd-card has different parameter it will play fine anyway after the next-button is pressed (the buffer will underrun when changing song).
I have done this before on avr using interrupts, but it was much smoother on the propeller using real multitasking and i still have cogs left to generate video signal and do more stuff! This chip really is amazing!