Class: Shazamio::SignatureGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/shazamio/algorithm.rb

Overview

Pure-Ruby reimplementation of Shazam's signature (audio fingerprint) generator. This is the algorithm the Python project calls "legacy" / pure-Python, used by the deprecated recognize_song; the newer recognize in Python instead calls into a compiled Rust extension (shazamio_core) for speed. There is no Ruby equivalent of that native extension here, so this pure-Ruby path (translated line-for-line from algorithm.py) is the only recognizer available in this port. It is correct but noticeably slower than the Rust version on long clips.

Constant Summary collapse

MAX_PEAKS =
255

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSignatureGenerator

Returns a new instance of SignatureGenerator.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/shazamio/algorithm.rb', line 59

def initialize
  @input_pending_processing = []
  @samples_processed = 0

  @ring_buffer_of_samples = RingBuffer.new(2048, default_value: 0)
  @fft_outputs = RingBuffer.new(256, default_value: Array.new(1025, 0.0))
  @spread_fft_output = RingBuffer.new(256, default_value: Array.new(1025, 0.0))

  @max_time_seconds = 3.1

  @next_signature = DecodedMessage.new
  @next_signature.sample_rate_hz = 16_000
  @next_signature.number_samples = 0
  @next_signature.frequency_band_to_sound_peaks = {}
end

Instance Attribute Details

#max_time_secondsObject

Returns the value of attribute max_time_seconds.



56
57
58
# File 'lib/shazamio/algorithm.rb', line 56

def max_time_seconds
  @max_time_seconds
end

#next_signatureObject (readonly)

Returns the value of attribute next_signature.



57
58
59
# File 'lib/shazamio/algorithm.rb', line 57

def next_signature
  @next_signature
end

#samples_processedObject

Returns the value of attribute samples_processed.



56
57
58
# File 'lib/shazamio/algorithm.rb', line 56

def samples_processed
  @samples_processed
end

Instance Method Details

#feed_input(samples) ⇒ Object

samples: Array of signed 16-bit, 16kHz mono PCM integers.



76
77
78
# File 'lib/shazamio/algorithm.rb', line 76

def feed_input(samples)
  @input_pending_processing.concat(samples)
end

#get_next_signatureObject



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/shazamio/algorithm.rb', line 80

def get_next_signature
  return nil if @input_pending_processing.length - @samples_processed < 128

  while (@input_pending_processing.length - @samples_processed >= 128) &&
        ((@next_signature.number_samples.to_f / @next_signature.sample_rate_hz < @max_time_seconds) ||
         (@next_signature.frequency_band_to_sound_peaks.values.sum(&:length) < MAX_PEAKS))
    chunk = @input_pending_processing[@samples_processed, 128]
    process_input(chunk)
    @samples_processed += 128
  end

  @ring_buffer_of_samples = RingBuffer.new(2048, default_value: 0)
  @fft_outputs = RingBuffer.new(256, default_value: Array.new(1025, 0.0))
  @spread_fft_output = RingBuffer.new(256, default_value: Array.new(1025, 0.0))

  @next_signature
end