Changeset 6701
- Timestamp:
- 06/30/09 18:04:10 (9 months ago)
- Location:
- trunk/liquidsoap/src
- Files:
-
- 6 modified
- 1 copied
-
Makefile (modified) (2 diffs)
-
formats/midiformat.ml (modified) (8 diffs)
-
stream/mFrame.mli (modified) (1 diff)
-
synth/keyboard_sdl.ml (modified) (1 diff)
-
synth/synth.ml (modified) (6 diffs)
-
synth/synth_op.ml (modified) (2 diffs)
-
visualization/midimeter.ml (copied) (copied from trunk/liquidsoap/src/visualization/vumeter.ml) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/liquidsoap/src/Makefile
r6695 r6701 35 35 $(if $(W_NSV),formats/nattyformat_mp3.ml) \ 36 36 $(if $(W_NATTY),formats/nattyformat.ml) \ 37 $(if $(W_MP3),formats/mp3.ml) 38 #formats/midiformat.ml37 $(if $(W_MP3),formats/mp3.ml) \ 38 formats/midiformat.ml 39 39 40 40 playlists = \ … … 144 144 $(if $(W_GL),visualization/GLvisualizer.ml) \ 145 145 $(if $(W_GL),visualization/vis_glvolume.ml) \ 146 visualization/video_volume.ml 146 visualization/video_volume.ml \ 147 visualization/midimeter.ml 147 148 148 149 synth = synth/synth.ml synth/synth_op.ml \ -
trunk/liquidsoap/src/formats/midiformat.ml
r6344 r6701 53 53 if division land 0x8000 = 0 then 54 54 ( 55 (* Delta-time ticks per quarter *) 55 56 log#f 5 "Ticks per quarter: %d" division; 56 57 Midi.Ticks_per_quarter division … … 59 60 let frames = (division lsr 8) land 0x7f in 60 61 let ticks = division land 0xff in 62 log#f 5 "SMPTE: %d * %d" frames ticks; 61 63 Midi.SMPTE (frames, ticks) 62 64 in … … 66 68 raise Invalid_header; 67 69 ); 68 log#f 5 " Tracks: %d"tracks;70 log#f 5 "Format: %d (%d tracks)" fmt tracks; 69 71 tracks, division 70 72 … … 90 92 !ans 91 93 in 94 let status = ref 0 in (* for running status *) 92 95 let read_event () = 93 96 let get_byte () = … … 103 106 ans 104 107 in 105 let cmd = (data.(!pos) lsr 4) land 0xf in 106 let chan = data.(!pos) land 0xf in 108 let advance len = 109 pos := !pos + len 110 in 111 let command = data.(!pos) in 107 112 incr pos; 108 let event = 113 let command = 114 if command land 0x80 <> 0 then 115 ( 116 status := command; 117 command 118 ) 119 else 120 ( 121 decr pos; 122 !status 123 ) 124 in 125 let cmd = (command lsr 4) land 0xf in 126 let chan = command land 0xf in 109 127 match cmd with 110 128 | 8 -> 111 129 let n = get_byte () in 112 130 let v = get_byte () in 113 Midi.Note_off (n, v)131 Some chan, Midi.Note_off (n, float v /. 127.) 114 132 | 9 -> 115 133 let n = get_byte () in 116 134 let v = get_byte () in 117 log#f 6 "Note on: %d %d" n v; 118 Midi.Note_on (n, v) 119 | 10 -> 135 Some chan, Midi.Note_on (n, float v /. 127.) 136 | 0xa -> 120 137 let n = get_byte () in 121 138 let v = get_byte () in 122 Midi.Aftertouch (n, v)123 | 11->139 Some chan, Midi.Aftertouch (n, float v /. 127.) 140 | 0xb -> 124 141 let c = get_byte () in 125 142 let v = get_byte () in 126 Midi.Control_change (c, v)127 | 12->143 Some chan, Midi.Control_change (c, v) 144 | 0xc -> 128 145 let p = get_byte () in 129 Midi.Patch p130 | 13->146 Some chan, Midi.Patch p 147 | 0xd -> 131 148 let c = get_byte () in 132 Midi.Channel_aftertouch c133 | 14->149 Some chan, Midi.Channel_aftertouch c 150 | 0xe -> 134 151 let l = get_byte () land 0x7f in 135 152 let h = get_byte () land 0x7f in 136 Midi.Pitch ((h lsl 7) + l) 137 | 15 -> 138 ( 139 let cmd = get_byte () in 140 match cmd with 141 | 0 -> 142 assert (get_byte () = 2); 143 let h = get_byte () in 144 let l = get_byte () in 145 Midi.Sequence_number ((h lsl 8) + l) 146 | 1 -> 147 let len = get_byte () in 148 Midi.Text (get_text len) 149 | 2 -> 150 let len = get_byte () in 151 Midi.Copyright (get_text len) 152 | 3 -> 153 let len = get_byte () in 154 Midi.Track_name (get_text len) 155 | 4 -> 156 let len = get_byte () in 157 Midi.Instrument_name (get_text len) 158 | 5 -> 159 let len = get_byte () in 160 Midi.Lyric (get_text len) 161 | 6 -> 162 let len = get_byte () in 163 Midi.Marker (get_text len) 164 | 7 -> 165 let len = get_byte () in 166 Midi.Cue (get_text len) 167 | _ -> 168 log#f 5 "Unknown command 15,%d" cmd; 169 raise Not_found 170 ) 153 Some chan, Midi.Pitch ((h lsl 7) + l) 171 154 | _ -> 172 (* log#f 5 "Unknown command %d" cmd; *) 173 raise Not_found 174 in 175 chan, event 155 match command with 156 | 0xf0 157 | 0xf7 -> 158 (* SysEx *) 159 let len = read_delta () in 160 advance len; 161 raise Not_found 162 | 0xff -> 163 ( 164 let cmd = get_byte () in 165 let len = read_delta () in 166 match cmd with 167 | 0 -> 168 assert (len = 2); 169 let h = get_byte () in 170 let l = get_byte () in 171 None, Midi.Sequence_number ((h lsl 8) + l) 172 | 1 -> 173 None, Midi.Text (get_text len) 174 | 2 -> 175 None, Midi.Copyright (get_text len) 176 | 3 -> 177 None, Midi.Track_name (get_text len) 178 | 4 -> 179 None, Midi.Instrument_name (get_text len) 180 | 5 -> 181 None, Midi.Lyric (get_text len) 182 | 6 -> 183 None, Midi.Marker (get_text len) 184 | 7 -> 185 None, Midi.Cue (get_text len) 186 | 0x2f (* End of track *) -> 187 assert (len = 0); 188 raise Not_found 189 | 0x51 (* Tempo in microseconds per quarter note *) -> 190 assert (len = 3); 191 let t1 = get_byte () in 192 let t2 = get_byte () in 193 let t3 = get_byte () in 194 let t = t1 lsl 16 + t2 lsl 8 + t3 in 195 ignore t; 196 None, Midi.Tempo t 197 | 0x58 (* Time signature *) -> 198 assert (len = 4); 199 let n = get_byte () in (* numerator *) 200 let d = get_byte () in (* denominator *) 201 let c = get_byte () in (* ticks in a metronome click *) 202 let b = get_byte () in (* 32nd notes to the quarter note *) 203 ignore (n, d, c, b); 204 None, Midi.Time_signature (n, d, c, b) 205 | 0x59 (* Key signature *) -> 206 assert (len = 2); 207 let sf = get_byte () in (* sharps / flats *) 208 let m = get_byte () in (* minor? *) 209 ignore (sf, m); 210 None, Midi.Key_signature (sf, m <> 0) 211 | 0x54 (* SMPTE Offset *) 212 | 0x7f (* Sequencer-specific data *) -> 213 advance len; 214 raise Not_found 215 | _ -> 216 advance len; 217 log#f 5 "Unknown meta-event %x" cmd; 218 raise Not_found 219 ) 220 | _ -> 221 advance 1; 222 log#f 5 "Unknown command %x (pos: %d)" command !pos; 223 raise Not_found 176 224 in 177 225 let ans = ref [] in 178 226 while !pos < len do 179 227 try 180 ans := (read_delta (), read_event ())::!ans 228 let d = read_delta () in 229 let e = read_event () in 230 ans := (d, e)::!ans 181 231 with 182 232 | Not_found -> () … … 186 236 let decoder file = 187 237 log#f 4 "Decoding %s..." file; 188 let fd = Unix.openfile file [Unix.O_RDONLY] 0 in238 let fd = Unix.openfile file [Unix.O_RDONLY] 0o644 in 189 239 let closed = ref false in 190 240 … … 202 252 (* We don't need to access the file anymore. *) 203 253 close (); 204 log#f 5 "Read %d events" (List.length tracks.(0)); 254 (* Convert delta-times in delta-liquidsoap-ticks. *) 255 for n = 0 to ntracks - 1 do 256 let tpq = 257 match division with 258 | Midi.Ticks_per_quarter tpq -> tpq 259 | _ -> assert false 260 in 261 let tempo = ref 125000 in 262 tracks.(n) <- 263 List.map 264 (fun (d,(c,e)) -> 265 let d = (d * !tempo / tpq) * Fmt.ticks_per_second () / 1000000 in 266 let d = d * 2 in (* TODO: remove this! *) 267 ( 268 match e with 269 | Midi.Tempo t -> 270 tempo := t 271 | _ -> () 272 ); 273 (d,(c,e)) 274 ) tracks.(n) 275 done; 276 (* Merge all tracks. *) 277 let track = ref tracks.(0) in (* TODO! *) 278 (* Filling function. *) 205 279 let fill buf = 206 1000 (* TODO *) 280 let m = MFrame.tracks buf in 281 (* TODO: why do we have to do this here??? *) 282 AFrame.blankify buf 0 (AFrame.size buf); 283 m.(0) := []; 284 let buflen = MFrame.size buf in 285 let offset_in_buf = ref 0 in 286 while !track <> [] && !offset_in_buf < buflen do 287 let d,(c,e) = List.hd !track in 288 (* Printf.printf "delta: %d\n%!" d; *) 289 offset_in_buf := !offset_in_buf + d; 290 if !offset_in_buf < buflen then 291 ( 292 track := List.tl !track; 293 match c with 294 | Some c -> 295 ( 296 match e with 297 | Midi.Note_on _ 298 | Midi.Note_off _ -> 299 (* Printf.printf "EVENT (chan %d)!\n%!" c; *) 300 let c = if c <> 10 then 0 else c in (* TODO: remove this *) 301 m.(c) := !(m.(c))@[!offset_in_buf, e] 302 | _ -> () (* TODO *) 303 ) 304 | None -> () (* TODO *) 305 ) 306 else 307 track := (!offset_in_buf - buflen,(c,e))::(List.tl !track) 308 done; 309 MFrame.add_break buf (MFrame.size buf); 310 0 207 311 in 208 312 { Decoder.fill = fill ; Decoder.close = fun () -> () } … … 213 317 214 318 (* TODO *) 319 (* 215 320 let metadatas ~format file = 216 321 [] 217 322 218 323 let () = Request.mresolvers#register "MID" metadatas 324 *) -
trunk/liquidsoap/src/stream/mFrame.mli
r6694 r6701 6 6 val is_partial : t -> bool 7 7 8 (** Number of video frames. *)8 (** Number of ticks in a MIDI frame. *) 9 9 val size : t -> int 10 10 -
trunk/liquidsoap/src/synth/keyboard_sdl.ml
r6699 r6701 98 98 Lang.add_operator "input.keyboard.sdl" 99 99 [ 100 "velocity", Lang.float_t, Some (Lang.float 0. 3), Some "Velocity of notes."100 "velocity", Lang.float_t, Some (Lang.float 0.8), Some "Velocity of notes." 101 101 ] 102 102 ~category:Lang.Input -
trunk/liquidsoap/src/synth/synth.ml
r6700 r6701 5 5 class type synth = 6 6 object 7 method set_volume : float -> unit 8 7 9 method note_on : int -> float -> unit 8 10 … … 10 12 11 13 method synth : float -> float array array -> int -> int -> unit 14 15 method reset : unit 12 16 end 13 17 … … 15 19 class virtual ['gs,'ns] base = 16 20 object (self) 21 val mutable volume = 1. 22 23 method set_volume v = volume <- v 24 17 25 val mutable state = None 18 26 … … 23 31 24 32 val mutable notes = [] 33 34 method reset = notes <- [] 25 35 26 36 method virtual state_init : 'gs … … 35 45 36 46 method note_on n v = 47 (* Limit the number of notes for now. TODO: parameter *) 48 if List.length notes > 8 then notes <- List.rev (List.tl (List.rev notes)); 37 49 notes <- (n, ref (self#note_init n v))::notes 38 50 … … 84 96 let phase i = ns.simple_phase +. float i /. freq *. ns.simple_freq in 85 97 for i = ofs to ofs + len - 1 do 86 buf.(i) <- buf.(i) +. ns.simple_ampl *. f (phase i)98 buf.(i) <- buf.(i) +. volume *. ns.simple_ampl *. f (phase i) 87 99 done; 88 100 gs, { ns with simple_phase = fst (modf (phase len)) } -
trunk/liquidsoap/src/synth/synth_op.ml
r6700 r6701 23 23 open Source 24 24 25 class synth (synth:Synth.synth) (source:source) chan =25 class synth (synth:Synth.synth) (source:source) chan volume = 26 26 object (self) 27 27 inherit operator [source] as super 28 29 initializer 30 synth#set_volume volume 28 31 29 32 method stype = source#stype … … 62 65 end 63 66 64 let () = 65 Lang.add_operator "synth.sine" 66 [ "", Lang.source_t, None, None ] 67 let register obj name descr = 68 Lang.add_operator ("synth." ^ name) 69 [ 70 "channel", Lang.int_t, Some (Lang.int 0), Some "MIDI channel to handle."; 71 "volume", Lang.float_t, Some (Lang.float 0.3), Some "Volume."; 72 "", Lang.source_t, None, None 73 ] 67 74 ~category:Lang.SoundSynthesis 68 ~descr :"Sine synthesiser."75 ~descr 69 76 (fun p _ -> 70 77 let f v = List.assoc v p in 78 let chan = Lang.to_int (f "channel") in 79 let volume = Lang.to_float (f "volume") in 71 80 let src = Lang.to_source (f "") in 72 new synth ( new Synth.sine :> Synth.synth) src 0)81 new synth (obj ()) src chan volume) 73 82 74 let () = 75 Lang.add_operator "synth.square" 76 [ "", Lang.source_t, None, None ] 77 ~category:Lang.SoundSynthesis 78 ~descr:"Square synthesiser." 79 (fun p _ -> 80 let f v = List.assoc v p in 81 let src = Lang.to_source (f "") in 82 new synth (new Synth.square :> Synth.synth) src 0) 83 84 let () = 85 Lang.add_operator "synth.saw" 86 [ "", Lang.source_t, None, None ] 87 ~category:Lang.SoundSynthesis 88 ~descr:"Saw synthesiser." 89 (fun p _ -> 90 let f v = List.assoc v p in 91 let src = Lang.to_source (f "") in 92 new synth (new Synth.saw :> Synth.synth) src 0) 83 let () = register (fun () -> (new Synth.sine :> Synth.synth)) "sine" "Sine synthesiser." 84 let () = register (fun () -> (new Synth.square :> Synth.synth)) "square" "Square synthesiser." 85 let () = register (fun () -> (new Synth.saw :> Synth.synth)) "saw" "Saw synthesiser." -
trunk/liquidsoap/src/visualization/midimeter.ml
r6527 r6701 21 21 *****************************************************************************) 22 22 23 (** VU meter. *)24 25 23 open Source 26 24 27 let screen_width = 80 28 let rms_max = -5. 29 let rms_min = -25. 30 31 let vol n v = 32 let v = Sutils.dB_of_lin v in 33 let ans = ref "" in 34 let barwidth = screen_width / n - 7 in 35 let barlen = int_of_float (float barwidth *. min 1. (max 0. ((v -. rms_min) /. (rms_max -. rms_min)))) in 36 for i = 0 to barlen - 1 do ans := !ans ^ "=" done; 37 for i = 0 to barwidth - barlen - 1 do ans := !ans ^ "." done; 38 Printf.sprintf "% 5.1f %s" v !ans 39 40 class vumeter source scroll = 25 class midimeter source = 41 26 object 42 27 inherit operator [source] as super … … 48 33 49 34 method get_frame buf = 50 let offset = AFrame.position buf in51 35 source#get buf; 52 let rms = AFrame.rms buf offset (AFrame.position buf - offset) in 53 let vol = Array.map (vol (Array.length rms)) rms in 54 let vol = Array.fold_left (fun ans s -> ans ^ " " ^ s) "" vol in 55 let vol = String.sub vol 2 (String.length vol - 2) in 56 if scroll then 57 Printf.printf "%s\n%!" vol 58 else 59 Printf.printf "\r%s%!" vol 36 let m = MFrame.tracks buf in 37 for c = 0 to Array.length m - 1 do 38 List.iter 39 (fun (t, e) -> 40 let s = 41 match e with 42 | Midi.Note_on (n, v) -> 43 Printf.sprintf "Note %d on at %.02f" n v 44 | Midi.Note_off (n, v) -> 45 Printf.sprintf "Note %d off at %.02f" n v 46 | _ -> "???" 47 in 48 Printf.printf "%d: %s.\n%!" c s 49 ) !(m.(c)) 50 done 60 51 end 61 52 62 53 let () = 63 Lang.add_operator "vumeter" 64 [ "scroll", Lang.bool_t, Some (Lang.bool false), Some "Scroll."; 65 "", Lang.source_t, None, None ] 54 Lang.add_operator "midimeter" 55 [ "", Lang.source_t, None, None ] 66 56 ~category:Lang.Visualization 67 ~descr:"VU meter (display the volume)." 57 ~flags:[Lang.Hidden; Lang.Experimental] 58 ~descr:"Display midi events." 68 59 (fun p _ -> 69 60 let f v = List.assoc v p in 70 let scroll, src = 71 Lang.to_bool (f "scroll"), 72 Lang.to_source (f "") 73 in 74 ((new vumeter src scroll):>Source.source)) 61 let src = Lang.to_source (f "") in 62 ((new midimeter src):>Source.source))
