/**
   * Check can write to file
   *
   * @param file
   * @throws IOException
   */
  public void precheck(File file) throws IOException {
    if (!file.exists()) {
      logger.severe(
          ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_NOT_FOUND.getMsg(file.getName()));
      throw new IOException(
          ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_NOT_FOUND.getMsg(file.getName()));
    }

    if (!file.canWrite()) {
      logger.severe(ErrorMessage.GENERAL_WRITE_FAILED.getMsg(file.getName()));
      throw new IOException(ErrorMessage.GENERAL_WRITE_FAILED.getMsg(file.getName()));
    }

    if (file.length() <= MINIMUM_FILESIZE) {
      logger.severe(
          ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_IS_TOO_SMALL.getMsg(file.getName()));
      throw new IOException(
          ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_IS_TOO_SMALL.getMsg(file.getName()));
    }
  }
  /**
   * Calculates hash with algorithm "MD5", "SHA-1" or SHA-256". Hash is calculated EXCLUDING
   * meta-data, like id3v1 or id3v2
   *
   * @return byte[] hash value in byte
   * @param String algorithm
   * @param int buffersize
   * @throws IOException
   * @throws InvalidAudioFrameException
   * @throws NoSuchAlgorithmException
   */
  public byte[] getHash(String algorithm, int bufferSize)
      throws InvalidAudioFrameException, IOException, NoSuchAlgorithmException {
    File mp3File = getFile();
    long startByte = getMP3StartByte(mp3File);

    int id3v1TagSize = 0;
    if (hasID3v1Tag()) {
      ID3v1Tag id1tag = getID3v1Tag();
      id3v1TagSize = id1tag.getSize();
    }

    InputStream inStream = Files.newInputStream(Paths.get(mp3File.getAbsolutePath()));

    byte[] buffer = new byte[bufferSize];

    MessageDigest digest = MessageDigest.getInstance(algorithm);

    inStream.skip(startByte);

    int read;
    long totalSize = mp3File.length() - startByte - id3v1TagSize;
    int pointer = buffer.length;

    while (pointer <= totalSize) {

      read = inStream.read(buffer);

      digest.update(buffer, 0, read);
      pointer += buffer.length;
    }
    read = inStream.read(buffer, 0, (int) totalSize - pointer + buffer.length);
    digest.update(buffer, 0, read);

    byte[] hash = digest.digest();

    return hash;
  }