├── .gitignore ├── CHANGELOG.md ├── src └── midi │ └── soundfont.clj └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .nrepl* 3 | *~ -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ## 0.1.1 4 | 5 | * `load-all-instruments!` can now optionally take an already-obtained reference to a javax.sound.midi.Soundbank in the place of a soundfont file. 6 | 7 | ## 0.1.0 8 | 9 | * Initial release 10 | * `load-all-instruments!` loads all instruments from a MIDI soundfont (provided as a File or InputStream) into a javax.sound.midi.Synthesizer. 11 | * `load-patch` and `midi-test` functions provided for testing purposes. 12 | -------------------------------------------------------------------------------- /src/midi/soundfont.clj: -------------------------------------------------------------------------------- 1 | (ns midi.soundfont 2 | (:require [clojure.java.io :as io]) 3 | (:import (javax.sound.midi MidiSystem Synthesizer))) 4 | 5 | (defprotocol Soundbank 6 | (soundbank-of [x])) 7 | 8 | (extend-protocol Soundbank 9 | Object 10 | (soundbank-of [☠] 11 | (throw (Exception. 12 | (format "Expected a File, InputStream, or Soundbank; got %s" 13 | (type ☠))))) 14 | 15 | java.io.File 16 | (soundbank-of [sf] (MidiSystem/getSoundbank sf)) 17 | 18 | java.io.InputStream 19 | (soundbank-of [sf] (MidiSystem/getSoundbank sf)) 20 | 21 | javax.sound.midi.Soundbank 22 | (soundbank-of [sb] sb)) 23 | 24 | (defn load-all-instruments! 25 | "Loads all of the instruments from a soundbank or soundfont into a MIDI 26 | synthesizer. 27 | 28 | `src` may be either an existing (i.e. pre-evaluated) soundbank, or a 29 | supported soundfont (i.e. a DLS or SF2 file) in the form of a File or 30 | an InputStream." 31 | [^Synthesizer synth src] 32 | (doto synth 33 | (.open); open synth, in case it isn't open already 34 | (.unloadAllInstruments (.getDefaultSoundbank synth)) 35 | (.loadAllInstruments (soundbank-of src)))) 36 | 37 | ;;; for testing purposes ;;; 38 | 39 | (defn load-patch [^Synthesizer synth patch-number] 40 | (let [channel (first (.getChannels synth))] 41 | (.programChange channel (dec patch-number)))) 42 | 43 | (defn midi-test [^Synthesizer synth] 44 | (let [channel (first (.getChannels synth)) 45 | demo-notes [43 47 50 55 59 62 67 71 74 79]] 46 | (doseq [note demo-notes] 47 | (. channel noteOn note 127) 48 | (Thread/sleep 250) 49 | (. channel noteOff note)))) 50 | 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # midi.soundfont 2 | 3 | [![Clojars Project](http://clojars.org/midi.soundfont/latest-version.svg)](http://clojars.org/midi.soundfont) 4 | 5 | A Clojure library for loading MIDI soundfonts into the JVM, and making it quick and easy to get nice sounds out of your MIDI system. :notes: 6 | 7 | ## Example: FluidR3 8 | 9 | FluidR3 is one of the most commonly used freeware General MIDI soundfonts. I've packaged it as a Maven dependency, with the .sf2 file itself as a resource and a namespaced var `midi.soundfont.fluid-r3/sf2` included in order to provide an easy way to access the soundfont from a separate Clojure project. 10 | The source code for this package is [here](https://bitbucket.org/daveyarwood/midi.soundfont.fluid-r3/src) -- it's a good example, if you're interested in packaging a soundfont yourself. 11 | 12 | To load the instruments from this soundfont into your JVM, first add the following to your dependencies: 13 | 14 | [midi.soundfont "0.1.0"] 15 | [org.bitbucket.daveyarwood/fluid-r3 "0.1.1"] 16 | 17 | Then you can do something like this: 18 | 19 | (require '[midi.soundfont :refer (load-all-instruments! midi-test load-patch)] 20 | '[midi.soundfont.fluid-r3 :as fluid-r3]) 21 | 22 | (import '(javax.sound.midi MidiSystem)) 23 | 24 | (def synth (MidiSystem/getSynthesizer)) 25 | (load-all-instruments! synth fluid-r3/sf2) 26 | 27 | (midi-test synth) ; you should hear a nice-sounding piano 28 | 29 | (load-patch synth 30) 30 | (midi-test synth) ; you should hear a gnarly distorted guitar! 31 | 32 | ## Packaging soundfonts 33 | 34 | Quality soundfonts can get pretty big -- FluidR3 is 141 MB. Unfortunately, Clojars has a 20 MB limit on package size, thus making it unsuitable for packaging any soundfonts larger than 20 MB. GitHub also places a strict limit of 100 MB for each file in a repo, and a total repo size limit of 1 GB. 35 | 36 | I was able to package FluidR3 by hosting the repo on Bitbucket -- they have a 2 GB total repo size limit, and no limits on individual file size -- and deploying the package to Maven Central. Deploying to Maven Central is a fairly complicated, but doable (if not somewhat painful) process. You can read more about it [here](https://github.com/technomancy/leiningen/blob/master/doc/DEPLOY.md). 37 | --------------------------------------------------------------------------------