Anonymous avatar Anonymous committed 7efa433

Array functions generalisation, sndarray impl (untested)

Comments (0)

Files changed (6)

examples_pygame/arraydemo.py

             raise SystemExit
 
 # Only required if N is not Numeric.
-pygame.surfarray.set_array_module(N)
+pygame.set_array_module(N)
 
 imagename = os.path.join('data', 'arraydemo.bmp')
 imgsurface = pygame.image.load(imagename)

pygame/__init__.py

 #our modules is with the import command (not the __import__ function)
 
 #first, the "required" modules
+from pygame.array import *
 from pygame.base import *
 from pygame.constants import *
 from pygame.version import *
+#!/usr/bin/env python
+
+'''Internal functions for dealing with Numeric, numpy and numarray.
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id$'
+
+from ctypes import *
+
+class _Numeric_PyArrayObject(Structure):
+    _fields_ = [('ob_refcnt', c_int),
+                ('ob_type', c_void_p),
+                ('data', POINTER(c_char)),
+                ('nd', c_int),
+                ('dimensions', POINTER(c_int)),
+                ('strides', POINTER(c_int)),
+                ('base', c_void_p),
+                ('descr', c_void_p),
+                ('flags', c_uint),
+                ('weakreflist', c_void_p)]
+
+# Numeric flags constants
+_CONTIGUOUS = 1
+_OWN_DIMENSIONS = 2
+_OWN_STRIDES = 4
+_OWN_DATA = 8
+_SAVESPACE = 16
+
+# numarray constants
+_MAXDIM = 40
+
+class _numarray_PyArrayObject(Structure):
+    _fields_ = [('ob_refcnt', c_int),
+                ('ob_type', c_void_p),
+                ('data', POINTER(c_char)),
+                ('nd', c_int),
+                ('dimensions', POINTER(c_int)),
+                ('strides', POINTER(c_int)),
+                ('base', c_void_p),
+                ('descr', c_void_p),
+                ('flags', c_uint),
+                ('_dimensions', c_int * _MAXDIM),
+                ('_strides', c_int * _MAXDIM),
+                ('_data', c_void_p),
+                ('_shadows', c_void_p),
+                ('nstrides', c_int),
+                ('byteoffset', c_long),
+                ('bytestride', c_long),
+                ('itemsize', c_long),
+                ('byteorder', c_char)]
+
+# Provide support for numpy and numarray in addition to Numeric.  To
+# be compatible with Pygame, by default the module will be unavailable
+# if Numeric is not available.  You can activate it to use any available
+# array module by calling set_array_module().
+try:
+    import Numeric
+    _array = Numeric
+except ImportError:
+    _array = None
+
+def set_array_module(module=None):
+    '''Set the array module to use; numpy, numarray or Numeric.
+
+    If no arguments are given, every array module is tried and the
+    first one that can be imported will be used.  The order of
+    preference is numpy, numarray, Numeric.  You can determine which
+    module was set with `get_array_module`.
+
+    :Parameters:
+        `module` : module or None
+            Module to use.
+
+    '''
+    global _array
+    if not module:
+        for name in ('numpy', 'numarray', 'Numeric'):
+            try:
+                set_array_module(__import__(name, locals(), globals(), []))
+            except ImportError:
+                pass
+    else:
+        _array = module
+
+def get_array_module():
+    '''Get the currently set array module.
+
+    If None is returned, no array module is set and the surfarray
+    functions will not be useable.
+
+    :rtype: module
+    '''
+    return _array
+
+def _check_array():
+    if not _array:
+        raise ImportError, \
+              'No array module set; use set_array_module if you want to ' + \
+              'use numpy or numarray instead of Numeric.'
+
+def _get_array_local_module(array):
+    # Given an array, determine what array module it is from.  Note that
+    # we don't require it to be the same module as _array, which is
+    # only for returned arrays.
+
+    # "strides" attribute is different in each module, so is hacky way
+    # to check.
+    if hasattr(array, 'strides'):
+        import numpy
+        return numpy
+    elif hasattr(array, '_strides'):
+        import numarray
+        return numarray
+    else:
+        import Numeric
+        return Numeric
+
+def _array_from_buffer(buffer, 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.frombuffer(buffer, typecode).reshape(shape)
+
+    elif _array.__name__ == 'Numeric':
+        # Free old data and point to new data, updating dimension size and
+        # clearing OWN_DATA flag so it doesn't get free'd.
+        array = _array.array([0], typecode)
+        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.free(array_obj.data)
+        except OSError:
+            pass # Couldn't find libc; accept a small memory leak
+        array_obj.data = cast(buffer, POINTER(c_char))
+        array_obj.dimensions.contents.value = reduce(lambda a,b:a*b, shape)
+        array_obj.flags &= ~_OWN_DATA
+        return _array.reshape(array, shape)
+
+    elif _array.__name__ == 'numarray':
+        # numarray PyArrayObject is source-compatible with Numeric,
+        # but deallocation is managed via a Python buffer object.
+        # XXX this fails under uncertain circumstances: reading the array
+        # never works, writing works for some arrays and not others.
+        array = _array.array([0], typecode)
+        array_obj = _numarray_PyArrayObject.from_address(id(array))
+        array_obj.dimensions.contents.value = reduce(lambda a,b:a*b, shape)
+        array._data = buffer
+        return _array.reshape(array, shape)
+
+    else:
+        assert False
 
     __slots__ = ['_chunk']
 
-    def __init__(self, file):
+    def __init__(self, file, _chunk=None):
         '''Create a new Sound object from a file.
 
         Load a new sound buffer from a filename or from a python file object.
         :Parameters:
             `file` : str or file-like object
                 The filename or file to load.
+            `_chunk` : None
+                Internal use only.
 
         '''
+        if _chunk:
+            self._chunk = _chunk
+            return
+
         _mixer_init_check()
 
         if hasattr(file, 'read'):

pygame/sndarray.py

+#!/usr/bin/env python
+
+'''Pygame module for accessing sound sample data.
+
+Functions to convert between Numeric arrays and Sound objects. This
+module will only be available when pygame can use the external Numeric package.
+
+Sound data is made of thousands of samples per second, and each sample is the
+amplitude of the wave at a particular moment in time. For example, in
+22-kHz format, element number 5 of the array is the amplitude of the wave
+after 5/22000 seconds.
+
+Each sample is an 8-bit or 16-bit integer, depending on the data format.
+A stereo sound file has two values per sample, while a mono sound file only has one.
+
+By default a Numeric array will be returned.  You can request a numpy
+or numarray array using `pygame.set_array_module`.
+'''
+
+__docformat__ = 'restructuredtext'
+__version__ = '$Id$'
+
+from SDL import *
+
+import pygame.array
+import pygame.base
+import pygame.mixer
+
+def _as_array(sound):
+    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_S16LE, AUDIO_S16BE)
+
+    return pygame.array._array_from_buffer(chunk.abuf, formatbytes,
+                                           shape, signed)
+
+def array(sound):
+    '''Copy Sound samples into an array.
+
+    Creates a new Numeric array for the sound data and copies the samples. The
+    array will always be in the format returned from pygame.mixer.get_init(). 
+
+    :Parameters:
+        `sound` : `Sound`
+            Sound data to copy.
+
+    :rtype: Numeric, numpy or numarray array
+    '''
+    return _as_array(sound).copy()
+
+def samples(sound):
+    '''Reference Sound samples into an array.
+
+    Creates a new Numeric array that directly references the samples in a 
+    Sound object. Modifying the array will change the Sound. The array
+    will always be in the format returned from pygame.mixer.get_init().
+
+    :Parameters:
+        `sound` : `Sound`
+            Sound data to reference.
+
+    :rtype: Numeric, numpy or numarray array
+    '''
+    # XXX not setting base pointer; up to caller to maintain ref to sound.
+    return _as_array(sound)
+
+def make_sound(array):
+    '''Convert an array into a Sound object.
+
+    Create a new playable Sound object from a Numeric array. The mixer module
+    must be initialized and the array format must be similar to the mixer
+    audio format.
+
+    :Parameters:
+        `array` : Numeric, numpy or numarray array
+            Array to copy.
+
+    :rtype: `Sound`
+    ''' 
+    ready, frequency, format, channels = Mix_QuerySpec()
+    if not ready:
+        raise pygame.base.error, 'Mixer not initialized'
+
+    mixerbytes = (format & 0xff) >> 3
+
+    module = pygame.array._get_array_local_module(array)
+    shape = module.shape(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()
+    chunk = Mix_Chunk()
+    chunk.allocated = 1
+    chunk.volume = 128
+    chunk.alen = len(data)
+    chunk._abuf = create_string_buffer(data)
+
+    return pygame.mixer.Sound(None, _chunk=chunk)
+            
+

pygame/surfarray.py

 
 from SDL import *
 
+import pygame.array
 import pygame.surface
 
-class _Numeric_PyArrayObject(Structure):
-    _fields_ = [('ob_refcnt', c_int),
-                ('ob_type', c_void_p),
-                ('data', POINTER(c_char)),
-                ('nd', c_int),
-                ('dimensions', POINTER(c_int)),
-                ('strides', POINTER(c_int)),
-                ('base', c_void_p),
-                ('descr', c_void_p),
-                ('flags', c_uint),
-                ('weakreflist', c_void_p)]
-
-# Numeric flags constants
-_CONTIGUOUS = 1
-_OWN_DIMENSIONS = 2
-_OWN_STRIDES = 4
-_OWN_DATA = 8
-_SAVESPACE = 16
-
-# numarray constants
-_MAXDIM = 40
-
-class _numarray_PyArrayObject(Structure):
-    _fields_ = [('ob_refcnt', c_int),
-                ('ob_type', c_void_p),
-                ('data', POINTER(c_char)),
-                ('nd', c_int),
-                ('dimensions', POINTER(c_int)),
-                ('strides', POINTER(c_int)),
-                ('base', c_void_p),
-                ('descr', c_void_p),
-                ('flags', c_uint),
-                ('_dimensions', c_int * _MAXDIM),
-                ('_strides', c_int * _MAXDIM),
-                ('_data', c_void_p),
-                ('_shadows', c_void_p),
-                ('nstrides', c_int),
-                ('byteoffset', c_long),
-                ('bytestride', c_long),
-                ('itemsize', c_long),
-                ('byteorder', c_char)]
-
-# Provide support for numpy and numarray in addition to Numeric.  To
-# be compatible with Pygame, by default the module will be unavailable
-# if Numeric is not available.  You can activate it to use any available
-# array module by calling set_array_module().
-try:
-    import Numeric
-    _array = Numeric
-except ImportError:
-    _array = None
-
-def set_array_module(module=None):
-    '''Set the array module to use; numpy, numarray or Numeric.
-
-    If no arguments are given, every array module is tried and the
-    first one that can be imported will be used.  The order of
-    preference is numpy, numarray, Numeric.  You can determine which
-    module was set with `get_array_module`.
-
-    :Parameters:
-        `module` : module or None
-            Module to use.
-
-    '''
-    global _array
-    if not module:
-        for name in ('numpy', 'numarray', 'Numeric'):
-            try:
-                set_array_module(__import__(name, locals(), globals(), []))
-            except ImportError:
-                pass
-    else:
-        _array = module
-
-def get_array_module():
-    '''Get the currently set array module.
-
-    If None is returned, no array module is set and the surfarray
-    functions will not be useable.
-
-    :rtype: module
-    '''
-    return _array
-
 def array2d(surface):
     '''Copy pixels into a 2d array.
 
 
     :rtype: Numeric array
     '''
-    _check_array()
+    pygame.array._check_array()
+    _array = pygame.array._array
 
     surf = surface._surf
     bpp = surf.format.BytesPerPixel
     shape = surf.h, surf.pitch / bpp
 
     surface.lock()
-    array = _array_from_buffer(surf.pixels.as_ctypes(), bpp, shape)
+    array = pygame.array._array_from_buffer(surf.pixels.as_ctypes(), bpp, shape)
     surface.lifelock(array)
     surface.unlock()
 
     array = array[:,:surf.w]
-    return _array.transpose(array)
+    return pygame.array._array.transpose(array)
 
 def array3d(surface):
     '''Copy pixels into a 3d array.
     :rtype: Numeric array
     '''
     array = array2d(surface)
+    _array = pygame.array._array
 
     surf = surface._surf
     format = surf.format
     shape = surf.h, surf.pitch 
 
     surface.lock()
-    array = _array_from_buffer(surf.pixels.as_bytes().as_ctypes(), 1, shape)
+    array = pygame.array._array_from_buffer(surf.pixels.as_bytes().as_ctypes(), 
+                                            1, shape)
     surface.lifelock(array)
     surface.unlock()
 
     array = array[:,:surf.w*bpp]
-    print surf.h * surf.w * bpp, _array.shape(array)
-    array = _array.reshape(array, (surf.h, surf.w, bpp))
+    array = pygame.array._array.reshape(array, (surf.h, surf.w, bpp))
     array = array[:,:,start:end:step]
-    return _array.transpose(array, (1, 0, 2))
+    return pygame.array._array.transpose(array, (1, 0, 2))
 
 def array_alpha(surface):
     '''Copy pixel alphas into a 2d array.
     else:
         array = array >> format.Ashift << format.Aloss
 
-    return array.astype(_array.UInt8)
+    return array.astype(pygame.array._array.UInt8)
 
 def pixels_alpha(surface):
     '''Reference pixel alphas into a 2d array.
     shape = surf.h, surf.pitch
 
     surface.lock()
-    array = _array_from_buffer(surf.pixels.as_bytes().as_ctypes(), 1, shape)
+    array = pygame.array._array_from_buffer(surf.pixels.as_bytes().as_ctypes(), 
+                                            1, shape)
     surface.lifelock(array)
     surface.unlock()
 
     array = array[:,:surf.w*4]
     array = array[:,startpixel::4]
-    return _array.transpose(array)
+    return pygame.array._array.transpose(array)
 
 def array_colorkey(surface):
     '''Copy the colorkey values into a 2d array.
     :rtype: Numeric or numpy array
     '''  
     array = array2d(surface)
+    _array = pygame.array._array
 
     if surface._surf.flags & SDL_SRCCOLORKEY:
         # XXX No work with numarray
 
     :rtype: `Surface`
     '''
-    _check_array()
+    pygame.array._check_array()
     
-    module = _get_array_local_module(array)
+    module = pygame.array._get_array_local_module(array)
     shape = module.shape(array)
 
     if len(shape) == 2:
 
     :rtype: `Surface`
     '''
-    _check_array()
+    pygame.array._check_array()
 
     surf = surface._surf
     bpp = surf.format.BytesPerPixel
 
     # Local array module, may be different to global array module.
-    module = _get_array_local_module(array)
+    module = pygame.array._get_array_local_module(array)
 
     # Transpose to traditional row ordering (row, column, [component])
     shape = module.shape(array)
     '''
     surf = surface._surf
 
-    module = _get_array_local_module(array)
+    module = pygame.array._get_array_local_module(array)
     shape = module.shape(array)
 
     if shape[-1] != 3:
 
     return array
 
-def _check_array():
-    if not _array:
-        raise ImportError, \
-              'No array module set; use set_array_module if you want to ' + \
-              'use numpy or numarray instead of Numeric.'
 
-def _get_array_local_module(array):
-    # Given an array, determine what array module it is from.  Note that
-    # we don't require it to be the same module as _array, which is
-    # only for returned arrays.
-
-    # "strides" attribute is different in each module, so is hacky way
-    # to check.
-    if hasattr(array, 'strides'):
-        import numpy
-        return numpy
-    elif hasattr(array, '_strides'):
-        import numarray
-        return numarray
-    else:
-        import Numeric
-        return Numeric
-
-def _array_from_buffer(buffer, bpp, shape):
-    typecode = (_array.UInt8, _array.UInt16, None, _array.UInt32)[bpp-1]
-    if _array.__name__ == 'numpy':
-        return _array.frombuffer(buffer, typecode).reshape(shape)
-
-    elif _array.__name__ == 'Numeric':
-        # Free old data and point to new data, updating dimension size and
-        # clearing OWN_DATA flag so it doesn't get free'd.
-        array = _array.array([0], typecode)
-        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.free(array_obj.data)
-        except OSError:
-            pass # Couldn't find libc; accept a small memory leak
-        array_obj.data = cast(buffer, POINTER(c_char))
-        array_obj.dimensions.contents.value = reduce(lambda a,b:a*b, shape)
-        array_obj.flags &= ~_OWN_DATA
-        return _array.reshape(array, shape)
-
-    elif _array.__name__ == 'numarray':
-        # numarray PyArrayObject is source-compatible with Numeric,
-        # but deallocation is managed via a Python buffer object.
-        # XXX this fails under uncertain circumstances: reading the array
-        # never works, writing works for some arrays and not others.
-        array = _array.array([0], typecode)
-        array_obj = _numarray_PyArrayObject.from_address(id(array))
-        array_obj.dimensions.contents.value = reduce(lambda a,b:a*b, shape)
-        array._data = buffer
-        return _array.reshape(array, shape)
-
-    else:
-        assert False
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.