Example #1
0
/*** 
      gx_audio_Update

     This function retrieves samples for the frame then set the next DMA parameters 
     Parameters will be taken in account only when current DMA operation is over

     To keep audio & video synchronized, DMA from external memory to audio interface is 
     started once by video update function when first frame is ready to be displayed, 
     then anytime video mode is changed and emulation resynchronized to video hardware.

     Once started, audio DMA restarts automatically when all samples have been played.
     At that time:
       - if DMA settings have not been updated, previous sound buffer will be played again
       - if DMA settings are updated too fast, one sound buffer frame might be skipped
     
     Therefore, in order to maintain perfect audio playback without any sound skipping  
     or lagging, we need to make sure frame emulation is completed and this function is 
     called before previous DMA transfer is finished and after it has been started.

     This is done by synchronizing frame emulation with audio DMA interrupt (which happens
     anytime audio DMA restarts). When video sync is enabled, to keep emulation in sync 
     with both video AND audio, an appropriate number of samples is rendered per frame by
     adjusting emulator output samplerate.
 ***/
int gx_audio_Update(int status)
{
  /* Current available soundbuffer */
  s16 *sb = (s16 *)(soundbuffer[bufferIndex]);

  /* Make sure current audio frame has not already been updated */
  if (status & AUDIO_UPDATE)
  {
    /* Retrieve audio samples (size must be multiple of 32 bytes) */
    bufferSize = audio_update(sb) * 4;
    DCFlushRange((void *)sb, bufferSize);

    /* Mark current audio frame as being updated */
    status &= ~AUDIO_UPDATE;
  }

  /* Wait until previous audio frame is started before pushing current audio frame into DMA */
  if ((status & AUDIO_WAIT) && !audioWait)
  {
    /* Update audio DMA settings for current frame */
    AUDIO_InitDMA((u32)sb, bufferSize);

    /* Next soundbuffer */
    bufferIndex = (bufferIndex + 1) % SOUND_BUFFER_NUM;

    /* Set audio wait flag */
    audioWait = audioSync;

    /* Current audio frame is ready for upcoming DMA */
    status &= ~AUDIO_WAIT;
  }

  return status;  
}
Example #2
0
/*** 
      gx_audio_Update

     This function retrieves samples for the frame then set the next DMA parameters 
     Parameters will be taken in account only when current DMA operation is over
 ***/
void gx_audio_Update(void)
{
  /* retrieve audio samples */
  int size = audio_update() * 4;

  /* set next DMA soundbuffer */
  s16 *sb = (s16 *)(soundbuffer[mixbuffer]);
  DCFlushRange((void *)sb, size);
  AUDIO_InitDMA((u32) sb, size);
  mixbuffer ^= 1;

  /* Start Audio DMA */
  /* this is called once to kick-off DMA from external memory to audio interface        */
  /* DMA operation is automatically restarted when all samples have been sent.          */
  /* If DMA settings are not updated at that time, previous sound buffer will be used.  */
  /* Therefore we need to make sure frame emulation is completed before current DMA is  */
  /* completed, either by synchronizing frame emulation with DMA start or by syncing it */
  /* with Vertical Interrupt and outputing a suitable number of samples per frame.      */
  /*                                                                                    */
  /* In both cases, audio DMA need to be synchronized with VSYNC and therefore need to  */
  /* be resynchronized (restarted) every time video settings are changed (hopefully,    */
  /* this generally happens while no music is played.                                   */                    
  if (!audioStarted)
  {
    /* restart audio DMA */
    AUDIO_StopDMA();
    AUDIO_StartDMA();
    audioStarted = 1;

    /* resynchronize emulation */
    frameticker = 1;
  }
}
Example #3
0
void Application::step(const JNIEnv *env)
{
     // quick exit if no rom loaded to step
     if (!_romLoaded)
     {
          return;
     }

     processInput();

     // calculate frameskipping
     _frameSkipCount=(_frameSkipCount+1)%(_frameSkip+1);

     // calc framerate
     /*_timeStart = _timeEnd;
     _timeEnd = now_ms();
     _timeDelta = (_timeEnd - _timeStart);
     FCEUI_printf("FPS: %g", _timeDelta);
     */

     // check for viewport change from last frame
     int update = bitmap.viewport.changed & 1;
     if (update)
     {
          int vwidth = bitmap.viewport.w + (2 * bitmap.viewport.x);
          int vheight = bitmap.viewport.h + (2 * bitmap.viewport.y);

          // interlaced mode
          if (config.render && interlaced)
          {
               vheight = vheight << 1;
          }

          LOGD("Bitmap Changed: %d, %d, %d, pitch: %d", bitmap.viewport.changed, vwidth, vheight, bitmap.pitch);
          Graphics.ReshapeEmuTexture(vwidth, vheight, SCREEN_RENDER_TEXTURE_WIDTH);

          _viewPortW = vwidth;
          _viewPortH = vheight;

          bitmap.viewport.changed &= ~1;

          bitmap.pitch = bitmap.viewport.w * bitmap.granularity;
     }

     // step emulation
     system_frame(_frameSkipCount);

     // draw the texture/fbo
     Graphics.DrawEMU(bitmap.data, _viewPortW, _viewPortH);

     // retrieve audio
     _ssize = audio_update() << 1;
     //if (!_audioInitialized) _ssize = 0;

     //LOGD("AudioSamples: %d", _ssize);

    //LOGD("DONE STEP");
}
Example #4
0
void *audio_playback(void *param)
{
  int rc;

  while(1) {
    audio_update(0);
    rc=usleep(1000); // 1ms sleep
  }
  return NULL;
}
Example #5
0
GPGX_EX void gpgx_advance(void)
{
	if (system_hw == SYSTEM_MCD)
		system_frame_scd(0);
	else if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
		system_frame_gen(0);
	else
		system_frame_sms(0);

	if (bitmap.viewport.changed & 1)
	{
		bitmap.viewport.changed &= ~1;
		update_viewport();
	}

	nsamples = audio_update(soundbuffer);
}
static void PlaySound()
{
    int size = audio_update() * 2;
    CellAudio->write((const int16_t* )soundbuffer, size);
}