@Override
  boolean processReadPair(Read r1, Read r2) {
    assert (r2 == null);
    final byte[] quals = r1.quality, bases = r1.bases;
    final byte[] match =
        (r1.match == null ? null : !r1.shortmatch() ? r1.match : Read.toLongMatchString(r1.match));
    if (match == null || quals == null || bases == null) {
      return false;
    }

    int subs = 0;
    int indels = 0;
    for (int qpos = 0, mpos = 0, last = quals.length - 1; mpos < match.length; mpos++) {

      final byte m = match[mpos];
      final byte mprev = match[Tools.max(mpos - 1, 0)];
      final byte mnext = match[Tools.min(mpos + 1, match.length - 1)];

      final byte q1 = quals[qpos];
      final byte b2 = bases[qpos];

      int sub = 0, indel = 0;
      if (m == 'S') {
        sub = 1;
      } else if (m == 'I') {
        indel = 1;
      } else if (m == 'm') {
        if (mprev == 'D' || mnext == 'D') {
          indel = 1;
        }
      } else if (m == 'D') {
        // do nothing
      } else if (m == 'C') {
        // do nothing
      } else {
        throw new RuntimeException(
            "Bad symbol m='"
                + ((char) m)
                + "'\n"
                + new String(match)
                + "\n"
                + new String(bases)
                + "\n");
      }
      subs += sub;
      indels += indel;
      if (q1 >= minq && q1 <= maxq) {
        if (sub > 0 || (indel > 0 && countIndels)) {
          return true;
        }
      }

      if (m != 'D') {
        qpos++;
      }
    }
    return keepPerfect && subs == 0 && indels == 0;
  }