docs: public String computeTrackSignature(final String title, final SearchableItem artist, final int duration,
                                          final WaveformDetail waveformDetail, final BeatGrid beatGrid) {
          final String safeTitle = (title == null)? "" : title;
          final String artistName = (artist == null)? "[no artist]" : artist.label;
          try {
              // Compute the SHA-1 hash of our fields
              MessageDigest digest = MessageDigest.getInstance("SHA1");
              digest.update(safeTitle.getBytes("UTF-8"));
              digest.update((byte) 0);
              digest.update(artistName.getBytes("UTF-8"));
              digest.update((byte) 0);
              digestInteger(digest, duration);
              digest.update(waveformDetail.getData());
              for (int i = 1; i <= beatGrid.beatCount; i++) {
                  digestInteger(digest, beatGrid.getBeatWithinBar(i));
                  digestInteger(digest, (int)beatGrid.getTimeWithinTrack(i));
              }
              byte[] result = digest.digest();
  
              // Create a hex string representation of the hash
              StringBuilder hex = new StringBuilder(result.length * 2);
              for (byte aResult : result) {
                  hex.append(Integer.toString((aResult & 0xff) + 0x100, 16).substring(1));
              }
  
              return hex.toString();
  
          } catch (NullPointerException e) {
              logger.info("Returning null track signature because an input element was null.", e);
          } catch (NoSuchAlgorithmException e) {
              logger.error("Unable to obtain SHA-1 MessageDigest instance for computing track signatures.", e);
          } catch (UnsupportedEncodingException e) {
              logger.error("Unable to work with UTF-8 string encoding for computing track signatures.", e);
          }
          return null;  // We were unable to compute a signature
      }