forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

OGG playback error

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
Criptych



Joined: 12 Sep 2009
Posts: 79

PostPosted: Wed Oct 28, 2009 5:03 am    Post subject: OGG playback error Reply with quote

I'm trying to add OGG playback to a program. Everything compiles fine, but when I try to play a file, I get the following error:
Code:
Program received signal SIGBUS, Bus error.
_malloc_r (reent_ptr=0x88ca8e0, bytes=<value optimized out>)
    at ../../../../../../newlib-1.17.0/newlib/libc/stdlib/mallocr.c:2376
2376    ../../../../../../newlib-1.17.0/newlib/libc/stdlib/mallocr.c: No such file or directory.
        in ../../../../../../newlib-1.17.0/newlib/libc/stdlib/mallocr.c
(gdb) bt
#0  _malloc_r (reent_ptr=0x88ca8e0, bytes=<value optimized out>)
    at ../../../../../../newlib-1.17.0/newlib/libc/stdlib/mallocr.c:2376
#1  0x0888fb40 in _calloc_r (reent_ptr=0x88ca8e0, n=<value optimized out>, elem_size=0)
    at ../../../../../../newlib-1.17.0/newlib/libc/stdlib/mallocr.c:3202
#2  0x0883f558 in vorbis_synthesis_headerin ()
#3  0x0882f990 in _fetch_headers ()
#4  0x08830260 in _ov_open1 ()
#5  0x08832c60 in ov_open_callbacks ()
#6  0x0880a8a4 in oggFileLoad (filename=0x8a9e110 "voice/0002.ogg")
    at oggplay.c:95
#7  0x0880ab90 in oggPlay (filename=0x8a9e110 "voice/0002.ogg")
    at oggplay.c:164


Sometimes the error occurs in ov_read instead of ov_open_callbacks. I've run out of ideas; what could be causing this?
Back to top
View user's profile Send private message
jimparis



Joined: 10 Jun 2005
Posts: 1179
Location: Boston

PostPosted: Wed Oct 28, 2009 7:16 am    Post subject: Reply with quote

It's in malloc, are you running out of RAM by any chance? Bus errors can also be caused by alignment problems. It's also possible (and more likely) that you are just corrupting memory and that's messing with the malloc data structures. If you can, try compiling the same code on the PC and run it under valgrind.
Back to top
View user's profile Send private message
Criptych



Joined: 12 Sep 2009
Posts: 79

PostPosted: Wed Oct 28, 2009 10:33 am    Post subject: Reply with quote

jimparis wrote:
It's in malloc, are you running out of RAM by any chance? Bus errors can also be caused by alignment problems. It's also possible (and more likely) that you are just corrupting memory and that's messing with the malloc data structures. If you can, try compiling the same code on the PC and run it under valgrind.

I thought malloc just returned NULL if there wasn't enough RAM? Anyway, I printed the available RAM as close to the crash as possible, and got ~17MB. The OGG I played is only a few hundred K, so that's probably not it.
The actual player code is sort of stripped-down from Sakya's LightMP3 OGG player, with some changes and additions to accommodate the way I'm using it:
Code:
#include "common.h"

#include <pspaudiolib.h>

#include <tremor/ivorbiscodec.h> //libtremor
#include <tremor/ivorbisfile.h>  //libtremor

struct oggFile_t
{
   struct OggVorbis_File vf;
   int loop, autounload;
   int lvol, rvol;
};

size_t ogg_read(void *ptr, size_t size, size_t nmemb, void *datasource)
{
    return pgeFileRead((pgeFile *)datasource, ptr, size * nmemb) / size;
}
int ogg_seek(void *datasource, ogg_int64_t offset, int whence)
{
    return pgeFileSeek((pgeFile *)datasource, (long)offset, whence);
}
long ogg_tell(void *datasource)
{
    return pgeFileSeek((pgeFile *)datasource, 0, PGE_FILE_CUR);
}
int ogg_close(void *datasource)
{
    return pgeFileClose((pgeFile *)datasource);
}

static ov_callbacks pspio_callbacks = { ogg_read, ogg_seek, ogg_close, ogg_tell };

static oggFile *ogg_info[PSP_NUM_AUDIO_CHANNELS] = { 0 };

static void oggDecodeCallback(void *buffer, u32 nsamples, void *pdata)
{
   if (!(buffer && nsamples)) return;

   oggFile *ogg = (oggFile *)pdata;

   int sect = 0;

   int nbytes = nsamples * 4;

   int res = 0;

   while (nbytes > 0)
   {
      res = ov_read(&(ogg->vf), buffer, nbytes, &sect);
      if (res == OV_HOLE) continue;
      if (res <= 0) break;
      nbytes -= res;
   }

   if (res <= 0 && ogg->autounload)
   {
      oggFileUnload(ogg);
   }
}

int oggInit()
{
   return pspAudioInit() < 0 ? 0 : 1;
}

void oggShutdown()
{
   pspAudioEnd();
}

void oggFileUnload(oggFile *ogg)
{
   ov_clear(&(ogg->vf));
}

oggFile *oggFileLoad(const char *filename)
{
   pgeFile *file = pgeFileOpen((char *)filename, PGE_FILE_RDONLY);

   if (!file) return 0;

   DEBUG("Before: %8dkB RAM free\n", pgeSystemGetFreeRam() >> 10);

   oggFile *ogg = (oggFile *)pgeMalloc(sizeof(oggFile));

   if (!ogg) return 0;

   int res = ov_open_callbacks(file, &(ogg->vf), 0, 0, pspio_callbacks);

   DEBUG("After:  %8dkB RAM free\n", pgeSystemGetFreeRam() >> 10);

   if (res < 0)
   {
      pgeFileClose(file);
      return 0;
   }

   vorbis_info *vi = ov_info(&(ogg->vf), -1);

   DEBUG("samplerate == %ld, channels == %d\n", vi->rate, vi->channels);

   if (vi->channels > 2)
   {
      oggFileUnload(ogg);
      return 0;
   }

   ogg->loop = ogg->autounload = 0;
   ogg->lvol = ogg->rvol = 0x8000;

   return ogg;
}

int oggFileLoop(oggFile *ogg, int loop)
{
   if (!ogg) return 0;
   int old = ogg->loop;
   ogg->loop = loop;
   return old;
}

void oggFileSetVolume(oggFile *ogg, int lvol, int rvol)
{
   if (!ogg) return;
   ogg->lvol = lvol;
   ogg->rvol = rvol;
}

int oggFilePlay(oggFile *ogg)
{
   int slot;
   for (slot = 0; slot < PSP_NUM_AUDIO_CHANNELS; ++slot)
   {
      if (!ogg_info[slot]) break;
   }

   if (slot < PSP_NUM_AUDIO_CHANNELS)
   {
      ogg_info[slot] = ogg;

      pspAudioSetVolume(slot, ogg->lvol, ogg->rvol);

      pspAudioSetChannelCallback(slot, oggDecodeCallback, ogg);

      return 1;
   }
   else if (ogg->autounload)
   {
      oggFileUnload(ogg);
   }

   return 0;
}

int oggPlay(const char *filename)
{
   oggFile *ogg = oggFileLoad(filename);

   if (!ogg) return 0;

   ogg->autounload = 1;

   return oggFilePlay(ogg);
}


AFAIK I'm not messing with anything dangerous, system structures and whatnot...
Back to top
View user's profile Send private message
jimparis



Joined: 10 Jun 2005
Posts: 1179
Location: Boston

PostPosted: Wed Oct 28, 2009 2:36 pm    Post subject: Reply with quote

I don't know what the pgeFile* functions do, but note that sceIoRead and sceIoWrite have buffer alignment restrictions that might be a problem. Can you add more debugging and see if it's reachign any of the callbacks? I don't necessarily trust the gdb backtrace.
Back to top
View user's profile Send private message
Criptych



Joined: 12 Sep 2009
Posts: 79

PostPosted: Thu Oct 29, 2009 12:33 am    Post subject: Reply with quote

jimparis wrote:
I don't know what the pgeFile* functions do, but note that sceIoRead and sceIoWrite have buffer alignment restrictions that might be a problem.

pgeFile* are I/O abstraction, i.e. so memory and disk files can be handled the same way. For disk files, they ultimately use sceIo*.

jimparis wrote:
Can you add more debugging and see if it's reachign any of the callbacks? I don't necessarily trust the gdb backtrace.

Sure, I was actually starting that when I saw your reply. :)

EDIT: From a test module that loads and plays an ~6MB track.
Code:
Before:    22528kB RAM free
ogg_seek(0x88f6730, 0, 1)
ogg_read(0x0, 1, 8500, 0x88f6730)
After:         0kB RAM free
oggFileLoad: ov_open_callbacks: res == -128
oggPlay returned 0

Apparently it tries to read into a NULL pointer, which may be related to the malloc problem I had before? Especially considering it goes from 20MB free RAM to zero. I looked up the error code, -128 is OV_EREAD; obviously there's going to be a read error if there's no memory to read into. :(

EDIT: I tried replacing pgeFile* with sceIo* and with stdio functions, and still get the same result both times.

@!#&^%*&^#$! Changed a few lines to use standard vorbis instead of Tremor, and now it works - still needs some tweaking, but it works. I guess I'll try it like this for now. Thanks for your suggestions. :)


Last edited by Criptych on Thu Oct 29, 2009 3:32 am; edited 1 time in total
Back to top
View user's profile Send private message
jimparis



Joined: 10 Jun 2005
Posts: 1179
Location: Boston

PostPosted: Thu Oct 29, 2009 3:22 am    Post subject: Reply with quote

libogg seems to have no error checking. If a malloc fails, calls like ogg_sync_buffer will return NULL which would lead directly to the read-into-NULL that you noticed. I don't know why, but it looks like you really are out of ram. Maybe try instrumenting libogg and libvorbis's malloc calls (they both use an _ogg_malloc macro that you can redefine)
Back to top
View user's profile Send private message
Criptych



Joined: 12 Sep 2009
Posts: 79

PostPosted: Fri Oct 30, 2009 6:41 am    Post subject: Reply with quote

That won't be necessary... I'm just very good at making stupid mistakes. I #included the Tremor headers, but linked with libvorbis and libvorbisfile - probably why it worked when I changed to the standard vorbis headers. Linking with libvorbisidec instead fixed it. Thanks for your help, anyway. :)
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group