Shop OBEX P1 Docs P2 Docs Learn Events
12-bit audio using video generator - first working concept - Page 2 — Parallax Forums

12-bit audio using video generator - first working concept

2»

Comments

  • LawsonLawson Posts: 870
    edited 2012-07-06 21:34
    Ahle2 wrote: »
    I was talking about "normal" amplifiers, class A, B, A/B, when I said "The amplifier might take a hit"!
    Of course, I still want to do some thinkering with class D someday.

    Well, since you're producing nice PWM with this code, a class D amplifier should be easy to build out of any H-bridge that's fast enough. Past that, a critically damped LCR filter on the output would help keep the speaker cool. Paralleling 3-4 CMOS logic gates, or buffers should also work at low powers.

    Lawson
  • T ChapT Chap Posts: 4,223
    edited 2012-07-07 07:19
    Ahle2 wrote: »
    For audio use you will need to have a very very very steep filter at around 20 kHz to get rid of the 50 kHz base frequency!
    In that respect duty DAC is better, but this technique will give higher resolution.

    I am curious to know if the noise you are referring to could be cancelled by outputting another out of audio range tone on other pins, flip the output with an opamp and sum.
  • Mark_TMark_T Posts: 1,981
    edited 2012-07-07 07:44
    Lawson wrote: »
    Well, since you're producing nice PWM with this code, a class D amplifier should be easy to build out of any H-bridge that's fast enough. Past that, a critically damped LCR filter on the output would help keep the speaker cool. Paralleling 3-4 CMOS logic gates, or buffers should also work at low powers.

    Lawson

    The R in the LCR should be the speaker. A simple approach is to make the impedance of L and C and R to be about the same at the cut-off frequency (usually around 30kHz). The L and C need to be low loss and have good power handling, otherwise you'll have substantial heating losses in them and non-linearities - basically the same design principles apply as for a SMPS.
  • pik33pik33 Posts: 2,394
    edited 2012-07-10 02:23
    There is something I cannot understand in this code (the base is version 0.03).

    This works:
                            mov     vscl,t2
                            waitvid ffffffff,ffffffff
    
                            mov     vscl,vscl_val
                            waitvid ff00ff00,t4
    
                            mov     vscl,t1
                            waitvid zero,zero
    
                            mov vscl,vscl_val2
                            waitvid ffffffff,ffffffff
    

    This is good, too:
                            mov     vscl,t1
                            waitvid zero,zero
    
                            mov     vscl,vscl_val
                            waitvid ff00ff00,t4
    
                            mov     vscl,t2
                            waitvid  ffffffff,ffffffff
    
                            mov vscl,vscl_val2
                            waitvid ffffffff,ffffffff
    


    And this is good, too:
                            mov     vscl,t1
                             waitvid zero,zero
     
                             mov     vscl,vscl_val
                             waitvid ff00ff00,t4
     
                             mov     vscl,t2
                             waitvid  ffffffff,ffffffff
     
                             mov vscl,vscl_val2
                             waitvid zero, zero
    

    And this is no matter if I shl t4,t3 or shr t4,t3

    All these variations gives the same, good sound quality, only signal shape on oscilloscope looks different.

    But this:

                             mov     vscl,vscl_val
                             waitvid ff00ff00,t4
    
                             mov     vscl,t1
                             waitvid zero,zero
     
                             mov     vscl,t2
                             waitvid  ffffffff,ffffffff
     
                             mov vscl,vscl_val2
                             waitvid ffffffff,ffffffff
    

    and this:
                              mov     vscl,t1
                              waitvid zero,zero
      
                              mov     vscl,t2
                              waitvid  ffffffff,ffffffff
      
                              mov     vscl,vscl_val
                              waitvid ff00ff00,t4
    
                              mov vscl,vscl_val2
                              waitvid ffffffff,ffffffff
    

    and this:
                              mov     vscl,vscl_val
                              waitvid ff00ff00,t4
    
                              mov     vscl,t1
                              waitvid zero,zero
      
                              mov     vscl,t2
                              waitvid  ffffffff,ffffffff
      
                              mov vscl,vscl_val2
                              waitvid zero, zero
    
    gives audible noise and audible distortions.

    And this is no matter if I shl t4,t3 or shr t4,t3, too

    Why?
  • Mark_TMark_T Posts: 1,981
    edited 2012-07-10 04:03
    I haven't examined the code in depth but I think whats wrong with the bad code examples is they generate runt pulses rather than a clean rectangular wave - the 4 different VSCL setups are for generating all zeros, all ones, the rising edge and the falling edge?. These have to be in the right order to avoid pulses that can fall to zero length (and thus dissappear) - this would certainly generate audible noise at the transistion. In fact I think the first "good" example might be doing this too?
  • pik33pik33 Posts: 2,394
    edited 2012-07-10 04:39
    The pulse is no problem. Replacing shl with shr generates short pulse instead of transition and it doesn't matter. I wanted to replace shl with shr,

    What I saw on the osciloscope is thicker vertical lines when looking at the result of "wrong" code. It seems to be jitter, pulse length varies. And I still don't know why. This problem blocks stereo version of this driver.

    And even more strange thing - this is good:
                            mov     vscl,vscl_val
                            waitvid ff00ff00,ff00ff00
    
                            mov     vscl,t1
                            waitvid zero,zero
    
                            mov     vscl,vscl_val
                            waitvid ff00ff00,t4
    
                            mov     vscl,t2
                            waitvid ffffffff,ffffffff
    
                            mov vscl,vscl_val2
                            waitvid zero,zero
    
    

    and this is bad (noises):
                            mov     vscl,vscl_val
                            waitvid ff00ff00,t4
    
                            mov     vscl,t1
                            waitvid zero,zero
    
                            mov     vscl,vscl_val
                            waitvid ff00ff00,ff00ff00
    
                            mov     vscl,t2
                            waitvid ffffffff,ffffffff
    
                            mov vscl,vscl_val2
                            waitvid zero,zero
    
  • pik33pik33 Posts: 2,394
    edited 2012-07-11 00:13
    I changed this topic to unsolved, I don't understand this at all.
    
                            mov     vscl,t1
                             waitvid zero,zero
     
    ' I cannot move this from here in any way!!!! 
    
                            mov     vscl,vscl_val
                             waitvid ff00ff00,t4
    
                             mov     vscl,t2
                             waitvid ffffffff,ffffffff
    
    
    I even made a combination of waitvids like this - vscl_test = $00001200, this can be something, no matters, and

    this is good:
                            mov vscl, vscl_test1
                            waitvid zero, zero
    
                            mov     vscl,vscl_val
                            waitvid ff00ff00,ff00ff00
    
                            mov     vscl,vscl_test1
                            waitvid ffffffff,ffffffff
    
                            mov     vscl,t1
                            waitvid zero,zero
    
                            mov     vscl,vscl_val
                            waitvid ff00ff00,t4
    
                            mov     vscl,t2
                            waitvid ffffffff,ffffffff
    
    


    this is bad
    
                            mov vscl, vscl_test1
                            waitvid zero, zero
    
                            mov     vscl,vscl_val
                            waitvid ff00ff00,t4
    
                            mov     vscl,vscl_test1
                            waitvid ffffffff,ffffffff
    
                            mov     vscl,t1
                            waitvid zero,zero
    
                            mov     vscl,vscl_val
                            waitvid ff00ff00,ff00ff00
    
                            mov     vscl,t2
                            waitvid ffffffff,ffffffff
    
    


    ???????????????????????
  • jmgjmg Posts: 15,179
    edited 2012-07-11 02:58
    If you can make the effect come and go at will, you must be halfway there...
    When you say 'bad', can you check the time/spectrum/magnitude of the 'bad', as that may contain a clue ?

    If you suspect edge effects, those can be cleaned up with an external Flip Flop, but the challenge will be what to clock it from ?
  • pik33pik33 Posts: 2,394
    edited 2012-07-11 04:06
    "Bad" is noise and distortion, audible when silent parts of music, or in 200 Hz test signal, as if it is something like 9 bits instead of 12.
  • pik33pik33 Posts: 2,394
    edited 2012-07-11 06:05
    The problem described above is still not solved, but ... all can be done simpler and better

    Two waitvids is sufficient, instead of 3

    This is the main loop now:
    loop                    mov     ptr,bufptr
                            add     ptr,bufcnt         'pointer to next sample
                            rdword  lsample,ptr        'get left sample
                            add     lsample,offset     'convert to unsigned
                            add     ptr, #2
                            rdword  rsample,ptr
                            and     lsample,ffff
                            add     rsample,offset
                            and     rsample,ffff
                            add     rsample,lsample
                            shr     rsample, #1
                            add     bufcnt,#4
                            and     bufcnt,bufmask
                            wrlong  bufcnt,bufptr2
    
                            shr rsample, #4
                            add rsample, #1
                            mov t1,rsample
                            mov t2,a1000
                            sub t2,t1
    
                            add     t2,vscl_val0
                            add     t1,vscl_val0
    
                            mov     vscl,t1
                            waitvid zero,zero
                            mov     vscl,t2
                            waitvid ffffffff,ffffffff
    
                            mov vscl,vscl_val2
                            waitvid zero,zero
    
    
                            jmp     #loop
    

    Edit: this will fail when sample value is very low or very big. There has to be 4 clocks place for mov vscl; sample has to be clipped for about 11..12 (from ~12 to ~4084)
  • kuronekokuroneko Posts: 3,623
    edited 2012-07-11 22:21
    pik33 wrote: »
    Edit: this will fail when sample value is very low or very big. There has to be 4 clocks place for mov vscl; sample has to be clipped for about 11..12 (from ~12 to ~4084)
    You can side-step this issue by using the pixel scale effect and the fact that the last pixel is repeated until all frame clocks are issued.
    DAT
    {               waitvid $FF00, -2       waitvid $FF00, #0       waitvid $FF00, #0
                                            waitvid $FF00, -1       waitvid $FF00, -2
    
                    low      vscl            low     vscl            low     vscl
    
                      1     $01000           256    $01100/$01F00   3841    $01F00/$01100
                      2     $02000           257    $01101/$01EFF   3842    $01F00/$02100
                      3     $03000           258    $01102/$01EFE   3843    $01F00/$03100
                     ..       ..             ..       ..             ..       ..
                    255     $FF000          3840    $01F00/$01100   4095    $01F00/$FF100
    }           
    
  • pik33pik33 Posts: 2,394
    edited 2012-07-11 22:56
    This is yet another way to use video generator registers :)

    At the next step I want to go down with bit resolution, to get oversampling/noise shaping, so this clipping issue will not be any problem but this vscl trick may still be useful.
  • pik33pik33 Posts: 2,394
    edited 2012-07-12 04:14
    Noise shaper a'la Mark_T experimental run success The one I run is 16-to-12 bit reduction noise shape filter without oversampling. And even without oversampling, this improved sound quality.:)
                            add     i1,rsample
                            add     i2,i1
                            mov     top,i2
                            sar     top,#4
                            mov     fb,top
                            shl     fb,#4
                            sub     i1,fb
                            sub     i2,fb
    
                            maxs    top, MAXVAL
                            mins    top, MINVAL
    

    It seems the propeller can output real hifi quality audio without external dac
  • Mark_TMark_T Posts: 1,981
    edited 2012-07-12 05:05
    Excellent! But I knew it works ;) - if anyone has access to decent audio test equipment it would be good to measure the THD, intermodulation distortion and S/N ratio for this... Or failing that younger ears than mine(!)

    Its possible to use CORDIC routines to generate 24 bit digital audio in real time as the signal source.
  • pik33pik33 Posts: 2,394
    edited 2012-07-13 06:00
    Now, there is 2x oversampling 11 bit wave player. Uses 2 cogs - one per channel. Noise free stereo wave player at last :) The Propeller put to extreme, pll @224 MHz...

    Can't go any further with oversampling without reducing bit resolution to 9 or using another cog as a noise shaper because of data processing overhead.

    Edit: ... and the amplifier is still overheating... :( 88 kHz is still too low frequency and it can amplify this. A filter is needed. Or more oversampling.
Sign In or Register to comment.