aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2017-11-02 10:18:04 +1300
committerTom Ryder <tom@sanctum.geek.nz>2017-11-02 10:18:04 +1300
commit0f5f9b5f2d2687508f04ba93f3cd8471e1790f91 (patch)
treec15b0e1252ea966b2b11af051b73a76eac66c71e
parentMerge branch 'hotfix/v0.06' into develop (diff)
downloadMusic-Lyrics-LRC-0f5f9b5f2d2687508f04ba93f3cd8471e1790f91.tar.gz
Music-Lyrics-LRC-0f5f9b5f2d2687508f04ba93f3cd8471e1790f91.zip
Parse any number of fractional seconds
Replace ts_to_msec() and msec_to_ts() functions with min_sec_to_msec() and msec_to_min_sec() versions, and abandon the hash-based approach for some plainer calculations. Also make the fractional seconds entirely optional if the period and all trailing digits are omitted from the timestamp. Mention that we can parse any number of fractional seconds, but that we only emit two decimal places (centiseconds).
-rw-r--r--lib/Music/Lyrics/LRC.pm68
1 files changed, 30 insertions, 38 deletions
diff --git a/lib/Music/Lyrics/LRC.pm b/lib/Music/Lyrics/LRC.pm
index 10204d0..d9258a0 100644
--- a/lib/Music/Lyrics/LRC.pm
+++ b/lib/Music/Lyrics/LRC.pm
@@ -45,9 +45,13 @@ our %RE = (
\[ # Opening left bracket
(\d+) # Minutes, capture
: # Colon
- (\d{2}) # Seconds, capture
- [.] # Period
- (\d{2}) # Hundredths of a second, capture
+ ( # Seconds group, capture
+ \d{2} # Whole seconds
+ (?: # Group for fractional seconds
+ [.] # Period
+ \d+ # At least one digit
+ )? # End optional fractional seconds group
+ ) # End seconds group
\] # Closing right bracket
[\t ]* # Any tabs or spaces
(.*\S) # Lyric line, capture
@@ -67,11 +71,10 @@ my %parsers = (
# A lyric line
lyric => sub {
- my ( $self, %ts, $text );
- ( $self, @ts{qw(min sec csec)}, $text ) = @_;
+ my ( $self, $min, $sec, $text ) = @_;
# Calculate the number of milliseconds
- my $msec = $self->ts_to_msec( \%ts );
+ my $msec = $self->_min_sec_to_msec( $min, $sec );
# Push a lyric hashref onto our list
$self->add_lyric( $msec, $text );
@@ -208,11 +211,10 @@ sub save {
# Convert milliseconds to timestamp hash
my $msec = $lyric->{time};
- my %ts = %{ $self->msec_to_ts($msec) };
+ my ( $min, $sec ) = $self->_msec_to_min_sec($msec);
# Write the line to the file, counting the lines
- $lines += printf {$fh} "[%02u:%02u.%02u]%s\n",
- @ts{qw(min sec csec)}, $lyric->{text}
+ $lines += printf {$fh} "[%02u:%05.2f]%s\n", $min, $sec, $lyric->{text}
or die "Failed lyric write: $ERRNO\n";
}
@@ -220,32 +222,28 @@ sub save {
return $lines;
}
-# Factors for timestamp<->millisecond conversions
-our %MSF = (
- min => 60_000,
- sec => 1_000,
- csec => 10,
+# Named constants for the conversion functions
+# This stands for "millisecond factors"
+my %MSF = (
+ sec => 1_000,
+ min => 60_000,
);
-# Convert an LRC timestamp hashref to milliseconds
-sub ts_to_msec {
- my ( $self, $ts ) = @_;
+# Convert a minutes-seconds pair to milliseconds
+sub _min_sec_to_msec {
+ my ( $self, $min, $sec ) = @_;
my $msec = 0;
- for my $k ( keys %{$ts} ) {
- $msec += $ts->{$k} * $MSF{$k};
- }
+ $msec += int $min * $MSF{min};
+ $msec += $sec * $MSF{sec};
return $msec;
}
-# Convert milliseconds to an LRC timestamp hashref
-sub msec_to_ts {
+# Convert milliseconds to a minutes-seconds pair
+sub _msec_to_min_sec {
my ( $self, $msec ) = @_;
- my %ts;
- for my $k (qw(min sec csec)) {
- $ts{$k} = int $msec / $MSF{$k};
- $msec %= $MSF{$k};
- }
- return \%ts;
+ my $min = int $msec / $MSF{min};
+ my $sec = ( int $msec ) % $MSF{min} / $MSF{sec};
+ return ( $min, $sec );
}
1;
@@ -349,16 +347,6 @@ Load lyrics from the given readable filehandle.
Save lyrics to the given writeable filehandle.
-=head2 C<ts_to_msec(\%ts)>
-
-Convert the internal LRC timestamp hash structure to milliseconds. You are
-probably not interested in this.
-
-=head2 C<msec_to_ts($msec)>
-
-Convert milliseconds to the internal LRC timestamp hash structure. You are
-probably not interested in this, either.
-
=head1 DIAGNOSTICS
=over 4
@@ -445,6 +433,10 @@ may change in future revisions.
The format accepted here is very liberal, and needs to be tested with lots of
different LRC files from the wild.
+Fractional seconds of any length can be parsed, and preserved in the
+millisecond count return by C<lyrics()>, but any resolution beyond 2 decimal
+places is lost on C<save()>.
+
The test suite is skeletal, and needs a lot of fleshing out.
=head1 AUTHOR