@@ -0,0 +1,52 @@
1+module BasicPitch.Cdn
2+ ( CdnModel
3+ , CdnSources
4+ , esmSources
5+ , loadModel
6+ , evaluateFrames
7+ , backend
8+ ) where
9+
10+import Prelude
11+
12+import Effect (Effect)
13+import Effect.Aff (Aff)
14+import Effect.Uncurried (EffectFn2, runEffectFn2)
15+import Promise (Promise)
16+import Promise.Aff (toAffE)
17+
18+-- | A basic-pitch model loaded from a CDN at runtime — see `loadModel`. Distinct
19+-- | from `BasicPitch.Model` so importing this module pulls in NO static
20+-- | `@spotify/basic-pitch` dependency (it would otherwise be bundled).
21+foreign import data CdnModel :: Type
22+
23+-- | The ES-module URLs to import basic-pitch and TensorFlow.js from at runtime.
24+type CdnSources = { basicPitch :: String, tfjs :: String }
25+
26+-- | Sensible defaults: esm.sh-hosted basic-pitch 1.0.1 and tfjs 4.22.0.
27+esmSources :: CdnSources
28+esmSources =
29+ { basicPitch: "https://esm.sh/@spotify/basic-pitch@1.0.1"
30+ , tfjs: "https://esm.sh/@tensorflow/tfjs@4.22.0"
31+ }
32+
33+-- | Load basic-pitch + tfjs from a CDN at runtime (a dynamic `import()` the bundler
34+-- | leaves alone — useful when a bundler chokes trying to bundle tfjs into the
35+-- | client), then load the model from `modelPath` (a URL to its `model.json`).
36+-- | Prefers the WebGL backend. The result is cached weights ready for inference.
37+loadModel :: CdnSources -> String -> Aff CdnModel
38+loadModel sources modelPath = toAffE (runEffectFn2 loadModelImpl sources modelPath)
39+
40+foreign import loadModelImpl :: EffectFn2 CdnSources String (Promise CdnModel)
41+
42+-- | Transcribe one buffer of mono samples (at 22050 Hz) to its frame-activation
43+-- | matrix — rows of 88 pitch activations (MIDI 21–108), ~11.6 ms per row. For
44+-- | streaming peak-pick detection on short windows, rather than full note events.
45+evaluateFrames :: CdnModel -> Array Number -> Aff (Array (Array Number))
46+evaluateFrames model samples = toAffE (runEffectFn2 evaluateFramesImpl model samples)
47+
48+foreign import evaluateFramesImpl :: EffectFn2 CdnModel (Array Number) (Promise (Array (Array Number)))
49+
50+-- | The TensorFlow.js backend the last-loaded model is running on (e.g. `"webgl"`),
51+-- | or `"?"` if it couldn't be determined — handy for a debug readout.
52+foreign import backend :: Effect String