1pub mod audio;
20pub mod chroma;
21pub mod codec;
22pub mod config;
23pub mod error;
24pub mod fft;
25pub mod fingerprint;
26pub mod pipeline;
27pub mod simd;
28pub mod types;
29
30pub use error::{Error, Result};
31pub use types::{Algorithm, Fingerprint};
32
33use pipeline::Pipeline;
34
35pub struct Fingerprinter {
40 algorithm: Algorithm,
41 pipeline: Pipeline,
42 started: bool,
43}
44
45impl Fingerprinter {
46 pub fn new(algorithm: Algorithm) -> Self {
48 Self {
49 algorithm,
50 pipeline: Pipeline::new(algorithm),
51 started: false,
52 }
53 }
54
55 pub fn start(&mut self, sample_rate: u32, num_channels: u16) -> Result<()> {
57 self.pipeline.start(sample_rate, num_channels)?;
58 self.started = true;
59 Ok(())
60 }
61
62 pub fn feed(&mut self, samples: &[i16]) -> Result<()> {
64 if !self.started {
65 return Err(Error::NotStarted);
66 }
67 self.pipeline.feed(samples);
68 Ok(())
69 }
70
71 pub fn finish(&mut self) -> Result<()> {
73 if !self.started {
74 return Err(Error::NotStarted);
75 }
76 self.pipeline.finish();
77 Ok(())
78 }
79
80 pub fn fingerprint(&self) -> &[u32] {
82 self.pipeline.fingerprint()
83 }
84
85 pub fn encode(&self) -> String {
87 fingerprint::compressor::compress(self.pipeline.fingerprint(), self.algorithm)
88 }
89
90 pub fn hash(&self) -> u32 {
92 fingerprint::simhash::simhash(self.pipeline.fingerprint())
93 }
94
95 pub fn algorithm(&self) -> Algorithm {
97 self.algorithm
98 }
99}
100
101pub fn fingerprint_audio(
103 samples: &[i16],
104 sample_rate: u32,
105 num_channels: u16,
106 algorithm: Algorithm,
107) -> Result<Fingerprint> {
108 let mut fp = Fingerprinter::new(algorithm);
109 fp.start(sample_rate, num_channels)?;
110 fp.feed(samples)?;
111 fp.finish()?;
112 Ok(Fingerprint::new(fp.fingerprint().to_vec(), algorithm))
113}
114
115pub fn encode_fingerprint(raw: &[u32], algorithm: Algorithm) -> String {
117 fingerprint::compressor::compress(raw, algorithm)
118}
119
120pub fn decode_fingerprint(encoded: &str) -> Result<(Vec<u32>, Algorithm)> {
122 fingerprint::decompressor::decompress(encoded)
123}
124
125pub fn hash_fingerprint(raw: &[u32]) -> u32 {
127 fingerprint::simhash::simhash(raw)
128}
129
130#[cfg(feature = "parallel")]
132pub fn fingerprint_batch(
133 inputs: &[(&[i16], u32, u16)],
134 algorithm: Algorithm,
135) -> Vec<Result<Fingerprint>> {
136 use rayon::prelude::*;
137
138 inputs
139 .par_iter()
140 .map(|&(samples, sample_rate, num_channels)| {
141 fingerprint_audio(samples, sample_rate, num_channels, algorithm)
142 })
143 .collect()
144}