├── libopenmpt.js.mem
├── tunes
├── chipsounds.mod
├── rfchip001.xm
├── cydonian sky.xm
└── mysteristerium.mod
├── fonts
└── amiga4ever_pro2.ttf
├── README.md
├── config.rb
├── css
├── style.css
├── normalize.min.css
├── screen.css
└── normalize.css
├── .gitignore
├── img
├── loop.svg
├── headphones.svg
├── pause.svg
└── play.svg
├── sass
└── screen.sass
├── index.html
└── js
└── chiptune2.js
/libopenmpt.js.mem:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergei-bondarenko/chiptune2.js/master/libopenmpt.js.mem
--------------------------------------------------------------------------------
/tunes/chipsounds.mod:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergei-bondarenko/chiptune2.js/master/tunes/chipsounds.mod
--------------------------------------------------------------------------------
/tunes/rfchip001.xm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergei-bondarenko/chiptune2.js/master/tunes/rfchip001.xm
--------------------------------------------------------------------------------
/tunes/cydonian sky.xm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergei-bondarenko/chiptune2.js/master/tunes/cydonian sky.xm
--------------------------------------------------------------------------------
/fonts/amiga4ever_pro2.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergei-bondarenko/chiptune2.js/master/fonts/amiga4ever_pro2.ttf
--------------------------------------------------------------------------------
/tunes/mysteristerium.mod:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sergei-bondarenko/chiptune2.js/master/tunes/mysteristerium.mod
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Radio.xm
2 |
3 | An endless stream of tracker music. [Listen here](https://cdn.rawgit.com/grez911/chiptune2.js/a64df323/index.html).
4 |
--------------------------------------------------------------------------------
/config.rb:
--------------------------------------------------------------------------------
1 | # Require any additional compass plugins here.
2 |
3 | # Set this to the root of your project when deployed:
4 | http_path = "."
5 | css_dir = "./css"
6 | sass_dir = "./sass"
7 | images_dir = "./img"
8 | javascripts_dir = "./js"
9 |
10 | # You can select your preferred output style here (can be overridden via the command line):
11 | # output_style = :expanded or :nested or :compact or :compressed
12 | # output_style = compact
13 |
14 | # To enable relative paths to assets via compass helper functions. Uncomment:
15 | # relative_assets = true
16 |
17 | # To disable debugging comments that display the original location of your selectors. Uncomment:
18 | # line_comments = false
19 | line_comments = false
20 |
21 | preferred_syntax = :sass
22 |
--------------------------------------------------------------------------------
/css/style.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: amiga;
3 | src: url("../fonts/amiga4ever_pro2.ttf");
4 | font-weight: 400;
5 | }
6 |
7 | body
8 | {
9 | background-color: #000000;
10 | color: #00FF00;
11 | font-family: "amiga";
12 | overflow: hidden;
13 | position: absolute;
14 | width: 100%;
15 | height: 100%;
16 | display: flex;
17 | justify-content: center; /*centers items on the line (the x-axis by default)*/
18 | align-items: center; /*centers items on the cross-axis (y by default)*/
19 | }
20 |
21 | a
22 | {
23 | color: #00FF00;
24 | text-decoration: none;
25 | }
26 |
27 | img
28 | {
29 | cursor: pointer;
30 | cursor: hand;
31 | }
32 |
33 | #main
34 | {
35 | width: 500px;
36 | }
37 |
38 | #title
39 | {
40 | text-align: center;
41 | }
42 |
43 | #button
44 | {
45 | margin-top: 15px;
46 | text-align: center;
47 | }
48 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io
2 |
3 | ### Windows ###
4 | # Windows image file caches
5 | Thumbs.db
6 | ehthumbs.db
7 |
8 | # Folder config file
9 | Desktop.ini
10 |
11 | # Recycle Bin used on file shares
12 | $RECYCLE.BIN/
13 |
14 | # Windows Installer files
15 | *.cab
16 | *.msi
17 | *.msm
18 | *.msp
19 |
20 | # Windows shortcuts
21 | *.lnk
22 |
23 |
24 | ### Linux ###
25 | *~
26 |
27 | # KDE directory preferences
28 | .directory
29 |
30 |
31 | ### OSX ###
32 | .DS_Store
33 | .AppleDouble
34 | .LSOverride
35 |
36 | # Icon must end with two \r
37 | Icon
38 |
39 |
40 | # Thumbnails
41 | ._*
42 |
43 | # Files that might appear on external disk
44 | .Spotlight-V100
45 | .Trashes
46 |
47 | # Directories potentially created on remote AFP share
48 | .AppleDB
49 | .AppleDesktop
50 | Network Trash Folder
51 | Temporary Items
52 | .apdisk
53 |
54 |
55 | ### Sass ###
56 | .sass-cache
57 | *.css.map
58 |
59 | # Webstorm IDE
60 | .idea
61 |
--------------------------------------------------------------------------------
/img/loop.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
14 |
--------------------------------------------------------------------------------
/img/headphones.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/img/pause.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
67 |
--------------------------------------------------------------------------------
/img/play.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
67 |
--------------------------------------------------------------------------------
/css/normalize.min.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v1.1.0 | MIT License | git.io/normalize */
2 | article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}html,button,input,select,textarea{font-family:sans-serif}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}h2{font-size:1.5em;margin:.83em 0}h3{font-size:1.17em;margin:1em 0}h4{font-size:1em;margin:1.33em 0}h5{font-size:.83em;margin:1.67em 0}h6{font-size:.67em;margin:2.33em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}blockquote{margin:1em 40px}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}p,pre{margin:1em 0}code,kbd,pre,samp{font-family:monospace,serif;_font-family:'courier new',monospace;font-size:1em}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}q{quotes:none}q:before,q:after{content:'';content:none}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}dl,menu,ol,ul{margin:1em 0}dd{margin:0 0 0 40px}menu,ol,ul{padding:0 0 0 40px}nav ul,nav ol{list-style:none;list-style-image:none}img{border:0;-ms-interpolation-mode:bicubic}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0;white-space:normal;*margin-left:-7px}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;*overflow:visible}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*height:13px;*width:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}
--------------------------------------------------------------------------------
/css/screen.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: amiga;
3 | src: url("../fonts/amiga4ever_pro2.ttf");
4 | font-weight: 400;
5 | }
6 |
7 | html, body {
8 | width: 100%;
9 | height: 100%;
10 | }
11 |
12 | body {
13 | background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ff5c00), color-stop(100%, #ff5a00));
14 | background: -webkit-linear-gradient(#ff5c00, #ff5a00);
15 | background: -moz-linear-gradient(#ff5c00, #ff5a00);
16 | background: -o-linear-gradient(#ff5c00, #ff5a00);
17 | background: linear-gradient(#ff5c00, #ff5a00);
18 | }
19 |
20 | .bg {
21 | width: 100%;
22 | width: calc(100% - 4rem);
23 | height: 100%;
24 | height: calc(100% - 4rem);
25 | position: absolute;
26 | top: 2rem;
27 | left: 2rem;
28 | z-index: -90;
29 | }
30 | .bg.bg1 {
31 | background-image: url("../img/headphones.svg");
32 | background-repeat: no-repeat;
33 | background-size: contain;
34 | background-position: center;
35 | }
36 |
37 | .banner {
38 | width: 100%;
39 | font-family: amiga, sans-serif;
40 | }
41 | .banner + .banner {
42 | margin-top: 2.4rem;
43 | }
44 |
45 | #headline, #demosong, #metadata, #controls, #choosefile {
46 | text-align: center;
47 | }
48 |
49 | #info {
50 | max-width: calc(100% - 2.6rem);
51 | padding: 1.25rem 1.3rem;
52 | background: rgba(20, 20, 20, 0.86);
53 | color: #f9f9f9;
54 | }
55 |
56 | #headline {
57 | max-width: calc(100% - 2rem);
58 | padding: 1.2rem 1rem;
59 | background: white;
60 | color: #232323;
61 | }
62 | #headline h1 {
63 | margin: 0;
64 | }
65 | @media only screen and (max-width: 45rem) {
66 | #headline h1 {
67 | font-size: 3rem;
68 | }
69 | }
70 | @media only screen and (min-width: 45rem) {
71 | #headline h1 {
72 | font-size: 4.5rem;
73 | }
74 | }
75 |
76 | #demosong {
77 | margin-top: 3rem;
78 | }
79 | #demosong a {
80 | color: #232323;
81 | font-size: 0.7rem;
82 | }
83 |
84 | #metadata {
85 | display: block;
86 | }
87 |
88 | #choosefile input {
89 | padding: 0.5rem;
90 | background: #f7f7f7;
91 | border-radius: 0.35rem;
92 | border: 1px solid rgba(215, 99, 34, 0.78);
93 | }
94 |
95 | #choosefile, #controls {
96 | margin-top: 1.9rem;
97 | }
98 |
99 | #demos {
100 | text-align: center;
101 | }
102 | #demos > div {
103 | display: inline-block;
104 | margin: 0 auto;
105 | text-align: left;
106 | border-radius: 0.35rem;
107 | border: 1px solid rgba(215, 99, 34, 0.78);
108 | padding: 1rem;
109 | background: white;
110 | }
111 | #demos > div h2 {
112 | margin: 0 0 0.5rem 0;
113 | font-size: 1.3rem;
114 | }
115 | #demos > div .song {
116 | display: block;
117 | text-decoration: none;
118 | color: #4c4cbd;
119 | }
120 | #demos > div .song + .song {
121 | margin-top: 0.65rem;
122 | }
123 | #demos > div .song .size {
124 | vertical-align: super;
125 | font-size: 0.6rem;
126 | margin-left: 0.3rem;
127 | }
128 | #demos > div .song .size:before {
129 | content: "(";
130 | }
131 | #demos > div .song .size:after {
132 | content: ")";
133 | }
134 |
135 | .control {
136 | width: 5rem;
137 | height: 5rem;
138 | border-radius: 2.5rem;
139 | background-color: #505050;
140 | display: inline-block;
141 | box-shadow: 0px 9px 0px #323232, 0px 9px 25px rgba(0, 0, 0, 0.7);
142 | transition: all 0.1s ease;
143 | cursor: pointer;
144 | }
145 | .control:active, .control.pressed {
146 | box-shadow: 0px 3px 0px #323232, 0px 3px 6px rgba(0, 0, 0, 0.7);
147 | }
148 | .control#play {
149 | background-image: url("../img/play.svg");
150 | background-size: 75%;
151 | background-position: 16px 9px;
152 | background-repeat: no-repeat;
153 | }
154 | .control#pause {
155 | background-image: url("../img/pause.svg");
156 | background-size: 75%;
157 | background-position: center;
158 | background-repeat: no-repeat;
159 | }
160 | .control#loop {
161 | display: none;
162 | }
163 | .control#loop + label {
164 | background-image: url("../img/loop.svg");
165 | background-size: 75%;
166 | background-position: center;
167 | background-repeat: no-repeat;
168 | }
169 | .control#loop:checked + label {
170 | box-shadow: 0px 3px 0px #323232, 0px 3px 6px rgba(0, 0, 0, 0.7);
171 | }
172 |
--------------------------------------------------------------------------------
/sass/screen.sass:
--------------------------------------------------------------------------------
1 | // chiptune2.js css
2 |
3 | @import compass
4 |
5 | // responsive design
6 | $mobile-width: 45rem
7 |
8 | @mixin respond-to($media)
9 | @if $media == desktop
10 | @media only screen and (min-width: $mobile-width)
11 | @content
12 | @else if $media == mobile
13 | @media only screen and (max-width: $mobile-width)
14 | @content
15 |
16 | // font
17 | @font-face
18 | font-family: amiga
19 | src: url('../fonts/amiga4ever_pro2.ttf')
20 | font-weight: 400
21 |
22 | // our design
23 | html, body
24 | width: 100%
25 | height: 100%
26 |
27 | body
28 | @include background(linear-gradient(#FF5C00, #FF5A00))
29 |
30 | .bg
31 | width: 100%
32 | width: calc(100% - 4rem)
33 | height: 100%
34 | height: calc(100% - 4rem)
35 | position: absolute
36 | top: 2rem
37 | left: 2rem
38 | z-index: -90
39 | &.bg1
40 | background-image: url('../img/headphones.svg')
41 | background-repeat: no-repeat
42 | background-size: contain
43 | background-position: center
44 |
45 | .banner
46 | width: 100%
47 | font-family: amiga, sans-serif
48 | + .banner
49 | margin-top: 2.4rem
50 |
51 | #headline, #demosong, #metadata, #controls, #choosefile
52 | text-align: center
53 |
54 | #info
55 | max-width: calc(100% - 2.6rem)
56 | padding: 1.25rem 1.3rem
57 | background: rgba(20, 20, 20, 0.86)
58 | color: #f9f9f9
59 |
60 | #headline
61 | max-width: calc(100% - 2rem)
62 | padding: 1.2rem 1rem
63 | background: #fff
64 | color: #232323
65 | h1
66 | margin: 0
67 | @include respond-to(mobile)
68 | font-size: 3rem
69 | @include respond-to(desktop)
70 | font-size: 4.5rem
71 |
72 | #demosong
73 | margin-top: 3rem
74 | a
75 | color: #232323
76 | font-size: 0.7rem
77 |
78 | #metadata
79 | display: block
80 |
81 | #choosefile
82 | input
83 | padding: 0.5rem
84 | background: #f7f7f7
85 | border-radius: 0.35rem
86 | border: 1px solid rgba(215, 99, 34, 0.78)
87 |
88 | #choosefile, #controls
89 | margin-top: 1.9rem
90 |
91 | #demos
92 | text-align: center
93 | > div
94 | display: inline-block
95 | margin: 0 auto
96 | text-align: left
97 | border-radius: 0.35rem
98 | border: 1px solid rgba(215, 99, 34, 0.78)
99 | padding: 1rem
100 | background: #fff
101 | h2
102 | margin: 0 0 0.5rem 0
103 | font-size: 1.3rem
104 | .song
105 | display: block
106 | text-decoration: none
107 | color: #4C4CBD
108 | + .song
109 | margin-top: 0.65rem
110 | .size
111 | vertical-align: super
112 | font-size: 0.6rem
113 | margin-left: 0.3rem
114 | &:before
115 | content: "("
116 | &:after
117 | content: ")"
118 |
119 |
120 | .control
121 | width: 5rem
122 | height: 5rem
123 | border-radius: 2.5rem
124 | background-color: rgb(80,80,80)
125 | display: inline-block
126 | box-shadow: 0px 9px 0px rgba(50,50,50,1), 0px 9px 25px rgba(0,0,0,.7)
127 | transition: all .1s ease
128 | cursor: pointer
129 |
130 | &:active, &.pressed
131 | box-shadow: 0px 3px 0px rgba(50,50,50,1), 0px 3px 6px rgba(0,0,0,.7)
132 |
133 | play
134 | background-image: url('../img/play.svg')
135 | background-size: 75%
136 | background-position: 16px 9px
137 | background-repeat: no-repeat
138 |
139 | pause
140 | background-image: url('../img/pause.svg')
141 | background-size: 75%
142 | background-position: center
143 | background-repeat: no-repeat
144 |
145 | loop
146 | display: none
147 | + label
148 | background-image: url('../img/loop.svg')
149 | background-size: 75%
150 | background-position: center
151 | background-repeat: no-repeat
152 | &:checked + label
153 | box-shadow: 0px 3px 0px rgba(50,50,50,1), 0px 3px 6px rgba(0,0,0,.7)
154 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Radio.xm
5 |
6 |
7 |
8 |
9 |
10 |
11 |
142 |
143 |
144 |
145 |
Loading...
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/js/chiptune2.js:
--------------------------------------------------------------------------------
1 | // audio context
2 | ChiptuneAudioContext = AudioContext || webkitAudioContext;
3 |
4 | // config
5 | function ChiptuneJsConfig(repeatCount, context) {
6 | this.repeatCount = repeatCount;
7 | this.context = context;
8 | }
9 |
10 | // player
11 | function ChiptuneJsPlayer(config) {
12 | this.config = config;
13 | this.context = config.context || new ChiptuneAudioContext;
14 | this.currentPlayingNode = null;
15 | this.handlers = [];
16 | }
17 |
18 | // event handlers section
19 | ChiptuneJsPlayer.prototype.fireEvent = function (eventName, response) {
20 | var handlers = this.handlers;
21 | if (handlers.length) {
22 | handlers.forEach(function (handler) {
23 | if (handler.eventName === eventName) {
24 | handler.handler(response);
25 | }
26 | })
27 | }
28 | }
29 |
30 | ChiptuneJsPlayer.prototype.addHandler = function (eventName, handler) {
31 | this.handlers.push({eventName: eventName, handler: handler});
32 | }
33 |
34 | ChiptuneJsPlayer.prototype.onEnded = function (handler) {
35 | this.addHandler('onEnded', handler);
36 | }
37 |
38 | ChiptuneJsPlayer.prototype.onError = function (handler) {
39 | this.addHandler('onError', handler);
40 | }
41 |
42 | // metadata
43 | ChiptuneJsPlayer.prototype.duration = function() {
44 | return Module._openmpt_module_get_duration_seconds(this.currentPlayingNode.modulePtr);
45 | }
46 |
47 | ChiptuneJsPlayer.prototype.metadata = function() {
48 | var data = {};
49 | var keys = Module.Pointer_stringify(Module._openmpt_module_get_metadata_keys(this.currentPlayingNode.modulePtr)).split(';');
50 | var keyNameBuffer = 0;
51 | for (var i = 0; i < keys.length; i++) {
52 | keyNameBuffer = Module._malloc(keys[i].length + 1);
53 | Module.writeStringToMemory(keys[i], keyNameBuffer);
54 | data[keys[i]] = Module.Pointer_stringify(Module._openmpt_module_get_metadata(player.currentPlayingNode.modulePtr, keyNameBuffer));
55 | Module._free(keyNameBuffer);
56 | }
57 | return data;
58 | }
59 |
60 | // playing, etc
61 | ChiptuneJsPlayer.prototype.load = function(input, callback) {
62 | var player = this;
63 | if (input instanceof File) {
64 | var reader = new FileReader();
65 | reader.onload = function() {
66 | return callback(reader.result); // no error
67 | }.bind(this);
68 | reader.readAsArrayBuffer(input);
69 | } else {
70 | var xhr = new XMLHttpRequest();
71 | xhr.open('GET', input, true);
72 | xhr.responseType = 'arraybuffer';
73 | xhr.onload = function(e) {
74 | if (xhr.status === 200) {
75 | return callback(xhr.response); // no error
76 | } else {
77 | player.fireEvent('onError', {type: 'onxhr'});
78 | }
79 | }.bind(this);
80 | xhr.onerror = function() {
81 | player.fireEvent('onError', {type: 'onxhr'});
82 | };
83 | xhr.onabort = function() {
84 | player.fireEvent('onError', {type: 'onxhr'});
85 | };
86 | xhr.send();
87 | }
88 | }
89 |
90 | ChiptuneJsPlayer.prototype.play = function(buffer) {
91 | this.stop();
92 | var processNode = this.createLibopenmptNode(buffer, this.config);
93 | if (processNode == null) {
94 | return;
95 | }
96 |
97 | // set config options on module
98 | Module._openmpt_module_set_repeat_count(processNode.modulePtr, this.config.repeatCount);
99 |
100 | this.currentPlayingNode = processNode;
101 | processNode.connect(this.context.destination);
102 | }
103 |
104 | ChiptuneJsPlayer.prototype.stop = function() {
105 | if (this.currentPlayingNode != null) {
106 | this.currentPlayingNode.disconnect();
107 | this.currentPlayingNode.cleanup();
108 | this.currentPlayingNode = null;
109 | }
110 | }
111 |
112 | ChiptuneJsPlayer.prototype.togglePause = function() {
113 | if (this.currentPlayingNode != null) {
114 | this.currentPlayingNode.togglePause();
115 | }
116 | }
117 |
118 | ChiptuneJsPlayer.prototype.createLibopenmptNode = function(buffer, config) {
119 | // TODO error checking in this whole function
120 |
121 | var maxFramesPerChunk = 4096;
122 | var processNode = this.context.createScriptProcessor(0, 0, 2);
123 | processNode.config = config;
124 | processNode.player = this;
125 | var byteArray = new Int8Array(buffer);
126 | var ptrToFile = Module._malloc(byteArray.byteLength);
127 | Module.HEAPU8.set(byteArray, ptrToFile);
128 | processNode.modulePtr = Module._openmpt_module_create_from_memory(ptrToFile, byteArray.byteLength, 0, 0, 0);
129 | processNode.paused = false;
130 | processNode.leftBufferPtr = Module._malloc(4 * maxFramesPerChunk);
131 | processNode.rightBufferPtr = Module._malloc(4 * maxFramesPerChunk);
132 | processNode.cleanup = function() {
133 | if (this.modulePtr != 0) {
134 | Module._openmpt_module_destroy(this.modulePtr);
135 | this.modulePtr = 0;
136 | }
137 | if (this.leftBufferPtr != 0) {
138 | Module._free(this.leftBufferPtr);
139 | this.leftBufferPtr = 0;
140 | }
141 | if (this.rightBufferPtr != 0) {
142 | Module._free(this.rightBufferPtr);
143 | this.rightBufferPtr = 0;
144 | }
145 | }
146 | processNode.stop = function() {
147 | this.disconnect();
148 | this.cleanup();
149 | }
150 | processNode.pause = function() {
151 | this.paused = true;
152 | }
153 | processNode.unpause = function() {
154 | this.paused = false;
155 | }
156 | processNode.togglePause = function() {
157 | this.paused = !this.paused;
158 | }
159 | processNode.onaudioprocess = function(e) {
160 | var outputL = e.outputBuffer.getChannelData(0);
161 | var outputR = e.outputBuffer.getChannelData(1);
162 | var framesToRender = outputL.length;
163 | if (this.ModulePtr == 0) {
164 | for (var i = 0; i < framesToRender; ++i) {
165 | outputL[i] = 0;
166 | outputR[i] = 0;
167 | }
168 | this.disconnect();
169 | this.cleanup();
170 | return;
171 | }
172 | if (this.paused) {
173 | for (var i = 0; i < framesToRender; ++i) {
174 | outputL[i] = 0;
175 | outputR[i] = 0;
176 | }
177 | return;
178 | }
179 | var framesRendered = 0;
180 | var ended = false;
181 | var error = false;
182 | while (framesToRender > 0) {
183 | var framesPerChunk = Math.min(framesToRender, maxFramesPerChunk);
184 | var actualFramesPerChunk = Module._openmpt_module_read_float_stereo(this.modulePtr, this.context.sampleRate, framesPerChunk, this.leftBufferPtr, this.rightBufferPtr);
185 | if (actualFramesPerChunk == 0) {
186 | ended = true;
187 | // modulePtr will be 0 on openmpt: error: openmpt_module_read_float_stereo: ERROR: module * not valid or other openmpt error
188 | error = !this.modulePtr;
189 | }
190 | var rawAudioLeft = Module.HEAPF32.subarray(this.leftBufferPtr / 4, this.leftBufferPtr / 4 + actualFramesPerChunk);
191 | var rawAudioRight = Module.HEAPF32.subarray(this.rightBufferPtr / 4, this.rightBufferPtr / 4 + actualFramesPerChunk);
192 | for (var i = 0; i < actualFramesPerChunk; ++i) {
193 | outputL[framesRendered + i] = rawAudioLeft[i];
194 | outputR[framesRendered + i] = rawAudioRight[i];
195 | }
196 | for (var i = actualFramesPerChunk; i < framesPerChunk; ++i) {
197 | outputL[framesRendered + i] = 0;
198 | outputR[framesRendered + i] = 0;
199 | }
200 | framesToRender -= framesPerChunk;
201 | framesRendered += framesPerChunk;
202 | }
203 | if (ended) {
204 | this.disconnect();
205 | this.cleanup();
206 | error ? processNode.player.fireEvent('onError', {type: 'openmpt'}) : processNode.player.fireEvent('onEnded');
207 | }
208 | }
209 | return processNode;
210 | }
211 |
212 |
--------------------------------------------------------------------------------
/css/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v1.1.0 | MIT License | git.io/normalize */
2 |
3 | /* ==========================================================================
4 | HTML5 display definitions
5 | ========================================================================== */
6 |
7 | /**
8 | * Correct `block` display not defined in IE 6/7/8/9 and Firefox 3.
9 | */
10 |
11 | article,
12 | aside,
13 | details,
14 | figcaption,
15 | figure,
16 | footer,
17 | header,
18 | hgroup,
19 | main,
20 | nav,
21 | section,
22 | summary {
23 | display: block;
24 | }
25 |
26 | /**
27 | * Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.
28 | */
29 |
30 | audio,
31 | canvas,
32 | video {
33 | display: inline-block;
34 | *display: inline;
35 | *zoom: 1;
36 | }
37 |
38 | /**
39 | * Prevent modern browsers from displaying `audio` without controls.
40 | * Remove excess height in iOS 5 devices.
41 | */
42 |
43 | audio:not([controls]) {
44 | display: none;
45 | height: 0;
46 | }
47 |
48 | /**
49 | * Address styling not present in IE 7/8/9, Firefox 3, and Safari 4.
50 | * Known issue: no IE 6 support.
51 | */
52 |
53 | [hidden] {
54 | display: none;
55 | }
56 |
57 | /* ==========================================================================
58 | Base
59 | ========================================================================== */
60 |
61 | /**
62 | * 1. Correct text resizing oddly in IE 6/7 when body `font-size` is set using
63 | * `em` units.
64 | * 2. Prevent iOS text size adjust after orientation change, without disabling
65 | * user zoom.
66 | */
67 |
68 | html {
69 | font-size: 100%; /* 1 */
70 | -webkit-text-size-adjust: 100%; /* 2 */
71 | -ms-text-size-adjust: 100%; /* 2 */
72 | }
73 |
74 | /**
75 | * Address `font-family` inconsistency between `textarea` and other form
76 | * elements.
77 | */
78 |
79 | html,
80 | button,
81 | input,
82 | select,
83 | textarea {
84 | font-family: sans-serif;
85 | }
86 |
87 | /**
88 | * Address margins handled incorrectly in IE 6/7.
89 | */
90 |
91 | body {
92 | margin: 0;
93 | }
94 |
95 | /* ==========================================================================
96 | Links
97 | ========================================================================== */
98 |
99 | /**
100 | * Address `outline` inconsistency between Chrome and other browsers.
101 | */
102 |
103 | a:focus {
104 | outline: thin dotted;
105 | }
106 |
107 | /**
108 | * Improve readability when focused and also mouse hovered in all browsers.
109 | */
110 |
111 | a:active,
112 | a:hover {
113 | outline: 0;
114 | }
115 |
116 | /* ==========================================================================
117 | Typography
118 | ========================================================================== */
119 |
120 | /**
121 | * Address font sizes and margins set differently in IE 6/7.
122 | * Address font sizes within `section` and `article` in Firefox 4+, Safari 5,
123 | * and Chrome.
124 | */
125 |
126 | h1 {
127 | font-size: 2em;
128 | margin: 0.67em 0;
129 | }
130 |
131 | h2 {
132 | font-size: 1.5em;
133 | margin: 0.83em 0;
134 | }
135 |
136 | h3 {
137 | font-size: 1.17em;
138 | margin: 1em 0;
139 | }
140 |
141 | h4 {
142 | font-size: 1em;
143 | margin: 1.33em 0;
144 | }
145 |
146 | h5 {
147 | font-size: 0.83em;
148 | margin: 1.67em 0;
149 | }
150 |
151 | h6 {
152 | font-size: 0.67em;
153 | margin: 2.33em 0;
154 | }
155 |
156 | /**
157 | * Address styling not present in IE 7/8/9, Safari 5, and Chrome.
158 | */
159 |
160 | abbr[title] {
161 | border-bottom: 1px dotted;
162 | }
163 |
164 | /**
165 | * Address style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome.
166 | */
167 |
168 | b,
169 | strong {
170 | font-weight: bold;
171 | }
172 |
173 | blockquote {
174 | margin: 1em 40px;
175 | }
176 |
177 | /**
178 | * Address styling not present in Safari 5 and Chrome.
179 | */
180 |
181 | dfn {
182 | font-style: italic;
183 | }
184 |
185 | /**
186 | * Address differences between Firefox and other browsers.
187 | * Known issue: no IE 6/7 normalization.
188 | */
189 |
190 | hr {
191 | -moz-box-sizing: content-box;
192 | box-sizing: content-box;
193 | height: 0;
194 | }
195 |
196 | /**
197 | * Address styling not present in IE 6/7/8/9.
198 | */
199 |
200 | mark {
201 | background: #ff0;
202 | color: #000;
203 | }
204 |
205 | /**
206 | * Address margins set differently in IE 6/7.
207 | */
208 |
209 | p,
210 | pre {
211 | margin: 1em 0;
212 | }
213 |
214 | /**
215 | * Correct font family set oddly in IE 6, Safari 4/5, and Chrome.
216 | */
217 |
218 | code,
219 | kbd,
220 | pre,
221 | samp {
222 | font-family: monospace, serif;
223 | _font-family: 'courier new', monospace;
224 | font-size: 1em;
225 | }
226 |
227 | /**
228 | * Improve readability of pre-formatted text in all browsers.
229 | */
230 |
231 | pre {
232 | white-space: pre;
233 | white-space: pre-wrap;
234 | word-wrap: break-word;
235 | }
236 |
237 | /**
238 | * Address CSS quotes not supported in IE 6/7.
239 | */
240 |
241 | q {
242 | quotes: none;
243 | }
244 |
245 | /**
246 | * Address `quotes` property not supported in Safari 4.
247 | */
248 |
249 | q:before,
250 | q:after {
251 | content: '';
252 | content: none;
253 | }
254 |
255 | /**
256 | * Address inconsistent and variable font size in all browsers.
257 | */
258 |
259 | small {
260 | font-size: 80%;
261 | }
262 |
263 | /**
264 | * Prevent `sub` and `sup` affecting `line-height` in all browsers.
265 | */
266 |
267 | sub,
268 | sup {
269 | font-size: 75%;
270 | line-height: 0;
271 | position: relative;
272 | vertical-align: baseline;
273 | }
274 |
275 | sup {
276 | top: -0.5em;
277 | }
278 |
279 | sub {
280 | bottom: -0.25em;
281 | }
282 |
283 | /* ==========================================================================
284 | Lists
285 | ========================================================================== */
286 |
287 | /**
288 | * Address margins set differently in IE 6/7.
289 | */
290 |
291 | dl,
292 | menu,
293 | ol,
294 | ul {
295 | margin: 1em 0;
296 | }
297 |
298 | dd {
299 | margin: 0 0 0 40px;
300 | }
301 |
302 | /**
303 | * Address paddings set differently in IE 6/7.
304 | */
305 |
306 | menu,
307 | ol,
308 | ul {
309 | padding: 0 0 0 40px;
310 | }
311 |
312 | /**
313 | * Correct list images handled incorrectly in IE 7.
314 | */
315 |
316 | nav ul,
317 | nav ol {
318 | list-style: none;
319 | list-style-image: none;
320 | }
321 |
322 | /* ==========================================================================
323 | Embedded content
324 | ========================================================================== */
325 |
326 | /**
327 | * 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3.
328 | * 2. Improve image quality when scaled in IE 7.
329 | */
330 |
331 | img {
332 | border: 0; /* 1 */
333 | -ms-interpolation-mode: bicubic; /* 2 */
334 | }
335 |
336 | /**
337 | * Correct overflow displayed oddly in IE 9.
338 | */
339 |
340 | svg:not(:root) {
341 | overflow: hidden;
342 | }
343 |
344 | /* ==========================================================================
345 | Figures
346 | ========================================================================== */
347 |
348 | /**
349 | * Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11.
350 | */
351 |
352 | figure {
353 | margin: 0;
354 | }
355 |
356 | /* ==========================================================================
357 | Forms
358 | ========================================================================== */
359 |
360 | /**
361 | * Correct margin displayed oddly in IE 6/7.
362 | */
363 |
364 | form {
365 | margin: 0;
366 | }
367 |
368 | /**
369 | * Define consistent border, margin, and padding.
370 | */
371 |
372 | fieldset {
373 | border: 1px solid #c0c0c0;
374 | margin: 0 2px;
375 | padding: 0.35em 0.625em 0.75em;
376 | }
377 |
378 | /**
379 | * 1. Correct color not being inherited in IE 6/7/8/9.
380 | * 2. Correct text not wrapping in Firefox 3.
381 | * 3. Correct alignment displayed oddly in IE 6/7.
382 | */
383 |
384 | legend {
385 | border: 0; /* 1 */
386 | padding: 0;
387 | white-space: normal; /* 2 */
388 | *margin-left: -7px; /* 3 */
389 | }
390 |
391 | /**
392 | * 1. Correct font size not being inherited in all browsers.
393 | * 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5,
394 | * and Chrome.
395 | * 3. Improve appearance and consistency in all browsers.
396 | */
397 |
398 | button,
399 | input,
400 | select,
401 | textarea {
402 | font-size: 100%; /* 1 */
403 | margin: 0; /* 2 */
404 | vertical-align: baseline; /* 3 */
405 | *vertical-align: middle; /* 3 */
406 | }
407 |
408 | /**
409 | * Address Firefox 3+ setting `line-height` on `input` using `!important` in
410 | * the UA stylesheet.
411 | */
412 |
413 | button,
414 | input {
415 | line-height: normal;
416 | }
417 |
418 | /**
419 | * Address inconsistent `text-transform` inheritance for `button` and `select`.
420 | * All other form control elements do not inherit `text-transform` values.
421 | * Correct `button` style inheritance in Chrome, Safari 5+, and IE 6+.
422 | * Correct `select` style inheritance in Firefox 4+ and Opera.
423 | */
424 |
425 | button,
426 | select {
427 | text-transform: none;
428 | }
429 |
430 | /**
431 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
432 | * and `video` controls.
433 | * 2. Correct inability to style clickable `input` types in iOS.
434 | * 3. Improve usability and consistency of cursor style between image-type
435 | * `input` and others.
436 | * 4. Remove inner spacing in IE 7 without affecting normal text inputs.
437 | * Known issue: inner spacing remains in IE 6.
438 | */
439 |
440 | button,
441 | html input[type="button"], /* 1 */
442 | input[type="reset"],
443 | input[type="submit"] {
444 | -webkit-appearance: button; /* 2 */
445 | cursor: pointer; /* 3 */
446 | *overflow: visible; /* 4 */
447 | }
448 |
449 | /**
450 | * Re-set default cursor for disabled elements.
451 | */
452 |
453 | button[disabled],
454 | html input[disabled] {
455 | cursor: default;
456 | }
457 |
458 | /**
459 | * 1. Address box sizing set to content-box in IE 8/9.
460 | * 2. Remove excess padding in IE 8/9.
461 | * 3. Remove excess padding in IE 7.
462 | * Known issue: excess padding remains in IE 6.
463 | */
464 |
465 | input[type="checkbox"],
466 | input[type="radio"] {
467 | box-sizing: border-box; /* 1 */
468 | padding: 0; /* 2 */
469 | *height: 13px; /* 3 */
470 | *width: 13px; /* 3 */
471 | }
472 |
473 | /**
474 | * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
475 | * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
476 | * (include `-moz` to future-proof).
477 | */
478 |
479 | input[type="search"] {
480 | -webkit-appearance: textfield; /* 1 */
481 | -moz-box-sizing: content-box;
482 | -webkit-box-sizing: content-box; /* 2 */
483 | box-sizing: content-box;
484 | }
485 |
486 | /**
487 | * Remove inner padding and search cancel button in Safari 5 and Chrome
488 | * on OS X.
489 | */
490 |
491 | input[type="search"]::-webkit-search-cancel-button,
492 | input[type="search"]::-webkit-search-decoration {
493 | -webkit-appearance: none;
494 | }
495 |
496 | /**
497 | * Remove inner padding and border in Firefox 3+.
498 | */
499 |
500 | button::-moz-focus-inner,
501 | input::-moz-focus-inner {
502 | border: 0;
503 | padding: 0;
504 | }
505 |
506 | /**
507 | * 1. Remove default vertical scrollbar in IE 6/7/8/9.
508 | * 2. Improve readability and alignment in all browsers.
509 | */
510 |
511 | textarea {
512 | overflow: auto; /* 1 */
513 | vertical-align: top; /* 2 */
514 | }
515 |
516 | /* ==========================================================================
517 | Tables
518 | ========================================================================== */
519 |
520 | /**
521 | * Remove most spacing between table cells.
522 | */
523 |
524 | table {
525 | border-collapse: collapse;
526 | border-spacing: 0;
527 | }
528 |
--------------------------------------------------------------------------------