Last active
May 3, 2017 08:59
-
-
Save jellea/79f0aa83c67132c59317c2ee3b30134f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open ReasonJs; | |
type uint8Array; | |
external int8Array : int => uint8Array = "window.Uint8Array" [@@bs.new]; | |
external get : uint8Array => int => int = "" [@@bs.get_index]; | |
[%%bs.raw{| | |
window.polyAudioContext = window.AudioContext || new window.webkitAudioContext | |
|}]; | |
let module Window = { | |
type window; | |
external get_inner_width : window => int = "innerWidth" [@@bs.get]; | |
external get_inner_height : window => int = "innerHeight" [@@bs.get]; | |
external get_window: window = "window" [@@bs.val]; | |
external width: int = "window.innerWidth" [@@bs.val]; | |
external height: int = "window.innerHeight" [@@bs.val]; | |
}; | |
let module Document = { | |
type element; | |
external query_selector : string => element = "document.querySelector" [@@bs.val]; | |
external getWidth : element => int = "width" [@@bs.get]; | |
external getHeight : element => int = "height" [@@bs.get]; | |
external request_animation_frame : (unit => unit) => unit = "window.requestAnimationFrame" [@@bs.val]; | |
external play_audio : element => 'promise = "play" [@@bs.send]; | |
external set_height : element => int => unit = "height" [@@bs.set]; | |
external set_width: element => int => unit = "width" [@@bs.set]; | |
external get_height : element => int = "height" [@@bs.get]; | |
external get_width : element => int = "width" [@@bs.get]; | |
}; | |
let module AudioNode = { | |
type audioNode; | |
type mediaElementSourceNode = audioNode; | |
type analyzerNode = audioNode; | |
external connect : audioNode => audioNode => unit = "connect" [@@bs.send]; | |
external get_byte_frequency_data : analyzerNode => uint8Array => array int = "getByteFrequencyData" [@@bs.send]; | |
external get_byte_time_domain_data : analyzerNode => uint8Array => array int = "getByteTimeDomainData" [@@bs.send]; | |
external fft_size : analyzerNode => int = "fftSize" [@@bs.get]; | |
external fft_size : analyzerNode => int => unit = "fftSize" [@@bs.set]; | |
external frequency_bin_count : analyzerNode => int = "frequencyBinCount" [@@bs.get]; | |
}; | |
let module AudioContext = { | |
type audioContext; | |
external destination : audioContext => AudioNode.audioNode = "destination" [@@bs.get]; | |
external create_audio_context : audioContext = "window.polyAudioContext" [@@bs.val]; | |
external create_analyzer : audioContext => AudioNode.analyzerNode = "createAnalyser" [@@bs.send]; | |
external create_media_element_source : audioContext => Document.element => AudioNode.mediaElementSourceNode = "createMediaElementSource" [@@bs.send]; | |
}; | |
let module Canvas = { | |
type canvasContext; | |
external fill_style : canvasContext => string => unit = "fillStyle" [@@bs.set]; | |
external fill_rect : canvasContext => int => int => int => int => unit = "fillRect" [@@bs.send]; | |
external line_width : canvasContext => int => unit = "lineWidth" [@@bs.set]; | |
external stroke_style : canvasContext => string => unit = "strokeStyle" [@@bs.set]; | |
external begin_path : canvasContext => unit = "beginPath" [@@bs.send]; | |
external stroke : canvasContext => unit = "stroke" [@@bs.send]; | |
external move_to : canvasContext => float => float => unit = "moveTo" [@@bs.send]; | |
external line_to : canvasContext => float => float => unit = "lineTo" [@@bs.send]; | |
external get_context : Document.element => string => canvasContext = "getContext" [@@bs.send]; | |
}; | |
let my_audio = Document.query_selector "#audio-one"; | |
let context = AudioContext.create_audio_context; | |
let player = AudioContext.create_media_element_source context my_audio; | |
let analyzer = AudioContext.create_analyzer context; | |
let _ = AudioNode.fft_size analyzer 512; | |
let buffer_length = AudioNode.frequency_bin_count analyzer; | |
let time_data_array = int8Array buffer_length; | |
let freq_data_array = int8Array buffer_length; | |
AudioNode.connect player (AudioContext.destination context); | |
AudioNode.connect player (analyzer); | |
Document.play_audio my_audio; | |
let canvas = Document.query_selector "#bg-canvas"; | |
let canvas_ctx = Canvas.get_context canvas "2d"; | |
let window_height = Window.height; | |
let window_width = Window.width; | |
let canvas_width = window_width - 100; | |
let canvas_height = window_height - 100; | |
let _ = Document.set_height canvas canvas_height; | |
let _ = Document.set_width canvas canvas_width; | |
let draw_oscillator_frame (off_x, off_y, width, height) => { | |
Canvas.fill_style canvas_ctx "rgb(144,221,203)"; | |
Canvas.fill_rect canvas_ctx off_x off_y width height; | |
Canvas.line_width canvas_ctx 1; | |
Canvas.stroke_style canvas_ctx "rgb(255,255,255)"; | |
let slice_width = float(width) *. 1.0 /. float buffer_length; | |
Canvas.begin_path canvas_ctx; | |
for x in 0 to buffer_length { | |
let v = float(get time_data_array x) /. 128.0; | |
let y = float(off_y) +. v *. float(height) /. 2.0 ; | |
let new_x = float(off_x) +. float(x) *. slice_width; | |
if(x === 0) { | |
Canvas.move_to canvas_ctx new_x y; | |
} else { | |
Canvas.line_to canvas_ctx new_x y; | |
}; | |
}; | |
Canvas.line_to canvas_ctx | |
(float(off_x) +. ceil(float(width))) | |
(float(off_y) +. ceil(float(height) /. 2.)); | |
Canvas.stroke canvas_ctx; | |
}; | |
let draw_freq_spectrum_frame (off_x, off_y, width, height) => { | |
Canvas.fill_style canvas_ctx "rgb(144,221,203)"; | |
Canvas.fill_rect canvas_ctx off_x off_y width height; | |
Canvas.line_width canvas_ctx 1; | |
Canvas.stroke_style canvas_ctx "rgb(255,255,255)"; | |
let slice_width = float(width) *. 1.0 /. float buffer_length; | |
Canvas.begin_path canvas_ctx; | |
for x in 0 to buffer_length { | |
let v = float(get freq_data_array x) /. 128.0; | |
let y = float(off_y) +. v *. float(height); | |
let new_x = float(off_x) +. float(x) *. slice_width; | |
if(x === 0) { | |
Canvas.move_to canvas_ctx new_x y; | |
} else { | |
Canvas.line_to canvas_ctx new_x y; | |
}; | |
}; | |
Canvas.line_to canvas_ctx | |
(float(off_x) +. ceil(float(width))) | |
(float(off_y) +. ceil(float(height) /. 2.)); | |
Canvas.stroke canvas_ctx; | |
}; | |
let rec render unit => { | |
let _ = AudioNode.get_byte_time_domain_data analyzer time_data_array; | |
let _ = AudioNode.get_byte_frequency_data analyzer freq_data_array; | |
/* first row */ | |
draw_oscillator_frame(0, 0, canvas_width/3-30, canvas_height/3-30); | |
draw_freq_spectrum_frame(canvas_width/3*2, 0, canvas_width/3-30, canvas_height/3-30); | |
draw_oscillator_frame(canvas_width/3, 0, canvas_width/3-30, canvas_height/3-30); | |
/* second row */ | |
draw_oscillator_frame(0, canvas_height/3, canvas_width/3*2-30, canvas_height/3-30); | |
draw_oscillator_frame(canvas_width/3*2, canvas_height/3, canvas_width/3-30, canvas_height/3-30); | |
/* third row */ | |
draw_oscillator_frame(0, canvas_height/3*2, canvas_width/3-30, canvas_height/3-30); | |
draw_oscillator_frame(canvas_width/3, canvas_height/3*2, canvas_width/3-30, canvas_height/3-30); | |
draw_oscillator_frame(canvas_width/3*2, canvas_height/3*2, canvas_width/3-30, canvas_height/3-30); | |
Document.request_animation_frame render; | |
}; | |
Document.request_animation_frame render; | |
/* | |
let myInterval = ReasonJs.setInterval (fun () => ReasonJs.Console.log "hello!") 1000; */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment