Anonymous avatar Anonymous committed 68a41ca

array and sound work

Comments (0)

Files changed (7)

 # BREAK = change breaks existing code
 # BUG	= fixed a bug that was (or could have been) crashing
 
+May 7, 2002
+	added the sndarray module
+	added surfarray.make_surface()
+
 April 25, 2002
 	added gl_set_attribute(), gl_get_attribute()
 
 <a href=ref/pygame_surfarray.html#array_alpha>pygame.surfarray.array_alpha</a> - get an array with a surface pixel alpha values<br>
 <a href=ref/pygame_surfarray.html#array_colorkey>pygame.surfarray.array_colorkey</a> - get an array with a surface colorkey values<br>
 <a href=ref/pygame_surfarray.html#blit_array>pygame.surfarray.blit_array</a> - quickly transfer an array to a Surface<br>
+<a href=ref/pygame_surfarray.html#make_surface>pygame.surfarray.make_surface</a> - create a new Surface from array data<br>
 <a href=ref/pygame_surfarray.html#map_array>pygame.surfarray.map_array</a> - map an array with RGB values into mapped colors<br>
 <a href=ref/pygame_surfarray.html#pixels2d>pygame.surfarray.pixels2d</a> - get a 2d reference array to a surface<br>
 <a href=ref/pygame_surfarray.html#pixels3d>pygame.surfarray.pixels3d</a> - get a 3d reference array to a surface<br>

docs/ref/pygame_sndarray.html

 Create a new playable Sound object from array data
 the Sound will be a copy of the array samples.
 <br>&nbsp;<br>
-The samples must be in the same format of the initialized
-mixer module. This means you must match the data type
-(8bit or 16bit) as well as match the number of channels
-(usually stereo or mono).
+The array must be 1-dimensional for mono sound, and.
+2-dimensional for stereo.
 </ul><br>&nbsp;<br>
 
 <a name=samples><font size=+2><b>samples

docs/ref/pygame_surfarray.html

 quickly transfer an array to a Surface</td></tr>
 
 
+<tr><td><a href=#make_surface>make_surface</a></td><td> -
+create a new Surface from array data</td></tr>
+
+
 <tr><td><a href=#map_array>map_array</a></td><td> -
 map an array with RGB values into mapped colors</td></tr>
 
 This function will temporarily lock the surface.
 </ul><br>&nbsp;<br>
 
+<a name=make_surface><font size=+2><b>make_surface
+</b></font><br><font size=+1><tt>
+pygame.surfarray.make_surface(array) -> Surface
+</tt></font><ul>
+Create a new software surface that closely resembles
+the data and format of the image array data.
+</ul><br>&nbsp;<br>
+
 <a name=map_array><font size=+2><b>map_array
 </b></font><br><font size=+1><tt>
 pygame.surfarray.map_array(surf, array3d) -> array2d
 static void sound_dealloc(PyObject* self)
 {
     	Mix_Chunk* chunk = PySound_AsChunk(self);
-printf("DELETE SOUND %p(%p)\n", self, chunk);
 	Mix_FreeChunk(chunk);
 	PyObject_DEL(self);
 }
 	final = PySound_New(chunk);
 	if(!final)
 		Mix_FreeChunk(chunk);
-printf("ALLOC SOUND %p(%p)\n", final, chunk);
 
 	return final;
 }
         array = sndarray_samples(self, arg);
         if(array)
         {
-            arraycopy = PyArray_Copy(array);
+            arraycopy = PyArray_Copy((PyArrayObject*)array);
             Py_DECREF(array);
         }
         return arraycopy;
     /*DOC*/    "Create a new playable Sound object from array data\n"
     /*DOC*/    "the Sound will be a copy of the array samples.\n"
     /*DOC*/    "\n"
-    /*DOC*/    "The samples must be in the same format of the initialized\n"
-    /*DOC*/    "mixer module. This means you must match the data type\n"
-    /*DOC*/    "(8bit or 16bit) as well as match the number of channels\n"
-    /*DOC*/    "(usually stereo or mono).\n"
+    /*DOC*/    "The array must be 1-dimensional for mono sound, and.\n"
+    /*DOC*/    "2-dimensional for stereo.\n"
     /*DOC*/ ;
 
 PyObject* sndarray_make_sound(PyObject* self, PyObject* arg)
     PyArrayObject *array;
     Mix_Chunk *chunk;
     Uint16 format;
-    int numchannels, samplesize;
-    int loop1, loop2, step1, step2;
+    int numchannels, samplesize, mixerbytes;
+    int loop1, loop2, step1, step2, length, length2;
     Uint8 *src, *dst;
 
     if(!PyArg_ParseTuple(arg, "O!", &PyArray_Type, &arrayobj))
     
     if(!Mix_QuerySpec(NULL, &format, &numchannels))
         return RAISE(PyExc_SDLError, "Mixer not initialized");
+    if(array->descr->type_num > PyArray_LONG)
+            return RAISE(PyExc_ValueError, "Invalid array datatype for sound");
 
-    /*test sample size*/
     if(format==AUDIO_S8 || format==AUDIO_U8)
-    {
-        if(array->descr->elsize != 1)
-            return RAISE(PyExc_ValueError, "Array must contain 8bit audio, to match mixer");
-    }
-    else if(array->descr->elsize != 2)
-        return RAISE(PyExc_ValueError, "Array must contain 16bit audio, to match mixer");
+        mixerbytes = 1;
+    else
+        mixerbytes = 2;
     
     /*test array dimensions*/
     if(numchannels==1)
         if(array->dimensions[1] != numchannels)
             return RAISE(PyExc_ValueError, "Array depth must match number of mixer channels");
     }
-
+    length = array->dimensions[0];
+    if(array->nd == 2)
+        length2 = array->dimensions[1];
+    
     /*create chunk, we are screwed if SDL_mixer ever does more than malloc/free*/
     chunk = (Mix_Chunk *)malloc(sizeof(Mix_Chunk));
     if ( chunk == NULL )
         return RAISE(PyExc_MemoryError, "Cannot allocate chunk\n");
     /*let's hope Mix_Chunk never changes also*/
-    chunk->alen = array->descr->elsize * array->dimensions[0] * numchannels;
+    chunk->alen = mixerbytes * length * numchannels;
     chunk->abuf = (Uint8*)malloc(chunk->alen);
     chunk->allocated = 1;
     chunk->volume = 128;
-    
-    
+
     if(array->nd == 1)
     {
         step1 = array->strides[0];
         src = (Uint8*)array->data;
         dst = (Uint8*)chunk->abuf;
-        if(array->descr->elsize == 1)
+        if(mixerbytes == 1)
         {
-            for(loop1 = 0; loop1 < array->dimensions[0]; loop1++)
+            switch(array->descr->elsize)
             {
-                *dst = *src;
-                dst += 1;
-                src += step1;
+            case 1:
+                for(loop1=0; loop1<length; loop1++, dst+=1, src+=step1)
+                    *(Uint8*)dst = (Uint8)*((Uint8*)src);
+                break;
+            case 2:
+                for(loop1=0; loop1<length; loop1++, dst+=1, src+=step1)
+                    *(Uint8*)dst = (Uint8)*((Uint16*)src);
+                break;
+            case 4:
+                for(loop1=0; loop1<length; loop1++, dst+=1, src+=step1)
+                    *(Uint8*)dst = (Uint8)*((Uint32*)src);
+                break;
             }
         }
         else
         {
-            for(loop1 = 0; loop1 < array->dimensions[0]; loop1++)
+            switch(array->descr->elsize)
             {
-                *(Uint16*)dst = *(Uint16*)src;
-                dst += 2;
-                src += step1;
+            case 1:
+                for(loop1=0; loop1<length; loop1++, dst+=2, src+=step1)
+                    *(Uint16*)dst = (Uint16)((*((Uint8*)src))<<8);
+                break;
+            case 2:
+                for(loop1=0; loop1<length; loop1++, dst+=2, src+=step1)
+                    *(Uint16*)dst = (Uint16)*((Uint16*)src);
+                break;
+            case 4:
+                for(loop1=0; loop1<length; loop1++, dst+=2, src+=step1)
+                    *(Uint16*)dst = (Uint16)*((Uint32*)src);
+                break;
             }
         }
     }
         step1 = array->strides[0];
         step2 = array->strides[1];
         dst = (Uint8*)chunk->abuf;
-        if(array->descr->elsize == 1)
+        if(mixerbytes == 1)
         {
-            for(loop1 = 0; loop1 < array->dimensions[0]; loop1++)
+            for(loop1=0; loop1<length; loop1++)
             {
                 src = (Uint8*)array->data + loop1*step1;
-                for(loop2 = 0; loop2 < array->dimensions[1]; loop2++)
+                switch(array->descr->elsize)
                 {
-                    *dst = *(src+loop2*step2);
-                    dst += 1;
+                case 1:
+                    for(loop2=0; loop2<length2; loop1++, dst+=1, src+=step2)
+                        *(Uint8*)dst = (Uint8)*((Uint8*)src);
+                    break;
+                case 2:
+                    for(loop1=0; loop1<length; loop1++, dst+=1, src+=step2)
+                        *(Uint8*)dst = (Uint8)*((Uint16*)src);
+                    break;
+                case 4:
+                    for(loop1=0; loop1<length; loop1++, dst+=1, src+=step2)
+                        *(Uint8*)dst = (Uint8)*((Uint32*)src);
+                    break;
                 }
             }
         }
         else
         {
-            for(loop1 = 0; loop1 < array->dimensions[0]; loop1++)
+            for(loop1 = 0; loop1 < length; loop1++)
             {
                 src = (Uint8*)array->data + loop1*step1;
-                for(loop2 = 0; loop2 < array->dimensions[1]; loop2++)
+               switch(array->descr->elsize)
                 {
-                    *(Uint16*)dst = *(Uint16*)(src+loop2*step2);
-                    dst += 2;
+                case 1:
+                    for(loop2=0; loop2<length2; loop1++, dst+=1, src+=step2)
+                        *(Uint16*)dst = (Uint16)(*((Uint8*)src)<<8);
+                    break;
+                case 2:
+                    for(loop1=0; loop1<length; loop1++, dst+=1, src+=step2)
+                        *(Uint16*)dst = (Uint16)*((Uint16*)src);
+                    break;
+                case 4:
+                    for(loop1=0; loop1<length; loop1++, dst+=1, src+=step2)
+                        *(Uint16*)dst = (Uint16)*((Uint32*)src);
+                    break;
                 }
             }
         }
     }
-    
-printf("%%returnsound\n");
+
     return PySound_New(chunk);
 }
 
 }
 
 
+    /*DOC*/ static char doc_make_surface[] =
+    /*DOC*/    "pygame.surfarray.make_surface(array) -> Surface\n"
+    /*DOC*/    "create a new Surface from array data\n"
+    /*DOC*/    "\n"
+    /*DOC*/    "Create a new software surface that closely resembles\n"
+    /*DOC*/    "the data and format of the image array data.\n"
+    /*DOC*/ ;
+
+PyObject* make_surface(PyObject* self, PyObject* arg)
+{
+	PyObject *arrayobj, *surfobj, *args;
+	SDL_Surface* surf;
+	SDL_PixelFormat *format;
+	PyArrayObject* array;
+	int sizex, sizey, bitsperpixel;
+        Uint32 rmask, gmask, bmask;
+
+	if(!PyArg_ParseTuple(arg, "O!", &PyArray_Type, &arrayobj))
+		return NULL;
+        array = (PyArrayObject*)arrayobj;
+        
+	if(!(array->nd == 2 || (array->nd == 3 && array->dimensions[2] == 3)))
+		return RAISE(PyExc_ValueError, "must be a valid 2d or 3d array\n");
+        if(array->descr->type_num > PyArray_LONG)
+                return RAISE(PyExc_ValueError, "Invalid array datatype for surface");
+        
+        if(array->nd == 2)
+        {
+            bitsperpixel = 8;
+            rmask = gmask = bmask = 0;
+        }
+        else
+        {
+            bitsperpixel = 32;
+            rmask = 0xFF<<16; gmask = 0xFF<<8; bmask = 0xFF;
+        }
+        sizex = array->dimensions[0];
+        sizey = array->dimensions[1];
+
+        surf = SDL_CreateRGBSurface(0, sizex, sizey, bitsperpixel, rmask, gmask, bmask, 0);
+        if(!surf)
+                return RAISE(PyExc_SDLError, SDL_GetError());
+        surfobj = PySurface_New(surf);
+        if(!surfobj)
+        {
+            SDL_FreeSurface(surf);
+            return NULL;
+        }
+        
+        args = Py_BuildValue("(OO)", surfobj, array);
+        if(!args)
+        {
+            Py_DECREF(surfobj);
+            return NULL;
+        }
+        blit_array(NULL, args);
+        Py_DECREF(args);
+        
+        if(PyErr_Occurred())
+        {
+            Py_DECREF(surfobj);
+            return NULL;
+        }
+        return surfobj;
+}
+
+    
+
 static PyMethodDef surfarray_builtins[] =
 {
 	{ "pixels2d", pixels2d, 1, doc_pixels2d },
 /*	{ "unmap_array", unmap_array, 1, doc_unmap_array },*/
 	{ "blit_array", blit_array, 1, doc_blit_array },
 /*	{ "clamp_array", clamp_array, 1, doc_clamp_array }, not quick enough to be worthwhile :[ */
+        { "make_surface", make_surface, 1, doc_make_surface },
 
 	{ NULL, NULL }
 };
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.