void noise_gate_U8(unsigned char *data, int len, int rate, int gate_on,
                   int hold_time, int release_time, int attack_time) {
  int i, is_on = 0, hold = 0, hold_ticks, rel_ticks, att_ticks, dec = 0;
  float fact = 1.0, c_rel, c_att;
  if (gate_on == 0)
    return;
  hold_ticks = hold_time * rate / 1000;
  rel_ticks = release_time * rate / 1000;
  att_ticks = attack_time * rate / 1000;
  c_rel = 1.0 / rel_ticks;
  c_att = 1.0 / att_ticks;
  for (i = 0; i < len; i++) {
    if (data[i] > (128 - gate_on) && data[i] < (128 + gate_on)) {
      if (!is_on) {
        hold++;
        if (hold > hold_ticks)
          is_on = dec = 1;
      } else {
        if (dec == 1) {
          fact -= c_rel;
          if (fact < 0.0) {
            fact = 0;
            dec = 0;
            data[i] = 128;
          } else
            data[i] = 128 + (data[i] - 128) * fact;
        } else
          data[i] = 128;
      }
    } else {
      if (is_on) {
        fact += c_att;
        if (fact > 1.0) {
          fact = 1.0;
          is_on = 0;
        } else
          data[i] = 128 + (data[i] - 128) * fact;
      }
      hold = 0;
    }
  }
}


x86 assembly (clang, -O0):
<noise_gate_U8>:
push   %rbp
mov    %rsp,%rbp
mov    0x10(%rbp),%eax
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %edx,-0x10(%rbp)
mov    %ecx,-0x14(%rbp)
mov    %r8d,-0x18(%rbp)
mov    %r9d,-0x1c(%rbp)
movl   $0x0,-0x24(%rbp)
movl   $0x0,-0x28(%rbp)
movl   $0x0,-0x38(%rbp)
movss  0xec7(%rip),%xmm0
movss  %xmm0,-0x3c(%rbp)
cmpl   $0x0,-0x14(%rbp)
jne    114d <noise_gate_U8+0x4d>
jmp    1381 <noise_gate_U8+0x281>
mov    -0x18(%rbp),%eax
imul   -0x10(%rbp),%eax
mov    $0x3e8,%ecx
cltd
idiv   %ecx
mov    %eax,-0x2c(%rbp)
mov    -0x1c(%rbp),%eax
imul   -0x10(%rbp),%eax
mov    $0x3e8,%ecx
cltd
idiv   %ecx
mov    %eax,-0x30(%rbp)
mov    0x10(%rbp),%eax
imul   -0x10(%rbp),%eax
mov    $0x3e8,%ecx
cltd
idiv   %ecx
mov    %eax,-0x34(%rbp)
cvtsi2sdl -0x30(%rbp),%xmm1
movsd  0xe78(%rip),%xmm0
divsd  %xmm1,%xmm0
cvtsd2ss %xmm0,%xmm0
movss  %xmm0,-0x40(%rbp)
cvtsi2sdl -0x34(%rbp),%xmm1
movsd  0xe5e(%rip),%xmm0
divsd  %xmm1,%xmm0
cvtsd2ss %xmm0,%xmm0
movss  %xmm0,-0x44(%rbp)
movl   $0x0,-0x20(%rbp)
mov    -0x20(%rbp),%eax
cmp    -0xc(%rbp),%eax
jge    1381 <noise_gate_U8+0x281>
mov    -0x8(%rbp),%rax
movslq -0x20(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
mov    $0x80,%ecx
sub    -0x14(%rbp),%ecx
cmp    %ecx,%eax
jle    12dc <noise_gate_U8+0x1dc>
mov    -0x8(%rbp),%rax
movslq -0x20(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
mov    -0x14(%rbp),%ecx
add    $0x80,%ecx
cmp    %ecx,%eax
jge    12dc <noise_gate_U8+0x1dc>
cmpl   $0x0,-0x24(%rbp)
jne    1235 <noise_gate_U8+0x135>
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
mov    -0x28(%rbp),%eax
cmp    -0x2c(%rbp),%eax
jle    1230 <noise_gate_U8+0x130>
movl   $0x1,-0x38(%rbp)
movl   $0x1,-0x24(%rbp)
jmp    12d7 <noise_gate_U8+0x1d7>
cmpl   $0x1,-0x38(%rbp)
jne    12c6 <noise_gate_U8+0x1c6>
movss  -0x40(%rbp),%xmm1
movss  -0x3c(%rbp),%xmm0
subss  %xmm1,%xmm0
movss  %xmm0,-0x3c(%rbp)
movss  -0x3c(%rbp),%xmm0
cvtss2sd %xmm0,%xmm1
xorps  %xmm0,%xmm0
ucomisd %xmm1,%xmm0
jbe    1288 <noise_gate_U8+0x188>
xorps  %xmm0,%xmm0
movss  %xmm0,-0x3c(%rbp)
movl   $0x0,-0x38(%rbp)
mov    -0x8(%rbp),%rax
movslq -0x20(%rbp),%rcx
movb   $0x80,(%rax,%rcx,1)
jmp    12c1 <noise_gate_U8+0x1c1>
mov    -0x8(%rbp),%rax
movslq -0x20(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
add    $0xffffff80,%eax
cvtsi2ss %eax,%xmm0
movss  -0x3c(%rbp),%xmm1
mulss  %xmm1,%xmm0
movss  0xd58(%rip),%xmm1
addss  %xmm1,%xmm0
cvttss2si %xmm0,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
movslq -0x20(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
jmp    12d2 <noise_gate_U8+0x1d2>
mov    -0x8(%rbp),%rax
movslq -0x20(%rbp),%rcx
movb   $0x80,(%rax,%rcx,1)
jmp    12d7 <noise_gate_U8+0x1d7>
jmp    136e <noise_gate_U8+0x26e>
cmpl   $0x0,-0x24(%rbp)
je     1367 <noise_gate_U8+0x267>
movss  -0x44(%rbp),%xmm0
addss  -0x3c(%rbp),%xmm0
movss  %xmm0,-0x3c(%rbp)
movss  -0x3c(%rbp),%xmm0
cvtss2sd %xmm0,%xmm0
movsd  0xd02(%rip),%xmm1
ucomisd %xmm1,%xmm0
jbe    1329 <noise_gate_U8+0x229>
movss  0xce8(%rip),%xmm0
movss  %xmm0,-0x3c(%rbp)
movl   $0x0,-0x24(%rbp)
jmp    1362 <noise_gate_U8+0x262>
mov    -0x8(%rbp),%rax
movslq -0x20(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
add    $0xffffff80,%eax
cvtsi2ss %eax,%xmm0
movss  -0x3c(%rbp),%xmm1
mulss  %xmm1,%xmm0
movss  0xcb7(%rip),%xmm1
addss  %xmm1,%xmm0
cvttss2si %xmm0,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
movslq -0x20(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
jmp    1367 <noise_gate_U8+0x267>
movl   $0x0,-0x28(%rbp)
jmp    1373 <noise_gate_U8+0x273>
mov    -0x20(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x20(%rbp)
jmp    11be <noise_gate_U8+0xbe>
pop    %rbp
ret

x86 assembly (clang, -O2):
<noise_gate_U8>:
push   %rbp
push   %rbx
test   %ecx,%ecx
je     128a <noise_gate_U8+0x18a>
test   %esi,%esi
jle    128a <noise_gate_U8+0x18a>
imul   %edx,%r8d
movslq %r8d,%rax
imul   $0x10624dd3,%rax,%r8
mov    %r8,%rax
shr    $0x3f,%rax
sar    $0x26,%r8
imul   %edx,%r9d
movslq %r9d,%rbp
imul   $0x10624dd3,%rbp,%rbp
mov    %rbp,%rbx
shr    $0x3f,%rbx
sar    $0x26,%rbp
add    %ebx,%ebp
imul   0x18(%rsp),%edx
movslq %edx,%rdx
imul   $0x10624dd3,%rdx,%rdx
mov    %rdx,%rbx
shr    $0x3f,%rbx
sar    $0x26,%rdx
add    %ebx,%edx
cvtsi2sd %ebp,%xmm0
movsd  0xe92(%rip),%xmm1
movapd %xmm1,%xmm2
divsd  %xmm0,%xmm2
xorps  %xmm0,%xmm0
cvtsd2ss %xmm2,%xmm0
xorps  %xmm2,%xmm2
cvtsi2sd %edx,%xmm2
add    %eax,%r8d
divsd  %xmm2,%xmm1
cvtsd2ss %xmm1,%xmm1
mov    $0x80,%r11d
sub    %ecx,%r11d
sub    $0xffffff80,%ecx
mov    %esi,%r10d
movss  0xe62(%rip),%xmm2
xor    %eax,%eax
mov    $0x1,%r9d
xorps  %xmm3,%xmm3
movss  0xe53(%rip),%xmm4
xor    %ebx,%ebx
movaps %xmm2,%xmm5
xor    %edx,%edx
xor    %esi,%esi
jmp    11ed <noise_gate_U8+0xed>
xor    %ebx,%ebx
cmp    %r8d,%esi
lea    0x1(%rsi),%esi
setge  %bl
cmovge %r9d,%edx
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
add    $0x1,%rax
cmp    %rax,%r10
je     128a <noise_gate_U8+0x18a>
movzbl (%rdi,%rax,1),%ebp
cmp    %ebp,%r11d
jge    1220 <noise_gate_U8+0x120>
cmp    %ebp,%ecx
jle    1220 <noise_gate_U8+0x120>
test   %ebx,%ebx
je     11c4 <noise_gate_U8+0xc4>
cmp    $0x1,%edx
jne    123a <noise_gate_U8+0x13a>
subss  %xmm0,%xmm5
ucomiss %xmm5,%xmm3
jbe    1262 <noise_gate_U8+0x162>
movb   $0x80,(%rdi,%rax,1)
mov    $0x1,%ebx
xorps  %xmm5,%xmm5
xor    %edx,%edx
jmp    11e0 <noise_gate_U8+0xe0>
nopl   0x0(%rax)
xor    %esi,%esi
test   %ebx,%ebx
jne    122a <noise_gate_U8+0x12a>
xor    %ebx,%ebx
jmp    11e0 <noise_gate_U8+0xe0>
addss  %xmm1,%xmm5
ucomiss %xmm2,%xmm5
jbe    1247 <noise_gate_U8+0x147>
movaps %xmm2,%xmm5
xor    %ebx,%ebx
jmp    11e0 <noise_gate_U8+0xe0>
movb   $0x80,(%rdi,%rax,1)
mov    $0x1,%ebx
xor    %edx,%edx
jmp    11e0 <noise_gate_U8+0xe0>
add    $0xffffff80,%ebp
xorps  %xmm6,%xmm6
cvtsi2ss %ebp,%xmm6
mulss  %xmm5,%xmm6
addss  %xmm4,%xmm6
cvttss2si %xmm6,%ebx
mov    %bl,(%rdi,%rax,1)
jmp    1280 <noise_gate_U8+0x180>
add    $0xffffff80,%ebp
xorps  %xmm6,%xmm6
cvtsi2ss %ebp,%xmm6
mulss  %xmm5,%xmm6
addss  %xmm4,%xmm6
cvttss2si %xmm6,%edx
mov    %dl,(%rdi,%rax,1)
mov    $0x1,%edx
mov    $0x1,%ebx
jmp    11e0 <noise_gate_U8+0xe0>
pop    %rbx
pop    %rbp
ret

LLVM IR (-O0):
define void @noise_gate_U8(i8* %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6) {
%8 = alloca i8*
%9 = alloca i32
%10 = alloca i32
%11 = alloca i32
%12 = alloca i32
%13 = alloca i32
%14 = alloca i32
%15 = alloca i32
%16 = alloca i32
%17 = alloca i32
%18 = alloca i32
%19 = alloca i32
%20 = alloca i32
%21 = alloca i32
%22 = alloca float
%23 = alloca float
%24 = alloca float
store i8* %0, i8** %8
store i32 %1, i32* %9
store i32 %2, i32* %10
store i32 %3, i32* %11
store i32 %4, i32* %12
store i32 %5, i32* %13
store i32 %6, i32* %14
store i32 0, i32* %16
store i32 0, i32* %17
store i32 0, i32* %21
store float 1.000000e+00, float* %22
%25 = load i32, i32* %11
%26 = icmp eq i32 %25, 0
br i1 %26, label %27, label %28
27: ; preds = %7
br label %156
28: ; preds = %7
%29 = load i32, i32* %12
%30 = load i32, i32* %10
%31 = mul nsw i32 %29, %30
%32 = sdiv i32 %31, 1000
store i32 %32, i32* %18
%33 = load i32, i32* %13
%34 = load i32, i32* %10
%35 = mul nsw i32 %33, %34
%36 = sdiv i32 %35, 1000
store i32 %36, i32* %19
%37 = load i32, i32* %14
%38 = load i32, i32* %10
%39 = mul nsw i32 %37, %38
%40 = sdiv i32 %39, 1000
store i32 %40, i32* %20
%41 = load i32, i32* %19
%42 = sitofp i32 %41 to double
%43 = fdiv double 1.000000e+00, %42
%44 = fptrunc double %43 to float
store float %44, float* %23
%45 = load i32, i32* %20
%46 = sitofp i32 %45 to double
%47 = fdiv double 1.000000e+00, %46
%48 = fptrunc double %47 to float
store float %48, float* %24
store i32 0, i32* %15
br label %49
49: ; preds = %153, %28
%50 = load i32, i32* %15
%51 = load i32, i32* %9
%52 = icmp slt i32 %50, %51
br i1 %52, label %53, label %156
53: ; preds = %49
%54 = load i8*, i8** %8
%55 = load i32, i32* %15
%56 = sext i32 %55 to i64
%57 = getelementptr inbounds i8, i8* %54, i64 %56
%58 = load i8, i8* %57
%59 = zext i8 %58 to i32
%60 = load i32, i32* %11
%61 = sub nsw i32 128, %60
%62 = icmp sgt i32 %59, %61
br i1 %62, label %63, label %123
63: ; preds = %53
%64 = load i8*, i8** %8
%65 = load i32, i32* %15
%66 = sext i32 %65 to i64
%67 = getelementptr inbounds i8, i8* %64, i64 %66
%68 = load i8, i8* %67
%69 = zext i8 %68 to i32
%70 = load i32, i32* %11
%71 = add nsw i32 128, %70
%72 = icmp slt i32 %69, %71
br i1 %72, label %73, label %123
73: ; preds = %63
%74 = load i32, i32* %16
%75 = icmp ne i32 %74, 0
br i1 %75, label %84, label %76
76: ; preds = %73
%77 = load i32, i32* %17
%78 = add nsw i32 %77, 1
store i32 %78, i32* %17
%79 = load i32, i32* %17
%80 = load i32, i32* %18
%81 = icmp sgt i32 %79, %80
br i1 %81, label %82, label %83
82: ; preds = %76
store i32 1, i32* %21
store i32 1, i32* %16
br label %83
83: ; preds = %82, %76
br label %122
84: ; preds = %73
%85 = load i32, i32* %21
%86 = icmp eq i32 %85, 1
br i1 %86, label %87, label %116
87: ; preds = %84
%88 = load float, float* %23
%89 = load float, float* %22
%90 = fsub float %89, %88
store float %90, float* %22
%91 = load float, float* %22
%92 = fpext float %91 to double
%93 = fcmp olt double %92, 0.000000e+00
br i1 %93, label %94, label %99
94: ; preds = %87
store float 0.000000e+00, float* %22
store i32 0, i32* %21
%95 = load i8*, i8** %8
%96 = load i32, i32* %15
%97 = sext i32 %96 to i64
%98 = getelementptr inbounds i8, i8* %95, i64 %97
store i8 -128, i8* %98
br label %115
99: ; preds = %87
%100 = load i8*, i8** %8
%101 = load i32, i32* %15
%102 = sext i32 %101 to i64
%103 = getelementptr inbounds i8, i8* %100, i64 %102
%104 = load i8, i8* %103
%105 = zext i8 %104 to i32
%106 = sub nsw i32 %105, 128
%107 = sitofp i32 %106 to float
%108 = load float, float* %22
%109 = call float @llvm.fmuladd.f32(float %107, float %108, float 1.280000e+02)
%110 = fptoui float %109 to i8
%111 = load i8*, i8** %8
%112 = load i32, i32* %15
%113 = sext i32 %112 to i64
%114 = getelementptr inbounds i8, i8* %111, i64 %113
store i8 %110, i8* %114
br label %115
115: ; preds = %99, %94
br label %121
116: ; preds = %84
%117 = load i8*, i8** %8
%118 = load i32, i32* %15
%119 = sext i32 %118 to i64
%120 = getelementptr inbounds i8, i8* %117, i64 %119
store i8 -128, i8* %120
br label %121
121: ; preds = %116, %115
br label %122
122: ; preds = %121, %83
br label %152
123: ; preds = %63, %53
%124 = load i32, i32* %16
%125 = icmp ne i32 %124, 0
br i1 %125, label %126, label %151
126: ; preds = %123
%127 = load float, float* %24
%128 = load float, float* %22
%129 = fadd float %128, %127
store float %129, float* %22
%130 = load float, float* %22
%131 = fpext float %130 to double
%132 = fcmp ogt double %131, 1.000000e+00
br i1 %132, label %133, label %134
133: ; preds = %126
store float 1.000000e+00, float* %22
store i32 0, i32* %16
br label %150
134: ; preds = %126
%135 = load i8*, i8** %8
%136 = load i32, i32* %15
%137 = sext i32 %136 to i64
%138 = getelementptr inbounds i8, i8* %135, i64 %137
%139 = load i8, i8* %138
%140 = zext i8 %139 to i32
%141 = sub nsw i32 %140, 128
%142 = sitofp i32 %141 to float
%143 = load float, float* %22
%144 = call float @llvm.fmuladd.f32(float %142, float %143, float 1.280000e+02)
%145 = fptoui float %144 to i8
%146 = load i8*, i8** %8
%147 = load i32, i32* %15
%148 = sext i32 %147 to i64
%149 = getelementptr inbounds i8, i8* %146, i64 %148
store i8 %145, i8* %149
br label %150
150: ; preds = %134, %133
br label %151
151: ; preds = %150, %123
store i32 0, i32* %17
br label %152
152: ; preds = %151, %122
br label %153
153: ; preds = %152
%154 = load i32, i32* %15
%155 = add nsw i32 %154, 1
store i32 %155, i32* %15
br label %49
156: ; preds = %27, %49
ret void
}

LLVM IR (-O2):
define void @noise_gate_U8(i8* nocapture %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6) {
%8 = icmp eq i32 %3, 0
br i1 %8, label %75, label %9
9: ; preds = %7
%10 = mul nsw i32 %4, %2
%11 = sdiv i32 %10, 1000
%12 = mul nsw i32 %5, %2
%13 = sdiv i32 %12, 1000
%14 = mul nsw i32 %6, %2
%15 = sdiv i32 %14, 1000
%16 = sitofp i32 %13 to double
%17 = fdiv double 1.000000e+00, %16
%18 = fptrunc double %17 to float
%19 = sitofp i32 %15 to double
%20 = fdiv double 1.000000e+00, %19
%21 = fptrunc double %20 to float
%22 = icmp sgt i32 %1, 0
br i1 %22, label %23, label %75
23: ; preds = %9
%24 = sub nsw i32 128, %3
%25 = add nsw i32 %3, 128
%26 = zext i32 %1 to i64
br label %27
27: ; preds = %23, %68
%28 = phi i64 [ 0, %23 ], [ %73, %68 ]
%29 = phi i32 [ 0, %23 ], [ %72, %68 ]
%30 = phi float [ 1.000000e+00, %23 ], [ %71, %68 ]
%31 = phi i32 [ 0, %23 ], [ %70, %68 ]
%32 = phi i32 [ 0, %23 ], [ %69, %68 ]
%33 = getelementptr inbounds i8, i8* %0, i64 %28
%34 = load i8, i8* %33
%35 = zext i8 %34 to i32
%36 = icmp slt i32 %24, %35
%37 = icmp sgt i32 %25, %35
%38 = select i1 %36, i1 %37, i1 false
%39 = icmp eq i32 %29, 0
br i1 %38, label %40, label %59
40: ; preds = %27
br i1 %39, label %41, label %47
41: ; preds = %40
%42 = add nsw i32 %32, 1
%43 = icmp slt i32 %32, %11
%44 = select i1 %43, i32 %31, i32 1
%45 = xor i1 %43, true
%46 = zext i1 %45 to i32
br label %68
47: ; preds = %40
%48 = icmp eq i32 %31, 1
br i1 %48, label %49, label %58
49: ; preds = %47
%50 = fsub float %30, %18
%51 = fcmp olt float %50, 0.000000e+00
br i1 %51, label %52, label %53
52: ; preds = %49
store i8 -128, i8* %33
br label %68
53: ; preds = %49
%54 = add nsw i32 %35, -128
%55 = sitofp i32 %54 to float
%56 = tail call float @llvm.fmuladd.f32(float %55, float %50, float 1.280000e+02)
%57 = fptoui float %56 to i8
store i8 %57, i8* %33
br label %68
58: ; preds = %47
store i8 -128, i8* %33
br label %68
59: ; preds = %27
br i1 %39, label %68, label %60
60: ; preds = %59
%61 = fadd float %30, %21
%62 = fcmp ogt float %61, 1.000000e+00
br i1 %62, label %68, label %63
63: ; preds = %60
%64 = add nsw i32 %35, -128
%65 = sitofp i32 %64 to float
%66 = tail call float @llvm.fmuladd.f32(float %65, float %61, float 1.280000e+02)
%67 = fptoui float %66 to i8
store i8 %67, i8* %33
br label %68
68: ; preds = %41, %59, %63, %60, %58, %53, %52
%69 = phi i32 [ %32, %52 ], [ %32, %53 ], [ %32, %58 ], [ %42, %41 ], [ 0, %60 ], [ 0, %63 ], [ 0, %59 ]
%70 = phi i32 [ 0, %52 ], [ 1, %53 ], [ 0, %58 ], [ %44, %41 ], [ %31, %60 ], [ %31, %63 ], [ %31, %59 ]
%71 = phi float [ 0.000000e+00, %52 ], [ %50, %53 ], [ %30, %58 ], [ %30, %41 ], [ 1.000000e+00, %60 ], [ %61, %63 ], [ %30, %59 ]
%72 = phi i32 [ 1, %52 ], [ 1, %53 ], [ 1, %58 ], [ %46, %41 ], [ 0, %60 ], [ 1, %63 ], [ 0, %59 ]
%73 = add nuw nsw i64 %28, 1
%74 = icmp eq i64 %73, %26
br i1 %74, label %75, label %27
75: ; preds = %68, %9, %7
ret void
}