Changeset 529 for ocaml-remix
- Timestamp:
- 11/19/07 15:39:53 (9 months ago)
- Files:
-
- ocaml-remix/trunk/FB.ml (modified) (1 diff)
- ocaml-remix/trunk/FB.mli (modified) (1 diff)
- ocaml-remix/trunk/FB_impl.c (modified) (3 diffs)
- ocaml-remix/trunk/Makefile (modified) (2 diffs)
- ocaml-remix/trunk/deck.ml (modified) (1 diff)
- ocaml-remix/trunk/envelope.ml (modified) (2 diffs)
- ocaml-remix/trunk/ladspa_raw.ml (modified) (1 diff)
- ocaml-remix/trunk/ladspa_raw.mli (modified) (1 diff)
- ocaml-remix/trunk/layer.ml (modified) (2 diffs)
- ocaml-remix/trunk/layer_test_sins.ml (modified) (1 diff)
- ocaml-remix/trunk/note.ml (modified) (3 diffs)
- ocaml-remix/trunk/oss.ml (modified) (1 diff)
- ocaml-remix/trunk/oss.mli (modified) (1 diff)
- ocaml-remix/trunk/oss_impl.c (modified) (2 diffs)
- ocaml-remix/trunk/sound.ml (modified) (3 diffs)
- ocaml-remix/trunk/sound.mli (modified) (1 diff)
- ocaml-remix/trunk/track.ml (modified) (1 diff)
- ocaml-remix/trunk/track_test_sins.ml (modified) (1 diff)
- ocaml-remix/trunk/transparency.ml (modified) (3 diffs)
- ocaml-remix/trunk/transparency.mli (modified) (1 diff)
- ocaml-remix/trunk/wave.ml (modified) (1 diff)
- ocaml-remix/trunk/wave.mli (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
ocaml-remix/trunk/FB.ml
r516 r529 4 4 external create_raw : int -> int -> buffer_raw = "c_FB_new_buffer";; 5 5 external free_raw : buffer_raw -> unit = "c_FB_free_buffer";; 6 external fill_raw : buffer_raw -> int -> (int -> float) -> int-> unit =6 external fill_raw : buffer_raw -> int -> int -> (int -> float) -> unit = 7 7 "c_FB_fill_buffer";; 8 external fill_from_raw : buffer_raw -> int -> buffer_raw -> int -> int -> unit = 9 "c_FB_fill_buffer_from_buffer";; 8 10 external add_raw : buffer_raw -> buffer_raw -> int -> buffer_raw = 9 11 "c_FB_add_buffers";; 12 external mult_raw : buffer_raw -> buffer_raw -> int -> buffer_raw = 13 "c_FB_mult_buffers";; 14 external at_raw : buffer_raw -> int -> float = "c_FB_at";; 15 external short_at_raw : buffer_raw -> int -> int = "c_FB_short_at";; 16 external split_raw : buffer_raw -> buffer_raw array -> int -> unit = 17 "c_FB_split_into_channels";; 18 external merge_raw : buffer_raw array -> buffer_raw -> int -> unit = 19 "c_FB_merge_channels";; 20 external blit_raw : buffer_raw -> int -> buffer_raw -> int -> int -> unit = 21 "c_FB_blit";; 22 external transparency_raw : buffer_raw -> buffer_raw -> buffer_raw -> int -> 23 buffer_raw = "c_FB_transparency";; 24 external average_raw : buffer_raw array -> int -> buffer_raw = "c_FB_average";; 10 25 11 26 exception ChannelsMismatch;; 27 exception BlitOutOfBounds;; 12 28 13 29 let create l c = (create_raw l c, l, c);; 14 30 let free (b,l,c) = free_raw b;; 15 let fill (b,l,c) f p = fill_raw b (l*c) f p;; 31 let fill (b,l,c) f = fill_raw b l c f;; 32 let fill_from_buffer (b,l,c) (bf,lf,cf) o = 33 if c != cf then raise ChannelsMismatch; 34 fill_from_raw b (l*c) bf (lf*cf) (o*c);; 16 35 let add (b1,l1,c1) (b2,l2,c2) = 17 36 if c1 != c2 then raise ChannelsMismatch; 18 37 let l = min l1 l2 in (add_raw b1 b2 (l*c1), l, c1);; 38 let mult (b1,l1,c1) (b2,l2,c2) = 39 if c1 != c2 then raise ChannelsMismatch; 40 let l = min l1 l2 in (mult_raw b1 b2 (l*c1), l, c1);; 41 let at (b,l,c) p = at_raw b p;; 42 let short_at (b,l,c) p = short_at_raw b p;; 43 let split (b,l,c) = 44 let raw_arr = Array.init c (fun i -> create_raw l 1) in 45 split_raw b raw_arr l; 46 Array.init c (fun i -> (raw_arr.(i), l, 1));; 47 let merge arr = 48 let raw_arr = Array.init (Array.length arr) 49 (fun i -> (match arr.(i) with | (b,_,_) -> b)) in 50 let len = (match arr.(0) with | (_,l,_) -> l) in 51 let out_arr = create_raw len (Array.length arr) in 52 merge_raw raw_arr out_arr len; 53 (out_arr, len, (Array.length arr));; 54 let blit (bs, ls, cs) spos (bd, ld, cd) dpos len = 55 if cs != cd then raise ChannelsMismatch; 56 if spos < 0 then raise BlitOutOfBounds; 57 if dpos < 0 then raise BlitOutOfBounds; 58 if (spos + len) > ls then raise BlitOutOfBounds; 59 if (dpos + len) > ld then raise BlitOutOfBounds; 60 blit_raw bs (spos * cs) bd (dpos * cd) (len * cd);; 61 let transparency (b1,l1,c1) (b2,l2,c2) (bt,lt,ct) = 62 if c1 != c2 then raise ChannelsMismatch; 63 if c1 != ct then raise ChannelsMismatch; 64 let len = min (min l1 l2) lt in 65 (transparency_raw b1 b2 bt (len * c1), len, c1);; 66 let average arr = 67 let raw_arr = Array.init (Array.length arr) 68 (fun i -> (match arr.(i) with | (b,_,_) -> b)) in 69 let (len,chans) = (match arr.(0) with | (_,l,c) -> (l,c)) in 70 (average_raw raw_arr (len * chans), len, chans);; 71 let length (b,l,c) = l;; 72 let size (b,l,c) = l * c;; 73 74 let fun_cache = ref [];; 75 let create_with_caching func period length channels offset = 76 let b = create length channels in 77 ( 78 try 79 let r = List.assoc (func, channels) (!fun_cache) in 80 fill_from_buffer b r offset 81 with Not_found -> 82 ( 83 let cache = create period channels in 84 fill cache func; 85 fill_from_buffer b cache offset; 86 fun_cache := ((func, channels), cache)::(!fun_cache) 87 ) 88 ); 89 b;; ocaml-remix/trunk/FB.mli
r516 r529 1 type buffer;; 1 type buffer_raw;; 2 type buffer = buffer_raw * int * int;; 2 3 3 4 val create : int -> int -> buffer;; 4 5 val free : buffer -> unit;; 5 val fill : buffer -> (int -> float) -> int -> unit;; 6 val fill : buffer -> (int -> float) -> unit;; 7 val fill_from_buffer : buffer -> buffer -> int -> unit;; 6 8 val add : buffer -> buffer -> buffer;; 9 val mult : buffer -> buffer -> buffer;; 10 val at : buffer -> int -> float;; 11 val short_at : buffer -> int -> int;; 12 val split : buffer -> buffer array;; 13 val merge : buffer array -> buffer;; 14 val blit : buffer -> int -> buffer -> int -> int -> unit;; 15 val transparency : buffer -> buffer -> buffer -> buffer;; 16 val average : buffer array -> buffer;; 17 18 val length : buffer -> int;; 19 val size : buffer -> int;; 20 21 val create_with_caching : (int -> float) -> int -> int -> int -> int -> buffer;; ocaml-remix/trunk/FB_impl.c
r516 r529 6 6 #include <caml/mlvalues.h> 7 7 8 #include <string.h> 9 #include <stdlib.h> 10 8 11 static void finalize_buffer(value block) { 9 12 float *data = (float *)Field(block, 1); … … 40 43 }; 41 44 42 CAMLprim c_FB_fill_buffer(value ml_buf, value ml_ size, value ml_callback,43 value ml_period) {44 45 CAMLparam4(ml_buf, ml_ size, ml_callback, ml_period);45 CAMLprim c_FB_fill_buffer(value ml_buf, value ml_length, value ml_channels, 46 value ml_callback) { 47 48 CAMLparam4(ml_buf, ml_length, ml_channels, ml_callback); 46 49 47 50 float *buffer = POINTER_FROM_BUFFER(ml_buf); 48 int size = Int_val(ml_size); 49 int i; 50 51 /* simple version for now */ 52 for (i = 0; i < size; i++) { 53 buffer[i] = (float)(Double_val(callback(ml_callback, Val_int(i)))); 54 } 55 56 CAMLreturn(Val_unit); 57 58 } 51 int length = Int_val(ml_length); 52 int channels = Int_val(ml_channels); 53 int i; 54 int j; 55 56 for (i = 0; i < length; i++) { 57 buffer[i*channels] = (float)(Double_val(callback(ml_callback, Val_int(i)))); 58 for (j = 1; j < channels; j++) { 59 buffer[i*channels+j] = buffer[i*channels]; 60 } 61 } 62 63 CAMLreturn(Val_unit); 64 65 } 66 67 CAMLprim c_FB_fill_buffer_from_buffer(value ml_buf, value ml_size, 68 value ml_fillbuf, value ml_fillsize, value ml_offset) { 69 70 CAMLparam5(ml_buf, ml_size, ml_fillbuf, ml_fillsize, ml_offset); 71 72 float *buffer = POINTER_FROM_BUFFER(ml_buf); 73 float *from = POINTER_FROM_BUFFER(ml_fillbuf); 74 int size = Int_val(ml_size); 75 int from_size = Int_val(ml_fillsize); 76 int from_offset = Int_val(ml_offset); 77 int pos; 78 79 /* offset first */ 80 if (from_offset > 0) { 81 memcpy(buffer, from + from_offset, 82 (from_size - from_offset) * sizeof(float)); 83 } 84 85 /* whole copies */ 86 pos = from_offset; 87 while ((pos + from_size) < size) { 88 memcpy(buffer + pos, from, from_size * sizeof(float)); 89 pos += from_size; 90 } 91 92 /* last bit */ 93 if (pos < size) { 94 memcpy(buffer + pos, from, (size - pos) * sizeof(float)); 95 } 96 97 CAMLreturn(Val_unit); 98 99 } 59 100 60 101 CAMLprim c_FB_add_buffers(value ml_bufa, value ml_bufb, value ml_size) { … … 75 116 76 117 } 118 119 CAMLprim c_FB_mult_buffers(value ml_bufa, value ml_bufb, value ml_size) { 120 121 CAMLparam3(ml_bufa, ml_bufb, ml_size); 122 123 int size = Int_val(ml_size); 124 float *bufa = POINTER_FROM_BUFFER(ml_bufa); 125 float *bufb = POINTER_FROM_BUFFER(ml_bufb); 126 float *data = malloc(sizeof(float) * size); 127 int i; 128 129 for (i = 0; i < size; i++) { 130 data[i] = bufa[i] * bufb[i]; 131 } 132 133 RETURN_NEW_BUFFER(data); 134 135 } 136 137 CAMLprim c_FB_transparency(value ml_bufa, value ml_bufb, value ml_trans, value 138 ml_size) { 139 140 CAMLparam4(ml_bufa, ml_bufb, ml_trans, ml_size); 141 142 int size = Int_val(ml_size); 143 float *bufa = POINTER_FROM_BUFFER(ml_bufa); 144 float *bufb = POINTER_FROM_BUFFER(ml_bufb); 145 float *trans = POINTER_FROM_BUFFER(ml_trans); 146 float *data = malloc(sizeof(float) * size); 147 int i; 148 149 for (i = 0; i < size; i++) { 150 data[i] = bufa[i] * trans[i] + bufb[i] * (1 - trans[i]); 151 } 152 153 RETURN_NEW_BUFFER(data); 154 } 155 156 CAMLprim c_FB_at(value ml_buffer, value ml_position) { 157 158 CAMLparam2(ml_buffer, ml_position); 159 160 float *buffer = POINTER_FROM_BUFFER(ml_buffer); 161 int position = Int_val(ml_position); 162 163 CAMLreturn(copy_double(buffer[position])); 164 165 } 166 167 CAMLprim c_FB_short_at(value ml_buffer, value ml_position) { 168 169 CAMLparam2(ml_buffer, ml_position); 170 171 float *buffer = POINTER_FROM_BUFFER(ml_buffer); 172 int position = Int_val(ml_position); 173 174 CAMLreturn(Val_int((int)(buffer[position]*32767))); 175 176 } 177 178 CAMLprim c_FB_split_into_channels(value ml_buffer, value ml_buffers, value ml_length) { 179 180 CAMLparam3(ml_buffer, ml_buffers, ml_length); 181 182 float *buffer = POINTER_FROM_BUFFER(ml_buffer); 183 int channels = Wosize_val(ml_buffers); 184 int length = Int_val(ml_length); 185 int i; 186 187 float **odata = malloc(channels * sizeof(float *)); 188 189 for (i = 0; i < channels; i++) { 190 value b = (value)Field(ml_buffers, i); 191 odata[i] = POINTER_FROM_BUFFER(b); 192 } 193 194 length *= channels; 195 196 for (i = 0; i < length; i++) { 197 odata[i % channels][i / channels] = buffer[i]; 198 } 199 200 free(odata); 201 202 CAMLreturn(Val_unit); 203 204 } 205 206 CAMLprim c_FB_merge_channels(value ml_buffers, value ml_buffer, value ml_length) { 207 208 CAMLparam3(ml_buffers, ml_buffer, ml_length); 209 210 int channels = Wosize_val(ml_buffers); 211 int length = Int_val(ml_length); 212 int i; 213 214 float **idata = malloc(channels * sizeof(float *)); 215 float *odata = POINTER_FROM_BUFFER(ml_buffer); 216 217 for (i = 0; i < channels; i++) { 218 value b = (value)Field(ml_buffers, i); 219 idata[i] = POINTER_FROM_BUFFER(b); 220 } 221 222 length *= channels; 223 224 for(i = 0; i < length; i++) { 225 odata[i] = idata[i % channels][i / channels]; 226 } 227 228 free(idata); 229 230 CAMLreturn(Val_unit); 231 232 } 233 234 CAMLprim c_FB_average(value ml_buffers, value ml_size) { 235 236 CAMLparam2(ml_buffers, ml_size); 237 int num_buffers = Wosize_val(ml_buffers); 238 int size = Int_val(ml_size); 239 int i, j; 240 241 float **idata = malloc(num_buffers * sizeof(float *)); 242 float *odata = malloc(size * sizeof(float)); 243 244 for (i = 0; i < num_buffers; i++) { 245 value b = (value)Field(ml_buffers, i); 246 idata[i] = POINTER_FROM_BUFFER(b); 247 } 248 249 for (i = 0; i < size; i++) { 250 odata[i] = 0; 251 for (j = 0; j < num_buffers; j++) { 252 odata[i] += idata[j][i]; 253 } 254 odata[i] /= num_buffers; 255 } 256 257 free(idata); 258 259 RETURN_NEW_BUFFER(odata); 260 261 } 262 263 CAMLprim c_FB_blit(value ml_src, value ml_srcpos, value ml_dst, value ml_dstpos, 264 value ml_length) { 265 266 CAMLparam5(ml_src, ml_srcpos, ml_dst, ml_dstpos, ml_length); 267 268 float *src = POINTER_FROM_BUFFER(ml_src); 269 float *dst = POINTER_FROM_BUFFER(ml_dst); 270 int srcpos = Int_val(ml_srcpos); 271 int dstpos = Int_val(ml_dstpos); 272 int length = Int_val(ml_length); 273 274 memcpy(dst + dstpos, src + srcpos, length * sizeof(float)); 275 276 CAMLreturn(Val_unit); 277 278 } ocaml-remix/trunk/Makefile
r516 r529 6 6 continuous_sound_test 7 7 INCLUDES=-I +extlib 8 OBJECTS=extLib unix oss ladspa_raw FB8 OBJECTS=extLib unix FB oss ladspa_raw 9 9 10 10 INTERFACES = $(patsubst %, %.mli, $(COMPONENTS)) 11 11 SOURCES = $(patsubst %, %.ml, $(COMPONENTS)) 12 OBJECTS_CMA = $(patsubst %, %.cma, $(OBJECTS))13 12 OBJECTS_CMXA = $(patsubst %, %.cmxa, $(OBJECTS)) 14 13 15 BINTESTS = $(patsubst %, %.bin, $(TESTS))16 14 OPTTESTS = $(patsubst %, %.opt, $(TESTS)) 17 15 18 16 OCAMLPP = -pp "camlp4o ./pa_operators.cmo" 19 OCAMLCARGS = $(INCLUDES) $(OBJECTS_CMA) -w s -g $(OCAMLPP)20 17 OCAMLOPTARGS = $(INCLUDES) $(OBJECTS_CMXA) -w s -g $(OCAMLPP) 21 22 18 23 19 pa_operators.cmo: pa_operators.ml 24 20 ocamlc -I +camlp4 camlp4lib.cma -pp camlp4of pa_operators.ml 25 26 remix.cma: $(INTERFACES) $(SOURCES) oss.cma ladspa_raw.cma27 ocamlc -c $(OCAMLCARGS) $(INTERFACES) $(SOURCES)28 ocamlc -a -g -o remix.cma $(SOURCES) oss.cma ladspa_raw.cma29 21 30 22 remix.cmxa: $(INTERFACES) $(SOURCES) oss.cmxa ladspa_raw.cmxa FB.cmxa … … 32 24 ocamlopt -a -o remix.cmxa $(SOURCES) 33 25 34 oss.cma: oss.mli oss.ml oss_impl.c 35 ocamlc -custom oss_impl.c oss.mli oss.ml -a -o oss.cma 36 37 oss.cmxa: oss.mli oss.ml oss_impl.c 26 oss.cmxa: FB.cmxa oss.mli oss.ml oss_impl.c 38 27 ocamlopt oss_impl.c oss.mli oss.ml -a -o oss.cmxa 39 40 ladspa_raw.cma: ladspa_raw.mli ladspa_raw.ml ladspa_impl.c41 ocamlc -custom ladspa_impl.c ladspa_raw.mli ladspa_raw.ml -a \42 -o ladspa_raw.cma43 28 44 29 ladspa_raw.cmxa: ladspa_raw.mli ladspa_raw.ml ladspa_impl.c 45 30 ocamlopt ladspa_impl.c ladspa_raw.mli ladspa_raw.ml -a \ 46 31 -o ladspa_raw.cmxa 47 48 32 FB.cmxa: FB.mli FB.ml FB_impl.c 49 33 ocamlopt FB_impl.c FB.mli FB.ml -a -o FB.cmxa 50 34 51 %.bin: remix.cma %.ml52 ocamlc $(OCAMLCARGS) $^ -o $@53 54 35 %.opt: remix.cmxa %.ml 55 36 ocamlopt $(OCAMLOPTARGS) $^ -o $@ 56 57 all: pa_operators.cmo remix.cma $(BINTESTS)58 37 59 38 all.opt: pa_operators.cmo remix.cmxa $(OPTTESTS) ocaml-remix/trunk/deck.ml
r512 r529 5 5 let add_track deck track = deck.tracks <- track::deck.tracks;; 6 6 7 let rec l_to_s l p = match l with8 | h::t -> (l_to_s t p) +. float_of_int h.(p)9 | [] -> 0.;;10 11 7 let to_note deck undersound remix extent (st,le) = 12 8 let raws = List.map 13 9 (fun l -> Track.to_note l undersound remix extent (st,le)) deck.tracks in 14 let num_raws = List.length raws in 15 let sample_len = Time.time_to_raw_time remix le in 16 Array.init sample_len 17 (fun p -> int_of_float ((l_to_s raws p) /. float_of_int num_raws));; 10 FB.average (Array.of_list raws);; 18 11 ocaml-remix/trunk/envelope.ml
r514 r529 1 1 type envelope = Remix.remix -> Time.time -> int -> float;; 2 2 3 let adsr length a d s r remix start pos = 4 let a = Time.time_to_raw_samples remix a in 5 let d = Time.time_to_raw_samples remix d in 6 let r = Time.time_to_raw_samples remix r in 7 if length = Time.Forever then 8 Printf.printf "can't create a non-terminating adsr envelope\n%!"; 9 let raw_length = Time.time_to_raw_samples remix length in 3 let _adsr a d s r raw_length pos = 10 4 if pos <= a 11 5 then float_of_int pos /. float_of_int a … … 16 10 else s *. float_of_int (raw_length - pos) /. float_of_int r;; 17 11 12 let adsr length a d s r remix start = 13 let a = Time.time_to_raw_time remix a in 14 let d = Time.time_to_raw_time remix d in 15 let r = Time.time_to_raw_time remix r in 16 if length = Time.Forever then 17 Printf.printf "can't create a non-terminating adsr envelope\n%!"; 18 let raw_length = Time.time_to_raw_time remix length in 19 _adsr a d s r raw_length;; 20 18 21 let apply envelope sound remix sound_start render_extent = 19 let ss = Time.time_to_raw_samples remix sound_start in 20 let (rs, rl) = Time.extent_to_raw_samples remix render_extent in 21 let raw_envelope = envelope remix sound_start in 22 let ss = Time.time_to_raw_time remix sound_start in 23 let (rs, rl) = Time.extent_to_raw_time remix render_extent in 24 let raw_envelope = FB.create rl (Remix.channels remix) in 25 let env_func t = envelope remix sound_start (t + rs - ss) in 22 26 let raw_sound = sound remix sound_start render_extent in 23 for i = rs - ss to rs - ss + rl - 1 do ( 24 let r = raw_envelope i in 25 let pos = i - rs + ss in 26 raw_sound.(pos) <- int_of_float (r *. float_of_int raw_sound.(pos)) 27 ) done; 28 raw_sound;; 27 FB.fill raw_envelope env_func; 28 FB.mult raw_sound raw_envelope;; ocaml-remix/trunk/ladspa_raw.ml
r510 r529 1 1 type plugin;; 2 2 type handle;; 3 type buffer ;;3 type buffer = FB.buffer_raw;; 4 4 5 5 type portDirection = Input | Output;; ocaml-remix/trunk/ladspa_raw.mli
r510 r529 3 3 type plugin;; 4 4 type handle;; 5 type buffer ;;5 type buffer = FB.buffer_raw;; 6 6 7 7 type portDirection = Input | Output;; ocaml-remix/trunk/layer.ml
r514 r529 60 60 let (raw_render_start, raw_render_length) = 61 61 Time.extent_to_raw_time remix render_extent in 62 let sound = Array.create (raw_render_length * Remix.channels remix) 0in62 let sound = FB.create raw_render_length (Remix.channels remix) in 63 63 let rec _layer_to_sound laylist = match laylist with 64 64 | [] -> () … … 68 68 if rl > 0 then ( 69 69 let raw_sound = (ss undersound) remix start (s, l) in 70 Array.blit raw_sound 0 sound 71 ((rs - raw_render_start) * Remix.channels remix) 72 (rl * Remix.channels remix)); 70 FB.blit raw_sound 0 sound (rs - raw_render_start) rl); 73 71 _layer_to_sound t) in 74 72 _layer_to_sound layer.la_notes; ocaml-remix/trunk/layer_test_sins.ml
r514 r529 8 8 9 9 let a t = Note.from_sound 10 (Envelope.apply (e t) (Wave.sin (Volume.constant 30000.) 440.));;10 (Envelope.apply (e t) (Wave.sin (Volume.constant 1.) 440.));; 11 11 let hi_a t = Note.from_sound 12 (Envelope.apply (e t) (Wave.square (Volume.constant 20000.) 880.));;12 (Envelope.apply (e t) (Wave.square (Volume.constant 0.7) 880.));; 13 13 let e t = Note.from_sound 14 (Envelope.apply (e t) (Wave.tri (Volume.constant 20000.) 660.));;14 (Envelope.apply (e t) (Wave.tri (Volume.constant 0.7) 660.));; 15 15 16 16 let layer = Layer.empty ();; ocaml-remix/trunk/note.ml
r512 r529 63 63 let num_in = List.length inAudioPorts in 64 64 let num_out = List.length outAudioPorts in 65 let create_in_buffers n sound length =66 let b = Array.init n (function _ -> Ladspa_raw.empty_buffer length) in67 Ladspa_raw.raw_sound_to_buffers sound b length; b in68 65 let create_out_buffers n length = 69 Array.init n (function _ -> Ladspa_raw.empty_buffer length) in 70 let connect portlist portpos h b i = 66 Array.init n (function _ -> FB.create length 1) in 67 let connect portlist portpos h b i = match b.(i) with 68 (buf, _, _) -> 71 69 Ladspa_raw.connect_port ladspa h.(i) (fst (List.nth portlist portpos)) 72 b .(i)in70 buf in 73 71 if num_in = 1 && num_out = 1 then ( 74 72 let raw_insound = insound remix extent render_extent in 75 73 let channels = Remix.channels remix in 76 let buffers = create_in_buffers channels raw_insound raw_lengthin74 let buffers = FB.split raw_insound in 77 75 let outbuffers = create_out_buffers channels raw_length in 78 76 for i = 0 to (channels - 1) do ( … … 81 79 Ladspa_raw.run ladspa handles.(i) raw_length 82 80 ) done; 83 Ladspa_raw.buffers_to_raw_sound outbuffers raw_length81 FB.merge outbuffers 84 82 ) else if num_in = 0 && num_out = 1 then ( 85 83 let channels = Remix.channels remix in … … 89 87 Ladspa_raw.run ladspa handles.(i) raw_length 90 88 ) done; 91 Ladspa_raw.buffers_to_raw_sound outbuffers raw_length89 FB.merge outbuffers 92 90 ) else raise InappropriatePlugin;; 93 91 ocaml-remix/trunk/oss.ml
r488 r529 6 6 "c_ex_sound_set_parms";; 7 7 8 external sound_write : soundDevice -> int array -> unit = "c_ex_sound_write";; 8 external sound_write_raw : soundDevice -> FB.buffer_raw -> int -> unit = 9 "c_ex_sound_write";; 10 11 let sound_write dev (b,l,c) = sound_write_raw dev b (l*c);; 9 12 10 13 external sound_close : soundDevice -> unit = "c_ex_sound_close";; ocaml-remix/trunk/oss.mli
r488 r529 3 3 val sound_open : unit -> soundDevice;; 4 4 val sound_set_parms : soundDevice -> int -> int -> unit;; 5 val sound_write : soundDevice -> int array-> unit;;5 val sound_write : soundDevice -> FB.buffer -> unit;; 6 6 val sound_close : soundDevice -> unit;; ocaml-remix/trunk/oss_impl.c
r488 r529 89 89 } 90 90 91 CAMLprim c_ex_sound_write(value ml_dev, value ml_data ) {91 CAMLprim c_ex_sound_write(value ml_dev, value ml_data, value ml_length) { 92 92 93 93 CAMLparam2(ml_dev, ml_data); … … 97 97 int i; 98 98 short *data; 99 float *indata; 99 100 100 101 dev = (SoundDevice *)Field(ml_dev, 0); 101 length = Wosize_val(ml_data);102 length = Int_val(ml_length); 102 103 data = malloc(length * sizeof(short)); 104 indata = ((float *)Field(ml_data, 1)); 103 105 104 106 for (i = 0; i < length; i++) { 105 data[i] = (short) Int_val(Field(ml_data, i));107 data[i] = (short)(indata[i] * 32767); 106 108 } 107 109 ocaml-remix/trunk/sound.ml
r514 r529 1 1 (* a raw sound is an array of int values *) 2 type raw_sound = int array;;2 type raw_sound = FB.buffer;; 3 3 4 4 (* but sounds have a start, a rendered start, and a rendered length *) … … 6 6 7 7 let silence r e (s,l) = 8 let raw_length = Time.time_to_raw_samplesr l in9 Array.create raw_length 0;;8 let length = Time.time_to_raw_time r l in 9 FB.create length (Remix.channels r);; 10 10 11 11 (* note: length applies to raw sounds *) 12 let length r s = (Array.length s) / (Remix.channels r);; 12 let length = FB.length;; 13 14 let size = FB.size;; 13 15 14 16 (* note: ignore start time when writing raw sounds *) 15 17 let write_raw_sound r out snd = 16 18 IO.nwrite out "RIFF"; 17 IO.write_i32 out (( Array.lengthsnd) * 2 + 36);19 IO.write_i32 out ((size snd) * 2 + 36); 18 20 IO.nwrite out "WAVE"; 19 21 IO.nwrite out "fmt "; (* format chunk *) … … 26 28 IO.write_i16 out 16; (* bits per sample - always 16 *) 27 29 IO.nwrite out "data"; (* data chunk *) 28 IO.write_i32 out (( Array.lengthsnd) * 2);29 for i = 0 to ( Array.length snd - 1) do IO.write_i16 out snd.(i) done;;30 IO.write_i32 out ((size snd) * 2); 31 for i = 0 to (size snd - 1) do IO.write_i16 out (FB.short_at snd i) done;; 30 32 31 33 let write output remix snd start render_extent = ocaml-remix/trunk/sound.mli
r514 r529 1 type raw_sound = int array;;1 type raw_sound = FB.buffer;; 2 2 3 3 (** a sound takes a remix, a start time, and a render extent, and generates raw ocaml-remix/trunk/track.ml
r514 r529 43 43 let raw_sound2 = sound2 remix extent2 rext in 44 44 let raw_trans = transparency remix text rext in 45 let len = min (min (Array.length raw_sound1) (Array.length raw_sound2)) 46 (Array.length raw_trans) in 47 let _mix a b c p = 48 int_of_float ( 49 float_of_int a.(p) *. (1. -. c.(p)) 50 +. 51 float_of_int b.(p) *. c.(p) 52 ) in 53 Array.init len (_mix raw_sound1 raw_sound2 raw_trans);; 45 FB.transparency raw_sound2 raw_sound1 raw_trans;; 54 46 55 47 (* ocaml-remix/trunk/track_test_sins.ml
r514 r529 4 4 let env t = Envelope.adsr t (Time.Seconds 0.2) (Time.Seconds 0.6) 0.7 5 5 (Time.Seconds 0.1);; 6 let a = Wave.sin (Volume.constant 30000.) (Tone.note Tone.a 0);;7 let e = Wave.sin (Volume.constant 20000.) (Tone.note Tone.e 1);;6 let a = Wave.sin (Volume.constant 1.) (Tone.note Tone.a 0);; 7 let e = Wave.sin (Volume.constant 0.7) (Tone.note Tone.e 1);; 8 8 let a t = Envelope.apply (env t) a;; 9 9 let e t = Envelope.apply (env t) e;; ocaml-remix/trunk/transparency.ml
r514 r529 1 type raw_transparency = float array;;1 type raw_transparency = FB.buffer;; 2 2 3 3 type transparency = Remix.remix -> Time.extent -> Time.extent -> … … 5 5 6 6 let linear_ramp start_val end_val remix (start, length) (ostart,olength) = 7 let _to_raw a = (Time.time_to_raw_time remix a) * Remix.channels remixin7 let _to_raw a = (Time.time_to_raw_time remix a) in 8 8 let raw_start = _to_raw start in 9 9 if length = Time.Forever then … … 15 15 float_of_int (pos + raw_ostart - raw_start) /. 16 16 float_of_int raw_length *. (end_val -. start_val) in 17 Array.init raw_olength _fill;; 17 let b = FB.create raw_olength (Remix.channels remix) in 18 FB.fill b _fill; b;; 18 19 19 20 let constant value remix (start, len) (rstart, rlength) = 20 Array.create (Time.time_to_raw_samples remix rlength) value;; 21 let len = (Time.time_to_raw_time remix rlength) in 22 let b = FB.create len (Remix.channels remix) in 23 FB.fill b (fun a -> value); b;; ocaml-remix/trunk/transparency.mli
r513 r529 1 type raw_transparency = float array;;1 type raw_transparency = FB.buffer;; 2 2 3 3 type transparency = Remix.remix -> Time.extent -> Time.extent ocaml-remix/trunk/wave.ml
r514 r529 1 1 type wave = Volume.volume -> float -> Sound.sound;; 2 2 3 (* generator amplitude period(in samples) start(in samples) channels 4 time(in samples) *) 5 type generator = float -> float -> int -> int -> int -> int;; 3 (* generator amplitude period start time *) 4 type generator = float -> float -> int -> int -> float;; 6 5 7 6 exception AmplitudeTooHigh;; 8 9 let round_to_int f =10 if f >= 0.11 then int_of_float (f +. 0.5)12 else int_of_float (f -. 0.5)13 7 14 8 (* these waves are phased globally so that clicks don't occur between 15 9 adjacent sounds. Hence we don't need to worry about the extent 16 10 of the sound, only the rendered extent *) 17 let sin_generator amp period start channelstime =18 let stime = (time + start) / channels * channelsin11 let sin_generator amp period start time = 12 let stime = time + start in 19 13 let coef = (float_of_int stime) *. 3.142 *. 2. in 20 round_to_int (amp *. (sin (coef /. period)));;14 amp *. (sin (coef /. period));; 21 15 22 let square_generator amp period start channelstime =16 let square_generator amp period start time = 23 17 if mod_float (float_of_int (time + start)) period < period/.2. 24 then int_of_float amp else0;;18 then amp else 0.0;; 25 19 26 let tri_generator amp period start channels time = 27 let stime = (time + start) / channels * channels in 28 int_of_float ( 29 (mod_float (float_of_int stime) period) /. period *. amp);; 20 let tri_generator amp period start time = 21 let stime = time + start in 22 (mod_float (float_of_int stime) period) /. period *. amp;; 30 23 31 24 let generate generator volume rate remix ss (start, length) = 32 let raw_length = Time.time_to_raw_samples remix length in 33 let raw_start = Time.time_to_raw_samples remix start in 34 let raw_ss = Time.time_to_raw_samples remix ss in 35 let period = float_of_int (Remix.samplerate remix * Remix.channels remix) 36 /. rate in 25 let raw_length = Time.time_to_raw_time remix length in 26 let raw_start = Time.time_to_raw_time remix start in 27 let raw_ss = Time.time_to_raw_time remix ss in 28 let period = float_of_int (Remix.samplerate remix) /. rate in 37 29 let offset = (raw_start - raw_ss) in 38 30 let channels = Remix.channels remix in 39 let vfunc = fun p -> Volume.amplitude remix volume 40 ((p + offset)/Remix.channels remix)in41 Array.init raw_length42 (fun p -> generator (vfunc p) period raw_start channels p);;31 let vfunc = fun p -> Volume.amplitude remix volume (p + offset) in 32 let buffer = FB.create raw_length channels in 33 FB.fill buffer (fun p -> generator (vfunc p) period raw_start p); 34 buffer;; 43 35 44 36 let sin = generate sin_generator;; ocaml-remix/trunk/wave.mli
r514 r529 2 2 type wave = Volume.volume -> float -> Sound.sound;; 3 3 4 (* generator amplitude period(in samples) start(in samples) channels 5 time(in samples) *) 6 type generator = float -> float -> int -> int -> int -> int;; 4 (* generator amplitude period(in samples) start(in samples) time(in samples) *) 5 type generator = float -> float -> int -> int -> float;; 7 6 8 7 val generate : generator -> wave;;
