DecoderAPI: pass SignedSongTime to decoder_initialized()
This commit is contained in:
parent
94f6380d69
commit
d9d97bd17b
|
@ -41,7 +41,7 @@
|
|||
void
|
||||
decoder_initialized(Decoder &decoder,
|
||||
const AudioFormat audio_format,
|
||||
bool seekable, float total_time)
|
||||
bool seekable, SignedSongTime duration)
|
||||
{
|
||||
DecoderControl &dc = decoder.dc;
|
||||
struct audio_format_string af_string;
|
||||
|
@ -59,9 +59,7 @@ decoder_initialized(Decoder &decoder,
|
|||
dc.out_audio_format = getOutputAudioFormat(audio_format);
|
||||
|
||||
dc.seekable = seekable;
|
||||
dc.total_time = total_time > 0
|
||||
? SignedSongTime::FromS(total_time)
|
||||
: SignedSongTime::Negative();
|
||||
dc.total_time = duration;
|
||||
|
||||
FormatDebug(decoder_domain, "audio_format=%s, seekable=%s",
|
||||
audio_format_to_string(dc.in_audio_format, &af_string),
|
||||
|
|
|
@ -53,12 +53,13 @@ class Error;
|
|||
* @param audio_format the audio format which is going to be sent to
|
||||
* decoder_data()
|
||||
* @param seekable true if the song is seekable
|
||||
* @param total_time the total number of seconds in this song; -1 if unknown
|
||||
* @param duration the total duration of this song; negative if
|
||||
* unknown
|
||||
*/
|
||||
void
|
||||
decoder_initialized(Decoder &decoder,
|
||||
AudioFormat audio_format,
|
||||
bool seekable, float total_time);
|
||||
bool seekable, SignedSongTime duration);
|
||||
|
||||
/**
|
||||
* Determines the pending decoder command.
|
||||
|
|
|
@ -62,7 +62,7 @@ adplug_file_decode(Decoder &decoder, Path path_fs)
|
|||
assert(audio_format.IsValid());
|
||||
|
||||
decoder_initialized(decoder, audio_format, false,
|
||||
player->songlength() / 1000.);
|
||||
SongTime::FromMS(player->songlength()));
|
||||
|
||||
int16_t buffer[2048];
|
||||
const unsigned frames_per_buffer = ARRAY_SIZE(buffer) / 2;
|
||||
|
|
|
@ -64,13 +64,11 @@ struct AudioFileInputStream {
|
|||
};
|
||||
|
||||
gcc_pure
|
||||
static double
|
||||
static SongTime
|
||||
audiofile_get_duration(AFfilehandle fh)
|
||||
{
|
||||
double frame_count = afGetFrameCount(fh, AF_DEFAULT_TRACK);
|
||||
double rate = afGetRate(fh, AF_DEFAULT_TRACK);
|
||||
|
||||
return frame_count / rate;
|
||||
return SongTime::FromScale<uint64_t>(afGetFrameCount(fh, AF_DEFAULT_TRACK),
|
||||
afGetRate(fh, AF_DEFAULT_TRACK));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
|
@ -208,10 +206,10 @@ audiofile_stream_decode(Decoder &decoder, InputStream &is)
|
|||
return;
|
||||
}
|
||||
|
||||
const double total_time = audiofile_get_duration(fh);
|
||||
const auto total_time = audiofile_get_duration(fh);
|
||||
|
||||
const uint16_t kbit_rate = (uint16_t)
|
||||
(is.GetSize() * 8.0 / total_time / 1000.0 + 0.5);
|
||||
(is.GetSize() * uint64_t(8000) / total_time.ToMS());
|
||||
|
||||
const unsigned frame_size = (unsigned)
|
||||
afGetVirtualFrameSize(fh, AF_DEFAULT_TRACK, true);
|
||||
|
@ -258,7 +256,7 @@ audiofile_get_duration(InputStream &is)
|
|||
if (fh == AF_NULL_FILEHANDLE)
|
||||
return -1;
|
||||
|
||||
int duration = int(audiofile_get_duration(fh));
|
||||
int duration = audiofile_get_duration(fh).RoundS();
|
||||
afCloseFile(fh);
|
||||
return duration;
|
||||
}
|
||||
|
|
|
@ -437,8 +437,10 @@ dsdiff_stream_decode(Decoder &decoder, InputStream &is)
|
|||
|
||||
/* calculate song time from DSD chunk size and sample frequency */
|
||||
offset_type chunk_size = metadata.chunk_size;
|
||||
float songtime = ((chunk_size / metadata.channels) * 8) /
|
||||
(float) metadata.sample_rate;
|
||||
|
||||
uint64_t n_frames = chunk_size / audio_format.channels;
|
||||
auto songtime = SongTime::FromScale<uint64_t>(n_frames,
|
||||
audio_format.sample_rate);
|
||||
|
||||
/* success: file was recognized */
|
||||
decoder_initialized(decoder, audio_format, is.IsSeekable(), songtime);
|
||||
|
|
|
@ -318,8 +318,8 @@ dsf_stream_decode(Decoder &decoder, InputStream &is)
|
|||
}
|
||||
/* Calculate song time from DSD chunk size and sample frequency */
|
||||
const auto n_blocks = metadata.n_blocks;
|
||||
float songtime = float(n_blocks * DSF_BLOCK_BITS) /
|
||||
(float) metadata.sample_rate;
|
||||
auto songtime = SongTime::FromScale<uint64_t>(n_blocks * DSF_BLOCK_SIZE,
|
||||
audio_format.sample_rate);
|
||||
|
||||
/* success: file was recognized */
|
||||
decoder_initialized(decoder, audio_format, is.IsSeekable(), songtime);
|
||||
|
|
|
@ -107,13 +107,13 @@ adts_find_frame(DecoderBuffer *buffer)
|
|||
}
|
||||
}
|
||||
|
||||
static float
|
||||
static SignedSongTime
|
||||
adts_song_duration(DecoderBuffer *buffer)
|
||||
{
|
||||
const InputStream &is = decoder_buffer_get_stream(buffer);
|
||||
const bool estimate = !is.CheapSeeking();
|
||||
if (estimate && !is.KnownSize())
|
||||
return -1;
|
||||
return SignedSongTime::Negative();
|
||||
|
||||
unsigned sample_rate = 0;
|
||||
|
||||
|
@ -146,7 +146,7 @@ adts_song_duration(DecoderBuffer *buffer)
|
|||
const auto offset = is.GetOffset()
|
||||
- decoder_buffer_available(buffer);
|
||||
if (offset <= 0)
|
||||
return -1;
|
||||
return SignedSongTime::Negative();
|
||||
|
||||
const auto file_size = is.GetSize();
|
||||
frames = (frames * file_size) / offset;
|
||||
|
@ -155,20 +155,18 @@ adts_song_duration(DecoderBuffer *buffer)
|
|||
}
|
||||
|
||||
if (sample_rate == 0)
|
||||
return -1;
|
||||
return SignedSongTime::Negative();
|
||||
|
||||
float frames_per_second = (float)sample_rate / 1024.0;
|
||||
assert(frames_per_second > 0);
|
||||
|
||||
return (float)frames / frames_per_second;
|
||||
return SignedSongTime::FromScale<uint64_t>(frames * uint64_t(1024),
|
||||
sample_rate);
|
||||
}
|
||||
|
||||
static float
|
||||
static SignedSongTime
|
||||
faad_song_duration(DecoderBuffer *buffer, InputStream &is)
|
||||
{
|
||||
auto data = ConstBuffer<uint8_t>::FromVoid(decoder_buffer_need(buffer, 5));
|
||||
if (data.IsNull())
|
||||
return -1;
|
||||
return SignedSongTime::Negative();
|
||||
|
||||
size_t tagsize = 0;
|
||||
if (data.size >= 10 && !memcmp(data.data, "ID3", 3)) {
|
||||
|
@ -180,20 +178,20 @@ faad_song_duration(DecoderBuffer *buffer, InputStream &is)
|
|||
tagsize += 10;
|
||||
|
||||
if (!decoder_buffer_skip(buffer, tagsize))
|
||||
return -1;
|
||||
return SignedSongTime::Negative();
|
||||
|
||||
data = ConstBuffer<uint8_t>::FromVoid(decoder_buffer_need(buffer, 5));
|
||||
if (data.IsNull())
|
||||
return -1;
|
||||
return SignedSongTime::Negative();
|
||||
}
|
||||
|
||||
if (data.size >= 8 && adts_check_frame(data.data) > 0) {
|
||||
/* obtain the duration from the ADTS header */
|
||||
|
||||
if (!is.IsSeekable())
|
||||
return -1;
|
||||
return SignedSongTime::Negative();
|
||||
|
||||
float song_length = adts_song_duration(buffer);
|
||||
auto song_length = adts_song_duration(buffer);
|
||||
|
||||
is.LockSeek(tagsize, IgnoreError());
|
||||
|
||||
|
@ -204,14 +202,14 @@ faad_song_duration(DecoderBuffer *buffer, InputStream &is)
|
|||
/* obtain the duration from the ADIF header */
|
||||
|
||||
if (!is.KnownSize())
|
||||
return -1;
|
||||
return SignedSongTime::Negative();
|
||||
|
||||
size_t skip_size = (data.data[4] & 0x80) ? 9 : 0;
|
||||
|
||||
if (8 + skip_size > data.size)
|
||||
/* not enough data yet; skip parsing this
|
||||
header */
|
||||
return -1;
|
||||
return SignedSongTime::Negative();
|
||||
|
||||
unsigned bit_rate = ((data.data[4 + skip_size] & 0x0F) << 19) |
|
||||
(data.data[5 + skip_size] << 11) |
|
||||
|
@ -220,11 +218,11 @@ faad_song_duration(DecoderBuffer *buffer, InputStream &is)
|
|||
|
||||
const auto size = is.GetSize();
|
||||
if (bit_rate == 0)
|
||||
return -1;
|
||||
return SignedSongTime::Negative();
|
||||
|
||||
return size * 8.0 / bit_rate;
|
||||
return SongTime::FromScale(size, bit_rate / 8);
|
||||
} else
|
||||
return -1;
|
||||
return SignedSongTime::Negative();
|
||||
}
|
||||
|
||||
static NeAACDecHandle
|
||||
|
@ -301,19 +299,21 @@ faad_decoder_decode(NeAACDecHandle decoder, DecoderBuffer *buffer,
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a song file's total playing time in seconds, as a float.
|
||||
* Returns 0 if the duration is unknown, and a negative value if the
|
||||
* file is invalid.
|
||||
* Determine a song file's total playing time.
|
||||
*
|
||||
* The first return value specifies whether the file was recognized.
|
||||
* The second return value is the duration.
|
||||
*/
|
||||
static float
|
||||
faad_get_file_time_float(InputStream &is)
|
||||
static std::pair<bool, SignedSongTime>
|
||||
faad_get_file_time(InputStream &is)
|
||||
{
|
||||
DecoderBuffer *buffer =
|
||||
decoder_buffer_new(nullptr, is,
|
||||
FAAD_MIN_STREAMSIZE * MAX_CHANNELS);
|
||||
float length = faad_song_duration(buffer, is);
|
||||
auto duration = faad_song_duration(buffer, is);
|
||||
bool recognized = !duration.IsNegative();
|
||||
|
||||
if (length < 0) {
|
||||
if (!recognized) {
|
||||
NeAACDecHandle decoder = faad_decoder_new();
|
||||
|
||||
decoder_buffer_fill(buffer);
|
||||
|
@ -321,36 +321,21 @@ faad_get_file_time_float(InputStream &is)
|
|||
AudioFormat audio_format;
|
||||
if (faad_decoder_init(decoder, buffer, audio_format,
|
||||
IgnoreError()))
|
||||
length = 0;
|
||||
recognized = true;
|
||||
|
||||
NeAACDecClose(decoder);
|
||||
}
|
||||
|
||||
decoder_buffer_free(buffer);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a song file's total playing time in seconds, as an int.
|
||||
* Returns 0 if the duration is unknown, and a negative value if the
|
||||
* file is invalid.
|
||||
*/
|
||||
static int
|
||||
faad_get_file_time(InputStream &is)
|
||||
{
|
||||
float length = faad_get_file_time_float(is);
|
||||
if (length < 0)
|
||||
return -1;
|
||||
|
||||
return int(length + 0.5);
|
||||
return std::make_pair(recognized, duration);
|
||||
}
|
||||
|
||||
static void
|
||||
faad_stream_decode(Decoder &mpd_decoder, InputStream &is,
|
||||
DecoderBuffer *buffer, const NeAACDecHandle decoder)
|
||||
{
|
||||
const float total_time = faad_song_duration(buffer, is);
|
||||
const auto total_time = faad_song_duration(buffer, is);
|
||||
|
||||
if (adts_find_frame(buffer) == 0)
|
||||
return;
|
||||
|
@ -449,11 +434,15 @@ static bool
|
|||
faad_scan_stream(InputStream &is,
|
||||
const struct tag_handler *handler, void *handler_ctx)
|
||||
{
|
||||
int file_time = faad_get_file_time(is);
|
||||
if (file_time < 0)
|
||||
auto result = faad_get_file_time(is);
|
||||
if (!result.first)
|
||||
return false;
|
||||
|
||||
tag_handler_invoke_duration(handler, handler_ctx, file_time);
|
||||
unsigned duration = result.second.IsNegative()
|
||||
? 0
|
||||
: result.second.RoundS();
|
||||
|
||||
tag_handler_invoke_duration(handler, handler_ctx, duration);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -514,9 +514,11 @@ ffmpeg_decode(Decoder &decoder, InputStream &input)
|
|||
return;
|
||||
}
|
||||
|
||||
int total_time = format_context->duration != (int64_t)AV_NOPTS_VALUE
|
||||
? format_context->duration / AV_TIME_BASE
|
||||
: 0;
|
||||
const SignedSongTime total_time =
|
||||
format_context->duration != (int64_t)AV_NOPTS_VALUE
|
||||
? SignedSongTime::FromScale<uint64_t>(format_context->duration,
|
||||
AV_TIME_BASE)
|
||||
: SignedSongTime::Negative();
|
||||
|
||||
decoder_initialized(decoder, audio_format,
|
||||
input.IsSeekable(), total_time);
|
||||
|
|
|
@ -136,10 +136,12 @@ flac_got_first_frame(struct flac_data *data, const FLAC__FrameHeader *header)
|
|||
|
||||
data->frame_size = data->audio_format.GetFrameSize();
|
||||
|
||||
const auto duration = SongTime::FromScale<uint64_t>(data->total_frames,
|
||||
data->audio_format.sample_rate);
|
||||
|
||||
decoder_initialized(data->decoder, data->audio_format,
|
||||
data->input_stream.IsSeekable(),
|
||||
(float)data->total_frames /
|
||||
(float)data->audio_format.sample_rate);
|
||||
duration);
|
||||
|
||||
data->initialized = true;
|
||||
|
||||
|
|
|
@ -144,10 +144,14 @@ flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd,
|
|||
|
||||
if (data->initialized) {
|
||||
/* done */
|
||||
|
||||
const auto duration2 =
|
||||
SongTime::FromScale<uint64_t>(data->total_frames,
|
||||
data->audio_format.sample_rate);
|
||||
|
||||
decoder_initialized(data->decoder, data->audio_format,
|
||||
data->input_stream.IsSeekable(),
|
||||
(float)data->total_frames /
|
||||
(float)data->audio_format.sample_rate);
|
||||
duration2);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -166,7 +166,8 @@ fluidsynth_file_decode(Decoder &decoder, Path path_fs)
|
|||
MPD core */
|
||||
|
||||
const AudioFormat audio_format(sample_rate, SampleFormat::S16, 2);
|
||||
decoder_initialized(decoder, audio_format, false, -1);
|
||||
decoder_initialized(decoder, audio_format, false,
|
||||
SignedSongTime::Negative());
|
||||
|
||||
DecoderCommand cmd;
|
||||
while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING) {
|
||||
|
|
|
@ -156,9 +156,9 @@ gme_file_decode(Decoder &decoder, Path path_fs)
|
|||
return;
|
||||
}
|
||||
|
||||
const float song_len = ti->length > 0
|
||||
? ti->length / 1000.0
|
||||
: -1.0;
|
||||
const SignedSongTime song_len = ti->length > 0
|
||||
? SignedSongTime::FromMS(ti->length)
|
||||
: SignedSongTime::Negative();
|
||||
|
||||
/* initialize the MPD decoder */
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ struct MadDecoder {
|
|||
mad_timer_t timer;
|
||||
unsigned char input_buffer[READ_BUFFER_SIZE];
|
||||
int32_t output_buffer[MP3_DATA_OUTPUT_BUFFER_SIZE];
|
||||
float total_time;
|
||||
SignedSongTime total_time;
|
||||
SongTime elapsed_time;
|
||||
SongTime seek_time;
|
||||
enum muteframe mute_frame;
|
||||
|
@ -713,11 +713,10 @@ parse_lame(struct lame *lame, struct mad_bitptr *ptr, int *bitlen)
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline float
|
||||
static inline SongTime
|
||||
mp3_frame_duration(const struct mad_frame *frame)
|
||||
{
|
||||
return mad_timer_count(frame->header.duration,
|
||||
MAD_UNITS_MILLISECONDS) / 1000.0;
|
||||
return ToSongTime(frame->header.duration);
|
||||
}
|
||||
|
||||
inline offset_type
|
||||
|
@ -745,13 +744,19 @@ MadDecoder::FileSizeToSongLength()
|
|||
if (input_stream.KnownSize()) {
|
||||
offset_type rest = RestIncludingThisFrame();
|
||||
|
||||
float frame_duration = mp3_frame_duration(&frame);
|
||||
const SongTime frame_duration = mp3_frame_duration(&frame);
|
||||
const SongTime duration =
|
||||
SongTime::FromScale<uint64_t>(rest,
|
||||
frame.header.bitrate / 8);
|
||||
total_time = duration;
|
||||
|
||||
total_time = (rest * 8.0) / frame.header.bitrate;
|
||||
max_frames = total_time / frame_duration + FRAMES_CUSHION;
|
||||
max_frames = (frame_duration.IsPositive()
|
||||
? duration.count() / frame_duration.count()
|
||||
: 0)
|
||||
+ FRAMES_CUSHION;
|
||||
} else {
|
||||
max_frames = FRAMES_CUSHION;
|
||||
total_time = 0;
|
||||
total_time = SignedSongTime::Negative();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -792,7 +797,7 @@ MadDecoder::DecodeFirstFrame(Tag **tag)
|
|||
if ((xing.flags & XING_FRAMES) && xing.frames) {
|
||||
mad_timer_t duration = frame.header.duration;
|
||||
mad_timer_multiply(&duration, xing.frames);
|
||||
total_time = ((float)mad_timer_count(duration, MAD_UNITS_MILLISECONDS)) / 1000;
|
||||
total_time = ToSongTime(duration);
|
||||
max_frames = xing.frames;
|
||||
}
|
||||
|
||||
|
@ -844,13 +849,13 @@ MadDecoder::~MadDecoder()
|
|||
}
|
||||
|
||||
/* this is primarily used for getting total time for tags */
|
||||
static int
|
||||
static std::pair<bool, SignedSongTime>
|
||||
mad_decoder_total_file_time(InputStream &is)
|
||||
{
|
||||
MadDecoder data(nullptr, is);
|
||||
return data.DecodeFirstFrame(nullptr)
|
||||
? data.total_time + 0.5
|
||||
: -1;
|
||||
? std::make_pair(true, data.total_time)
|
||||
: std::make_pair(false, SignedSongTime::Negative());
|
||||
}
|
||||
|
||||
long
|
||||
|
@ -1085,11 +1090,15 @@ static bool
|
|||
mad_decoder_scan_stream(InputStream &is,
|
||||
const struct tag_handler *handler, void *handler_ctx)
|
||||
{
|
||||
const int total_time = mad_decoder_total_file_time(is);
|
||||
if (total_time < 0)
|
||||
const auto result = mad_decoder_total_file_time(is);
|
||||
if (!result.first)
|
||||
return false;
|
||||
|
||||
tag_handler_invoke_duration(handler, handler_ctx, total_time);
|
||||
unsigned duration = result.second.IsNegative()
|
||||
? 0
|
||||
: result.second.RoundS();
|
||||
|
||||
tag_handler_invoke_duration(handler, handler_ctx, duration);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -170,7 +170,8 @@ mikmod_decoder_file_decode(Decoder &decoder, Path path_fs)
|
|||
const AudioFormat audio_format(mikmod_sample_rate, SampleFormat::S16, 2);
|
||||
assert(audio_format.IsValid());
|
||||
|
||||
decoder_initialized(decoder, audio_format, false, 0);
|
||||
decoder_initialized(decoder, audio_format, false,
|
||||
SignedSongTime::Negative());
|
||||
|
||||
Player_Start(handle);
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ mod_decode(Decoder &decoder, InputStream &is)
|
|||
|
||||
decoder_initialized(decoder, audio_format,
|
||||
is.IsSeekable(),
|
||||
ModPlug_GetLength(f) / 1000.0);
|
||||
SongTime::FromMS(ModPlug_GetLength(f)));
|
||||
|
||||
DecoderCommand cmd;
|
||||
do {
|
||||
|
|
|
@ -149,7 +149,8 @@ mp4_file_decode(Decoder &mpd_decoder, Path path_fs)
|
|||
/* initialize the MPD core */
|
||||
|
||||
const MP4Timestamp scale = MP4GetTrackTimeScale(handle, track);
|
||||
const float duration = ((float)MP4GetTrackDuration(handle, track)) / scale + 0.5f;
|
||||
const SongTime duration = SongTime::FromScale<uint64_t>(MP4GetTrackDuration(handle, track),
|
||||
scale);
|
||||
const MP4SampleId num_samples = MP4GetTrackNumberOfSamples(handle, track);
|
||||
|
||||
decoder_initialized(mpd_decoder, audio_format, true, duration);
|
||||
|
|
|
@ -180,7 +180,7 @@ mpcdec_decode(Decoder &mpd_decoder, InputStream &is)
|
|||
|
||||
decoder_initialized(mpd_decoder, audio_format,
|
||||
is.IsSeekable(),
|
||||
mpc_streaminfo_get_length(&info));
|
||||
SongTime::FromS(mpc_streaminfo_get_length(&info)));
|
||||
|
||||
DecoderCommand cmd = DecoderCommand::NONE;
|
||||
do {
|
||||
|
|
|
@ -131,9 +131,11 @@ mpd_mpg123_file_decode(Decoder &decoder, Path path_fs)
|
|||
|
||||
/* tell MPD core we're ready */
|
||||
|
||||
decoder_initialized(decoder, audio_format, true,
|
||||
(float)num_samples /
|
||||
(float)audio_format.sample_rate);
|
||||
const auto duration =
|
||||
SongTime::FromScale<uint64_t>(num_samples,
|
||||
audio_format.sample_rate);
|
||||
|
||||
decoder_initialized(decoder, audio_format, true, duration);
|
||||
|
||||
if (mpg123_info(handle, &info) != MPG123_OK) {
|
||||
info.vbr = MPG123_CBR;
|
||||
|
|
|
@ -253,9 +253,10 @@ MPDOpusDecoder::HandleBOS(const ogg_packet &packet)
|
|||
|
||||
eos_granulepos = LoadEOSGranulePos(input_stream, &decoder,
|
||||
opus_serialno);
|
||||
const double duration = eos_granulepos >= 0
|
||||
? double(eos_granulepos) / opus_sample_rate
|
||||
: -1.0;
|
||||
const auto duration = eos_granulepos >= 0
|
||||
? SignedSongTime::FromScale<uint64_t>(eos_granulepos,
|
||||
opus_sample_rate)
|
||||
: SignedSongTime::Negative();
|
||||
|
||||
const AudioFormat audio_format(opus_sample_rate,
|
||||
SampleFormat::S16, channels);
|
||||
|
|
|
@ -40,12 +40,12 @@ pcm_stream_decode(Decoder &decoder, InputStream &is)
|
|||
const bool reverse_endian = mime != nullptr &&
|
||||
strcmp(mime, "audio/x-mpd-cdda-pcm-reverse") == 0;
|
||||
|
||||
const double time_to_size = audio_format.GetTimeToSize();
|
||||
const auto frame_size = audio_format.GetFrameSize();
|
||||
|
||||
float total_time = -1;
|
||||
if (is.KnownSize())
|
||||
total_time = is.GetSize() / time_to_size;
|
||||
const auto total_time = is.KnownSize()
|
||||
? SignedSongTime::FromScale<uint64_t>(is.GetSize() / frame_size,
|
||||
audio_format.sample_rate)
|
||||
: SignedSongTime::Negative();
|
||||
|
||||
decoder_initialized(decoder, audio_format,
|
||||
is.IsSeekable(), total_time);
|
||||
|
|
|
@ -159,11 +159,11 @@ get_song_num(const char *path_fs)
|
|||
}
|
||||
|
||||
/* get the song length in seconds */
|
||||
static int
|
||||
static SignedSongTime
|
||||
get_song_length(Path path_fs)
|
||||
{
|
||||
if (songlength_database == nullptr)
|
||||
return -1;
|
||||
return SignedSongTime::Negative();
|
||||
|
||||
char *sid_file = get_container_name(path_fs);
|
||||
SidTuneMod tune(sid_file);
|
||||
|
@ -171,7 +171,7 @@ get_song_length(Path path_fs)
|
|||
if(!tune) {
|
||||
LogWarning(sidplay_domain,
|
||||
"failed to load file for calculating md5 sum");
|
||||
return -1;
|
||||
return SignedSongTime::Negative();
|
||||
}
|
||||
char md5sum[SIDTUNE_MD5_LENGTH+1];
|
||||
tune.createMD5(md5sum);
|
||||
|
@ -183,7 +183,7 @@ get_song_length(Path path_fs)
|
|||
"Database", md5sum, &num_items, nullptr);
|
||||
if(!values || song_num>num_items) {
|
||||
g_strfreev(values);
|
||||
return -1;
|
||||
return SignedSongTime::Negative();
|
||||
}
|
||||
|
||||
int minutes=strtol(values[song_num-1], nullptr, 10);
|
||||
|
@ -199,7 +199,7 @@ get_song_length(Path path_fs)
|
|||
|
||||
g_strfreev(values);
|
||||
|
||||
return (minutes*60)+seconds;
|
||||
return SignedSongTime::FromS((minutes * 60) + seconds);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -220,8 +220,9 @@ sidplay_file_decode(Decoder &decoder, Path path_fs)
|
|||
const int song_num = get_song_num(path_fs.c_str());
|
||||
tune.selectSong(song_num);
|
||||
|
||||
int song_len=get_song_length(path_fs);
|
||||
if(song_len==-1) song_len=default_songlength;
|
||||
auto duration = get_song_length(path_fs);
|
||||
if (duration.IsNegative() && default_songlength > 0)
|
||||
duration = SongTime::FromS(default_songlength);
|
||||
|
||||
/* initialize the player */
|
||||
|
||||
|
@ -292,12 +293,14 @@ sidplay_file_decode(Decoder &decoder, Path path_fs)
|
|||
const AudioFormat audio_format(48000, SampleFormat::S16, channels);
|
||||
assert(audio_format.IsValid());
|
||||
|
||||
decoder_initialized(decoder, audio_format, true, (float)song_len);
|
||||
decoder_initialized(decoder, audio_format, true, duration);
|
||||
|
||||
/* .. and play */
|
||||
|
||||
const unsigned timebase = player.timebase();
|
||||
song_len *= timebase;
|
||||
const unsigned end = duration.IsNegative()
|
||||
? 0u
|
||||
: duration.ToScale<uint64_t>(timebase);
|
||||
|
||||
DecoderCommand cmd;
|
||||
do {
|
||||
|
@ -334,7 +337,7 @@ sidplay_file_decode(Decoder &decoder, Path path_fs)
|
|||
decoder_command_finished(decoder);
|
||||
}
|
||||
|
||||
if (song_len > 0 && player.time() >= (unsigned)song_len)
|
||||
if (end > 0 && player.time() >= end)
|
||||
break;
|
||||
|
||||
} while (cmd != DecoderCommand::STOP);
|
||||
|
@ -382,9 +385,10 @@ sidplay_scan_file(Path path_fs,
|
|||
tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK, track);
|
||||
|
||||
/* time */
|
||||
int song_len=get_song_length(path_fs);
|
||||
if (song_len >= 0)
|
||||
tag_handler_invoke_duration(handler, handler_ctx, song_len);
|
||||
const auto duration = get_song_length(path_fs);
|
||||
if (!duration.IsNegative())
|
||||
tag_handler_invoke_duration(handler, handler_ctx,
|
||||
duration.RoundS());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -140,10 +140,11 @@ static SF_VIRTUAL_IO vio = {
|
|||
/**
|
||||
* Converts a frame number to a timestamp (in seconds).
|
||||
*/
|
||||
static float
|
||||
static SongTime
|
||||
frame_to_time(sf_count_t frame, const AudioFormat *audio_format)
|
||||
{
|
||||
return (float)frame / (float)audio_format->sample_rate;
|
||||
return SongTime::FromScale<uint64_t>(frame,
|
||||
audio_format->sample_rate);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -202,6 +202,16 @@ vorbis_init(gcc_unused const config_param ¶m)
|
|||
return true;
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
static SignedSongTime
|
||||
vorbis_duration(OggVorbis_File &vf)
|
||||
{
|
||||
auto total = ov_time_total(&vf, -1);
|
||||
return total >= 0
|
||||
? SignedSongTime::FromS(total)
|
||||
: SignedSongTime::Negative();
|
||||
}
|
||||
|
||||
static void
|
||||
vorbis_stream_decode(Decoder &decoder,
|
||||
InputStream &input_stream)
|
||||
|
@ -237,11 +247,8 @@ vorbis_stream_decode(Decoder &decoder,
|
|||
return;
|
||||
}
|
||||
|
||||
float total_time = ov_time_total(&vf, -1);
|
||||
if (total_time < 0)
|
||||
total_time = 0;
|
||||
|
||||
decoder_initialized(decoder, audio_format, vis.seekable, total_time);
|
||||
decoder_initialized(decoder, audio_format, vis.seekable,
|
||||
vorbis_duration(vf));
|
||||
|
||||
#ifdef HAVE_TREMOR
|
||||
char buffer[4096];
|
||||
|
|
|
@ -160,8 +160,9 @@ wavpack_decode(Decoder &decoder, WavpackContext *wpc, bool can_seek)
|
|||
? format_samples_float
|
||||
: format_samples_int;
|
||||
|
||||
const float total_time = float(WavpackGetNumSamples(wpc))
|
||||
/ audio_format.sample_rate;
|
||||
const auto total_time =
|
||||
SongTime::FromScale<uint64_t>(WavpackGetNumSamples(wpc),
|
||||
audio_format.sample_rate);
|
||||
|
||||
const int bytes_per_sample = WavpackGetBytesPerSample(wpc);
|
||||
const int output_sample_size = audio_format.GetFrameSize();
|
||||
|
|
|
@ -86,8 +86,11 @@ wildmidi_file_decode(Decoder &decoder, Path path_fs)
|
|||
return;
|
||||
}
|
||||
|
||||
decoder_initialized(decoder, audio_format, true,
|
||||
info->approx_total_samples / WILDMIDI_SAMPLE_RATE);
|
||||
const auto duration =
|
||||
SongTime::FromScale<uint64_t>(info->approx_total_samples,
|
||||
WILDMIDI_SAMPLE_RATE);
|
||||
|
||||
decoder_initialized(decoder, audio_format, true, duration);
|
||||
|
||||
DecoderCommand cmd;
|
||||
do {
|
||||
|
|
|
@ -30,7 +30,7 @@ void
|
|||
decoder_initialized(Decoder &decoder,
|
||||
const AudioFormat audio_format,
|
||||
gcc_unused bool seekable,
|
||||
float duration)
|
||||
SignedSongTime duration)
|
||||
{
|
||||
struct audio_format_string af_string;
|
||||
|
||||
|
@ -39,7 +39,7 @@ decoder_initialized(Decoder &decoder,
|
|||
|
||||
fprintf(stderr, "audio_format=%s duration=%f\n",
|
||||
audio_format_to_string(audio_format, &af_string),
|
||||
duration);
|
||||
duration.ToDoubleS());
|
||||
|
||||
decoder.initialized = true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue