static void reduce_matrix(AudioMix *am, const double *matrix, int stride)

{

    int i, o;



    memset(am->output_zero, 0, sizeof(am->output_zero));

    memset(am->input_skip,  0, sizeof(am->input_skip));

    memset(am->output_skip, 0, sizeof(am->output_skip));



    /* exclude output channels if they can be zeroed instead of mixed */

    for (o = 0; o < am->out_channels; o++) {

        int zero = 1;



        /* check if the output is always silent */

        for (i = 0; i < am->in_channels; i++) {

            if (matrix[o * stride + i] != 0.0) {

                zero = 0;

                break;

            }

        }

        /* check if the corresponding input channel makes a contribution to

           any output channel */

        if (o < am->in_channels) {

            for (i = 0; i < am->out_channels; i++) {

                if (matrix[i * stride + o] != 0.0) {

                    zero = 0;

                    break;

                }

            }

        }

        if (zero) {

            am->output_zero[o] = 1;

            am->out_matrix_channels--;

        }

    }

    if (am->out_matrix_channels == 0) {

        am->in_matrix_channels = 0;

        return;

    }



    /* skip input channels that contribute fully only to the corresponding

       output channel */

    for (i = 0; i < FFMIN(am->in_channels, am->out_channels); i++) {

        int skip = 1;



        for (o = 0; o < am->out_channels; o++) {

            int i0;

            if ((o != i && matrix[o * stride + i] != 0.0) ||

                (o == i && matrix[o * stride + i] != 1.0)) {

                skip = 0;

                break;

            }

            /* if the input contributes fully to the output, also check that no

               other inputs contribute to this output */

            if (o == i) {

                for (i0 = 0; i0 < am->in_channels; i0++) {

                    if (i0 != i && matrix[o * stride + i0] != 0.0) {

                        skip = 0;

                        break;

                    }

                }

            }

        }

        if (skip) {

            am->input_skip[i] = 1;

            am->in_matrix_channels--;

        }

    }

    /* skip input channels that do not contribute to any output channel */

    for (; i < am->in_channels; i++) {

        int contrib = 0;



        for (o = 0; o < am->out_channels; o++) {

            if (matrix[o * stride + i] != 0.0) {

                contrib = 1;

                break;

            }

        }

        if (!contrib) {

            am->input_skip[i] = 1;

            am->in_matrix_channels--;

        }

    }

    if (am->in_matrix_channels == 0) {

        am->out_matrix_channels = 0;

        return;

    }



    /* skip output channels that only get full contribution from the

       corresponding input channel */

    for (o = 0; o < FFMIN(am->in_channels, am->out_channels); o++) {

        int skip = 1;

        int o0;



        for (i = 0; i < am->in_channels; i++) {

            if ((o != i && matrix[o * stride + i] != 0.0) ||

                (o == i && matrix[o * stride + i] != 1.0)) {

                skip = 0;

                break;

            }

        }

        /* check if the corresponding input channel makes a contribution to

           any other output channel */

        i = o;

        for (o0 = 0; o0 < am->out_channels; o0++) {

            if (o0 != i && matrix[o0 * stride + i] != 0.0) {

                skip = 0;

                break;

            }

        }

        if (skip) {

            am->output_skip[o] = 1;

            am->out_matrix_channels--;

        }

    }

    if (am->out_matrix_channels == 0) {

        am->in_matrix_channels = 0;

        return;

    }

}
