Bit Crushing

Algorithm development and general DSP issues

Moderator: frank

Post Reply
Sweetalk
Posts: 141
Joined: Thu Oct 15, 2009 5:13 am

Bit Crushing

Post 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?
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

Well, what you are showing is 3-bit not 8-bit. That may be the issue.
Frank Thomson
Experimental Noize
Sweetalk
Posts: 141
Joined: Thu Oct 15, 2009 5:13 am

Post 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.
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post 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.
Frank Thomson
Experimental Noize
Sweetalk
Posts: 141
Joined: Thu Oct 15, 2009 5:13 am

Post 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.
Sweetalk
Posts: 141
Joined: Thu Oct 15, 2009 5:13 am

Post 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!!
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post 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.
Frank Thomson
Experimental Noize
Sweetalk
Posts: 141
Joined: Thu Oct 15, 2009 5:13 am

Post by Sweetalk »

You're right!, I'll check it later and re-post it. Thanks!
NeoJoven86
Posts: 1
Joined: Tue Sep 11, 2018 12:32 pm

Re: Bit Crushing

Post 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

frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Re: Bit Crushing

Post 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
Frank Thomson
Experimental Noize
Post Reply