def close
      return if @closed

      # The RIFF specification requires that each chunk be aligned to an even number of bytes,
      # even if the byte count is an odd number. Therefore if an odd number of bytes has been
      # written, write an empty padding byte.
      #
      # See http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/riffmci.pdf, page 11.
      bytes_written = @total_sample_frames * @format.block_align
      if bytes_written.odd?
        @io.write(EMPTY_BYTE)
      end

      # We can't know what chunk sizes to write for the RIFF and data chunks until all
      # samples have been written, so go back to the beginning of the file and re-write
      # those chunk headers with the correct sizes.
      @io.seek(@start_pos)
      write_header(@total_sample_frames)

      if @io_source == :file_name
        @io.close
      else
        # If writing to an injected IO instance, seek back to the end of the file, which
        # seems like a more expected place for the position to be than at the end of the
        # header. For example, seeking back to the end allows writing consecutive files
        # to the same IO without overwriting the previous file.
        @io.seek(0, IO::SEEK_END)
      end
      @closed = true
    end
def close
      return if @closed

      # The RIFF specification requires that each chunk be aligned to an even number of bytes,
      # even if the byte count is an odd number. Therefore if an odd number of bytes has been
      # written, write an empty padding byte.
      #
      # See http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Docs/riffmci.pdf, page 11.
      bytes_written = @total_sample_frames * @format.block_align
      if bytes_written.odd?
        @io.write(EMPTY_BYTE)
      end

      # We can't know what chunk sizes to write for the RIFF and data chunks until all
      # samples have been written, so go back to the beginning of the file and re-write
      # those chunk headers with the correct sizes.
      @io.seek(@start_pos)
      write_header(@total_sample_frames)

      if @io_source == :file_name
        @io.close
      else
        # If writing to an injected IO instance, seek back to the end of the file, which
        # seems like a more expected place for the position to be than at the end of the
        # header. For example, seeking back to the end allows writing consecutive files
        # to the same IO without overwriting the previous file.
        @io.seek(0, IO::SEEK_END)
      end
      @closed = true
    end
Public: Closes the Writer. After a Writer is closed, no more sample data can be written
 to it.

 Note that the wave file will NOT be valid until this method is called. The wave file
 format requires certain information about the amount of sample data, and this can't be
 determined until all samples have been written. (This method doesn't need to be called
 when passing a block to Writer.new, as this method will automatically be called when
 the block exits).

 If you initialized the Writer with an externally created IO instance, note that
 the IO instance won't be closed when the Writer is closed. You'll need to manually close
 the IO yourself. This is on purpose, because the Writer can't know what you may/may not
 want to do with the IO after closing the Writer.

 Examples

   square_wave_samples = ([0.5] * 100) + ([-0.5] * 100)
   buffer = Buffer.new(square_wave_samples, Format.new(1, :float, 44100))

   # Basic example of closing a Writer
   writer = Writer.new("my_file.wav", Format.new(:mono, :pcm_16, 44100))
   writer.write(buffer)
   writer.close
   writer.close # Does nothing, since Writer is already closed

   # Closing a Writer writing to an externally opened IO
   file = File.open("my_file.wav", "wb")
   writer = Writer.new(file, Format.new(:mono, :pcm_16, 44100))
   writer.close
   # file is still open at this point, so it should be manually closed
   file.close

   # Trying to write to a Writer that has already been closed
   writer = Writer.new("my_file.wav", Format.new(:mono, :pcm_16, 44100))
   writer.close
   # This will raise WriterClosedError, since the Writer is already closed
   writer.write(buffer)

   # close() needs to be called for the Wave file to be valid
   writer = Writer.new("my_file.wav", Format.new(:mono, :pcm_16, 44100))
   writer.write(buffer)
   exit
   # At this point "my_file.wav" won't be a valid Wave file, because close
   # was never called

   # But, close() doesn't need to be called when constructing the Writer
   # with a block, because it is automatically called when the block exits.
   Writer.new("my_file.wav", Format.new(:mono, :pcm_16, 44100)) do |writer|
     writer.write(buffer)
   end
   # Writer is automatically closed here, because block has exited

 Returns nothing. Has side effect of closing the Writer. If the Writer is already
 closed, does nothing.