Class: HeadMusic::Time::SmpteTimecode

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/head_music/time/smpte_timecode.rb

Overview

Represents a SMPTE (Society of Motion Picture and Television Engineers) timecode

SMPTE timecode is used for synchronizing audio and video in professional production. It represents time as HH:MM:SS:FF (hours:minutes:seconds:frames).

The framerate determines how many frames occur per second. Common framerates:

  • 24 fps: Film standard
  • 25 fps: PAL video standard (Europe)
  • 30 fps: NTSC video standard (North America)
  • 29.97 fps: NTSC drop-frame

Examples:

Creating a timecode at 1 hour

timecode = HeadMusic::Time::SmpteTimecode.new(1, 0, 0, 0)
timecode.to_s # => "01:00:00:00"

Parsing from a string

timecode = HeadMusic::Time::SmpteTimecode.parse("02:30:45:15")
timecode.hour # => 2
timecode.minute # => 30

Normalizing with overflow

timecode = HeadMusic::Time::SmpteTimecode.new(0, 0, 0, 60, framerate: 30)
timecode.normalize!
timecode.to_s # => "00:00:02:00" (frames carried into seconds)

Comparing timecodes

tc1 = HeadMusic::Time::SmpteTimecode.new(1, 0, 0, 0)
tc2 = HeadMusic::Time::SmpteTimecode.new(1, 30, 0, 0)
tc1 < tc2 # => true

Constant Summary collapse

DEFAULT_FRAMERATE =

Default framerate (30 fps NTSC)

30
SECONDS_PER_MINUTE =

Seconds per minute

60
MINUTES_PER_HOUR =

Minutes per hour

60

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hour = 0, minute = 0, second = 0, frame = 0, framerate: DEFAULT_FRAMERATE) ⇒ SmpteTimecode

Create a new SMPTE timecode

Parameters:

  • hour (Integer, String) (defaults to: 0)

    the hour component (default: 0)

  • minute (Integer, String) (defaults to: 0)

    the minute component (default: 0)

  • second (Integer, String) (defaults to: 0)

    the second component (default: 0)

  • frame (Integer, String) (defaults to: 0)

    the frame component (default: 0)

  • framerate (Integer) (defaults to: DEFAULT_FRAMERATE)

    frames per second (default: 30)



78
79
80
81
82
83
84
85
# File 'lib/head_music/time/smpte_timecode.rb', line 78

def initialize(hour = 0, minute = 0, second = 0, frame = 0, framerate: DEFAULT_FRAMERATE)
  @hour = hour.to_i
  @minute = minute.to_i
  @second = second.to_i
  @frame = frame.to_i
  @framerate = framerate
  @total_frames = nil
end

Instance Attribute Details

#frameInteger (readonly)

Returns the frame component.

Returns:

  • (Integer)

    the frame component



47
48
49
# File 'lib/head_music/time/smpte_timecode.rb', line 47

def frame
  @frame
end

#framerateInteger (readonly)

Returns frames per second (default: 30 for NTSC).

Returns:

  • (Integer)

    frames per second (default: 30 for NTSC)



50
51
52
# File 'lib/head_music/time/smpte_timecode.rb', line 50

def framerate
  @framerate
end

#hourInteger (readonly)

Returns the hour component.

Returns:

  • (Integer)

    the hour component



38
39
40
# File 'lib/head_music/time/smpte_timecode.rb', line 38

def hour
  @hour
end

#minuteInteger (readonly)

Returns the minute component.

Returns:

  • (Integer)

    the minute component



41
42
43
# File 'lib/head_music/time/smpte_timecode.rb', line 41

def minute
  @minute
end

#secondInteger (readonly)

Returns the second component.

Returns:

  • (Integer)

    the second component



44
45
46
# File 'lib/head_music/time/smpte_timecode.rb', line 44

def second
  @second
end

Class Method Details

.parse(identifier) ⇒ SmpteTimecode

Parse a timecode from a string representation

Examples:

SmpteTimecode.parse("02:30:45:15")

Parameters:

  • identifier (String)

    timecode in "HH:MM:SS:FF" format

Returns:



67
68
69
# File 'lib/head_music/time/smpte_timecode.rb', line 67

def self.parse(identifier)
  new(*identifier.scan(/\d+/)[0..3])
end

Instance Method Details

#<=>(other) ⇒ Integer

Compare this timecode to another

Parameters:

Returns:

  • (Integer)

    -1 if less than, 0 if equal, 1 if greater than



139
140
141
# File 'lib/head_music/time/smpte_timecode.rb', line 139

def <=>(other)
  to_total_frames <=> other.to_total_frames
end

#normalize!self

Normalize the timecode, handling overflow and underflow

This method modifies the timecode in place, carrying excess values from lower levels to higher levels (frames → seconds → minutes → hours). Also handles negative values by borrowing from higher levels.

Examples:

timecode = SmpteTimecode.new(0, 0, 0, 60, framerate: 30)
timecode.normalize! # => "00:00:02:00"

Returns:

  • (self)

    returns self for method chaining



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/head_music/time/smpte_timecode.rb', line 111

def normalize!
  @total_frames = nil # Invalidate cached value

  # Carry frames into seconds
  if frame >= framerate || frame.negative?
    second_delta, @frame = frame.divmod(framerate)
    @second += second_delta
  end

  # Carry seconds into minutes
  if second >= SECONDS_PER_MINUTE || second.negative?
    minute_delta, @second = second.divmod(SECONDS_PER_MINUTE)
    @minute += minute_delta
  end

  # Carry minutes into hours
  if minute >= MINUTES_PER_HOUR || minute.negative?
    hour_delta, @minute = minute.divmod(MINUTES_PER_HOUR)
    @hour += hour_delta
  end

  self
end

#to_aArray<Integer>

Convert timecode to array format

Returns:

  • (Array<Integer>)

    [hour, minute, second, frame]



90
91
92
# File 'lib/head_music/time/smpte_timecode.rb', line 90

def to_a
  [hour, minute, second, frame]
end

#to_sString

Convert timecode to string format with zero padding

Returns:

  • (String)

    timecode in "HH:MM:SS:FF" format



97
98
99
# File 'lib/head_music/time/smpte_timecode.rb', line 97

def to_s
  format("%02d:%02d:%02d:%02d", hour, minute, second, frame)
end

#to_total_framesInteger Also known as: to_i

Convert timecode to total frames from the beginning

Returns:

  • (Integer)

    total frames



146
147
148
149
150
151
152
153
154
155
156
# File 'lib/head_music/time/smpte_timecode.rb', line 146

def to_total_frames
  return @total_frames if @total_frames

  total = 0
  total += hour * MINUTES_PER_HOUR * SECONDS_PER_MINUTE * framerate
  total += minute * SECONDS_PER_MINUTE * framerate
  total += second * framerate
  total += frame

  @total_frames = total
end