Documentation Index
Fetch the complete documentation index at: https://mintlify.com/hitenpatel/songprint/llms.txt
Use this file to discover all available pages before exploring further.
SignatureGenerator requires 16kHz mono 16-bit PCM delivered as a ShortArray. Raw audio from device microphones, media decoders, or file demuxers rarely arrives in that format — it is typically stereo, at 44100 Hz or 48000 Hz, and packed as raw bytes. The Pcm object provides two utility functions that handle the conversion in a single, chainable step.
Pcm.bytesToShorts
bytesToShorts decodes a ByteArray of 16-bit little-endian PCM into a ShortArray of individual samples. This is the direct format produced by AudioRecord when configured with AudioFormat.ENCODING_PCM_16BIT, as well as by most media extractor and codec output buffers.
import io.github.hitenpatel.songprint.Pcm
// pcmBytes: ByteArray read from AudioRecord, a file decoder, etc.
val samples: ShortArray = Pcm.bytesToShorts(pcmBytes)
Each pair of consecutive bytes is treated as a single little-endian signed 16-bit integer. The resulting ShortArray has exactly pcmBytes.size / 2 elements.
Pcm.resampleToMono16k
resampleToMono16k converts an interleaved multi-channel ShortArray at any sample rate into 16kHz mono. It performs two operations in sequence:
- Channel averaging — all channels in each frame are averaged together to produce a single mono sample. Only the channel count needs to be known; the channel layout does not matter.
- Linear-interpolation resampling — the mono signal is resampled to exactly 16000 Hz using linear interpolation between adjacent samples.
Signature:
fun resampleToMono16k(samples: ShortArray, sampleRate: Int, channels: Int): ShortArray
Converting 44100 Hz stereo to 16kHz mono:
import io.github.hitenpatel.songprint.Pcm
// samples: ShortArray decoded from 44100 Hz, 2-channel PCM
val mono16k: ShortArray = Pcm.resampleToMono16k(
samples = samples,
sampleRate = 44100,
channels = 2,
)
// mono16k is now 16kHz mono, ready for SignatureGenerator
If sampleRate is already 16000 and channels is 1, the function returns the input array unchanged — there is no unnecessary copy.
For the typical Android AudioRecord or MediaExtractor pipeline — 44100 Hz stereo, 16-bit PCM — chain the two calls:
import io.github.hitenpatel.songprint.Pcm
// Step 1: decode raw bytes into shorts
val samples: ShortArray = Pcm.bytesToShorts(rawPcmBytes)
// Step 2: downsample to 16kHz mono
val mono16k: ShortArray = Pcm.resampleToMono16k(samples, sampleRate = 44100, channels = 2)
// mono16k is now ready for SignatureGenerator().generateSignature(mono16k)
The same pattern works for any source rate and channel count — substitute the actual values for sampleRate and channels.
Aim for 10–12 seconds of audio for the best match reliability. Shorter clips can match, but fingerprint density is lower and the Shazam endpoint is less confident in noisy or low-quality recordings.
SignatureGenerator requires exactly 16kHz input. Passing audio at the wrong sample rate will not raise an error — it will silently produce a signature with shifted frequencies that will not match anything in the database. Always verify that the sampleRate argument passed to resampleToMono16k matches the actual rate of the source signal.
The resampler uses linear interpolation between adjacent samples. This is fast and adds no dependencies, and it is perfectly suited for recognition workloads — SignatureGenerator’s peak-detection algorithm is robust to the minor artifacts linear resampling introduces. It is not a replacement for a high-quality SRC library in a production audio processing pipeline.