Skip to main content

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.

Pcm is a Kotlin object (singleton) providing two utility functions for converting raw PCM audio into the 16kHz mono ShortArray format required by SignatureGenerator. It handles the two most common preparation steps: decoding raw little-endian PCM bytes into samples, and downmixing and resampling from arbitrary formats to 16kHz mono. It is pure common Kotlin — no platform-specific APIs, no external dependencies.

Object declaration

object Pcm

Functions

bytesToShorts

fun bytesToShorts(pcm: ByteArray): ShortArray
Decodes a raw 16-bit little-endian PCM byte array into an array of signed 16-bit samples.
pcm
ByteArray
required
Raw 16-bit little-endian PCM bytes, as produced by most audio APIs (Android AudioRecord, WAV file data chunks, etc.). Must contain an even number of bytes; the last byte is silently ignored if the length is odd.
Returns ShortArray — the decoded PCM samples. The output length is pcm.size / 2. Each pair of consecutive bytes [i*2, i*2+1] is interpreted as a little-endian signed 16-bit integer: (pcm[i*2] & 0xFF) | (pcm[i*2+1] << 8).
import io.github.hitenpatel.songprint.Pcm

// Bytes captured from AudioRecord or read from a WAV data chunk
val pcmBytes: ByteArray = audioRecord.readRawBytes()

val samples: ShortArray = Pcm.bytesToShorts(pcmBytes)
// samples.size == pcmBytes.size / 2

resampleToMono16k

fun resampleToMono16k(samples: ShortArray, sampleRate: Int, channels: Int): ShortArray
Converts interleaved multi-channel PCM at any sample rate to 16kHz mono using channel averaging and linear-interpolation resampling.
samples
ShortArray
required
Interleaved multi-channel PCM samples at the original sample rate. For stereo (channels = 2) the layout is [L0, R0, L1, R1, ...]; for mono (channels = 1) the layout is a plain sample sequence. The array length must be a multiple of channels.
sampleRate
Int
required
Original sample rate in Hz (e.g. 44100, 48000, 22050). The function resamples from this rate to SignatureGenerator.SAMPLE_RATE (16000 Hz).
channels
Int
required
Number of interleaved channels (e.g. 1 for mono, 2 for stereo). All channels are averaged together to produce the mono signal before resampling.
Returns ShortArray — resampled 16kHz mono PCM samples. If sampleRate is already 16000 and channels is 1, the input ShortArray is returned unchanged with no allocation. The function performs two steps in order:
  1. Channel averaging — if channels >= 2, pairs of interleaved frames are averaged into a single mono sample per frame.
  2. Linear-interpolation resampling — the mono signal is resampled to 16kHz. For each output sample, a source position is computed as outputIndex / ratio; the fractional part is used to linearly interpolate between the two surrounding input samples.
import io.github.hitenpatel.songprint.Pcm

val samples = Pcm.bytesToShorts(pcmBytes)

// From 44.1kHz stereo to 16kHz mono
val mono16k = Pcm.resampleToMono16k(samples, sampleRate = 44100, channels = 2)

// From 48kHz mono to 16kHz mono
val mono16kFrom48 = Pcm.resampleToMono16k(samples48, sampleRate = 48000, channels = 1)

// Already 16kHz mono — returns input ShortArray unchanged, no allocation
val unchanged = Pcm.resampleToMono16k(mono16kSamples, sampleRate = 16000, channels = 1)

Typical usage pattern

The two functions chain naturally into the preparation step before fingerprinting:
import io.github.hitenpatel.songprint.Pcm
import io.github.hitenpatel.songprint.SignatureGenerator

// Step 1: decode raw bytes from your audio source
val samples = Pcm.bytesToShorts(pcmBytes)

// Step 2: downsample and downmix to 16kHz mono
val mono16k = Pcm.resampleToMono16k(samples, sampleRate = 44100, channels = 2)

// Step 3: generate the fingerprint
val signature = SignatureGenerator().generateSignature(mono16k)
Provide at least a few seconds of audio in pcmBytes; SignatureGenerator processes up to MAX_TIME_SECONDS (3.1 s) of audio before stopping peak collection.
The resampler uses linear interpolation. It is fast and produces results that are entirely appropriate for audio recognition workloads. It is not a studio-grade resampler — do not use it where high-fidelity audio reconstruction matters.
Pcm uses only the common Kotlin standard library — there are no JVM, Android, or native-specific imports. It compiles and runs on any Kotlin Multiplatform target, including jvm, android, iosArm64, js, and wasmJs.

Build docs developers (and LLMs) love