How to optimally normalize filter coefficients? I have designed an IIR filter in Matlab that comprises the following biquads
0.244   0.002   0.244   1   -1.432  0.543
0.244   -0.345  0.244   1   -1.555  0.777
0.244   -0.388  0.244   1   -1.652  0.943

I want to implement this filter in a 16-bit DSP. Before converting the coefficients to short int, I therefore normalize them by dividing all coefficients by the largest magnitude present in the matrix (in this case 1.652). This results in
b0      b1      b2      a0       a1     a2
0.147   0.001   0.147   0.605   -0.866  0.328
0.147   -0.208  0.147   0.605   -0.941  0.470
0.147   -0.235  0.147   0.605   -1      0.570

I then convert these coefficients to 16-bit values ranging from +32767 to -32768. I implemented the filter using the Transposed Direct Form II.

The I realized that the gain is very low although the filter shows 0 dB in the passband when testing it in Matlab.
The algorithm is as follows. It iterates through all biquads and reintroduces their ouputs to the next one as necessary.
for (k = 0; k &lt; N_sos; k++) {

    y_n = (short) ((s1[k][1] + b[k][0] * x_n) &gt;&gt; 15);

    s1[k][0] = s2[k][1] + b[k][1] * x_n - a[k][1] * y_n;

    s2[k][0] = b[k][2] * x_n - a[k][2] * y_n;

    s1[k][1] = s1[k][0];

    s2[k][1] = s2[k][0];

    x_n = y_n;
}

IIR_out = y_n;


Notice that I have not taken the a0 coefficient into account. Since it usually is 1, it does not matter. But I wonder if the missing gain is caused by this missing coefficient. I tried multiplying y_n with it by exchanging
y_n = (short) ((s1[k][1] + b[k][0] * x_n) &gt;&gt; 15);

with
y_n = (short) a[k][0] * ((s1[k][1] + b[k][0] * x_n) &gt;&gt; 15);

but this heavily distorts the signal.
The OP should first implement the filter using floating point to confirm all specifications and structure. Once confirmed there is no &quot;optimal&quot; since the solution is a trade between precision required and accuracy needed in the result but typically the design approach is to use 2 more bits of precision for the coefficients over what is used in the datapath; scale all coefficients accordingly, let the filter grow the signal with an extended precision accumulator (such that no clipping occurs with input set to the maximum possible signal) and then scale the output back to the datapath precision.
See my further details on this at this answer recently posted:
What is the correct gain of an RRC Filter?