Example #1
0
static void *gx_audio_init(const char *device, unsigned rate, unsigned latency)
{
   gx_audio_t *wa = (gx_audio_t*)memalign(32, sizeof(*wa));
   if (!wa)
      return NULL;

   gx_audio_data = wa;

   memset(wa, 0, sizeof(*wa));

   AUDIO_Init(NULL);
   AUDIO_RegisterDMACallback(dma_callback);

   if (rate < 33000)
   {
      AUDIO_SetDSPSampleRate(AI_SAMPLERATE_32KHZ);
      g_settings.audio.out_rate = 32000;
   }
   else
   {
      AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
      g_settings.audio.out_rate = 48000;
   }

   LWP_InitQueue(&wa->cond);

   wa->dma_write = BLOCKS - 1;
   DCFlushRange(wa->data, sizeof(wa->data));
   AUDIO_InitDMA((uint32_t)wa->data[wa->dma_next], CHUNK_SIZE);
   AUDIO_StartDMA();

   return wa;
}
Example #2
0
// Called whenever more audio data is required.
static void play_more_audio()
{
	// Copy from mix buffer to DMA buffer.
	sample* const		src_begin	= &mix_buffer[mix_buffer_pointer];
	sample* const		dst_begin	= &dma_buffers[current_dma_buffer][0];
	const sample* const	dst_end		= dst_begin + samples_per_dma_buffer;
	sample*				src			= src_begin;
	sample*				dst			= dst_begin;
	while (dst != dst_end)
	{
		// We have to swap the channels, because Quake stores the left
		// channel first, whereas the GameCube expects right first.
		const u32 mix_sample = *src;
		*src++ = 0;
		*dst++ = (mix_sample >> 16) | ((mix_sample & 0x0000ffff) << 16);
	}

	// Set up the DMA.
	const u32		dma_src_address	= (u32)(dst_begin);
	const size_t	bytes			= samples_per_dma_buffer * sizeof(sample);
	AUDIO_InitDMA(dma_src_address, bytes);

	// Flush the data cache.
	DCFlushRange(dst_begin, bytes);

	// Start the DMA.
	AUDIO_StartDMA();

	// Move the mix buffer pointer.
	mix_buffer_pointer = (mix_buffer_pointer + samples_per_dma_buffer) % samples_per_mix_buffer;

	// Use the other DMA buffer next time.
	current_dma_buffer = 1 - current_dma_buffer;
}
Example #3
0
int
sound_lowlevel_init( const char *device, int *freqptr, int *stereoptr )
{
  switch(*freqptr) {
  case 32000:
    samplerate = AI_SAMPLERATE_32KHZ;
    break;
  case 48000:
    samplerate = AI_SAMPLERATE_48KHZ;
    break;
  default:
    printf("Sample rate %d not supported on Wii\n", *freqptr);
    return 1;
  }

  sfifo_init( &sound_fifo, BUFSIZE );
  *stereoptr = 1;
  
  AUDIO_Init( NULL );
  AUDIO_SetDSPSampleRate( samplerate );

#ifndef DISPLAY_AUDIO
  AUDIO_RegisterDMACallback( sound_dmacallback );
  memset( dmabuf, 0, BUFSIZE );
  AUDIO_InitDMA( (u32)dmabuf, BUFSIZE );
  DCFlushRange( dmabuf, dmalen );
  AUDIO_StartDMA();
#endif
  
  return 0;
}
Example #4
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 #5
0
static void audio_resume(void)
{
	playing = true;
	if(AUDIO_GetDMAEnableFlag()==0)
	{
		switch_buffers();
		AUDIO_StartDMA();
	}
}
Example #6
0
static void
sound_dmacallback( void )
{
  if( sfifo_used( &sound_fifo ) < 128) return;
  
  dmalen = MIN( BUFSIZE, sfifo_used( &sound_fifo ) );
  sfifo_read( &sound_fifo, dmabuf, dmalen );
  DCFlushRange( dmabuf, dmalen );
  AUDIO_InitDMA( (u32)dmabuf, dmalen );
  AUDIO_StartDMA();
}
Example #7
0
static void StartDMA(void)
{
    AUDIO_StopDMA();
    soundpos++;
    if (soundpos >= NUMSOUNDBLOCKS)
        soundpos = 0;

    AUDIO_InitDMA((u32)stereodata16[soundpos], soundtruelen * 4);
    DCFlushRange((void *)stereodata16[soundpos], soundtruelen * 4);
    AUDIO_StartDMA();
}
Example #8
0
static void 
switch_buffers(void)
{
  AUDIO_StopDMA();
  
  cur_buffer ^= 1;

  AUDIO_InitDMA((u32)buffer[cur_buffer], buffer_size[cur_buffer]);
  AUDIO_StartDMA();

  LWP_ThreadSignal(audio_queue);
}
Example #9
0
int SNDWiiInit()
{
    AUDIO_Init(NULL);
    AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);

    soundpos = 0;
    soundlen = 44100 / 60; // 60 for NTSC or 50 for PAL. Initially assume it's going to be NTSC.
    soundtruelen = 48000 / 60;
    truesoundoffset = stereodata16[0];

    memset(stereodata16, 0, SOUNDBUFSIZE);

    issoundmuted = 0;

    AUDIO_RegisterDMACallback(StartDMA);
    AUDIO_InitDMA((u32)stereodata16[soundpos], soundlen * 4);
    DCFlushRange((void *)stereodata16[soundpos], soundlen * 4);
    AUDIO_StartDMA();

    return 0;
}
Example #10
0
void OSystem_Wii::initSfx() {
	_mixer = new Audio::MixerImpl(this, 48000);

	sfx_thread_running = false;
	sfx_thread_quit = false;

	sfx_stack = (u8 *) memalign(32, SFX_THREAD_STACKSIZE);

	if (sfx_stack) {
		memset(sfx_stack, 0, SFX_THREAD_STACKSIZE);

		LWP_InitQueue(&sfx_queue);

		s32 res = LWP_CreateThread(&sfx_thread, sfx_thread_func, _mixer, sfx_stack,
									SFX_THREAD_STACKSIZE, SFX_THREAD_PRIO);

		if (res) {
			printf("ERROR creating sfx thread: %d\n", res);
			LWP_CloseQueue(sfx_queue);
			return;
		}

		sfx_thread_running = true;
	}

	for (u32 i = 0; i < SFX_BUFFERS; ++i) {
		sound_buffer[i] = (u8 *) memalign(32, SFX_THREAD_FRAG_SIZE);
		memset(sound_buffer[i], 0, SFX_THREAD_FRAG_SIZE);
		DCFlushRange(sound_buffer[i], SFX_THREAD_FRAG_SIZE);
	}

	_mixer->setReady(true);

	sb_hw = 0;

	AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
	AUDIO_RegisterDMACallback(audio_switch_buffers);
	AUDIO_InitDMA((u32) sound_buffer[sb_hw], SFX_THREAD_FRAG_SIZE);
	AUDIO_StartDMA();
}
Example #11
0
static void *gx_audio_init(const char *device, unsigned rate, unsigned latency)
{
   if (g_audio)
      return g_audio;

   AUDIO_Init(NULL);
   AUDIO_RegisterDMACallback(dma_callback);

   if (rate < 33000)
   {
      AUDIO_SetDSPSampleRate(AI_SAMPLERATE_32KHZ);
      g_settings.audio.out_rate = 32000;
   }
   else
   {
      AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
      g_settings.audio.out_rate = 48000;
   }

   if (!g_audio)
   {
      g_audio = memalign(32, sizeof(*g_audio));
      memset(g_audio, 0, sizeof(*g_audio));
      LWP_InitQueue(&g_audio->cond);
   }
   else
   {
      memset(g_audio->data, 0, sizeof(g_audio->data));
      g_audio->dma_busy = g_audio->dma_next = 0;
      g_audio->write_ptr = 0;
      g_audio->nonblock = false;
   }

   g_audio->dma_write = BLOCKS - 1;
   DCFlushRange(g_audio->data, sizeof(g_audio->data));
   AUDIO_InitDMA((u32)g_audio->data[g_audio->dma_next], CHUNK_SIZE);
   AUDIO_StartDMA();

   return g_audio;
}
Example #12
0
static int play(void *data, int remaining, int flags)
{
	int processed = 0;
	int samples = BUFFER_SIZE / (sizeof(s16) * HW_CHANNELS);
	s16 *source = (s16 *)data;

	while (remaining >= request_size && get_space() >= request_size)
	{
		copy_channels((s16 *)buffers[buffer_fill], source, samples, processed, remaining);
		DCStoreRangeNoSync(buffers[buffer_fill], BUFFER_SIZE);

		buffer_fill = (buffer_fill + 1) % BUFFER_COUNT;

		processed += request_size;
		source += request_size / sizeof(s16);
		buffered += BUFFER_SIZE;
		remaining -= request_size;		
	}

	if ((flags & AOPLAY_FINAL_CHUNK) && remaining > 0)
	{
		samples = remaining / (sizeof(s16) * HW_CHANNELS);
		memset(buffers[buffer_fill], 0, BUFFER_SIZE);
		copy_channels((s16 *)buffers[buffer_fill], source, samples, processed, 0);
		DCStoreRangeNoSync(buffers[buffer_fill], BUFFER_SIZE);
		buffer_fill = (buffer_fill + 1) % BUFFER_COUNT;

		processed += remaining;
		buffered += BUFFER_SIZE;
	}

	if (!playing)// && buffered > request_size)
	{
		playing = true;
		switch_buffers();
		AUDIO_StartDMA();
	}
	return processed;
}
Example #13
0
static void inline play_buffer(void){
#ifndef THREADED_AUDIO
	// We should wait for the other buffer to finish its DMA transfer first
	while( AUDIO_GetDMABytesLeft() );
	AUDIO_StopDMA();

#else // THREADED_AUDIO
	// Wait for a sample to actually be played to work around a deadlock
	LWP_SemWait(first_audio);
	
	// This thread will keep giving buffers to the audio as they come
	while(thread_running){

	// Wait for a buffer to be processed
	LWP_SemWait(buffer_full);
#endif

	// Make sure the buffer is in RAM, not the cache
	DCFlushRange(buffer[thread_buffer], buffer_size);

	// Actually send the buffer out to be played next
	AUDIO_InitDMA((unsigned int)&buffer[thread_buffer], buffer_size);

#ifdef THREADED_AUDIO
	// Wait for the audio interface to be free before playing
	LWP_SemWait(audio_free);
#endif

	// Start playing the buffer
	AUDIO_StartDMA();

#ifdef THREADED_AUDIO
	// Move the index to the next buffer
	NEXT(thread_buffer);
	}
#endif
}
Example #14
0
static int
wii_audio_start(audio_mode_t *am, audio_fifo_t *af)
{
  audio_buf_t *ab;
  int tbuf = 0, i;
  uint32_t level;
  int64_t pts;
  media_pipe_t *mp;

  prop_sub_t *s_vol;

  s_vol =
    prop_subscribe(PROP_SUB_DIRECT_UPDATE,
		   PROP_TAG_CALLBACK_FLOAT, set_mastervol, NULL,
		   PROP_TAG_ROOT, prop_mastervol,
		   NULL);

  LWP_InitQueue(&audio_queue);

  AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
  AUDIO_RegisterDMACallback(switch_buffers);

  AUDIO_StartDMA();

  while(1) {
    
    level = IRQ_Disable();
    while(tbuf == cur_buffer)
      LWP_ThreadSleep(audio_queue);
    tbuf = cur_buffer;
    IRQ_Restore(level);

    ab = af_deq(af, 0);
    
    if(am != audio_mode_current) {
      /* We're not the selected audio output anymore, return. */
      if(ab != NULL)
	ab_free(ab);
      break;
    }

    if(ab != NULL) {
      const int16_t *src = (const int16_t *)ab->ab_data;
      int16_t *dst = (int16_t *)buffer[!tbuf];
      for(i = 0; i < ADMA_BUFFER_SIZE / 2; i++)
	*dst++ = (*src++ * audio_vol) >> 16;

      /* PTS is the time of the first frame of this audio packet */

      if((pts = ab->ab_pts) != AV_NOPTS_VALUE && ab->ab_mp != NULL) {

#if 0
	/* Convert the frame delay into micro seconds */

	d = (fr * 1000 / aam->aam_sample_rate) * 1000;

	/* Subtract it from our timestamp, this will yield
	   the PTS for the sample currently played */

	pts -= d;

	/* Offset with user configure delay */
#endif

	pts += am->am_audio_delay * 1000;

	mp = ab->ab_mp;

	hts_mutex_lock(&mp->mp_clock_mutex);
	mp->mp_audio_clock = pts;
	mp->mp_audio_clock_realtime = showtime_get_ts();
	mp->mp_audio_clock_epoch = ab->ab_epoch;

	hts_mutex_unlock(&mp->mp_clock_mutex);

      }
      ab_free(ab);

    } else {
      memset(buffer[!tbuf], 0, ADMA_BUFFER_SIZE);
    }
    DCFlushRange(buffer[!tbuf], ADMA_BUFFER_SIZE);

  }
Example #15
0
static bool wii_audio_start(void *data)
{
   (void)data;
   AUDIO_StartDMA();
   return true;
}