Zachary Kotlarek 13 лет назад
Родитель
Сommit
e1c4f89da6
1 измененных файлов с 88 добавлено и 14 удалено
  1. 88 14
      dmx/rifftrax.pl

+ 88 - 14
dmx/rifftrax.pl

@@ -22,7 +22,7 @@ my %RIFFS     = (
 	},
 	'82469' => {
 		'file'   => 'Harry Potter/Harry Potter 2_ The Chamber of Secrets.mp3',
-		'offset' => 100,
+		'offset' => 133,
 		'rate'   => 1.0,
 	}
 );
@@ -45,13 +45,15 @@ DMX::stateSocket($STATE_SOCK);
 DMX::stateSubscribe($STATE_SOCK);
 
 # State
-my $newState = 'OFF';
-my $riff     = 0;
-my $riffLast = $riff;
-my $url      = '';
-my $urlLast  = $url;
-my %exists   = ();
-my $pullLast = time();
+my $state     = 'OFF';
+my $stateLast = $state;
+my $riff      = 0;
+my $riffLast  = $riff;
+my $url       = '';
+my $urlLast   = $url;
+my $nudge     = 0;
+my %exists    = ();
+my $pullLast  = time();
 
 # Validate the path for all our riff files at launch
 foreach my $id (keys(%RIFFS)) {
@@ -75,13 +77,14 @@ foreach my $id (keys(%RIFFS)) {
 # Loop forever
 while (1) {
 
-	# Save the last RIFF
-	$riffLast = $riff;
+	# Save the last RIFF and state
+	$stateLast = $state;
+	$riffLast  = $riff;
 
 	# Wait for state updates
 	my $cmdState = DMX::readState($DELAY, \%exists, undef(), undef());
 	if (defined($cmdState)) {
-		$newState = $cmdState;
+		$state    = $cmdState;
 		$pullLast = time();
 	}
 
@@ -103,18 +106,24 @@ while (1) {
 		# If a RIFF was active, clear it
 		if ($riff) {
 			if ($DEBUG) {
-				print STDERR "RIFF cleared\n";
+				print STDERR "RIFF complete\n";
 			}
-			$riff = 0;
+			Audio::drop('RIFF');
+			$riff  = 0;
+			$nudge = 0;
 		}
 
 		# Activate a new RIFF, if applicable
 		if ($url =~ /\/library\/parts\/(\d+)\//) {
 			if (exists($RIFFS{$1})) {
 				if ($DEBUG) {
-					print STDERR 'Matched RIFF: ' . $1 . ' => ' . $RIFFS{$riff}{'path'};
+					print STDERR 'Matched RIFF: ' . $1 . ' => ' . $RIFFS{$1}{'path'};
 				}
 				$riff = $1;
+
+				Audio::addLoad('RIFF', $RIFFS{$riff}{'path'});
+				Audio::rate('RIFF', $RIFFS{$riff}{'rate'});
+				Audio::background('RIFF');
 			}
 		}
 	}
@@ -139,4 +148,69 @@ while (1) {
 		close($fh);
 		rename($tmp, $OUTPUT_FILE);
 	}
+
+	# Sync
+	if ($riff) {
+		if ($DEBUG) {
+			print STDERR "Syncing\n";
+		}
+
+		# Play/pause to match the video
+		if ($stateLast ne $state) {
+			if ($state eq 'PAUSE') {
+				Audio::pause('RIFF');
+			} elsif ($state eq 'PLAY') {
+				Audio::background('RIFF');
+			}
+		}
+
+		# Get the video and riff playback positions
+		my $riffTime = Audio::position('RIFF', undef());
+		my $videoTime = $exists{'PLAYING_POSITION'};
+
+		# Convert to seconds
+		my @parts = split(/\-/, $videoTime);
+		$videoTime = 0;
+		if (scalar(@parts) == 3) {
+			$videoTime = ($parts[0] * 3600) + ($parts[1] * 60) + $parts[2];
+		} elsif (scalar(@parts) == 2) {
+			$videoTime = ($parts[0] * 60) + $parts[1];
+		} else {
+			$videoTime = $parts[0];
+		}
+
+		# Calculate the adjusted riff time and the error between the riff and video times
+		my $riffAdjTime = ($riffTime * $RIFFS{$riff}{'rate'}) - $RIFFS{$riff}{'offset'} + $nudge;
+		my $error       = $videoTime - $riffAdjTime;
+
+		# Debug
+		if ($DEBUG) {
+			print STDERR "\tRiff time: " . $riffTime . "\n";
+			print STDERR "\tVideo time: " . $videoTime . "\n";
+			print STDERR "\tAdjusted riff time: " . $riffAdjTime . "\n";
+			print STDERR "\tError: " . $error . "\n";
+		}
+
+		# Adjust the riff position if we're off by 1 second or more
+		if (abs($error) >= 1) {
+			my $newPos = $riffTime + $error;
+			if ($newPos < 0) {
+				Audio::pause('RIFF');
+			} else {
+
+				# Play/pause as needed, before we adjust
+				# The state-change detection should handle most of this
+				# But double-check while adjusting in case things get out-of-sync
+				my $playing = Audio::playing('RIFF');
+				if ($state eq 'PLAY' && !$playing) {
+					Audio::background('RIFF');
+				} elsif ($state ne 'PLAY' && $playing) {
+					Audio::pause('RIFF');
+				}
+
+				# Always adjust
+				Audio::position('RIFF', $newPos);
+			}
+		}
+	}
 }