diff --git a/include/audio/audio.h b/include/audio/audio.h index a20b6e3..5c95e74 100644 --- a/include/audio/audio.h +++ b/include/audio/audio.h @@ -27,6 +27,7 @@ SceUInt64 Audio_GetPosition(void); SceUInt64 Audio_GetLength(void); SceUInt64 Audio_GetPositionSeconds(void); SceUInt64 Audio_GetLengthSeconds(void); +void Audio_Seek(SceUInt64 index); void Audio_Term(void); #endif diff --git a/include/audio/flac.h b/include/audio/flac.h index 0411b2f..f445f48 100644 --- a/include/audio/flac.h +++ b/include/audio/flac.h @@ -9,6 +9,7 @@ SceUInt8 FLAC_GetChannels(void); void FLAC_Decode(void *buf, unsigned int length, void *userdata); SceUInt64 FLAC_GetPosition(void); SceUInt64 FLAC_GetLength(void); +SceUInt64 FLAC_Seek(SceUInt64 index); void FLAC_Term(void); #endif diff --git a/include/audio/mp3.h b/include/audio/mp3.h index cd6c26b..bab7523 100644 --- a/include/audio/mp3.h +++ b/include/audio/mp3.h @@ -9,6 +9,7 @@ SceUInt8 MP3_GetChannels(void); void MP3_Decode(void *buf, unsigned int length, void *userdata); SceUInt64 MP3_GetPosition(void); SceUInt64 MP3_GetLength(void); +SceUInt64 MP3_Seek(SceUInt64 index); void MP3_Term(void); #endif diff --git a/include/audio/ogg.h b/include/audio/ogg.h index 34adacb..c8f2a9a 100644 --- a/include/audio/ogg.h +++ b/include/audio/ogg.h @@ -9,6 +9,7 @@ SceUInt8 OGG_GetChannels(void); void OGG_Decode(void *buf, unsigned int length, void *userdata); SceUInt64 OGG_GetPosition(void); SceUInt64 OGG_GetLength(void); +SceUInt64 OGG_Seek(SceUInt64 index); void OGG_Term(void); #endif diff --git a/include/audio/opus.h b/include/audio/opus.h index 550da56..883438e 100644 --- a/include/audio/opus.h +++ b/include/audio/opus.h @@ -9,6 +9,7 @@ SceUInt8 OPUS_GetChannels(void); void OPUS_Decode(void *buf, unsigned int length, void *userdata); SceUInt64 OPUS_GetPosition(void); SceUInt64 OPUS_GetLength(void); +SceUInt64 OPUS_Seek(SceUInt64 index); void OPUS_Term(void); #endif diff --git a/include/audio/wav.h b/include/audio/wav.h index a1b5696..fb07126 100644 --- a/include/audio/wav.h +++ b/include/audio/wav.h @@ -9,6 +9,7 @@ SceUInt8 WAV_GetChannels(void); void WAV_Decode(void *buf, unsigned int length, void *userdata); SceUInt64 WAV_GetPosition(void); SceUInt64 WAV_GetLength(void); +SceUInt64 WAV_Seek(SceUInt64 index); void WAV_Term(void); #endif diff --git a/include/audio/xm.h b/include/audio/xm.h index e17c2f9..5fc3c14 100644 --- a/include/audio/xm.h +++ b/include/audio/xm.h @@ -9,6 +9,7 @@ SceUInt8 XM_GetChannels(void); void XM_Decode(void *buf, unsigned int length, void *userdata); SceUInt64 XM_GetPosition(void); SceUInt64 XM_GetLength(void); +SceUInt64 XM_Seek(SceUInt64 index); void XM_Term(void); #endif diff --git a/source/audio/audio.c b/source/audio/audio.c index 71008e5..0b03ab2 100644 --- a/source/audio/audio.c +++ b/source/audio/audio.c @@ -279,6 +279,37 @@ SceUInt64 Audio_GetLengthSeconds(void) { return (Audio_GetLength() / Audio_GetSampleRate()); } +void Audio_Seek(SceUInt64 index) { + switch(file_type) { + case FILE_TYPE_FLAC: + FLAC_Seek(index); + break; + + case FILE_TYPE_MP3: + MP3_Seek(index); + break; + + case FILE_TYPE_OGG: + OGG_Seek(index); + break; + + case FILE_TYPE_OPUS: + OPUS_Seek(index); + break; + + case FILE_TYPE_WAV: + WAV_Seek(index); + break; + + case FILE_TYPE_XM: + XM_Seek(index); + break; + + default: + break; + } +} + void Audio_Term(void) { switch(file_type) { case FILE_TYPE_FLAC: diff --git a/source/audio/flac.c b/source/audio/flac.c index 489a4e0..f080bcd 100644 --- a/source/audio/flac.c +++ b/source/audio/flac.c @@ -109,7 +109,7 @@ SceUInt8 FLAC_GetChannels(void) { void FLAC_Decode(void *buf, unsigned int length, void *userdata) { frames_read += drflac_read_pcm_frames_s16(flac, (drflac_uint64)length, (drflac_int16 *)buf); - if (frames_read == flac->totalPCMFrameCount) + if (frames_read >= flac->totalPCMFrameCount) playing = SCE_FALSE; } @@ -121,6 +121,17 @@ SceUInt64 FLAC_GetLength(void) { return flac->totalPCMFrameCount; } +SceUInt64 FLAC_Seek(SceUInt64 index) { + drflac_uint64 seek_frame = (flac->totalPCMFrameCount * (index / 450.0)); + + if (drflac_seek_to_pcm_frame(flac, seek_frame) == DRFLAC_TRUE) { + frames_read = seek_frame; + return frames_read; + } + + return -1; +} + void FLAC_Term(void) { frames_read = 0; diff --git a/source/audio/mp3.c b/source/audio/mp3.c index 66e7800..53c18db 100644 --- a/source/audio/mp3.c +++ b/source/audio/mp3.c @@ -123,6 +123,15 @@ int MP3_Init(const char *path) { if (error != MPG123_OK) return error; + error = mpg123_param(mp3, MPG123_FLAGS, MPG123_FORCE_SEEKABLE | MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS, 0.0); + if (error != MPG123_OK) + return error; + + // Let the seek index auto-grow and contain an entry for every frame + error = mpg123_param(mp3, MPG123_INDEX_SIZE, -1, 0.0); + if (error != MPG123_OK) + return error; + error = mpg123_param(mp3, MPG123_ADD_FLAGS, MPG123_PICTURE, 0.0); if (error != MPG123_OK) return error; @@ -163,15 +172,16 @@ int MP3_Init(const char *path) { } } - total_samples = mpg123_length(mp3); mpg123_getformat(mp3, &sample_rate, &channels, NULL); mpg123_format_none(mp3); - mpg123_format(mp3, sample_rate, channels, MPG123_ENC_SIGNED_16); + mpg123_format(mp3, 44100, channels, MPG123_ENC_SIGNED_16); + + total_samples = mpg123_length(mp3); return 0; } SceUInt32 MP3_GetSampleRate(void) { - return sample_rate; + return 44100; } SceUInt8 MP3_GetChannels(void) { @@ -183,7 +193,7 @@ void MP3_Decode(void *buf, unsigned int length, void *userdata) { mpg123_read(mp3, buf, length * (sizeof(SceInt16) * 2), &done); frames_read += done/(sizeof(SceInt16) * 2); - if (frames_read == total_samples) + if (frames_read >= total_samples) playing = SCE_FALSE; } @@ -195,6 +205,17 @@ SceUInt64 MP3_GetLength(void) { return total_samples; } +SceUInt64 MP3_Seek(SceUInt64 index) { + off_t seek_frame = (total_samples * (index / 450.0)); + + if (mpg123_seek(mp3, seek_frame, SEEK_SET) >= 0) { + frames_read = seek_frame; + return frames_read; + } + + return -1; +} + void MP3_Term(void) { frames_read = 0; diff --git a/source/audio/ogg.c b/source/audio/ogg.c index e539eb5..a32a61c 100644 --- a/source/audio/ogg.c +++ b/source/audio/ogg.c @@ -108,7 +108,7 @@ void OGG_Decode(void *buf, unsigned int length, void *userdata) { OGG_FillBuffer((char *)buf); samples_read = ov_pcm_tell(&ogg); - if (samples_read == max_lenth) + if (samples_read >= max_lenth) playing = SCE_FALSE; } @@ -120,6 +120,17 @@ SceUInt64 OGG_GetLength(void) { return max_lenth; } +SceUInt64 OGG_Seek(SceUInt64 index) { + ogg_int64_t seek_sample = (max_lenth * (index / 450.0)); + + if (ov_pcm_seek(&ogg, seek_sample) >= 0) { + samples_read = seek_sample; + return samples_read; + } + + return -1; +} + void OGG_Term(void) { samples_read = 0; diff --git a/source/audio/opus.c b/source/audio/opus.c index 7bba2c0..d85165a 100644 --- a/source/audio/opus.c +++ b/source/audio/opus.c @@ -86,7 +86,7 @@ void OPUS_Decode(void *buf, unsigned int length, void *userdata) { if (read) samples_read = op_pcm_tell(opus); - if (samples_read == max_samples) + if (samples_read >= max_samples) playing = SCE_FALSE; } @@ -98,6 +98,19 @@ SceUInt64 OPUS_GetLength(void) { return max_samples; } +SceUInt64 OPUS_Seek(SceUInt64 index) { + if (op_seekable(opus) >= 0) { + ogg_int64_t seek_sample = (max_samples * (index / 450.0)); + + if (op_pcm_seek(opus, seek_sample) >= 0) { + samples_read = seek_sample; + return samples_read; + } + } + + return -1; +} + void OPUS_Term(void) { samples_read = 0; diff --git a/source/audio/wav.c b/source/audio/wav.c index f359bc7..7963c71 100644 --- a/source/audio/wav.c +++ b/source/audio/wav.c @@ -23,7 +23,7 @@ SceUInt8 WAV_GetChannels(void) { void WAV_Decode(void *buf, unsigned int length, void *userdata) { frames_read += drwav_read_pcm_frames_s16(&wav, (drwav_uint64)length, (drwav_int16 *)buf); - if (frames_read == wav.totalPCMFrameCount) + if (frames_read >= wav.totalPCMFrameCount) playing = SCE_FALSE; } @@ -35,6 +35,17 @@ SceUInt64 WAV_GetLength(void) { return wav.totalPCMFrameCount; } +SceUInt64 WAV_Seek(SceUInt64 index) { + drwav_uint64 seek_frame = (wav.totalPCMFrameCount * (index / 450.0)); + + if (drwav_seek_to_pcm_frame(&wav, seek_frame) == DRWAV_TRUE) { + frames_read = seek_frame; + return frames_read; + } + + return -1; +} + void WAV_Term(void) { frames_read = 0; drwav_uninit(&wav); diff --git a/source/audio/xm.c b/source/audio/xm.c index 571633c..9f7b1c9 100644 --- a/source/audio/xm.c +++ b/source/audio/xm.c @@ -10,7 +10,9 @@ static SceUInt64 samples_read = 0, total_samples = 0; int XM_Init(const char *path) { xmp = xmp_create_context(); - if (xmp_load_module(xmp, (char *)path) < 0) + char *xmp_path = strdup(path); + + if (xmp_load_module(xmp, xmp_path) < 0) return -1; xmp_start_player(xmp, 44100, 0); @@ -38,7 +40,7 @@ void XM_Decode(void *buf, unsigned int length, void *userdata) { xmp_play_buffer(xmp, buf, (int)length * (sizeof(SceInt16) * 2), 0); samples_read += length; - if (samples_read == total_samples) + if (samples_read >= total_samples) playing = SCE_FALSE; } @@ -50,6 +52,17 @@ SceUInt64 XM_GetLength(void) { return total_samples; } +SceUInt64 XM_Seek(SceUInt64 index) { + int seek_sample = (total_samples * (index / 450.0)); + + if (xmp_seek_time(xmp, seek_sample/44.1) >= 0) { + samples_read = seek_sample; + return samples_read; + } + + return -1; +} + void XM_Term(void) { samples_read = 0; xmp_end_player(xmp); diff --git a/source/menus/menu_audioplayer.c b/source/menus/menu_audioplayer.c index 319afe7..a2ce1b5 100644 --- a/source/menus/menu_audioplayer.c +++ b/source/menus/menu_audioplayer.c @@ -217,6 +217,18 @@ void Menu_PlayAudio(char *path) { if (pressed & SCE_CTRL_ENTER) Audio_Pause(); + if (Touch_CheckHeld() && Touch_GetX() >= 460 && Touch_GetX() <= 910 && Touch_GetY() >= 480 && Touch_GetY() <= 505) { + // Pause first if not paused. + if (!Audio_IsPaused()) + Audio_Pause(); + + Audio_Seek(Touch_GetX() - 460); + + // Unpause. + if (Audio_IsPaused()) + Audio_Pause(); + } + if (pressed & SCE_CTRL_TRIANGLE) { if (state == MUSIC_STATE_SHUFFLE) state = MUSIC_STATE_NONE;