gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > SMF Library (Timer issue & maybe some other problems)

#177414 - hacker013 - Thu May 31, 2012 5:05 pm

I was bored so I started again trying to get the spinal movie player code to work and in lib form. This where my results (is using gba-jpeg & libfb from dragonminded (fixed to work with latest libnds)):

smf.h
Code:

#ifndef IMLIB_SMF
#define IMLIB_SMF

#include <nds.h>
#include "gba-jpeg.h"
#include "gba-jpeg-decode.h"
#include "libcommon.h"

struct VIDEO_HEADER
{
  short   height;
  int      framecount;
  int      vidoffset;
  int      taboffset;
} vidhead;

FILE* vidFile;
u32 rawSize = 11500; // 22050/12 = 1/12 second of sound?
u32 audio_offset = 0; //was 58
u16 sndBufPointer = 0;
u32 frame_offset;
u16 frame_count=0;
u16 pixSize=0;

char* pixBuf;
char* buffer;
char* bitmap;

bool smf_play(char* filename);
void smf_update_frame();
void smf_update_sound();
void smf_stop();

#endif


smf.c
Code:

#include "smf.h"

/*
  Original movie player by Spinal
  Redesign by Faust IMetal
 
  Requires timer 1 and 2
 
  - Rewritten for LibFB
  - Removed PALib depedencie
  -
*/

void smf_update_frame()
{
   fseek (vidFile , frame_offset, SEEK_SET);
   fread(&pixSize,2,1,vidFile);
   memset(pixBuf,0,16000);   // 98304
   fread(pixBuf, 1, pixSize, vidFile);
   frame_offset+=2+pixSize;
   JPEG_DecompressImage(pixBuf, &bitmap, 256, 192);
         
   fb_setBG(&bitmap);
   frame_count++;
   if(vidhead.framecount < frame_count)
   {
      smf_stop();
   }
}

void smf_update_sound()
{
   soundPlaySample(&buffer[sndBufPointer * rawSize], SoundFormat_16Bit, (u32)rawSize, 11025, 127, 64, 0, 0);
   sndBufPointer++;
   if (sndBufPointer == 4) sndBufPointer = 0;
   audio_offset=(58+(float)1837.5*(frame_count+6)); // 1837.5 = 22050/12
   audio_offset = audio_offset >>1 <<1; // must be even number for some reason.
   fseek (vidFile , audio_offset , SEEK_SET);
   fread(&buffer[sndBufPointer * rawSize],1,rawSize,vidFile);
}

void smf_stop()
{
   fclose(vidFile);
   free(bitmap);
   free(buffer);
   free(pixBuf);
   timerStop(1);
   timerStop(2);
}

bool smf_play(char* filename)
{
   soundEnable();

   pixBuf = (char*) malloc(16000);
   if(pixBuf==NULL) return false;
   buffer = (char*) malloc (sizeof(char)*rawSize*4);
   if(buffer==NULL) return false;
   bitmap = (char*) malloc(256*192*2);
   if(buffer==NULL) return false;


   int frm_number[250]; // 250 frame numbers for progress bar
   int frm_offset[250]; // 250 locations for progress bar
   
   vidFile = fopen (filename, "rb"); //rb = read
   if(vidFile==NULL) return false;
   
   // read the file header
   fread(&vidhead.height,2,1,vidFile); // either 192 or 144   
   fread(&vidhead.framecount,4,1,vidFile);
   fread(&vidhead.vidoffset,4,1,vidFile);
   fread(&vidhead.taboffset,4,1,vidFile);
   // read the progress bar data
   fseek (vidFile , vidhead.taboffset , SEEK_SET);
   fread(&frm_offset[0],4,250,vidFile);
   fread(&frm_number[0],4,250,vidFile);

    frame_offset = vidhead.vidoffset;

   // Set timers
   timerStart(1, ClockDivider_1024, TIMER_FREQ_1024(12), smf_update_sound);
   timerStart(2, ClockDivider_1024, TIMER_FREQ_1024(12), smf_update_frame); // 1024/12=85.3333333 (from old palib based code for calc the timer :S
   return true;
}


- Some test smf file This one does work correctly in the spinal movie player (made in 2008 for neo contest)
- Original source from Spinal

First the whole code was in the smf_play function, it did run but after a few seconds it hung (I ques it is a memory leak). Then I tried to move it in a library from with easy to use functions and instead of counting the ticks from the timer to use the timer callbacks. But now it doesn't play anymore. Does someone see where I could have made a mistake ?

~Hacker013

EDIT:
- Added Original source from Spinal.
- Added some test smf file.

EDIT2:

I fixed the code some bit, it now hangs after a few seconds. I hope you guys can see whats wrong ^^

smf.h
Code:

#ifndef SMF_LIB_INCLUDE
#define SMF_LIB_INCLUDE

#ifdef __cplusplus
extern "C" {
#endif

#include <nds.h>

bool smf_play(char* filename);
void smf_update_frame();
void smf_update_sound();
void smf_update();
void smf_stop();

#ifdef __Cplusplus
}
#endif

#endif


smf.c
Code:

/*
  Original movie player by Spinal
  Redesign by Faust IMetal
 
  Requires timer 1 and 2
 
  - Rewritten for LibFB
  - Removed PALib depedencie
*/

#include "smf.h"

#ifdef __cplusplus
extern "C" {
#endif

#include <nds.h>
#include "libcommon.h" //Frame Buffer
#include "gba-jpeg-decode.h" //JPEG Decoding

struct VIDEO_HEADER
{
  short   height;
  int      framecount;
  int      vidoffset;
  int      taboffset;
} vidhead;

FILE* vidFile;
u32 rawSize = 11500; // 22050/12 = 1/12 second of sound?
u32 audio_offset = 0; //was 58
u16 sndBufPointer = 0;
u32 frame_offset;
u16 frame_count=0;
u16 pixSize=0;

bool smf_playing=false;

char* pixBuf;
char* buffer;
u16* bitmap;

void smf_update_frame()
{
   fseek (vidFile , frame_offset, SEEK_SET);
   fread(&pixSize,2,1,vidFile);
   memset(pixBuf,0,16000);   // 98304
   fread(pixBuf, 1, pixSize, vidFile);
   frame_offset+=2+pixSize;
   JPEG_DecompressImage((const unsigned char*)pixBuf, bitmap, 256, 192);
         
   fb_setBG(bitmap);
   frame_count++;
}

void smf_update_sound()
{
   soundPlaySample(&buffer[sndBufPointer * rawSize], SoundFormat_16Bit, (u32)rawSize, 11025, 127, 64, 0, 0);
   sndBufPointer++;
   if (sndBufPointer == 4) sndBufPointer = 0;
   audio_offset=(58+(float)1837.5*(frame_count+6)); // 1837.5 = 22050/12
   audio_offset = audio_offset >>1 <<1; // must be even number for some reason.
   fseek (vidFile , audio_offset , SEEK_SET);
   fread(&buffer[sndBufPointer * rawSize],1,rawSize,vidFile);
}

void smf_update()
{
   if(vidhead.framecount >= frame_count)
   {
      if(timerTick(1)>=512)
      {
         timerStop(1);
         timerStart(1, ClockDivider_1024, TIMER_FREQ_1024(2), NULL);
         
         smf_update_sound();
      }
      
      if(timerTick(2)>85)
      {
         timerStop(2);
         timerStart(2, ClockDivider_1024, TIMER_FREQ_1024(12), NULL);
         
         smf_update_frame();
      }
   } else {
      smf_stop();
   }
}

void smf_stop()
{
   if(smf_playing)
   {
      fclose(vidFile);
      free(bitmap);
      free(buffer);
      free(pixBuf);
      timerStop(1);
      timerStop(2);
   
      smf_playing=false;
   }
}

bool smf_play(char* filename)
{
   if(smf_playing) return false;
   
   soundEnable();
   
   frame_count=0;
   audio_offset=0;

   pixBuf = (char*) malloc(16000);
   if(pixBuf==NULL) return false;
   buffer = (char*) malloc (sizeof(char)*rawSize*4);
   if(buffer==NULL) return false;
   bitmap = malloc(256*192*2);
   if(buffer==NULL) return false;


   int frm_number[250]; // 250 frame numbers for progress bar
   int frm_offset[250]; // 250 locations for progress bar
   
   vidFile = fopen (filename, "rb"); //rb = read
   if(vidFile==NULL) return false;
   
   // read the file header
   fread(&vidhead.height,2,1,vidFile); // either 192 or 144   
   fread(&vidhead.framecount,4,1,vidFile);
   fread(&vidhead.vidoffset,4,1,vidFile);
   fread(&vidhead.taboffset,4,1,vidFile);
   // read the progress bar data
   fseek (vidFile , vidhead.taboffset , SEEK_SET);
   fread(&frm_offset[0],4,250,vidFile);
   fread(&frm_number[0],4,250,vidFile);

    frame_offset = vidhead.vidoffset;

   // Set timers
   timerStart(1, ClockDivider_1024, TIMER_FREQ_1024(2), NULL);
   timerStart(2, ClockDivider_1024, TIMER_FREQ_1024(12), NULL); // 1024/12=85.3333333 (from old palib based code for calc the timer :S
   
   smf_playing=true;
   
   return true;
}

#ifdef __Cplusplus
}
#endif


Moved the vars to the .c file, because of a wierd reason they conflicted if they where defined within the header (the gave conflicts within a random function and didn't want to compile).

Hope you guys can help me out ^^

~Hacker013
_________________
Website / Blog

Let the nds be with you.

#177423 - headspin - Fri Jun 01, 2012 4:54 am

I haven't checked out why it's hanging but the jpeg decompressor needs modification to work on the DS. You can download the updated source from here (bottom of the page).
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game

#177424 - hacker013 - Fri Jun 01, 2012 7:53 am

I'm already using that version ^^ That's not the problem, the decompression works fine and also the sound for a few seconds and then both will hang.

EDIT:
After some debugging I found out it hangs within the 25th frame after the sound decode :S
_________________
Website / Blog

Let the nds be with you.

#177439 - hacker013 - Tue Jun 05, 2012 8:18 pm

Fixed both bugs, the sound only is still stuttering... After I fixed that I will release the source ^^
_________________
Website / Blog

Let the nds be with you.