Anonymous avatar Anonymous committed e98132a

sndarray complete.

Comments (0)

Files changed (4)

 __version__ = '$Id$'
 
 from ctypes import *
+import sys
 
 class _Numeric_PyArrayObject(Structure):
     _fields_ = [('ob_refcnt', c_int),
         import Numeric
         return Numeric
 
+def _array_from_string(string, bpp, shape, signed=False):
+    if signed:
+        typecode = (_array.Int8, _array.Int16, None, _array.Int32)[bpp-1]
+    else:
+        typecode = (_array.UInt8, _array.UInt16, None, _array.UInt32)[bpp-1]
+
+    if _array.__name__ == 'numpy':
+        return _array.fromstring(string, typecode).reshape(shape)
+    elif _array.__name__ == 'numarray':
+        return _array.fromstring(string, typecode, shape)
+    elif _array.__name__ == 'Numeric':
+        return _array.reshape(_array.fromstring(string, typecode), shape)
+
 def _array_from_buffer(buffer, bpp, shape, signed=False):
     if signed:
         typecode = (_array.Int8, _array.Int16, None, _array.Int32)[bpp-1]
         array_obj = _Numeric_PyArrayObject.from_address(id(array))
         assert array_obj.flags & _OWN_DATA != 0
         try:
-            if sys.platform == 'windows':
-                libc = cdll.msvcrt
-            else:
-                libc = cdll.load_version('c', 6)
+            libc = _get_libc()
             libc.free(array_obj.data)
         except OSError:
             pass # Couldn't find libc; accept a small memory leak
 
     else:
         assert False
+
+def _get_libc():
+    if sys.platform == 'windows':
+        return cdll.msvcrt
+    else:
+        return cdll.load_version('c', 6)
 
         return Mix_GroupCount(id(self))
 
-    def get_length():
+    def get_length(self):
         '''Get the length of the Sound.
 
         Return the length of this Sound in seconds.

pygame/sndarray.py

 __version__ = '$Id$'
 
 from SDL import *
+from SDL.mixer import *
 
 import pygame.array
 import pygame.base
 import pygame.mixer
 
 def _as_array(sound):
+    chunk = sound._chunk
+
     ready, frequency, format, channels = Mix_QuerySpec()
     if not ready:
         raise pygame.base.error, 'Mixer not initialized'
     else:
         shape = (chunk.alen / formatbytes / 2, 2)
 
-    signed = format in (AUDIO_S8, AUDIO_S16LE, AUDIO_S16BE)
+    signed = format in (AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB)
 
-    return pygame.array._array_from_buffer(chunk.abuf, formatbytes,
+    return pygame.array._array_from_buffer(chunk.abuf.as_ctypes(), formatbytes,
                                            shape, signed)
 
 def array(sound):
 
     :rtype: Numeric, numpy or numarray array
     '''
-    return _as_array(sound).copy()
+    chunk = sound._chunk
+
+    ready, frequency, format, channels = Mix_QuerySpec()
+    if not ready:
+        raise pygame.base.error, 'Mixer not initialized'
+
+    formatbytes = (format & 0xff) >> 3
+    if channels == 1:
+        shape = (chunk.alen / formatbytes,)
+    else:
+        shape = (chunk.alen / formatbytes / 2, 2)
+
+    signed = format in (AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB)
+
+    return pygame.array._array_from_string(chunk.abuf.to_string(), formatbytes,
+                                           shape, signed)
 
 def samples(sound):
     '''Reference Sound samples into an array.
     if len(shape) != channels or (len(shape) == 2 and shape[1] != channels):
         raise ValueError, \
              'Array must be have same number of dimensions as mixer channels.'
+    
+    data = array.tostring()
 
-    data = array.tostring()
-    chunk = Mix_Chunk()
+    # Malloc a buffer and copy in the sound data (mixer will take care
+    # of freeing it).
+    libc = pygame.array._get_libc()
+    libc.malloc.restype = POINTER(c_ubyte)
+    ptr = libc.malloc(len(data))
+    memmove(ptr, data, len(data))
+
+    # Don't just instantiate Mix_Chunk here, otherwise Python GC will free
+    # it.  We want mixer to free it with Mix_FreeChunk, so do a manual malloc.
+    buf = libc.malloc(sizeof(Mix_Chunk))
+    chunk = Mix_Chunk.from_address(addressof(buf.contents))
     chunk.allocated = 1
     chunk.volume = 128
     chunk.alen = len(data)
-    chunk._abuf = create_string_buffer(data)
+    chunk._abuf = ptr
 
     return pygame.mixer.Sound(None, _chunk=chunk)
-            
 

pygame/surfarray.py

                              flags=re.DOTALL)
         data = ''.join(pattern.findall(data))
 
-    if bpp == 1:
-        t = _array.UInt8
-    elif bpp == 2:
-        t = _array.UInt16
-    elif bpp == 3:
+    if bpp == 3:
         # Pad each triplet of bytes with another zero
         pattern = re.compile('...', flags=re.DOTALL)
         data = '\0'.join(pattern.findall(data))
             data += '\0'
         else:
             data = '\0' + data
-        t = _array.UInt32
         bpp = 4
-    elif bpp == 4:
-        t = _array.UInt32
 
     shape = surf.h, surf.w
-
-    if _array.__name__ == 'numpy':
-        ar = _array.fromstring(data, t).reshape(shape)
-    elif _array.__name__ == 'numarray':
-        ar = _array.fromstring(data, t, shape)
-    elif _array.__name__ == 'Numeric':
-        ar = _array.fromstring(data, t).resize(shape)
+    ar = pygame.array._array_from_string(data, bpp, shape)
 
     return _array.transpose(ar)
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.