// 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); } } } }
static inline void unlock(void) { sceKernelSignalSema(g_sema, 1); }
static int pmp_output_thread(SceSize input_length, void *input) { volatile struct pmp_play_struct *p = *((void **) input); sceCtrlSetSamplingCycle(0); sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); SceCtrlData previous_controller; sceCtrlPeekBufferPositive(&previous_controller, 1); unsigned int first_video_frame = 1; unsigned int current_buffer_number = 0; while (p->return_request == 0) { volatile struct pmp_decode_buffer_struct *current_buffer = &p->decoder.output_frame_buffers[current_buffer_number]; if (pmp_wait(p, p->semaphore_can_get, "pmp_output_thread: sceKernelWaitSema failed on semaphore_can_get") == 0) { break; } if (sceKernelSignalSema(p->semaphore_can_show, 1) < 0) { p->return_result = "pmp_output_thread: sceKernelSignalSema failed on semaphore_can_show"; p->return_request = 1; break; } if (p->seek == 0) { current_buffer->first_delay -= 500; sceKernelDelayThread(current_buffer->first_delay < 1 ? 1 : current_buffer->first_delay); sceAudioOutputBlocking(0, PSP_AUDIO_VOLUME_MAX, current_buffer->audio_frame); } pmp_input(p, &previous_controller); if (p->seek == 0) { int i = 1; for (; i < current_buffer->number_of_audio_frames; i++) { sceAudioOutputBlocking(0, PSP_AUDIO_VOLUME_MAX, current_buffer->audio_frame + p->decoder.audio_frame_size * i); } current_buffer->last_delay -= 500; sceKernelDelayThread(current_buffer->last_delay < 1 ? 1 : current_buffer->last_delay); } current_buffer_number = (current_buffer_number + 1) % p->decoder.number_of_frame_buffers; if (pmp_wait(p, p->semaphore_show_done, "pmp_output_thread: sceKernelWaitSema failed on semaphore_show_done") == 0) { break; } if (first_video_frame == 1) { first_video_frame = 0; } else { if (sceKernelSignalSema(p->semaphore_can_put, 1) < 0) { p->return_result = "pmp_output_thread: sceKernelSignalSema failed on semaphore_can_put"; p->return_request = 1; break; } } while (p->return_request == 0 && p->paused == 1) { sceKernelDelayThread(100000); pmp_input(p, &previous_controller); } } return(0); }
char *pmp_play_start(volatile struct pmp_play_struct *p) { sceKernelStartThread(p->output_thread, 4, &p); sceKernelStartThread(p->show_thread, 4, &p); int current_video_frame = 0; while (p->return_request == 0 && current_video_frame != p->decoder.reader.file.header.video.number_of_frames) { if (pmp_wait(p, p->semaphore_can_put, "pmp_play_start: sceKernelWaitSema failed on semaphore_can_put") == 0) { break; } //modify by cooleyes 2007/02/01 char *result = pmp_decode_get((struct pmp_decode_struct *) &p->decoder, current_video_frame, p->audio_stream, p->audio_channel, 1, p->volume_boost, p->aspect_ratio, p->zoom, p->luminosity_boost, p->show_interface, p->subtitle, p->subtitle_format, p->loop); //char *result = pmp_decode_get((struct pmp_decode_struct *) &p->decoder, current_video_frame, p->audio_stream, 1, p->volume_boost, p->aspect_ratio, p->zoom, p->luminosity_boost, p->show_interface, p->subtitle, p->subtitle_format, p->loop); //modify end if (result != 0) { p->return_result = result; p->return_request = 1; break; } if (sceKernelSignalSema(p->semaphore_can_get, 1) < 0) { p->return_result = "pmp_play_start: sceKernelSignalSema failed on semaphore_can_get"; p->return_request = 1; break; } current_video_frame = pmp_next_video_frame(p, current_video_frame); if ((p->loop == 1) && (current_video_frame == p->decoder.reader.file.header.video.number_of_frames)) { current_video_frame = 0; } } //*/ 2006.08.28 cooleyes if (current_video_frame == p->decoder.reader.file.header.video.number_of_frames) { p->last_keyframe_pos = 0; } //*/ sceKernelDelayThread(1000000); p->return_request = 1; sceKernelWaitThreadEnd(p->output_thread, 0); sceKernelWaitThreadEnd(p->show_thread, 0); return(p->return_result); }
void Psp2Audio::BGM_Play(std::string const& file, int volume, int pitch, int fadein) { // If a BGM is currently playing, we kill it BGM_Stop(); sceKernelWaitSema(BGM_Mutex, 1, NULL); if (BGM != NULL){ free(BGM->audiobuf); free(BGM->audiobuf2); audio_decoder.reset(); free(BGM); BGM = NULL; } // Opening file FILE* stream = FileFinder::fopenUTF8(file, "rb"); if (!stream) { Output::Warning("Couldn't open music file %s", file.c_str()); sceKernelSignalSema(BGM_Mutex, 1); return; } // Trying to use internal decoder audio_decoder = AudioDecoder::Create(stream, file); if (audio_decoder == NULL){ fclose(stream); Output::Warning("Unsupported music format (%s)", file.c_str()); sceKernelSignalSema(BGM_Mutex, 1); return; } // Initializing internal audio decoder int audiotype; fseek(stream, 0, SEEK_SET); if (!audio_decoder->Open(stream)) Output::Error("An error occured in audio decoder (%s)", audio_decoder->GetError().c_str()); audio_decoder->SetLooping(true); AudioDecoder::Format int_format; int samplerate; audio_decoder->SetFormat(48000, AudioDecoder::Format::S16, 2); audio_decoder->GetFormat(samplerate, int_format, audiotype); if (samplerate != 48000) Output::Warning("Cannot resample music file. Music will be distorted."); // Initializing music block DecodedMusic* myFile = (DecodedMusic*)malloc(sizeof(DecodedMusic)); // Check for file audiocodec if (audiotype == 2) myFile->isStereo = true; else myFile->isStereo = false; // Setting audiobuffer size myFile->audiobuf = (uint8_t*)malloc(AUDIO_BUFSIZE); myFile->audiobuf2 = (uint8_t*)malloc(AUDIO_BUFSIZE); myFile->cur_audiobuf = myFile->audiobuf; //Setting default streaming values myFile->handle = stream; myFile->endedOnce = false; // Passing new music block to the audio thread BGM = myFile; // Music settings audio_decoder->SetFade(0, volume, fadein); audio_decoder->SetPitch(pitch); BGM->tick = DisplayUi->GetTicks(); BGM->vol = volume; // Starting BGM BGM->isNewTrack = true; BGM->isPlaying = true; sceKernelSignalSema(BGM_Mutex, 1); }
void Unlock() { sceKernelSignalSema(handle, 1); }
/* Subroutine sceDdrdb_driver_05D50F41 - Address 0x00002B3C */ s32 sceDdrdbEncrypt(u8 *pSrcData, SceSize size) { s32 status; SceSize workSize; s32 tmpStatus; u32 i; tmpStatus = sceKernelWaitSema(g_semaId, 1, NULL); //0x00002B78 if (tmpStatus != SCE_ERROR_OK) return SCE_ERROR_SEMAPHORE; if (size <= SCE_DNAS_USER_DATA_MAX_LEN && IS_AES_BLOCK_LEN_MULTIPLE(size)) { // 0x00002B84 & 0x00002B90 // 0x00002C10 - 0x00002C24 /* Set up the work area for KIRK. */ KirkAESHeader *pAesHdr = (KirkAESHeader *)g_pWorkData; pAesHdr->mode = 4; pAesHdr->unk4 = 0; pAesHdr->unk8 = 0; pAesHdr->keyIndex = 0xB; pAesHdr->dataSize = size; /* Copy data to be encrypted into work area. */ u8 *pData = g_pWorkData + sizeof(KirkAESHeader); for (i = 0; i < size; i++) // 0x00002C34 - 0x00002C50 pData[i] = pSrcData[i]; //0x00002C50 workSize = size + sizeof(KirkAESHeader); //0x00002C58 status = SCE_DNAS_ERROR_OPERATION_FAILED; /* Encrypt the specified data. */ tmpStatus = sceUtilsBufferCopyWithRange(g_pWorkData, workSize, g_pWorkData, workSize, KIRK_CMD_ENCRYPT_AES_CBC_IV_NONE); //0x00002C6C if (tmpStatus == SCE_ERROR_OK) { //0x00002C74 /* Copy encrypted data into provided buffer. */ for (i = 0; i < size; i++) pSrcData[i] = pData[i]; status = SCE_ERROR_OK; //0x00002CAC } } else { status = SCE_DNAS_ERROR_INVALID_ARGUMENTS; // 0x00002BA0 /* * UOFW: size here is > SCE_DDRDB_MAX_BUFFER_SIZE, so more data gets cleared * below then neccessary. Depending on size, we even clear data which does not * belong to the work area. * Another note: Why do we have to clear any data in this case? The work area * wasn't set up. workSize should be 0. */ workSize = size + sizeof(KirkAESHeader); //0x00002B9C } /* Clear the work area. */ for (i = 0; i < workSize; i++) //0x00002BB0 - 0x00002BC4 g_pWorkData[i] = 0; tmpStatus = sceKernelSignalSema(g_semaId, 1); return (tmpStatus != SCE_ERROR_OK) ? SCE_ERROR_SEMAPHORE : status; //0x00002BD4 - 0x00002BDC }
void Psp2Ui::UpdateDisplay() { sceKernelWaitSema(GPU_Mutex, 1, NULL); memcpy(vita2d_texture_get_datap(next_texture), vita2d_texture_get_datap(main_texture), vita2d_texture_get_stride(main_texture)*240); sceKernelSignalSema(GPU_Mutex, 1); }
/*---------------------------------------------------------------------- | NPT_PSPMutex::Unlock +---------------------------------------------------------------------*/ NPT_Result NPT_PSPMutex::Unlock() { sceKernelSignalSema(m_semaphore, 1); return NPT_SUCCESS; }
int T_Audio(SceSize _args, void *_argp) { DecoderThreadData* D = *((DecoderThreadData**)_argp); sceKernelWaitSema(D->Audio->m_SemaphoreStart, 1, 0); for(;;) { if(D->Audio->m_iAbort != 0) break; if(D->Audio->m_iFullBuffers > 0) { sceAudioOutputBlocking(D->Audio->m_AudioChannel, PSP_AUDIO_VOLUME_MAX, D->Audio->m_pAudioBuffer[D->Audio->m_iPlayBuffer]); D->Audio->m_iPlayBuffer = (D->Audio->m_iPlayBuffer + 1) % D->Audio->m_iNumBuffers; sceKernelWaitSema(D->Audio->m_SemaphoreLock, 1, 0); D->Audio->m_iFullBuffers--; sceKernelSignalSema(D->Audio->m_SemaphoreLock, 1); } else { sceKernelDelayThread(1000); } sceKernelDelayThread(100); stop_pmf(); /*Human-Behind ** use to stop*/ if(stop == 1) { break; }/*Human-Behind ** use to stop*/ } while(D->Audio->m_iFullBuffers > 0) { sceAudioOutputBlocking(D->Audio->m_AudioChannel, PSP_AUDIO_VOLUME_MAX, D->Audio->m_pAudioBuffer[D->Audio->m_iPlayBuffer]); D->Audio->m_iPlayBuffer = (D->Audio->m_iPlayBuffer + 1) % D->Audio->m_iNumBuffers; sceKernelWaitSema(D->Audio->m_SemaphoreLock, 1, 0); D->Audio->m_iFullBuffers--; sceKernelSignalSema(D->Audio->m_SemaphoreLock, 1); sceKernelDelayThread(100); stop_pmf(); /*Human-Behind ** use to stop*/ if(stop == 1) { break; }/*Human-Behind ** use to stop*/ } sceKernelExitThread(0); return 0; }
void Psp2Audio::SE_Play(std::string const& file, int volume, int pitch) { // Opening file FILE* stream = FileFinder::fopenUTF8(file, "rb"); if (!stream) { Output::Warning("Couldn't open sound file %s", file.c_str()); return; } // Pick the next free SE slot. // Does not need synchronisation 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) { fclose(stream); Output::Warning("SE: No free channels available (%s)", file.c_str()); return; } DecodedSound& sfx = sfx_sounds[idx]; sfx.decoder = AudioDecoder::Create(stream, file); if (sfx.decoder == nullptr){ fclose(stream); Output::Warning("Unsupported sound format (%s)", file.c_str()); return; } // Initializing internal audio decoder int audiotype; AudioDecoder* decoder = sfx.decoder.get(); if (!decoder->Open(stream)) { Output::Warning("Error occured in audio decoder (%s)", audio_decoder->GetError().c_str()); return; } decoder->SetLooping(false); AudioDecoder::Format int_format; int samplerate; decoder->SetFormat(48000, AudioDecoder::Format::S16, 2); decoder->GetFormat(samplerate, int_format, audiotype); if (samplerate != 48000) Output::Warning("Cannot resample sound file. Sound will be distorted."); // Check for file audiocodec sfx.isStereo = audiotype == 2; // Setting default streaming values sfx.cur_audiobuf = sfx.audiobuf; decoder->SetPitch(pitch); decoder->SetVolume(volume); // Wait and signal is required to prevent reordering sceKernelWaitSema(SFX_Mutex_ID, 1, NULL); sfx.isPlaying = false; sfx.isFinished = false; sceKernelSignalSema(SFX_Mutex_ID, 1); // Start one SE thread sceKernelSignalSema(SFX_Mutex, 1); }
void Psp2Audio::BGM_Stop() { sceKernelWaitSema(BGM_Mutex, 1, NULL); if (BGM != NULL) BGM->isPlaying = false; sceKernelSignalSema(BGM_Mutex, 1); }
void Psp2Audio::BGM_Resume() { sceKernelWaitSema(BGM_Mutex, 1, NULL); if (BGM != NULL && (!BGM->isPlaying)) BGM->isPlaying = true; sceKernelSignalSema(BGM_Mutex, 1); }
sceKernelDeleteSema(sema); sema = sceKernelCreateSema("signal", 0, -3, 3, NULL); PRINT_SEMAPHORE(sema); SIGNAL_TEST("Start negative", sema, 1); sceKernelDeleteSema(sema); SIGNAL_TEST("NULL", 0, 1); SIGNAL_TEST("Invalid", 0xDEADBEEF, 1); SIGNAL_TEST("Deleted", sema, 1); TWO_STEP_SCHED_TEST("Signal other then same", 0, 0, result = sceKernelSignalSema(sema2, 1); , result = sceKernelSignalSema(sema1, 1); ); BASIC_SCHED_TEST("NULL", result = sceKernelSignalSema(0, 0); ); BASIC_SCHED_TEST("Other + 2", result = sceKernelSignalSema(sema2, 2); ); BASIC_SCHED_TEST("Other + 1", result = sceKernelSignalSema(sema2, 1); ); BASIC_SCHED_TEST("Other - 1", result = sceKernelSignalSema(sema2, -1); ); BASIC_SCHED_TEST("Same + 2",
/* Subroutine sceDdrdb_driver_B33ACB44 - Address 0x00002CB0 */ s32 sceDdrdbDecrypt(u8 *pSrcData, SceSize size) { s32 status; s32 workSize; s32 tmpStatus; u32 i; tmpStatus = sceKernelWaitSema(g_semaId, 1, NULL); //0x00002CF0 if (tmpStatus != SCE_ERROR_OK) return SCE_ERROR_SEMAPHORE; if (size <= SCE_DNAS_USER_DATA_MAX_LEN && IS_AES_BLOCK_LEN_MULTIPLE(size)) { //0x00002CFC & 0x00002CD0 // 0x00002D8C - 0x00002DA4 /* Set up the work area for KIRK. */ KirkAESHeader *pAesHdr = (KirkAESHeader *)g_pWorkData; pAesHdr->mode = 5; pAesHdr->unk4 = 0; pAesHdr->unk8 = 0; pAesHdr->keyIndex = 0xB; pAesHdr->dataSize = size; /* Copy data to be decrypted into work area. */ u8 *pData = g_pWorkData + sizeof(KirkAESHeader); for (i = 0; i < size; i++) //0x00002DB4 - 0x00002DD0 pData[i] = pSrcData[i]; workSize = size + sizeof(KirkAESHeader); //0x00002DD8 status = SCE_DNAS_ERROR_OPERATION_FAILED; //0x00002DF0 & 0x00002DF8 /* Decrypt the specified data. */ tmpStatus = sceUtilsBufferCopyWithRange(g_pWorkData, workSize, g_pWorkData, workSize, KIRK_CMD_DECRYPT_AES_CBC_IV_NONE); //0x00002DEC if (tmpStatus == SCE_ERROR_OK) { //0x00002DF4 /* Copy the computed data back into the provided buffer. */ for (i = 0; i < size; i++) //0x00002E04 - 0x00002E20 /* * UOFW: Is this correct? We are copying <size> bytes from the beginning of the * the work data, which includes the KIRK AES header. If the header is still * inside the workData after decryption, we copy wrong data over and miss out * the last <sizeof(KirkAESHeader)> bits of the data to be decrypted. * * Note: sceDdrdbEncrypt() assumes the header is still there and skips it accordingly. */ pSrcData[i] = g_pWorkData[i]; //0x00002E20 status = SCE_ERROR_OK; //0x00002E20 } } else { status = SCE_DNAS_ERROR_INVALID_ARGUMENTS; //0x00002D10 & 0x00002D18 /* * UOFW: size here is > SCE_DDRDB_MAX_BUFFER_SIZE, so more data gets cleared * below then neccessary. Depending on size, we even clear data which does not * belong to the work area. * Another note: Why do we have to clear any data in this case? The work area * wasn't set up. workSize should be 0. */ workSize = size + sizeof(KirkAESHeader); //0x00002D14 } /* Clear the work area. */ for (i = 0; i < workSize; i++) // 0x00002D20 - 0x00002D3C g_pWorkData[i] = 0; tmpStatus = sceKernelSignalSema(g_semaId, 1); //0x00002D44 return (tmpStatus != SCE_ERROR_OK) ? SCE_ERROR_SEMAPHORE : status; //0x00002D4C & 0x00002D50 & 0x00002D54 }
int T_Decoder(SceSize _args, void *_argp) { int retVal; int oldButtons = 0; SceCtrlData pad; #if DEBUG_TIMING int start, end; char s[200]; #endif int iInitAudio = 1; SceInt32 iVideoStatus = 0; int videoFrameCount = 0; int audioFrameCount = 0; SceInt32 unknown = 0; int iThreadsRunning = 0; SceInt32 m_iAudioCurrentTimeStamp = 0; SceInt32 m_iVideoCurrentTimeStamp = 0; SceInt32 m_iVideoLastTimeStamp = 0; DecoderThreadData* D = *((DecoderThreadData**)_argp); SceUInt32 m_iLastPacketsWritten = D->Reader->m_Ringbuffer->iUnk1; SceInt32 m_iLastPacketsAvailable = sceMpegRingbufferAvailableSize(D->Reader->m_Ringbuffer); D->Connector->initConnector(); for(;;) { sceKernelDelayThread(1); scePowerTick(0); sceCtrlReadBufferPositive(&pad, 1); int buttonDown = (oldButtons ^ pad.Buttons) & pad.Buttons; if (buttonDown & PSP_CTRL_CIRCLE) { break; } if( iThreadsRunning == 0 && IsRingbufferFull(D->Reader) && D->Video->m_iNumBuffers == D->Video->m_iFullBuffers) { iThreadsRunning = 1; sceKernelSignalSema(D->Video->m_SemaphoreStart, 1); sceKernelSignalSema(D->Audio->m_SemaphoreStart, 1); } if(D->Reader->m_Status == ReaderThreadData::READER_ABORT) { break; } else if(D->Reader->m_Status == ReaderThreadData::READER_EOF) { retVal = sceMpegRingbufferAvailableSize(D->Reader->m_Ringbuffer); if(retVal == D->Reader->m_RingbufferPackets) break; } if(!IsRingbufferFull(D->Reader)) { sceKernelWaitSema(D->Reader->m_Semaphore, 1, 0); if(D->Reader->m_Status == ReaderThreadData::READER_ABORT) break; } if (DEBUG_USERDATA) { SceInt32 unknown2[2]; SceUInt32 i; unknown2[0] = 0x12345678; unknown2[1] = 0xABCDEF98; retVal = sceMpegGetUserdataAu(&D->m_Mpeg, D->m_MpegStreamUserdata, D->m_MpegAuUserdata, unknown2); u8 *esBuffer = (u8 *) D->m_MpegAuUserdata->iEsBuffer; SceUInt32 esSize = D->m_MpegAuUserdata->iAuSize; sprintf(s, "sceMpegGetUserdataAu result 0x%08X", retVal); debug(s); if (retVal == 0) { sprintf(s, "sceMpegGetUserdataAu unknown[0]=0x%08X, unknown[1]=0x%08X, esBuffer=0x%08X, esSize=0x%X", unknown2[0], unknown2[1], D->m_MpegAuUserdata->iEsBuffer, esSize); debug(s); debug(D->m_MpegAuUserdata); for (i = 0; i < esSize; i += 8) { sprintf(s, "0x%08X: %02X %02X %02X %02X %02X %02X %02X %02X", D->m_MpegAuUserdata->iEsBuffer + i, esBuffer[i], esBuffer[i+1], esBuffer[i+2], esBuffer[i+3], esBuffer[i+4], esBuffer[i+5], esBuffer[i+6], esBuffer[i+7]); debug(s); } } } if(D->Audio->m_iFullBuffers < D->Audio->m_iNumBuffers) { #if DEBUG_TIMING start = sceKernelGetSystemTimeLow(); #endif retVal = sceMpegGetAtracAu(&D->m_Mpeg, D->m_MpegStreamAtrac, D->m_MpegAuAtrac, &unknown); #if DEBUG_TIMING end = sceKernelGetSystemTimeLow(); sprintf(s, "Duration sceMpegGetAtracAu %d, return %X, presentation timeStamp %d (%d), decode timeStamp %d", end - start, retVal, D->m_MpegAuAtrac->iPts, m_iAudioCurrentTimeStamp + D->m_iAudioFrameDuration, D->m_MpegAuAtrac->iDts); debug(s); debug(D->m_MpegAuAtrac); debug(D->Reader->m_Ringbuffer); #endif if(retVal != 0) { if(!IsRingbufferFull(D->Reader)) { sceKernelWaitSema(D->Reader->m_Semaphore, 1, 0); if(D->Reader->m_Status == ReaderThreadData::READER_ABORT) break; } } else { if(m_iAudioCurrentTimeStamp >= D->m_iLastTimeStamp - D->m_iVideoFrameDuration) break; #if DEBUG_TIMING start = sceKernelGetSystemTimeLow(); #endif retVal = sceMpegAtracDecode(&D->m_Mpeg, D->m_MpegAuAtrac, D->Audio->m_pAudioBuffer[D->Audio->m_iDecodeBuffer], iInitAudio); #if DEBUG_TIMING end = sceKernelGetSystemTimeLow(); sprintf(s, "Duration sceMpegAtracDecode %d, return %X", end - start, retVal); debug(s); debug(D->Reader->m_Ringbuffer); #endif if(retVal != 0) { sprintf(D->m_LastError, "sceMpegAtracDecode() failed: 0x%08X", retVal); break; } if(D->m_MpegAuAtrac->iPts == 0xFFFFFFFF) m_iAudioCurrentTimeStamp += D->m_iAudioFrameDuration; else m_iAudioCurrentTimeStamp = D->m_MpegAuAtrac->iPts; if(m_iAudioCurrentTimeStamp <= 0x15F90 /* video start ts */ - D->m_iAudioFrameDuration) iInitAudio = 1; D->Audio->m_iBufferTimeStamp[D->Audio->m_iDecodeBuffer] = m_iAudioCurrentTimeStamp; if(iInitAudio == 0) { D->Connector->sendAudioFrame(audioFrameCount, D->Audio->m_pAudioBuffer[D->Audio->m_iDecodeBuffer], D->m_MpegAtracOutSize, m_iAudioCurrentTimeStamp); audioFrameCount++; sceKernelWaitSema(D->Audio->m_SemaphoreLock, 1, 0); D->Audio->m_iFullBuffers++; sceKernelSignalSema(D->Audio->m_SemaphoreLock, 1); D->Audio->m_iDecodeBuffer = (D->Audio->m_iDecodeBuffer + 1) % D->Audio->m_iNumBuffers; } iInitAudio = 0; } } if(!IsRingbufferFull(D->Reader)) { sceKernelWaitSema(D->Reader->m_Semaphore, 1, 0); if(D->Reader->m_Status == ReaderThreadData::READER_ABORT) break; } if(D->Video->m_iFullBuffers < D->Video->m_iNumBuffers) { #if DEBUG_TIMING start = sceKernelGetSystemTimeLow(); #endif retVal = sceMpegGetAvcAu(&D->m_Mpeg, D->m_MpegStreamAVC, D->m_MpegAuAVC, &unknown); #if DEBUG_TIMING end = sceKernelGetSystemTimeLow(); sprintf(s, "Duration sceMpegGetAvcAu %d, return %X, presentation timeStamp %d (%d), decode timeStamp %d", end - start, retVal, D->m_MpegAuAVC->iPts, m_iVideoCurrentTimeStamp + 3004, D->m_MpegAuAVC->iDts); debug(s); debug(D->m_MpegAuAVC); debug(D->Reader->m_Ringbuffer); #endif if((SceUInt32)retVal == 0x80618001) { if(!IsRingbufferFull(D->Reader)) { sceKernelWaitSema(D->Reader->m_Semaphore, 1, 0); if(D->Reader->m_Status == ReaderThreadData::READER_ABORT) break; } } else if(retVal != 0) { sprintf(D->m_LastError, "sceMpegGetAvcAu() failed: 0x%08X", retVal); break; } else { if(m_iVideoCurrentTimeStamp >= D->m_iLastTimeStamp - D->m_iVideoFrameDuration) break; #if DEBUG_TIMING start = sceKernelGetSystemTimeLow(); #endif retVal = sceMpegAvcDecode(&D->m_Mpeg, D->m_MpegAuAVC, BUFFER_WIDTH, &D->Video->m_pVideoBuffer[D->Video->m_iPlayBuffer], &iVideoStatus); #if DEBUG_TIMING end = sceKernelGetSystemTimeLow(); sprintf(s, "Duration sceMpegAvcDecode %d, return %X", end - start, retVal); debug(s); debug(D->Reader->m_Ringbuffer); #endif if(retVal != 0) { sprintf(D->m_LastError, "sceMpegAvcDecode() failed: 0x%08X", retVal); break; } if(D->m_MpegAuAVC->iPts == 0xFFFFFFFF) m_iVideoCurrentTimeStamp += 0x0BBC; else m_iVideoCurrentTimeStamp = D->m_MpegAuAVC->iPts; if(iVideoStatus == 1) { SceUInt32 m_iPacketsWritten = D->Reader->m_Ringbuffer->iUnk1; SceInt32 m_iPacketsAvailable = sceMpegRingbufferAvailableSize(D->Reader->m_Ringbuffer); SceInt32 m_iDeltaPacketsWritten = m_iPacketsWritten - m_iLastPacketsWritten; if (m_iDeltaPacketsWritten < 0) { m_iDeltaPacketsWritten += D->Reader->m_Ringbuffer->iPackets; } SceInt32 m_iDeltaPacketsAvailable = m_iPacketsAvailable - m_iLastPacketsAvailable; SceInt32 m_iConsumedPackets = m_iDeltaPacketsAvailable + m_iDeltaPacketsWritten; m_iLastPacketsWritten = m_iPacketsWritten; m_iLastPacketsAvailable = m_iPacketsAvailable; D->Connector->sendVideoFrame(videoFrameCount, D->Video->m_pVideoBuffer[D->Video->m_iPlayBuffer], m_iVideoCurrentTimeStamp, D->Reader, m_iConsumedPackets); videoFrameCount++; D->Video->m_iBufferTimeStamp[D->Video->m_iPlayBuffer] = m_iVideoLastTimeStamp; sceKernelWaitSema(D->Video->m_SemaphoreLock, 1, 0); D->Video->m_iFullBuffers++; sceKernelSignalSema(D->Video->m_SemaphoreLock, 1); } m_iVideoLastTimeStamp = m_iVideoCurrentTimeStamp; } } if(!IsRingbufferFull(D->Reader)) { sceKernelWaitSema(D->Reader->m_Semaphore, 1, 0); if(D->Reader->m_Status == ReaderThreadData::READER_ABORT) break; } } D->Connector->exitConnector(); sceKernelSignalSema(D->Audio->m_SemaphoreStart, 1); sceKernelSignalSema(D->Video->m_SemaphoreStart, 1); D->Reader->m_Status = ReaderThreadData::READER_ABORT; D->Audio->m_iAbort = 1; while(D->Video->m_iFullBuffers > 0) { sceKernelWaitSema(D->Video->m_SemaphoreWait, 1, 0); sceKernelSignalSema(D->Video->m_SemaphoreLock, 1); } sceMpegAvcDecodeStop(&D->m_Mpeg, BUFFER_WIDTH, D->Video->m_pVideoBuffer, &iVideoStatus); if(iVideoStatus > 0) { sceKernelWaitSema(D->Video->m_SemaphoreLock, 1, 0); D->Video->m_iFullBuffers++; sceKernelSignalSema(D->Video->m_SemaphoreLock, 1); } D->Video->m_iAbort = 1; sceMpegFlushAllStream(&D->m_Mpeg); sceKernelExitThread(0); return 0; }
int signalSema(int sema){ return sceKernelSignalSema(sema, 1); }
int fillFileBuffer() { // wait for semaphore to be open sceKernelWaitSema(mutex, 1, 0); // Open the file if it's not open. if (SongIsChanged == 1) { SongIsChanged = 0; if (file>0) sceIoClose(file); // If the file wasn't closed before (got to next song before reaching EOF), close it now file = 0; } if (file <= 0) { char cd[1024]; memset(cd, 0, sizeof(cd)); getcwd(cd, sizeof(cd) - 1); char fileName[1024]; memset(fileName, 0, sizeof(fileName)); snprintf(fileName, sizeof(fileName) - 1, "%s/%s", cd, Song); file = sceIoOpen(fileName, PSP_O_RDONLY, 777); if (file <= 0) { pspDebugScreenPrintf("Failed (%s).\n", Song); sceKernelSignalSema(mutex, 1); /* * do something when file is not loaded */ return 1; } // Get the size. fileSize = sceIoLseek(file, 0, SEEK_END); sceIoLseek(file, 0, SEEK_SET); } // Find out how much to keep and how much to fill. const unsigned int bytesToKeep = stream.bufend - stream.next_frame; unsigned int bytesToFill = sizeof(fileBuffer) - bytesToKeep; //pspDebugScreenPrintf("bytesToFill = %u, bytesToKeep = %u.\n", bytesToFill, bytesToKeep); // Want to keep any bytes? if (bytesToKeep) { // Copy the tail to the head. memmove(fileBuffer, fileBuffer + sizeof(fileBuffer) - bytesToKeep, bytesToKeep); } // Read into the rest of the file buffer. unsigned char* bufferPos = fileBuffer + bytesToKeep; while (bytesToFill > 0) { // Read some. //pspDebugScreenPrintf("Reading %u bytes...\n", bytesToFill); const unsigned int bytesRead = sceIoRead(file, bufferPos, bytesToFill); // EOF? if (bytesRead == 0) { sceKernelSignalSema(mutex, 1); return 2; //handle stuff when end of file with return value !!!NOT HERE } // Adjust where we're writing to. bytesToFill -= bytesRead; bufferPos += bytesRead; filePos += bytesRead; //pspDebugScreenPrintf("Read %u bytes from the file, %u left to fill.\n", bytesRead, bytesToFill); //pspDebugScreenPrintf("%u%%.\n", filePos * 100 / fileSize); } // release the semaphore sceKernelSignalSema(mutex, 1); 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; } } } }