Viznut's waves?

Basic and Machine Language

Moderator: Moderators

User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: Viznut's waves?

Post by chysn »

I'm not hearing any differences with the noise register. I honestly didn't expect to since, you know, random.
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Viznut's waves?

Post by Mike »

R'zo, chysn - that guy once again engaged in his namesake activity. Just ignore the troll.
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: Viznut's waves?

Post by chysn »

Mike wrote: Sat Jul 17, 2021 12:06 am R'zo, chysn - that guy once again engaged in his namesake activity. Just ignore the troll.
Well, it's no hardship for me to experiment. Although, Noizer, if you have previous posts or code examples that might be instructive, I'm all ears!

Today, my wife has taken my children golfing with their grandfather up north... Basically, I'm all alone this weekend. So today's project is going to be recording all sixteen (yes, I know that a couple are duplicates) Viznut waveforms into Serum to generate a wavetable for my Sequential Pro 3. If anything good comes of it, I'll post a recording.

I've got an oscilloscope coming tomorrow, and I'll write some code to try to do real-time movement.

Update: All 16 waveforms as single-cycle WAV files are now attached, along with a Serum wavetable file. In the unlikely event you happen to have a Pro 3, that wavetable is available here: http://www.wav2pro3.com/?3a6ca64709b5ae ... 4fcbfc36e5
Screen Shot 2021-07-17 at 6.08.54 PM.png
Attachments
ViznutWaves.zip
(85.72 KiB) Downloaded 52 times
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: Viznut's waves?

Post by chysn »

The self-modifying frequency-setting code is thoroughly unnecessary. There seems to be no difference in the result if I use a zero-page location (stx zp ...later... lda zp) as opposed to setting the immediate mode operand. Nothing cares about that one extra cycle in real life. And the initial frequency doesn't matter all that much anyway, once the waveform is set up.

This is important because I'm working on a cartridge-based project, in which such code would be possible but annoying to put into practice.
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: Viznut's waves?

Post by chysn »

mathom wrote: Fri Jul 16, 2021 12:01 am Wow! It sounds very cool. The tone is reminiscent of FM synthesis which I suppose stands to reason? Seems to work on both real hardware and vice.
Yeah, it has that clangy jagged quality for which phase distortion synthesis is famous. But the nominal VIC square wave is so mellow that this will be a welcome addition to the toolbox, although I don't have a great mental model for how it actually works.
User avatar
R'zo
Vic 20 Nerd
Posts: 514
Joined: Fri Jan 16, 2015 11:48 pm

Re: Viznut's waves?

Post by R'zo »

I have viznuts code rewritten, fully commented. I manually tracked values through the code and tbh I'm more confused now than I was before but it works. I wrote a basic routine to test it with all voices and waves. I have a small bug somewhere in the code but I will post it as soon as I get it buffed out.
R'zo
I do not believe in obsolete...
User avatar
R'zo
Vic 20 Nerd
Posts: 514
Joined: Fri Jan 16, 2015 11:48 pm

Re: Viznut's waves?

Post by R'zo »

Here's the demo. It works and sounds beautiful on hardware however it is very inconstant in Vice emulation.
vizwav.7z
(921 Bytes) Downloaded 76 times
The controller is written in basic. It runs with any expansion configuration. Load with {LOAD"VIZNUT",8}.

Code: Select all

100 rem "vizwav test demo"
110 rem "for the vic 20"
120 rem "with any memory"
130 rem "configuration"
140 rem "load with ,8"
150 rem "variables"
160 ps=831 : wv=828 : fq=829 :cn=830 : ki=203
170 dim sd(15)
180 for t=0 to 12
190 if t>8 then x=2
200 sd(t)=(t*2) : next t : sd(13)=36 : sd(14)=42 :sd(15)=44

210 rem "title screen"
220 print "{clear}{black}{down*5}        vizwav"
230 print "{down} pulse wave generater"
240 print "{down}     test program{return*4}"

250 rem "load vizwav "
260 for lp = 0 to 80
270 read a : poke wv+lp,a : next lp

280 rem "selection screen"
290 input "{down}select voice 1-3{return}";x
300 if x<1 or x>3 then print "incorrect input" : goto 290
310 poke cn , x+9

320 input "{down}select wave 0-15{return}";x
330 if x<0 or x>15 then print "incorrect input" : goto320
340 poke wv , sd(x)

350 input "{down}select tone 128-255{return}";x
360 if x<128 or x>255 then print "incorrect input" : goto350
370 poke fq , x

380 sys ps

390 print "{down}select tone 128-255"
400 input "0=return{return}";x
410 if x=0 then poke 36873 + peek(cn)-9 , 126 : goto 290
420 if x<128 or x>255 then print "incorrect input" : goto350
430 poke fq ,x : goto 380

440 rem "vizwav data"
450 DATA 0,0,0,120,172,62,3,169
460 DATA 126,153,0,144,160,255,234,234
470 DATA 234,234,234,136,208,248,169,7
480 DATA 141,14,144,173,60,3,174,61
490 DATA 3,172,62,3,142,130,3,140
500 DATA 113,3,140,124,3,190,128,3
510 DATA 133,254,9,127,143,12,144,132
520 DATA 255,160,7,169,127,7,254,143
530 DATA 12,144,136,208,246,169,128,234
540 DATA 164,255,153,0,144,96,253,254
550 DATA 251
The wave generator is written in assembly with CBM PRG Studio. Viznuts code starts at "pwp". Before that i included a routine for the maximum time necessary (currently more than, I'll get more finite later. I also setup registors and a routine for passing a/x/y values from basic.

I manually tracked the value through the code (my work is shown) I'm still having trouble wrapping my mind around how the rotation and bit mask are actually functioning but i understand the idea. I still don't understand why the code only uses 8 bits for the shift register when the voice channels use 16. Are we using 2 bits for every bit, ignoring bits or is there something I'm not seeing here?

Code: Select all

;      " VIZNUTS WAVEFORMS "
;       By               :      Ryan Liston
;       Original code by :      "Viznut"
;       Description      :      pulse wave form generator
;       Target           :      Commodore Vic-20 
;----------------------------------------------------
;
;controls

start_address           = $033c       ;start address
shift_registor          = %0010010    ;shift registor in a
initial_frequency       = $87         ;initial fquency 128-255 in x
channel                 = $0c         ;channel $0a-$0c in y
temp_1    = $fe         ;(temp storage for the a registor(shift registor))
temp_2    = $ff         ;(temp storage for the y registor (channel))
          
;-------------------------------------------------------------------------------          

* = start_address

;------------------------------------------------------------------------------
;This section sets up a,x,y. In Vinnuts code this 
;occurs before the routine is called.  

a_register byte $00     ; a_register=shift registor $00-$ff
          ;$33c=%0010010
x_register byte $00     ; x_register=initial frequency $80-$ff
          ;$33d=$87
y_register byte $00     ; y_registor=channel $0a-$0c
          ;$33e=$0c

pre_set sei             ;turn interupts off for precision timing
        ;i=1  

        ldy     y_register      ;3/4    loads channel
        ;y=$0c
        
        lda     #$7e             ;seta a to $7e
        ;a=$7e
        
        sta     $9000,y         ;stores a to $900c
        ;$900c=$7e
          
delay   ldy   #$ff      ;loads y with $ff
        ;y=255  

loop    nop             ;adds extra delay time
        nop             ;adds extra delay time
        nop             ;adds extra delay time
        nop             ;adds extra delay time
        nop             ;adds extra delay time
        dey             ;decrements timer
        ;y=y-1  
        
        bne     loop    ;loop until y=0
        ;if not y=0 then loop
        ;else continue  
        
        lda   #7        ;loads a with 7
        ;a=7  
        
        sta     $900e   ;sets volume
        ;$900e=7
        
        lda     a_register      ;3/4    loads shift register
        ;a=%0010010 ($12)

        
        ldx     x_register      ;3/4    loads initial frequency
        ;x=$87
        
        ldy     y_register      ;3/4    loads channel
        ;y=$0c

;-------------------------------------------------------------------------------

;This is the actual start of Viznuts code

pwp     stx     init_freq       ;3/4    alters the value on the 
        ;init_freq=$87          ;       initial frequency in
                                ;       line  xxxx
        sty     ch_0            ;3/4    alters memory at ch_0
        ;ch0=$0c
        
        sty     ch_1            ;3/4    an ch_1 to set voice channel
        ;ch1=$0c
        
        ldx     fq_mask-$a,y    ;3/4    loads frequency mask for voice      
        ;x=$fb(%11111011)
        
        sta     temp_1          ;2/3    stores the shift register in 
        ;temp_1=$fb(%11111011)  ;       temp_1 
        
        ora     #$7f            ;2/2    ors a with #$7f(%01111111)
        ;%11111011 or %01111111 = %11111111($ff)
        ;a=%11111111($ff)

        
        
         axs    $900c           ;3/4     ands a with bit mask stores at $900c
ch_0=*-2 ;%11111111 and %11111011 = %11111011  
        ;$900c=%11111011($fb)
        
        
        
        sty     temp_2          ;2/3    stores y(channel) at temp_2
        ;temp_2=$0c 
    
 
        ldy     #$07            ;2/2    loads y with 7
        ;y = 7
          
io      lda     #$7f            ;2/2    loads a with $7f
        ;a=$7f  
        
        aso     temp_1          ;2/5    a=(temp_1<<1)or $7f 
        
        ;pass 1: (y=7)  (%11111011<<1) = %11110110
                ;%11110110 or %01111111 = %11111111($ff)
                ;a = %11111111($ff)
        
        ;pass 2; (y=6)  (%11110110<<1) = %11101100
                ;%11101100 or %01111111 = %11111111($ff)
                ;a = %11111111($ff)
        
        ;pass 3; (y=5)  (%11101100<<1) = %11011000
                ;%11011000 or %01111111 = %11111111($ff)
                ;a = %11111111($ff)
         
        ;pass 4; (y=4)  (%11011000<<1) = %10110000
                ;%10110000 or %01111111 = %11111111($ff)
                ;a = %11111111($ff)
        
        ;pass 5; (y=3)  (%10110000<<1) = %01100000
                ;%01100000 or %01111111 = %01111111($ff)
                ;a = %01111111($7f)
        
        ;pass 6; (y=2)  (%01100000<<1) = %11000000
                ;%11000000 or %01111111 = %11111111($ff)
                ;a = %01111111($ff)
        
        ;pass 7; (y=1)  (%11000000<<1) = %10000000
                ;%10000000 or %01111111 = %11111111($ff)
                ;a = %11111111($ff)
        
        axs     $900c           ;3/4    ands a with bit mask stores at $900c
        
ch_1=*-2

        ;pass 1: (y=7)  %11111111 and %11111011 = %11111011     
                ;$900c=%11111011($fb)        

        ;pass 2: (y=6)  %11111111 and %11111011 = %11111011     
                ;$900c=%11111011($fb)        
        
        ;pass 3: (y=5)  %11111111 and %11111011 = %11111011     
                ;$900c=%11111011($fb)        
        
        ;pass 4: (y=4)  %11111111 and %11111011 = %11111011     
                ;$900c=%11111011($fb)        

        ;pass 5: (y=3)  %01111111 and %11111h11 = %01111011     
                ;$900c=%01111011($fb)        

        ;pass 6: (y=2)  %11111111 and %11111011 = %11111011     
                ;$900c=%11111011($fb)        

        ;pass 7: (y=1)  %11111111 and %11111011 = %11111011     
                ;$900c=%11111011($fb)        
        
        dey                     ;1/2    y=y-1

        ;pass 1:(y=7)   y=6

        ;pass 2:(y=6)   y=5
        
        ;pass 3:(y=5)   y=4
        
        ;pass 4:(y=4)   y=3

        ;pass 5:(y=3)   y=2
        
        ;pass 6:(y=2)   y=1
        
        ;pass 7:(y=1)   y=0
        
        bne     io              ;2/3    if not y=0 then branch to i0
                                        ;       else continue
        ;pass 1;(y=6)   branch to io            

        ;pass 2;(y=5)   branch to io
        
        ;pass 3;(y=4)   branch to io
        
        ;pass 4;(y=3)   branch to io
                
        ;pass 5;(y=2)   branch to io
       
        ;pass 6;(y=1)   branch to io
        
        ;pass 7;(y=0)   continue
        
        lda     #128            ;2/2    loads a with the initial frequency
        
        ;a=$87        

init_freq = *-1         
         
        nop                     ;1/2    burns 2 cycles
        ; no opperation
       
        ldy     temp_2          ;2/3    loads y with channel index stored
        ;y=$0c                          at temp_2

no_set  sta $9000,y             ;3/5    stores initial freaquency to $9000+y
        ;$900c=$87
        
         rts             ; exit routine
          
fq_mask = *
v_0a    byte    $fd     ;low voice bit mask %11111101
v_0b    byte    $fe     ;mid voice bit mask %11111110
v_0c    byte    $fb     ;hi voice bit mask %11111011
Now that I have this working I'm going to play around with it a little more and then I can add this to the tracker that I've been working on (I hoping to be able to include midi out tracks as well but that will be another thread) and create a really nice synth program as well (also hoping to be able to include midi out as well as in).

Thank you everyone for your help.

@chysn - I'm curious to see what you have planned.
R'zo
I do not believe in obsolete...
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: Viznut's waves?

Post by chysn »

R'zo wrote: Sun Jul 18, 2021 7:43 pm I still don't understand why the code only uses 8 bits for the shift register when the voice channels use 16. Are we using 2 bits for every bit, ignoring bits or is there something I'm not seeing here?
The answer to this lies in this rule:

Code: Select all

  - If the voice is ON: the lowest bit becomes the complement of the previous top bit.
When you flip bit 0 on every rotation like this, you essentially double the size of your shift register's period. This is always one of the "tips and tricks" for the Music Thing Modular Turing Machine; one of its parameters is the probability that bit 0 of the 16-bit register will flip after each triggered rotation. Setting the probability to 100% results in a repeating 32-note pattern. Likewise, when you always flip bit 0 of an 8-bit pattern, you wind up with a 16-bit pattern, with one half being the complement of the other half.
@chysn - I'm curious to see what you have planned.
I've been playing with cartridge-based contemporary VIC-20 music programs like Synthesound and VIC Music Composer. These were horrible by even 1981 standards, hard to use and buggy and unfun. So I'm hoping to contribute to that literature with Eris Composer. The reference to Eris is more in line with Discordianism than with the original Greek tradition, with Eris being the goddess of chaos (not necessarily the goddess of strife, as the Greeks envisioned her). One shouldn't confuse chaos strictly with disorder or strife; viewed through a certain lens, our brains find order in chaos. In music, especially, we identify rhythms easily when simple sets of rules go to work.

It'll be a sort of anti-tracker. :D The interface will owe a lot to Ableton, with some joystick control thrown in.
VIC-20 Projects: wAx Assembler, TRBo: Turtle RescueBot, Helix Colony, Sub Med, Trolley Problem, Dungeon of Dance, ZEPTOPOLIS, MIDI KERNAL, The Archivist, Ed for Prophet-5

WIP: MIDIcast BASIC extension

he/him/his
Post Reply