diff --git a/src/libs/decoders/mp3.cpp b/src/libs/decoders/mp3.cpp index 7484ca83..90d7ca90 100644 --- a/src/libs/decoders/mp3.cpp +++ b/src/libs/decoders/mp3.cpp @@ -24,8 +24,9 @@ #endif #include - #include // provides: SDL_malloc, SDL_realloc, SDL_free, SDL_memcpy, and SDL_memset +#include + #define DR_MP3_IMPLEMENTATION #define DR_MP3_NO_STDIO 1 #define DRMP3_FREE(p) SDL_free((p)) @@ -108,31 +109,30 @@ static Uint32 MP3_read(Sound_Sample* const sample, void* buffer, Uint32 desired_ static_cast(buffer))); } /* MP3_read */ -static Sint32 MP3_open(Sound_Sample* const sample, const char* const ext) +static int32_t MP3_open(Sound_Sample* const sample, const char* const ext) { (void) ext; // deliberately unused Sound_SampleInternal* const internal = static_cast(sample->opaque); - Sint32 result(0); // assume failure until proven otherwise + bool result = false; // assume failure until proven otherwise mp3_t* p_mp3 = (mp3_t*) SDL_calloc(1, sizeof (mp3_t)); - if (p_mp3 != nullptr) { + if (p_mp3) { p_mp3->p_dr = (drmp3*) SDL_calloc(1, sizeof (drmp3)); - if (p_mp3->p_dr != nullptr) { - result = drmp3_init(p_mp3->p_dr, mp3_read, mp3_seek, sample, nullptr, nullptr); - if (result == DRMP3_TRUE) { + if (p_mp3->p_dr) { + if (drmp3_init(p_mp3->p_dr, mp3_read, mp3_seek, sample, nullptr, nullptr) == DRMP3_TRUE) { SNDDBG(("MP3: Accepting data stream.\n")); sample->flags = SOUND_SAMPLEFLAG_CANSEEK; - sample->actual.channels = p_mp3->p_dr->channels; + sample->actual.channels = static_cast(p_mp3->p_dr->channels); sample->actual.rate = p_mp3->p_dr->sampleRate; - sample->actual.format = AUDIO_S16SYS; // returns native byte-order based on architecture - const Uint64 num_frames = populate_seek_points(internal->rw, p_mp3, MP3_FAST_SEEK_FILENAME); // status will be 0 or pcm_frame_count - if (num_frames != 0) { - const unsigned int rate = p_mp3->p_dr->sampleRate; - internal->total_time = ( static_cast(num_frames) / rate) * 1000; - internal->total_time += (num_frames % rate) * 1000 / rate; - result = 1; - } else { - internal->total_time = -1; - } + sample->actual.format = AUDIO_S16SYS; // native byte-order based on architecture + + // frame count is agnostic of sample size and number of channels + const uint64_t num_frames = + populate_seek_points(internal->rw, p_mp3, MP3_FAST_SEEK_FILENAME, result); + + // total_time needs milliseconds + internal->total_time = (num_frames != 0) ? + static_cast(ceil_divide(num_frames * 1000u, sample->actual.rate)) + : -1; } } } @@ -141,11 +141,12 @@ static Sint32 MP3_open(Sound_Sample* const sample, const char* const ext) internal->decoder_private = p_mp3; // if anything went wrong then tear down our private structure - if (result == 0) { + if (!result) { + SNDDBG(("MP3: Failed to open the data stream.\n")); MP3_close(sample); } - return result; + return static_cast(result); } /* MP3_open */ static Sint32 MP3_rewind(Sound_Sample* const sample) @@ -159,9 +160,9 @@ static Sint32 MP3_seek(Sound_Sample* const sample, const Uint32 ms) { Sound_SampleInternal* const internal = static_cast(sample->opaque); mp3_t* p_mp3 = static_cast(internal->decoder_private); - const float frames_per_ms = sample->actual.rate / 1000.0f; - const drmp3_uint64 frame_offset = static_cast(frames_per_ms) * ms; - const Sint32 result = drmp3_seek_to_pcm_frame(p_mp3->p_dr, frame_offset); + const uint64_t sample_rate = sample->actual.rate; + const drmp3_uint64 pcm_frame = ceil_divide(sample_rate * ms, 1000u); + const drmp3_bool32 result = drmp3_seek_to_pcm_frame(p_mp3->p_dr, pcm_frame); return (result == DRMP3_TRUE); } /* MP3_seek */ diff --git a/src/libs/decoders/mp3_seek_table.cpp b/src/libs/decoders/mp3_seek_table.cpp index 517d3da8..e5a6c886 100644 --- a/src/libs/decoders/mp3_seek_table.cpp +++ b/src/libs/decoders/mp3_seek_table.cpp @@ -80,6 +80,7 @@ #include // Local headers +#include "support.h" #include "xxhash.h" // #include "../../../include/logging.h" #include "mp3_seek_table.h" @@ -99,13 +100,13 @@ using std::ofstream; // time point. The trade-off is as follows: // - a large number means slower in-game seeking but a smaller fast-seek file. // - a smaller numbers (below 10) results in fast seeks on slow hardware. -#define FRAMES_PER_SEEK_POINT 7 +#define FRAMES_PER_SEEK_POINT 7u // Returns the size of a file in bytes (if valid), otherwise 0 -size_t get_file_size(const char* filename) { +uint64_t get_file_size(const char* filename) { struct stat stat_buf; int rc = stat(filename, &stat_buf); - return rc == 0 ? stat_buf.st_size : -1; + return rc == 0 ? static_cast(stat_buf.st_size) : 0u; } @@ -147,7 +148,7 @@ Uint64 calculate_stream_hash(struct SDL_RWops* const context) { // have the same trailing 32KB of content. The different seeds will produce // unique hashes. XXH64_state_t* const state = XXH64_createState(); - const Uint64 seed = stream_size; + const uint64_t seed = static_cast(stream_size); XXH64_reset(state, seed); while (total_bytes_read < static_cast(tail_size)) { @@ -186,9 +187,9 @@ Uint64 generate_new_seek_points(const char* filename, drmp3_uint64 pcm_frame_count(0); // Get the number of compressed MP3 frames and the number of uncompressed PCM frames. - drmp3_bool8 result = drmp3_get_mp3_and_pcm_frame_count(p_dr, - &mp3_frame_count, - &pcm_frame_count); + drmp3_bool32 result = drmp3_get_mp3_and_pcm_frame_count(p_dr, + &mp3_frame_count, + &pcm_frame_count); if ( result != DRMP3_TRUE || mp3_frame_count < FRAMES_PER_SEEK_POINT @@ -202,11 +203,13 @@ Uint64 generate_new_seek_points(const char* filename, // the decoded PCM times. // We also take into account the desired number of "FRAMES_PER_SEEK_POINT", // which is defined above. - drmp3_uint32 num_seek_points = static_cast(mp3_frame_count)/FRAMES_PER_SEEK_POINT + 1; + drmp3_uint32 num_seek_points = static_cast + (ceil_divide(mp3_frame_count, FRAMES_PER_SEEK_POINT)); + seek_points_vector.resize(num_seek_points); result = drmp3_calculate_seek_points(p_dr, - &num_seek_points, - reinterpret_cast(seek_points_vector.data())); + &num_seek_points, + reinterpret_cast(seek_points_vector.data())); if (result != DRMP3_TRUE || num_seek_points == 0) { // LOG_MSG("MP3: failed to calculate sufficient seek points for stream"); @@ -300,7 +303,13 @@ Uint64 load_existing_seek_points(const char* filename, // attempting to read it from the fast-seek file and (if it can't be read for any reason), it // calculates new data. It makes use of the above two functions. // -Uint64 populate_seek_points(struct SDL_RWops* const context, mp3_t* p_mp3, const char* seektable_filename) { +uint64_t populate_seek_points(struct SDL_RWops* const context, + mp3_t* p_mp3, + const char* seektable_filename, + bool &result) { + + // assume failure until proven otherwise + result = false; // Calculate the stream's xxHash value. Uint64 stream_hash = calculate_stream_hash(context); @@ -334,12 +343,13 @@ Uint64 populate_seek_points(struct SDL_RWops* const context, mp3_t* p_mp3, const // Finally, regardless of which scenario succeeded above, we now have our seek points! // We bind our seek points to the dr_mp3 object which will be used for fast seeking. - drmp3_bool8 result = drmp3_bind_seek_table(p_mp3->p_dr, - p_mp3->seek_points_vector.size(), - reinterpret_cast(p_mp3->seek_points_vector.data())); - if (result != DRMP3_TRUE) { - // LOG_MSG("MP3: could not bind the seek points to the dr_mp3 object"); + if(drmp3_bind_seek_table(p_mp3->p_dr, + static_cast(p_mp3->seek_points_vector.size()), + reinterpret_cast(p_mp3->seek_points_vector.data())) + != DRMP3_TRUE) { return 0; } + + result = true; return pcm_frame_count; } diff --git a/src/libs/decoders/mp3_seek_table.h b/src/libs/decoders/mp3_seek_table.h index 16a8f89e..222ba5d2 100644 --- a/src/libs/decoders/mp3_seek_table.h +++ b/src/libs/decoders/mp3_seek_table.h @@ -54,4 +54,7 @@ struct mp3_t { std::vector seek_points_vector; }; -Uint64 populate_seek_points(struct SDL_RWops* const context, mp3_t* p_mp3, const char* seektable_filename); +uint64_t populate_seek_points(struct SDL_RWops* const context, + mp3_t* p_mp3, + const char* seektable_filename, + bool &result);