Page 1 of 1

Bit Crushing

Posted: Mon Aug 06, 2012 1:55 pm
by Sweetalk
Hi all! I'm working on a bit crusher and came out with a simple idea about the implementation:

Code: Select all

rdax   adcl,1
rdax   adcr,1
and   %01110000_00000000_00000000  ;Mask to 8-bit resolution
wrax  dacl,1
wrax  dacr,0
With the AND mask I want to lower the resolution of the input. The program does the trick, but there's a LOT of noise, the signal gets amplified really hard. I tried to lower less the resolution but as soon as I lower one bit, the noise starts. Any toughs?

Posted: Mon Aug 06, 2012 2:26 pm
by frank
Well, what you are showing is 3-bit not 8-bit. That may be the issue.

Posted: Mon Aug 06, 2012 2:30 pm
by Sweetalk
frank wrote:Well, what you are showing is 3-bit not 8-bit. That may be the issue.
My bad on typing it here. Even if I make a 23bit the noise comes out.

Posted: Mon Aug 06, 2012 2:39 pm
by frank
Try this:

Code: Select all

crush equ 0xfc0000 ;define the bit mask - 6 bits here
clr
rdax adcl,0.5
rdax adcr,0.5
skp neg,invit; working with 2's comp numbers, if negative skip down
and crush
skp gez,outter
invit:
sof -1.0,0 ; for negative samples, invert them,
and crush ; mask the data
sof -1.0,0 ; invert it back
outter:
wrax dacl,1.0
wrax dacr,1.0
And I think the issue with your code was that you were putting a 0 in the MSB position which flip negative values to positive.

Posted: Tue Aug 07, 2012 7:34 am
by Sweetalk
frank wrote:Try this:

Code: Select all

crush equ 0xfc0000 ;define the bit mask - 6 bits here
clr
rdax adcl,0.5
rdax adcr,0.5
skp neg,invit; working with 2's comp numbers, if negative skip down
and crush
skp gez,outter
invit:
sof -1.0,0 ; for negative samples, invert them,
and crush ; mask the data
sof -1.0,0 ; invert it back
outter:
wrax dacl,1.0
wrax dacr,1.0
And I think the issue with your code was that you were putting a 0 in the MSB position which flip negative values to positive.
Thank you!!, the problem was that the negative part of the signal gets positive with the mask. Now I modified the code and invert the signal first if it's negative, mask and then invert it back.

Also put a pot skip routine to get several bitrates.

Posted: Tue Aug 07, 2012 9:05 am
by Sweetalk
Here's the code!

Code: Select all

;BIT CRUSHER
;Mono Input, Mono output, Wet only
;POT2: BIT RATE, 8-steps: 24 bits, 16 bits, 14 bits, 12 bits, 10 bits, 8 bits, 6 bits, 4 bits
equ	bit	reg0

rdax	adcl,	0.5
rdax	adcr,	0.5
skp	neg,	1
wrax	bit,	0
sof	-1,	0
wrax	bit,	0

;Prepare skip routine with POT2. 8 steps.
rdax	pot2,	1
and   %01110000_00000000_00000000   	
skp	zro,	BIT24
sof	1,	-1/8
skp	zro,	BIT16
sof	1,	-1/8
skp	zro,	BIT14
sof	1,	-1/8
skp	zro,	BIT12
sof	1,	-1/8
skp	zro,	BIT10
sof	1,	-1/8
skp	zro,	BIT8
sof	1,	-1/8
skp	zro,	BIT6
sof	1,	-1/8
clr
skp	zro,	BIT4

BIT4:					;4 Bits
rdax	bit,	1
and   %11110000_00000000_00000000
wrax	bit,	0
skp	zro,	OUTPUT

BIT6:					;6 Bits
rdax	bit,	1
and   %11111000_00000000_00000000
wrax	bit,	0
skp	zro,	OUTPUT

BIT8:					;8 Bits
rdax	bit,	1
and   %11111100_00000000_00000000
wrax	bit,	0
skp	zro,	OUTPUT

BIT10:					;10 Bits
rdax	bit,	1
and   %11111110_00000000_00000000
wrax	bit,	0
skp	zro,	OUTPUT

BIT12:					;12 Bits
rdax	bit,	1
and   %11111111_00000000_00000000
wrax	bit,	0
skp	zro,	OUTPUT

BIT14:					;14 Bits
rdax	bit,	1
and   %11111111_10000000_00000000
wrax	bit,	0
skp	zro,	OUTPUT

BIT16:					;16 Bits
rdax	bit,	1
and   %11111111_11000000_00000000
wrax	bit,	0
skp	zro,	OUTPUT

BIT24:					;24 Bits
clr
skp	zro,	OUTPUT


OUTPUT:
rdax	bit,	0.5
skp	gez,	1
sof	-1,	0
wrax	dacl,	1
wrax	dacr,	0
Enjoy!!

Posted: Tue Aug 07, 2012 10:18 am
by frank
I don't think the code is doing what you intended it to do, if we look at the start (comments added by me):

Code: Select all

rdax   adcl,   0.5   ; read in right in
rdax   adcr,   0.5    ; add left in
skp   neg,   1   ; if negative skip next instruction
wrax   bit,   0   ; save acc to bit and make it 0
sof   -1,   0   ; skipped here if negative and invert the signal BUT if the signal was positive we are here with a 0 in acc
wrax   bit,   0 ; write positive value (if was negative) into bit or write 0 over the above positive value
Basically, if the value was positive you are writing 0 to bit. There is also a problem at the end:

Code: Select all

OUTPUT:
rdax   bit,   0.5   ; read bit 
skp   gez,   1   ; bit is always zero or positive due to above code
sof   -1,   0   ; never do this since bit is never negative
wrax   dacl,   1
wrax   dacr,   0 
What you want to do is save the original value somewhere then refer to it to check sign, not bit since it was made positive.

Posted: Tue Aug 07, 2012 10:43 am
by Sweetalk
You're right!, I'll check it later and re-post it. Thanks!

Re: Bit Crushing

Posted: Mon Apr 08, 2019 7:11 am
by NeoJoven86
I wanted to follow Frank's suggestions for modifying the code and have not been successful. Any help would be appreciated.

Code: Select all

;BITCRUSHER
;Mono Input, Mono output, Wet only
;POT2: Bit Depth, 8-steps; 24 bits, 16 bits, 14 bits, 12 bits, 10 bits, 8 bits, 6 bits, 4 bits
;register equates ;
equ bit reg0
equ bitsgn reg1

;Bitcrusher
clr
rdax adcl, 0.5 ; read in left
rdax adcr, 0.5 ; read in right
skp gez, 4 ; if ACC >= 0, then skip 4 instructions (sign is positive)
wrax bitsgn, 1 ; write ACC to bitsign (only if negative)
sof -1.0, 0 ; invert the number in the ACC (only if was negative)
wrax bit, 0 write ACC to bit, clear ACC  (only if was negative)
skp zro, 2 ; if ACC = 0, then skip 2 instructions (only if was negative)
wrax bitsgn, 1 ; write ACC to bitsign (sign is positive)
wrax bit, 0 ; write ACC to bit  (sign is positive)

;Prepare skip routine with POT2. 8 steps.
rdax pot2, 1.0
and %01110000_00000000_00000000
skp zro, BIT24
sof 1, -1/8
skp zro, BIT16
sof 1, -1/8
skp zro, BIT14
sof 1, -1/8
skp zro, BIT12
sof 1, -1/8
skp zro, BIT10
sof 1, -1/8
skp zro, BIT8
sof 1, -1/8
skp zro, BIT6
sof 1, -1/8
clr
skp zro, BIT4

BIT4: ;4 Bits
rdax bit, 1
and 0xf00000 ; %11110000_00000000_00000000
wrax bit, 0
skp zro, OUTPUT

BIT6: ;6 Bits
rdax bit, 1
and 0xfc0000 ; %11111100_00000000_00000000
wrax bit, 0
skp zro, OUTPUT

BIT8: ;8 Bits
rdax bit, 1
and 0xff0000 ; %11111111_00000000_00000000
wrax bit, 0
skp zro, OUTPUT

BIT10: ;10 Bits
rdax bit, 1
and 0xffc000 ; %11111111_11000000_00000000
wrax bit, 0
skp zro, OUTPUT

BIT12: ;12 Bits
rdax bit, 1
and 0xfff000 ; %11111111_11110000_00000000
wrax bit, 0
skp zro, OUTPUT

BIT14: ;14 Bits
rdax bit, 1
and 0xfffc00 ; %11111111_11111100_00000000
wrax bit, 0
skp zro, OUTPUT

BIT16: ;16 Bits
rdax bit, 1
and 0xffff00 ; %11111111_11111111_00000000
wrax bit, 0
skp zro, OUTPUT

BIT24: ;24 Bits
clr
skp zro, OUTPUT

OUTPUT: 
rdax bitsgn, 1.0 read in bitsign to ACC, multiply by 1.0
skp gez, 3 ; if ACC >= 0, then skip 3 instructions
rdax bit, 1.0 ; read in bit to ACC, multiply by 1.0 (only if negative)
sof -1.0, 0 ; invert back the number in the ACC (only if negative)
skp neg, 1 ; if ACC < 0, then skip 1 instruction (only if negative)
rdax bit, 1 ; read in bit to ACC, multiply by 1.0
wrax dacl, 1.0 ; write outputs
wrax dacr, 0; zero ACC


Re: Bit Crushing

Posted: Mon Apr 15, 2019 5:24 pm
by frank
You need to tell me what the problem seems to be. Noise? No output?

Edit: One thing I see is in the output you do:
rdax bitsgn, 1.0
skp gez, 3
rdax bit, 1.0
sof -1.0, 0
skp neg, 1
rdax bit, 1 <<<<< ACC still has bitsgn in it so you are adding bit to bitsgn basically doubling the value if positive