                      (map-indexed #(-> [[id %] %2]) urls)))
         sound-req))
 
+(defn start-exercise-custom-sounds [this]
+  (go
+    (let [{::keys [custom-sounds-req]} (om/props this)
+          progress-chan (handle-progress (om/parent this) (async/chan 10))
+          sounds        (<! (audio/load-sound-library
+                              (flatten-request custom-sounds-req)
+                              progress-chan))]
+      (um/set-value! (om/parent this) ::custom-sounds sounds))
+    nil))
+
 (om/defui ^:once Exercise
   static uc/InitialAppState
   (initial-state [_ _] {::ex-answer              nil

                        ::hints-used             0
                        ::play-notes             play-notes
                        ::started?               false
                        ::custom-sounds-progress {:ui/progress-value 0
                                                  :ui/progress-total 1}
                        ::custom-sounds-req      nil})

  (componentDidMount [this]
    (let [{::keys [custom-sounds-req]} (om/props this)]
      (if custom-sounds-req
        (if @audio/*audio-context*
          (start-exercise-custom-sounds this)
          (um/set-value! (om/parent this) ::context-missing true)))))

  (render [this]
    (let [{::keys [options ex-answer ex-total-questions streak-count notes hints context-missing
                   hints-used started? custom-sounds-req custom-sounds custom-sounds-progress]
           :as    props} (om/props this)
          state        (-> this om/get-reconciler om/app-state deref)
