Issue #18950: Fix miscellaneous bugs in the sunau module.

Au_read.readframes() now updates current file position and reads correct
number of frames from multichannel stream.  Au_write.writeframesraw() now
correctly updates current file position.  Au_read.getnframes() now returns an
integer (as in Python 2).  Au_read and Au_write now correctly works with file
object if start file position is not a zero.
diff --git a/Lib/sunau.py b/Lib/sunau.py
index 6775a53..5212370 100644
--- a/Lib/sunau.py
+++ b/Lib/sunau.py
@@ -205,6 +205,10 @@
                     break
         else:
             self._info = ''
+        try:
+            self._data_pos = file.tell()
+        except (AttributeError, OSError):
+            self._data_pos = None
 
     def getfp(self):
         return self._file
@@ -222,7 +226,7 @@
         if self._data_size == AUDIO_UNKNOWN_SIZE:
             return AUDIO_UNKNOWN_SIZE
         if self._encoding in _simple_encodings:
-            return self._data_size / self._framesize
+            return self._data_size // self._framesize
         return 0                # XXX--must do some arithmetic here
 
     def getcomptype(self):
@@ -257,7 +261,8 @@
             if nframes == AUDIO_UNKNOWN_SIZE:
                 data = self._file.read()
             else:
-                data = self._file.read(nframes * self._framesize * self._nchannels)
+                data = self._file.read(nframes * self._framesize)
+            self._soundpos += len(data) // self._framesize
             if self._encoding == AUDIO_FILE_ENCODING_MULAW_8:
                 import audioop
                 data = audioop.ulaw2lin(data, self._sampwidth)
@@ -265,8 +270,10 @@
         return None             # XXX--not implemented yet
 
     def rewind(self):
+        if self._data_pos is None:
+            raise OSError('cannot seek')
+        self._file.seek(self._data_pos)
         self._soundpos = 0
-        self._file.seek(self._hdr_size)
 
     def tell(self):
         return self._soundpos
@@ -274,7 +281,9 @@
     def setpos(self, pos):
         if pos < 0 or pos > self.getnframes():
             raise Error('position not in range')
-        self._file.seek(pos * self._framesize + self._hdr_size)
+        if self._data_pos is None:
+            raise OSError('cannot seek')
+        self._file.seek(self._data_pos + pos * self._framesize)
         self._soundpos = pos
 
     def close(self):
@@ -390,10 +399,10 @@
 
     def writeframesraw(self, data):
         self._ensure_header_written()
-        nframes = len(data) / self._framesize
         if self._comptype == 'ULAW':
             import audioop
             data = audioop.lin2ulaw(data, self._sampwidth)
+        nframes = len(data) // self._framesize
         self._file.write(data)
         self._nframeswritten = self._nframeswritten + nframes
         self._datawritten = self._datawritten + len(data)
@@ -455,6 +464,10 @@
             length = AUDIO_UNKNOWN_SIZE
         else:
             length = self._nframes * self._framesize
+        try:
+            self._form_length_pos = self._file.tell()
+        except (AttributeError, OSError):
+            self._form_length_pos = None
         _write_u32(self._file, length)
         self._datalength = length
         _write_u32(self._file, encoding)
@@ -464,7 +477,9 @@
         self._file.write(b'\0'*(header_size - len(self._info) - 24))
 
     def _patchheader(self):
-        self._file.seek(8)
+        if self._form_length_pos is None:
+            raise OSError('cannot seek')
+        self._file.seek(self._form_length_pos)
         _write_u32(self._file, self._datawritten)
         self._datalength = self._datawritten
         self._file.seek(0, 2)
diff --git a/Misc/NEWS b/Misc/NEWS
index 6289eb2..86a8e35 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -71,6 +71,13 @@
 Library
 -------
 
+- Issue #18950: Fix miscellaneous bugs in the sunau module.
+  Au_read.readframes() now updates current file position and reads correct
+  number of frames from multichannel stream.  Au_write.writeframesraw() now
+  correctly updates current file position.  Au_read.getnframes() now returns an
+  integer (as in Python 2).  Au_read and Au_write now correctly works with file
+  object if start file position is not a zero.
+
 - Issue #19053: ZipExtFile.read1() with non-zero argument no more returns empty
   bytes until end of data.