Reuse sounds and patterns by importing their definitions. A module is an ordinary Volta file: you can share a few voices, a pattern collection or a complete song.
Try a bundled library#
This example uses Volta's bundled drum library:
import "drums" (kick, hat)
timingVersion = 2
tempo = 120bpm
beat = play kick !"c3 c3 c3 c3" |> gain 0.6
ticks = play hat !"~ c3 ~ c3 ~ c3 ~ c3" |> gain 0.25
The parenthesized names select the definitions you want. The library must contain those names and make them public. See The standard library for available sounds and patterns.
Use your own module#
Save this as voices.volta beside your song:
soft = patch {
source = sine (freq pitch),
ampEnv = adsr 8ms 100ms 0.4 200ms,
gain = 0.15
}
Then use it from a separate song file:
import "voices" (soft)
lead = play soft !"c4 e4 g4 c5"
These are two separate files. Opening a code example creates a working copy of that block; it does not create modules shown in another block. Save the song beside voices.volta before running it. In browser Studio, make the module available in your workspace's files.
Names and namespaces#
Definitions are public by default. Prefix a definition with priv to keep it internal; public definitions can still use that private helper.
Use an alias when you want a module's names grouped together:
import "drums" as drumkit
beat = play drumkit.clap !"~ c3 ~ c3"
Two modules can have definitions with the same name. Use aliases to distinguish them, or rename one name as you import it:
import "drums" (kick as boom)
beat = play boom !"c2 ~ c2 ~"
The song now sees the library's kick as boom, so it is free to define a kick of its own.
Selectively importing the same bare name twice, or defining a song binding with an imported bare name, is an error that suggests either escape. See Names and library imports.
A module can pass names on from another module with pub import. A kit module that writes pub import "drums" (kick, hat as hh) lets songs write import "kit" (kick, hh) or kit.hh without knowing where the sounds live. Only named bindings can be re-exported; priv names never can.
Where imports come from#
Import paths are quoted strings. A local import "voices" looks for voices.volta. Desktop Studio checks the importing file's directory and song search locations, then the workspace and installed libraries. Bundled libraries are also available from scratch songs, including Reference examples. Your own local module takes precedence over a bundled module of the same name, and the editor shows a note at the import saying which module it hides.
A path is one or more names separated by / ("kits/808"), each made of letters, digits, _, - and .. Leave off the .volta extension (the error offers the fix), and do not use .., a leading / or \. Matching is case-exact on every computer: import "drums" does not find Drums.volta, and the error names the file it found.
Two different files can share a name. If kits/a/tone.volta and kits/b/tone.volta are each imported as "tone" by a module beside them, each module keeps its own tone. The same file imported under two spellings is one module, included once.
A published pack's own imports never reach your files: inside @owner/pack, import "tone" finds only a bundled library module, so a tone.volta in your song folder cannot change someone else's pack.
Browser Studio resolves modules from its available workspace sources and bundled libraries. Saved or edited sources take precedence over bundled copies. An unavailable module produces an import error; add the file or correct the import path, then run again. Module errors identify the module containing the problem.
Imports can depend on other imports, but circular dependencies are errors. Importing a library does not automatically play all of its tracks: only the material used by the song is included. Local imports do not select package versions or install dependencies for you. See Versions, history and comparisons for published packs.
Editor help for imports#
Write a -- comment directly above a definition (no blank line between) and it becomes that definition's documentation wherever the module is browsed or imported; an @doc "…" annotation takes precedence. The first paragraph of the comment block at the top of the file is the module's one-line blurb, and a -- @tags a, b line tags it:
-- drums — a small, reusable percussion kit.
-- @tags kit, electronic
-- kick — a punchy sine kick with a fast pitch drop.
kick = patch { source = sine (freq pitch), ampEnv = adsr 0ms 100ms 0 80ms, gain = vel }
In the editor (language server and workbench):
- hovering an imported name shows its type, doc, kind and
from "drums"; hovering the quoted path shows the module's blurb and exports; - typing inside
import "…"offers module paths spelled the way they resolve (kits/808for a file in akitsfolder), and inside( … )the module's exports with their docs; - renamed names (
(kick as k808)) and names a module re-exports withpub importhover, complete and jump to the definition in the module that really defines them; - an import you never use is a warning (a renamed name counts as used only under its new name; a
pub importis never unused), removed by Remove unused import or Organize Imports, which keepasandpub; - a bad import path with an obvious fix (a trailing
.volta,\instead of/) offers Change toimport "…"; - Extract to module… moves selected definitions (and helpers only they use) into a module file and imports them back.
One compiler function, volta_compiler::module_summary(src) (wasm export module_summary(src) → JSON), describes a module for every surface: { blurb, tags, imports: [{ path, names, alias, public, locals }], exports: [{ name, kind, doc, category, signature, origin, origin_name }], ok } (public, locals, origin and origin_name appear only when set). A pub import re-export is listed first, under the name importers use, with origin naming the module it comes from; module_summary_with(src, lookup) describes it (kind, doc, signature) from that module's source when the caller can supply it, otherwise it is a bare value. Private definitions and a song's main or song are not exports. kind is one of instrument, effect, pattern, function, module, value or track, read from the definition's syntax alone (a patch, a !"…" pattern, an @category "effect", a lambda that pipes its first argument through an audio effect, …), so a definition built by calling another module's function reads as value. A type export is listed as value with category: "type". A file that does not parse still summarizes its intact definitions, with ok: false. See Language server and editor support § Editor help for imports for the editor rules.
Import a complete performance#
Use songSource station.film 0s with import "my-score" as station to preserve an imported song's arrangement, tempo, meter, automation and mixer in one stereo source. The finite performance prepares before playback. See Play a complete imported song for timing, required audio and limits.