Skip to content

[Feature]: Constant Q Transform (CQT) #20

Description

@gabyfle

Initial Checklist

  • I have searched the existing issues to ensure this feature has not already been requested.

Problem Statement & User Value

As an audio machine learning engineer, I want to use a Constant Q Transform (CQT) spectrogram as input to my neural network, so that the model can more easily learn features for tasks like instrument classification, chord recognition, and cover song identification, leveraging a representation that mirrors the geometric structure of music.

Acceptance Criteria (Definition of Done)

Core CQT Functionality (SoundML.Transform.cqt)

  • A new function SoundML.Transform.cqt is implemented and exposed in the public API.
  • The function accepts a 1D Rune tensor (single-channel) or 2D Rune tensor (multi-channel, shape (channels, samples)) of real-valued floating-point numbers as input.
  • The function returns a 2D (single-channel) or 3D (multi-channel) Rune tensor of complex numbers, with dimensions corresponding to (channels, n_bins, n_frames).
  • The implementation is based on the efficient recursive octave-based algorithm described by Schörkhuber and Klapuri, which is the state-of-the-art approach used by reference libraries like Librosa.
  • The output values are numerically validated against the output of librosa.cqt for a canonical set of test signals (e.g., sine waves, impulses, real audio clips) to within a tight tolerance (10^{-5} relative error).

Performance & Error Handling

  • Performance benchmarks demonstrate that the OCaml implementation's execution time is competitive with (i.e., within 1.5x of) the librosa CQT implementation when run on identical hardware.
  • The function raises typed exceptions for invalid input parameters (e.g., Invalid_argument "sr must be positive", Invalid_argument "fmin must be positive", Invalid_argument "n_bins must be at least bins_per_octave").
  • Memory usage is profiled and confirmed to be efficient and free of leaks. The recursive algorithm's design should prevent the creation of excessively large intermediate data structures, a known issue with naive CQT approaches.

Documentation & Testing

  • The public API is fully documented in the corresponding .mli interface file, with clear explanations for each function, parameter, return value, and any raised exceptions.
  • The documentation includes at least two clear usage examples:
    • a basic CQT computation with default parameters,
    • a high-resolution CQT for detailed analysis (e.g., 36 bins per octave),
  • Unit tests provide 100% coverage for all parameter validation logic and edge cases.
  • Integration tests cover the full transform pipeline and validate numerical correctness against pre-computed reference values generated by librosa.

Proposed Solution or Technical Approach (Optional)

This feature will be implemented within the Tranform module. The core of the implementation will be the recursive, octave-based CQT algorithm as detailed by Schörkhuber and Klapuri.

Algorithmic Breakdown

  • Filter/Kernel Generation: A preliminary function will pre-compute the CQT filter kernels in the frequency domain. A sparse spectral kernel is derived from the FFT of the windowed temporal basis functions. Then these kernels are calculated once based on user parameters (sr, fmin, n_bins, etc.) and stored for reuse.
  • Recursive CQT Core: A main recursive function will orchestrate the transform.
    • Base Case: If the lowest required octave is reached, compute its CQT via kernel multiplication and return the result.
    • Recursive Step:
      • Compute the CQT for the current (highest remaining) octave. This involves framing the input signal, taking the FFT of each frame, and performing a sparse matrix multiplication in the frequency domain between the FFT frames and the pre-computed spectral kernel for that octave.
      • Prepare the signal for the next lower octave. This requires applying a high-quality low-pass filter (e.g., a sixth-order Butterworth IIR filter, as suggested in the reference implementation ) to prevent aliasing, followed by downsampling the signal by a factor of 2.
      • Make a recursive call with the filtered, downsampled signal to compute the CQT for all lower octaves.
      • Concatenate the CQT results from the current octave with the results from the recursive call along the frequency axis.

Additional Context (Mockups, Links, etc.)

No response

References

  • Brown, J. C. (1991). "Calculation of a constant Q spectral transform." The Journal of the Acoustical Society of America, 89(1), 425–434.

    • Foundational paper that introduced the CQT for musical analysis
  • Brown, J. C., & Puckette, M. S. (1992). "An efficient algorithm for the calculation of a constant Q transform." The Journal of the Acoustical Society of America, 92(5), 2698–2701.

    • First efficient, FFT-based method using sparse spectral kernels.
  • Schörkhuber, C., & Klapuri, A. (2010). "Constant-Q transform toolbox for music processing." Proceedings of the 7th Sound and Music Computing Conference.

    • Modern, state-of-the-art recursive octave-based algorithm that provides further efficiency gains and enables a high-quality inverse transform. This paper defines the target algorithm for this implementation.
  • Librosa: librosa.cqt and librosa.icqt

  • Essentia: essentia.standard.ConstantQ

Code of Conduct

Metadata

Metadata

Assignees

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions