Example #1
0
/***
 * Shuts down the audio systems and frees the buffers.
 */
void audio_shutdown()
{
    int i;
    stop_audio = 1;

    for (i = 0; i < AUDIO_CHANNELS; i++)
    {
        if (audio_status[i].ThreadHandle != -1)
        {
            sceKernelDeleteThread(audio_status[i].ThreadHandle);
        }

        audio_status[i].ThreadHandle = -1;
    }

    for (i = 0; i < AUDIO_CHANNELS; i++)
    {
        if (audio_status[i].Handle != -1)
        {
            sceAudioOutReleasePort(audio_status[i].Handle);
            audio_status[i].Handle = -1;
        }
    }

    free_buffers();
    sceKernelDeleteMutex(audio_mutex);
}
Example #2
0
void pl_snd_shutdown()
{
  int i;
  sound_ready = 0;
  sound_stop = 1;

  for (i = 0; i < AUDIO_CHANNELS; i++)
  {
    if (sound_stream[i].thread_handle != -1)
    {
      //sceKernelWaitThreadEnd(sound_stream[i].threadhandle,NULL);
      sceKernelDeleteThread(sound_stream[i].thread_handle);
    }

    sound_stream[i].thread_handle = -1;
  }

  for (i = 0; i < AUDIO_CHANNELS; i++)
  {
    if (sound_stream[i].sound_ch_handle != -1)
    {
      sceAudioOutReleasePort(sound_stream[i].sound_ch_handle);
      sound_stream[i].sound_ch_handle = -1;
    }
  }

  free_buffers();
}
Example #3
0
static THREAD_ENTRY _audioThread(void* context) {
	struct mPSP2AudioContext* audio = (struct mPSP2AudioContext*) context;
	uint32_t zeroBuffer[PSP2_SAMPLES] = {0};
	void* buffer = zeroBuffer;
	int audioPort = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_MAIN, PSP2_SAMPLES, 48000, SCE_AUDIO_OUT_MODE_STEREO);
	while (audio->running) {
		MutexLock(&audio->mutex);
		if (buffer != zeroBuffer) {
			// Can only happen in successive iterations
			audio->samples -= PSP2_SAMPLES;
			ConditionWake(&audio->cond);
		}
		if (audio->samples >= PSP2_SAMPLES) {
			buffer = &audio->buffer[audio->readOffset];
			audio->readOffset += PSP2_SAMPLES;
			if (audio->readOffset >= PSP2_AUDIO_BUFFER_SIZE) {
				audio->readOffset = 0;
			}
			// Don't mark samples as read until the next loop iteration to prevent
			// writing to the buffer while being read (see above)
		} else {
			buffer = zeroBuffer;
		}
		MutexUnlock(&audio->mutex);

		sceAudioOutOutput(audioPort, buffer);
	}
	sceAudioOutReleasePort(audioPort);
	return 0;
}
static int streamThread(unsigned int args, void* arg){

	int vol, dec_vol;

	for(;;) {

		// A pretty bad way to close thread
		if(termStream){
			termStream = false;
			if (bgm_chn != 0xDEAD){
				sceAudioOutReleasePort(bgm_chn);
				bgm_chn = 0xDEAD;
			}
			sceKernelExitDeleteThread(0);
		}

		sceKernelWaitSema(BGM_Mutex, 1, NULL);
		if (BGM == NULL || (!BGM->isPlaying)){
			sceKernelSignalSema(BGM_Mutex, 1);
			continue;
		}

		// Seems like audio ports are thread dependant on PSVITA :/
		if (BGM->isNewTrack){
			uint8_t audio_mode = BGM->isStereo ? SCE_AUDIO_OUT_MODE_STEREO : SCE_AUDIO_OUT_MODE_MONO;
			int nsamples = AUDIO_BUFSIZE / ((audio_mode+1)<<1);
			if (bgm_chn == 0xDEAD) bgm_chn = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_MAIN, nsamples, 48000, audio_mode);
			sceAudioOutSetConfig(bgm_chn, nsamples, 48000, audio_mode);
			vol = BGM->vol * 327;
			int vol_stereo[] = {vol, vol};
			sceAudioOutSetVolume(bgm_chn, SCE_AUDIO_VOLUME_FLAG_L_CH | SCE_AUDIO_VOLUME_FLAG_R_CH, vol_stereo);
			BGM->isNewTrack = false;
		}

		// Volume changes support
		dec_vol = audio_decoder->GetVolume();
		if (dec_vol != vol){
			vol = dec_vol * 327;
			int vol_stereo[] = {vol, vol};
			sceAudioOutSetVolume(bgm_chn, SCE_AUDIO_VOLUME_FLAG_L_CH | SCE_AUDIO_VOLUME_FLAG_R_CH, vol_stereo);
			vol = dec_vol;
		}


		// Audio streaming feature
		if (BGM->handle != NULL){
			if (BGM->cur_audiobuf == BGM->audiobuf) BGM->cur_audiobuf = BGM->audiobuf2;
			else BGM->cur_audiobuf = BGM->audiobuf;
			audio_decoder->Decode(BGM->cur_audiobuf, AUDIO_BUFSIZE);
			if (audio_decoder->GetLoopCount() > 0){ // EoF
				BGM->endedOnce = true;
			}
			int res = sceAudioOutOutput(bgm_chn, BGM->cur_audiobuf);
			if (res < 0) Output::Error("An error occurred in audio thread (0x%lX)", res);
		}

		sceKernelSignalSema(BGM_Mutex, 1);

	}
}
Example #5
0
static void VITAAUD_CloseDevice(_THIS)
{
    if (this->hidden->channel >= 0) {
        sceAudioOutReleasePort(this->hidden->channel);
        this->hidden->channel = -1;
    }

    if (this->hidden->rawbuf != NULL) {
        free(this->hidden->rawbuf);
        this->hidden->rawbuf = NULL;
    }
}
Example #6
0
static int audioMainLoop(SceSize args, void* argp)
{
    psp_audio_t* psp = *((psp_audio_t**)argp);

#ifdef VITA
    int port = sceAudioOutOpenPort(PSP2_AUDIO_OUT_PORT_TYPE_MAIN, AUDIO_OUT_COUNT,
                                   psp->rate, PSP2_AUDIO_OUT_MODE_STEREO);
#else
    sceAudioSRCChReserve(AUDIO_OUT_COUNT, psp->rate, 2);
#endif

    while (psp->running)
    {
        /* Get a non-volatile copy. */
        uint16_t readPos = psp->readPos;
        bool cond        = ((uint16_t)(psp->writePos - readPos) & AUDIO_BUFFER_SIZE_MASK)
                           < (AUDIO_OUT_COUNT * 2);

#ifdef VITA
        sceAudioOutOutput(port,
                          cond ? psp->zeroBuffer : (psp->buffer + readPos));
#else
        sceAudioSRCOutputBlocking(PSP_AUDIO_VOLUME_MAX, cond ? (psp->zeroBuffer)
                                  : (psp->buffer + readPos));
#endif

        if (!cond)
        {
            readPos += AUDIO_OUT_COUNT;
            readPos &= AUDIO_BUFFER_SIZE_MASK;
            psp->readPos = readPos;
        }
    }

#ifdef VITA
    sceAudioOutReleasePort(port);
#else
    sceAudioSRCChRelease();
#endif
    sceKernelExitThread(0);
    return 0;
}
Example #7
0
/***
 * Initializes the audio buffers and a callback thread for each channel.
 */
int setup_audio()
{
    int i, j, failed;

    stop_audio = 0;

    for (i = 0; i < AUDIO_CHANNELS; i++)
    {
        audio_status[i].Handle = -1;
        audio_status[i].ThreadHandle = -1;
        audio_status[i].LeftVolume = PSP_AUDIO_MAX_VOLUME;
        audio_status[i].RightVolume = PSP_AUDIO_MAX_VOLUME;
        audio_status[i].Callback = NULL;
        audio_status[i].Userdata = NULL;

        for (j = 0; j < 2; j++)
        {
            audio_buffer[i][j] = NULL;
            audio_buffer_samples[i][j] = 0;
        }
    }

    /* Initialize buffers */
    for (i = 0; i < AUDIO_CHANNELS; i++)
    {
        for (j = 0; j < 2; j++)
        {
            if (!(audio_buffer[i][j] = (short*)malloc(AUDIO_SAMPLE_COUNT * sizeof(PspStereoSample))))
            {
                printf("Couldn't initialize audio buffer for channel %i, bailing.", i);
                free_buffers();
                sceKernelExitProcess(0);

                return 0;
            }

            audio_buffer_samples[i][j] = AUDIO_SAMPLE_COUNT;
        }
    }

    /* Initialize channels */
    for (i = 0, failed = 0; i < AUDIO_CHANNELS; i++)
    {
        audio_status[i].Handle = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_VOICE, AUDIO_SAMPLE_COUNT, AUDIO_OUTPUT_RATE, SCE_AUDIO_OUT_MODE_STEREO);

        if (audio_status[i].Handle < 0)
        {
            failed = 1;
            break;
        }
    }

    if (failed)
    {
        for (i = 0; i < AUDIO_CHANNELS; i++)
        {
            if (audio_status[i].Handle != -1)
            {
                sceAudioOutReleasePort(audio_status[i].Handle);
                audio_status[i].Handle = -1;
            }
        }

        printf("Couldn't open audio port for the device, bailing.");
        free_buffers();
        sceKernelExitProcess(0);

        return 0;
    }

    char label[16];
    strcpy(label, "audiotX");

    for (i = 0; i < AUDIO_CHANNELS; i++)
    {
        label[6] = '0' + i;
        audio_status[i].ThreadHandle =
            sceKernelCreateThread(label, (void*)&audio_channel_thread, 0x10000100, 0x10000,
                0, 0, NULL);

        if (audio_status[i].ThreadHandle < 0)
        {
            audio_status[i].ThreadHandle = -1;
            failed = 1;
            break;
        }

        if (sceKernelStartThread(audio_status[i].ThreadHandle, sizeof(i), &i) != 0)
        {
            failed = 1;
            break;
        }
    }

    if (failed)
    {
        stop_audio = 1;

        for (i = 0; i < AUDIO_CHANNELS; i++)
        {
            if (audio_status[i].ThreadHandle != -1)
            {
                sceKernelDeleteThread(audio_status[i].ThreadHandle);
            }

            audio_status[i].ThreadHandle = -1;
        }


        printf("Couldn't initialize audio callback thread. Bailing.");
        sceKernelExitProcess(0);

        return 0;
    }

    // initialize the buffer our libretro audio callback will fill with data as it's available
    retro_audio_callback_buffer = (int16_t*)malloc(sizeof(int16_t) * AUDIO_SAMPLE_COUNT * 4);

    if (!retro_audio_callback_buffer)
    {
        printf("Couldn't initialize retro_audio_callback_buffer. Bailing.");
        sceKernelExitProcess(0);
    }

    curr_buffer_frames = 0;

    // setup our callbacks
    set_audio_channel_callback(0, audio_callback, 0);

    // initialize the audio buffer mutex
    audio_mutex = sceKernelCreateMutex("AudioMutex", 0, 1, 0);

    return AUDIO_SAMPLE_COUNT;
}
Example #8
0
// Audio thread code
static int bgmThread(unsigned int args, void* arg){
	
	// Initializing audio port
	int ch = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_MAIN, NSAMPLES, 48000, SCE_AUDIO_OUT_MODE_STEREO);
	sceAudioOutSetConfig(ch, -1, -1, -1);
	old_vol = bgmvolume.value;
	int vol = 32767 * bgmvolume.value;
	int vol_stereo[] = {vol, vol};
	sceAudioOutSetVolume(ch, SCE_AUDIO_VOLUME_FLAG_L_CH | SCE_AUDIO_VOLUME_FLAG_R_CH, vol_stereo);
	
	DecodedMusic* mus;
	for (;;){
		
		// Waiting for an audio output request
		sceKernelWaitSema(Audio_Mutex, 1, NULL);
		
		// Fetching track
		mus = BGM;
		
		// Checking if a new track is available
		if (mus == NULL){
			
			//If we enter here, we probably are in the exiting procedure
			if (mustExit){
				sceAudioOutReleasePort(ch);
				mustExit = false;
				sceKernelExitDeleteThread(0);
			}
		
		}
		
		// Initializing audio decoder
		audio_decoder = AudioDecoder::Create(mus->handle, "Track");
		audio_decoder->Open(mus->handle);
		audio_decoder->SetLooping(mus->loop);
		audio_decoder->SetFormat(48000, AudioDecoder::Format::S16, 2);
		
		// Initializing audio buffers
		mus->audiobuf = (uint8_t*)malloc(BUFSIZE);
		mus->audiobuf2 = (uint8_t*)malloc(BUFSIZE);
		mus->cur_audiobuf = mus->audiobuf;
		
		// Audio playback loop
		for (;;){
		
			// Check if the music must be paused
			if (mus->pauseTrigger || mustExit){
			
				// Check if the music must be closed
				if (mus->closeTrigger){
					free(mus->audiobuf);
					free(mus->audiobuf2);
					audio_decoder.reset();
					free(mus);
					BGM = NULL;
					if (!mustExit){
						sceKernelSignalSema(Talk_Mutex, 1);
						break;
					}
				}
				
				// Check if the thread must be closed
				if (mustExit){
				
					// Check if the audio stream has already been closed
					if (mus != NULL){
						mus->closeTrigger = true;
						continue;
					}
					
					// Recursively closing all the threads
					sceAudioOutReleasePort(ch);
					mustExit = false;
					sceKernelExitThread(0);
					
				}
			
				mus->isPlaying = !mus->isPlaying;
				mus->pauseTrigger = false;
			}
			
			// Check if a volume change is required
			if (mus->changeVol){
				old_vol = bgmvolume.value;
				int vol = 32767 * bgmvolume.value;
				int vol_stereo[] = {vol, vol};
				sceAudioOutSetVolume(ch, SCE_AUDIO_VOLUME_FLAG_L_CH | SCE_AUDIO_VOLUME_FLAG_R_CH, vol_stereo);
				mus->changeVol = false;
			}
			
			if (mus->isPlaying){
				
				// Check if audio playback finished
				if ((!mus->loop) && audio_decoder->IsFinished()) mus->isPlaying = false;
				
				// Update audio output
				if (mus->cur_audiobuf == mus->audiobuf) mus->cur_audiobuf = mus->audiobuf2;
				else mus->cur_audiobuf = mus->audiobuf;
				audio_decoder->Decode(mus->cur_audiobuf, BUFSIZE);	
				sceAudioOutOutput(ch, mus->cur_audiobuf);
				
			}
			
		}
		
	}
	
}
Example #9
0
int pl_snd_init(int sample_count,
                int stereo)
{
  int i, j, failed;
  sound_stop = 0;
  sound_ready = 0;

  /* Check sample count */
  if (sample_count <= 0) sample_count = DEFAULT_SAMPLES;
  sample_count = PL_SND_ALIGN_SAMPLE(sample_count);

  pl_snd_channel_info *ch_info;
  for (i = 0; i < AUDIO_CHANNELS; i++)
  {
    ch_info = &sound_stream[i];
    ch_info->sound_ch_handle = -1;
    ch_info->thread_handle = -1;
    ch_info->left_vol = VOLUME_MAX;
    ch_info->right_vol = VOLUME_MAX;
    ch_info->callback = NULL;
    ch_info->user_data = NULL;
    ch_info->paused = 1;
    ch_info->stereo = stereo;

    for (j = 0; j < 2; j++)
    {
      ch_info->sample_buffer[j] = NULL;
      ch_info->samples[j] = 0;
    }
  }

  /* Initialize buffers */
  for (i = 0; i < AUDIO_CHANNELS; i++)
  {
    ch_info = &sound_stream[i];
    for (j = 0; j < 2; j++)
    {
      if (!(ch_info->sample_buffer[j] =
              (short*)malloc(sample_count * get_bytes_per_sample(i))))
      {
        free_buffers();
        return 0;
      }

      ch_info->samples[j] = sample_count;
    }
  }

  /* Initialize channels */
  for (i = 0, failed = 0; i < AUDIO_CHANNELS; i++)
  {
    sound_stream[i].sound_ch_handle =
      sceAudioOutOpenPort(PSP2_AUDIO_OUT_PORT_TYPE_MAIN,
                        sample_count, 48000,
                        (stereo)
                          ? PSP2_AUDIO_OUT_MODE_STEREO
                          : PSP2_AUDIO_OUT_MODE_MONO);

    if (sound_stream[i].sound_ch_handle < 0)
    {
      failed = 1;
      break;
    }
  }

  if (failed)
  {
    for (i = 0; i < AUDIO_CHANNELS; i++)
    {
      if (sound_stream[i].sound_ch_handle != -1)
      {
        sceAudioOutReleasePort(sound_stream[i].sound_ch_handle);
        sound_stream[i].sound_ch_handle = -1;
      }
    }

    free_buffers();
    return 0;
  }

  sound_ready = 1;

  char label[16];
  strcpy(label, "audiotX");

  for (i = 0; i < AUDIO_CHANNELS; i++)
  {
    label[6] = '0' + i;
    sound_stream[i].thread_handle =
      sceKernelCreateThread(label, (void*)&channel_thread, 0x10000100, 0x10000,
        0, 0, NULL);

    if (sound_stream[i].thread_handle < 0)
    {
      sound_stream[i].thread_handle = -1;
      failed = 1;
      break;
    }

    if (sceKernelStartThread(sound_stream[i].thread_handle, sizeof(i), &i) != 0)
    {
      failed = 1;
      break;
    }
  }

  if (failed)
  {
    sound_stop = 1;
    for (i = 0; i < AUDIO_CHANNELS; i++)
    {
      if (sound_stream[i].thread_handle != -1)
      {
        //sceKernelWaitThreadEnd(sound_stream[i].threadhandle,NULL);
        sceKernelDeleteThread(sound_stream[i].thread_handle);
      }

      sound_stream[i].thread_handle = -1;
    }

    sound_ready = 0;
    free_buffers();
    return 0;
  }

  return sample_count;
}
Example #10
0
static int audioMainLoop(SceSize args, void* argp)
{
   psp_audio_t* psp = *((psp_audio_t**)argp);

#ifdef VITA
   int port = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_MAIN, AUDIO_OUT_COUNT,
      psp->rate, SCE_AUDIO_OUT_MODE_STEREO);
#else
   sceAudioSRCChReserve(AUDIO_OUT_COUNT, psp->rate, 2);
#endif

   while (psp->running)
   {
#ifdef VITA
      
      //sys_event_queue_receive(id, &event, SYS_NO_TIMEOUT);

      sceKernelLockLwMutex((struct SceKernelLwMutexWork*)&psp->lock, 1, 0);
      uint16_t readPos = psp->readPos;
      uint16_t readPos2 = psp->readPos;
      bool cond        = ((uint16_t)(psp->writePos - readPos) & AUDIO_BUFFER_SIZE_MASK)
            < (AUDIO_OUT_COUNT * 2);
      if (!cond)
      {
         readPos += AUDIO_OUT_COUNT;
         readPos &= AUDIO_BUFFER_SIZE_MASK;
         psp->readPos = readPos;
      }
      sceKernelUnlockLwMutex((struct SceKernelLwMutexWork*)&psp->lock, 1);
      sceKernelSignalLwCond(&psp->cond);
      
      sceAudioOutOutput(port,
        cond ? (psp->zeroBuffer)
              : (psp->buffer + readPos2));
              
      
#else
      /* Get a non-volatile copy. */
      uint16_t readPos = psp->readPos;
      bool cond        = ((uint16_t)(psp->writePos - readPos) & AUDIO_BUFFER_SIZE_MASK)
            < (AUDIO_OUT_COUNT * 2);

      sceAudioSRCOutputBlocking(PSP_AUDIO_VOLUME_MAX, cond ? (psp->zeroBuffer)
            : (psp->buffer + readPos));

      if (!cond)
      {
         readPos += AUDIO_OUT_COUNT;
         readPos &= AUDIO_BUFFER_SIZE_MASK;
         psp->readPos = readPos;
      }

#endif

   }

#ifdef VITA
   sceAudioOutReleasePort(port);
#else
   sceAudioSRCChRelease();
   sceKernelExitThread(0);
#endif
   return 0;
}
static int sfxThread(unsigned int args, void* arg){
	int ch = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_MAIN, 64, 48000, SCE_AUDIO_OUT_MODE_STEREO);
	if (ch < 0){
		Output::Warning("SFX Thread: Cannot open audio port");
		sceKernelExitDeleteThread(0);
	}

	for (;;){
		sceKernelWaitSema(SFX_Mutex, 1, NULL);

		// Check if the thread must be closed
		if (mustExit){
			sfx_exited++;
			if (sfx_exited < AUDIO_CHANNELS) sceKernelSignalSema(SFX_Mutex, 1);
			else mustExit = false;
			sceAudioOutReleasePort(ch);
			sceKernelExitDeleteThread(0);
		}

		// Pick the next SE that wants to be played
		sceKernelWaitSema(SFX_Mutex_ID, 1, NULL);
		int idx = -1;
		for (int i = 0; i < AUDIO_CHANNELS; ++i) {
			if (!sfx_sounds[i].isPlaying && !sfx_sounds[i].isFinished) {
				idx = i;
				break;
			}
		}

		if (idx == -1) {
			sceKernelSignalSema(SFX_Mutex_ID, 1);
			// Shouldn't happen...
			Output::Warning("No pending SE found");
			continue;
		} else {
			sfx_sounds[idx].isPlaying = true;
			sceKernelSignalSema(SFX_Mutex_ID, 1);
		}

		DecodedSound& sfx = sfx_sounds[idx];

		// Preparing audio port
		uint8_t audio_mode = sfx.isStereo ? SCE_AUDIO_OUT_MODE_STEREO : SCE_AUDIO_OUT_MODE_MONO;
		int nsamples = AUDIO_BUFSIZE / ((audio_mode+1)<<1);
		sceAudioOutSetConfig(ch, nsamples, 48000, audio_mode);
		int vol = sfx.decoder->GetVolume() * 327;
		int vol_stereo[] = {vol, vol};
		sceAudioOutSetVolume(ch, SCE_AUDIO_VOLUME_FLAG_L_CH | SCE_AUDIO_VOLUME_FLAG_R_CH, vol_stereo);

		// Playing sound
		while (!sfx.isFinished){
			if (sfx.cur_audiobuf == sfx.audiobuf) sfx.cur_audiobuf = sfx.audiobuf2;
			else sfx.cur_audiobuf = sfx.audiobuf;
			sfx.decoder->Decode(sfx.cur_audiobuf, AUDIO_BUFSIZE);
			sceAudioOutOutput(ch, sfx.cur_audiobuf);
			if (sfx.decoder->IsFinished()) { // EoF
				// SE slot is free again
				sfx.isFinished = true;
				break;
			}
		}
	}

}