pyquist.web

Clients for external music data sources.

freesound

FreeSound API client.

Most users only need fetch_freesound(), which downloads a sound by URL or numeric ID and returns it as an pyquist.Audio. Previews download without authentication; fetching the original uncompressed file requires the FreeSound OAuth2 flow (walked through interactively on first use).

Credentials and downloaded files are cached under CACHE_DIR / "freesound".

pyquist.web.freesound.url_to_id(id_or_url)[source]

Parses a FreeSound URL or numeric ID into an integer sound ID.

Accepted forms:

  • 123456 — raw int

  • "123456" — numeric string

  • "https://freesound.org/sounds/123456/"

  • "https://freesound.org/people/<user>/sounds/123456/"

  • http:// and www. variants of the above

Raises ValueError if the input isn’t a recognized FreeSound URL or a numeric ID.

Parameters:

id_or_url (Union[int, str])

Return type:

int

pyquist.web.freesound.fetch_metadata(sound_id, *, reauthenticate=False)[source]

Fetches the FreeSound JSON metadata for a sound (cached on disk).

Parameters:
  • sound_id (int)

  • reauthenticate (bool)

Return type:

dict

pyquist.web.freesound.fetch_audio_bytes(sound_id, *, preview_tag='preview-hq-ogg', reauthenticate=False)[source]

Downloads the raw audio bytes for a sound, plus its metadata.

Parameters:
  • sound_id (int) – FreeSound numeric ID.

  • preview_tag (Optional[str]) – Which preview to download. One of "preview-hq-ogg" (default), "preview-hq-mp3", "preview-lq-ogg", or "preview-lq-mp3". Pass None to download the original uncompressed file instead — this requires OAuth2 and triggers an interactive auth flow on first use.

  • reauthenticate (bool) – Force a re-prompt of API credentials.

Return type:

Tuple[bytes, dict]

Returns (audio_bytes, metadata). Both are cached on disk so repeated calls for the same sound are free.

pyquist.web.freesound.fetch_freesound(id_or_url, *, preview_tag='preview-hq-ogg', reauthenticate=False)[source]

Fetches an Audio (and metadata) from FreeSound by URL or numeric ID.

Example:

from pyquist.web import fetch_freesound
audio, meta = fetch_freesound(
    "https://freesound.org/people/cdonahueucsd/sounds/337131/"
)
Parameters:
  • id_or_url (Union[int, str]) – A FreeSound URL or numeric sound ID. See url_to_id() for the recognized URL forms.

  • preview_tag (Optional[str]) – Which preview to fetch (default high-quality OGG). Pass None to fetch the original uncompressed file (OAuth2 required).

  • reauthenticate (bool) – Force a re-prompt of API credentials.

Return type:

Tuple[Audio, dict]

Returns:

(audio, metadata)audio is decoded via pyquist.Audio.from_file() and metadata is the raw JSON dict returned by the FreeSound API.

theorytab

TheoryTab API client.

TheoryTab is a community database of pop-song melody and chord progressions hosted by Hooktheory. This module fetches a song by URL or 11-character ID and turns it into pyquist pyquist.Score objects ready for rendering.

Most users only need fetch(), which combines fetch_theorytab_json() (network + caching) with theorytab_json_to_score() (parsing).

Downloaded JSON is cached under CACHE_DIR / "theorytab" so repeat lookups are free.

pyquist.web.theorytab.fetch_theorytab_json(id_or_url, *, ignore_cache=False)[source]

Fetches the raw TheoryTab JSON for a song, caching it on disk.

Parameters:
  • id_or_url (str) – A bare 11-character TheoryTab song ID or any URL that contains it as the idOfSong query parameter.

  • ignore_cache (bool) – If True, re-fetch even if a cached copy exists.

Raises:
  • ValueError – if id_or_url can’t be parsed.

  • RuntimeError – on a non-200 response from the Hooktheory API or unexpected response shape.

  • NotImplementedError – if the song’s data is in a legacy format without parsed jsonData.

Return type:

dict

pyquist.web.theorytab.theorytab_json_to_score(song_data, *, durations_in_beats=False, melody_octave=5, harmony_octave=4)[source]

Parses a TheoryTab JSON object into a metronome and two scores.

The time of each event is in beats (starting from 0). Pair it with the returned BasicMetronome when rendering so beats are converted to seconds.

Chord events are emitted as one Event per chord tone in root position, each with a "pitch" kwarg — so a triad at beat 4 becomes three events sharing time == 4.0.

Parameters:
  • song_data (dict) – TheoryTab JSON (as returned by fetch_theorytab_json()).

  • durations_in_beats (bool) – If False (default), each event’s kwargs["duration"] is converted to seconds via the song’s tempo. If True, durations stay in beats and the instrument is responsible for any further conversion.

  • melody_octave (int) – Octave offset added to melody pitches.

  • harmony_octave (int) – Octave offset added to harmony pitches.

Return type:

Tuple[Metronome, Score, Score]

Returns:

(metronome, melody, harmony) where metronome is a BasicMetronome carrying the song’s tempo, and melody / harmony are Score objects.

Raises:

NotImplementedError – if the song’s time signature / tempo / key structure is more complex than this parser supports.

pyquist.web.theorytab.fetch_theorytab(id_or_url, **kwargs)[source]

Fetches and parses a TheoryTab song in one call.

Equivalent to theorytab_json_to_score(fetch_theorytab_json(id_or_url), **kwargs).

Example:

from pyquist.web import fetch_theorytab
metronome, melody, harmony = fetch_theorytab(
    "https://hookpad.hooktheory.com/?idOfSong=RPxeJeJaob_"
)

To get a URL: find a song on TheoryTab, right-click “Open in Hookpad”, and “Copy Link Address.”

Parameters:
Return type:

Tuple[Metronome, Score, Score]