Prop sound quality question
I decided to write my own wave playing program on the prop, to learn how to use sound with it. After 12 straight hours, I got it up and running. Problem is, the sound is muddy, like a very low bitrate mp3. But before I put time into fixing it, I need to know if the prop is capable of cd quality sound, or is that the best I can do?
Comments
This will be a non-issue for the Propeller 2 as it has built-in DACs.
Here is my player: http://forums.parallax.com/showthread.php/140767-A-new-topic-for-vga-%28not-only%29-sid-player
Compile with BST with unused method removal or it doesn't fit in 32k.
You can find a sound driver in it, which output noise free sound using ~300 KHz/8 bit sampling with noise shaping filter.
And one more thing: Propeller Demo Board has bad low pass filters (~1.6 kHz @3dB) - I had to modify this on my demo board. This filter makes the sound dull. No high freqs.
arg1 := $18000000 | left arg2 := $18000000 | right
...which clearly shows the counters are being setup in DUTY cycle mode (single-ended). This is what I do in my player code, too. That said, when playing in low-frequency, 16-bit WAV file (especially pure tones), unexpected noise will show up without using Chip's stereo_duty cog. The best solution, which I used once, is a high-speed SPI DAC -- but they're expensive.
To compile Propplay with std prop tools, it may be sufficient to remove a "demo" method from the VGA driver.
This is ncowav version for using with a propplay. Get a full version of this from its topic on the propeller forum }} _clkmode = xtal1+pll16x _clkfreq = 80_000_000 _SD_DO = 0 _SD_CLK = 1 _SD_DI = 2 _SD_CS = 3 _SD_WP = -1 ' -1 ifnot installed. _SD_CD = -1 ' -1 ifnot installed. VAR ' long bufnum long cog long buf[512] long bufnum pub getbuf return @buf pub getbufnum return @bufnum PUB start(left, right, mode, addr) smode:=mode longfill(@buf,0,512) if mode==1 bufptr:=@buf overval:=7 delay:=259 if mode==0 bufptr:=addr overval:=9 delay:=288 stop leftcounter := ((left & $1F) + constant(100000 << 23)) rightcounter := ((right & $1F) + constant(100000 << 23)) outputmask := |<left | |<right 'coginit (7,@init,@bufnum) cog:=1+cognew(@init, @bufnum) return cog PUB stop if cog>0 cogstop(cog-1) cog := 0 DAT org 0 'initialization init mov ctra,leftcounter ' nco mode mov ctrb,rightcounter mov frqa,#1 ' frq=1 for pwm mode mov frqb,#1 mov dira,outputmask ' enable output on selected pins mov bufptr2,par mov time,cnt add time,delay loop cmp smode,#0 wz if_z jmp #p3 mov ptr,bufptr ' compute pointer to sample add ptr,bufcnt rdword lsample,ptr ' get left shl lsample,#16 add ptr, #2 rdword rsample,ptr ' get right sar lsample,#16 shl rsample,#16 ' extend sign to 32 bits sar rsample,#16 add bufcnt,#4 and bufcnt,bufmask p4 mov over,overval wrlong bufcnt,bufptr2 ' write actual sample number for main program jmp #p2 p3 mov ptr,bufptr rdlong lsample,ptr sar lsample,#16 mov rsample, lsample shl rsample,#1 add lsample, rsample shl rsample,#1 add lsample, rsample sar lsample,#3 mov rsample,lsample jmp #p4 p2 add i1l,lsample ' noise shape left add i2l,i1l mov topl,i2l sar topl,#8 mov fbl,topl shl fbl,#8 sub i1l,fbl sub i2l,fbl add i1r,rsample ' noise shape right add i2r,i1r mov topr,i2r sar topr,#8 mov fbr,topr shl fbr,#8 sub i1r,fbr sub i2r,fbr maxs topr, maxval ' clip max to avoid clicks mins topr, minval add topr, #$80 ' convert to 8 bit unsigned and topr, #$FF maxs topl, maxval mins topl, minval add topl, #$80 and topl, #$FF waitcnt time, delay neg phsa, topr ' Output. neg phsb, topl ' Output. djnz over,#p2 jmp #loop leftcounter long 0 rightcounter long 0 outputmask long 0 delay long 259 bufmask long 00_0000_0000_0000_0000_0111_1111_1111 overval long 7 maxval long 127 minval long -127 bufptr long 0 bufptr2 long 0 bufcnt long 0 smode long 0 over res 1 lsample res 1 rsample res 1 time res 1 topl res 1 topr res 1 fbl res 1 fbr res 1 i1r res 1 i1l res 1 i2l res 1 i2r res 1 ptr res 1 fit 496 {{ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 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. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }}
Are you doing a PWM pulse train?
If so... then (80 MHz / 44.1 KHz) = 1,814 so the bit resolution is about 11 bits then right? I suppose that is enough for good audio. 8-bits is too low.
He also said to use pin 0 of COG 0 because the electrical path was the shortest.
Not with sigma-delta conversion and noise-shaping, no. You can get 24 bit audio happily out using 11 bit PWM, and PWM is orders of magnitude less sensitive
to jitter than NCO mode. Without understanding sigma-delta and noise-shaping it all looks like magic.
A-new-topic-for-vga-not-only -sid-player?
12-bit-audio-using-video-generator-first-working-concept
Return-to-duty-dac-oversampling-noise-shaped-player
A-simple-dithered-wav-player-now-dithers-every-1-microsecond
Post #11 in that last one also has Mark_T's very interesting class D sigma-delta driver. That drives the class D by the phase difference between two counters.
In "real life" only audible noise from a demoboard when using ncowav is its amplifier noise.
Also, I changed demoboard RC filter, shifting 3dB freq from 1.6 to 21 kHz.
We have a 16-bit sample, for example $1280. When output as 8 bit, it will be constant $12. When output after noise shaping filter it will be something like 12-13-12-13-12-13
Average is 12.5 (=>1280) and you have unhearable noise (square wave) @ 150 kHz.
Near all quantization noise goes to the ultrasonic range, and you have noise free sound, The noise is still there, but you can't hear it.
This is a noise shaper, all magic is here:
add i1l,lsample ' noise shape left add i2l,i1l mov topl,i2l sar topl,#8 mov fbl,topl shl fbl,#8 sub i1l,fbl sub i2l,fbl
We have two integrators, i1l and i2l (for the left channel). Top 8 bits from second integrator goes to the output, and then are subtracted from both integrators. So, what is really integrated, is the quantization noise, and when there is more than 8 bit integrated, it is added to the output.