Skip to content

Commit 65b84db

Browse files
authored
Merge pull request #294 from Aanchi-glitch2744/main
Created a Drum Player Machine
2 parents cacf1cb + e9493c9 commit 65b84db

File tree

3 files changed

+608
-0
lines changed

3 files changed

+608
-0
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Document</title>
7+
<link rel="stylesheet" href="./styles.css">
8+
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,600' rel='stylesheet' type='text/css'>
9+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
10+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
11+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
12+
13+
</head>
14+
<body>
15+
<header>
16+
<button id="play-pause" data-playing="false"><i class="fa fa-play"></i></button>
17+
<label>Try Making your own beat...</label>
18+
</header>
19+
<div class="container player"></div>
20+
<audio id="1" src="https://freewavesamples.com/files/Bass-Drum-1.wav"></audio>
21+
<audio id="2" src="https://freewavesamples.com/files/Ensoniq-ESQ-1-Snare.wav"></audio>
22+
<audio id="3" src="https://freewavesamples.com/files/Closed-Hi-Hat-1.wav"></audio>
23+
<audio id="4" src="https://freewavesamples.com/files/Ensoniq-SQ-1-Open-Hi-Hat.wav"></audio>
24+
<audio id="5" src="https://freewavesamples.com/files/Floor-Tom-1.wav"></audio>
25+
26+
<script src="scripts.js"></script>
27+
</body>
28+
</html>
Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
/**
2+
* Javascript Drum Machine
3+
* @author Sebastian Inman
4+
* @version 1.0.0
5+
* @desc This is a javascript experiment created
6+
* to demonstrate music patterns in the web browser.
7+
* I started this project just for fun and intend on
8+
* adding more to it and keeping this pen updated.
9+
* All drum samples were provided by 99Samples:
10+
* http://99sounds.org/drum-samples/
11+
*/
12+
13+
(function(DrummerJS, $, undefined) {
14+
15+
'use strict';
16+
17+
// ======================================
18+
// establish public variables and methods
19+
// ======================================
20+
21+
DrummerJS.title = 'Javascript Drum Machine';
22+
DrummerJS.description = 'Create audio loops using drum samples.'
23+
DrummerJS.author = 'Sebastian Inman';
24+
25+
var $_container = $('.player');
26+
var $_containerWidth = $_container.width();
27+
var $_containerHeight = $_container.height();
28+
29+
var $_setBPM = $('#set-bpm');
30+
var $_playPauseBtn = $('#play-pause');
31+
var $_setSamplesBtn = $('#set-samples');
32+
33+
var $_toggleRowBtn;
34+
var $_sampleBtn;
35+
36+
var _urlHash;
37+
38+
var _sampleList = 'default';
39+
40+
var _totalSteps = 16;
41+
var _totalRows = 5;
42+
43+
var _currentStep = 1;
44+
45+
var _sampleRate = 44100;
46+
var _minuteInSeconds = 60;
47+
var _beatsPerMinute = 90;
48+
49+
var _stepDelay;
50+
51+
var calculateBPM = function() {
52+
53+
_stepDelay = Math.round(((_sampleRate * _minuteInSeconds) / (_beatsPerMinute * _totalSteps)) / _totalSteps);
54+
55+
return _stepDelay;
56+
57+
};
58+
59+
// =======================================================
60+
// creates namespace provider which helps isolate
61+
// implementated code from the global namespace, providing
62+
// a single point of access for functions and methods.
63+
// =======================================================
64+
// this keeps the code more organized and allows the code
65+
// to be combined into more logical sections.
66+
// =======================================================
67+
68+
DrummerJS.handler = (function() {
69+
70+
function _handler() {
71+
72+
/**
73+
* @var _this
74+
* @desc in a 'non-strict' environment, 'this' is bound to
75+
* the global scope (if it hasn't been bound to anything else).
76+
* in 'strict' mode it is set to undefined. we store it in a
77+
* variable to avoid scope conflicts.
78+
*/
79+
80+
var _this = this;
81+
82+
var _isPlaying;
83+
84+
this.playPauseHandler = function(button) {
85+
86+
calculateBPM();
87+
88+
var status = button.data('playing');
89+
90+
if(status === 'true') {
91+
92+
button.data('playing', 'false').html('<i class="fa fa-play"></i>');
93+
94+
_this.stopAudio();
95+
96+
}else {
97+
98+
button.data('playing', 'true').html('<i class="fa fa-pause"></i>');
99+
100+
_this.startAudio();
101+
102+
}
103+
104+
};
105+
106+
this.pageLoad = function() {
107+
108+
if(!window.location.hash) {
109+
110+
window.location.hash = '!/';
111+
112+
}
113+
114+
_urlHash = window.location.hash.split('/');
115+
116+
};
117+
118+
this.toggleSample = function(sample) {
119+
120+
sample.toggleClass('active');
121+
122+
};
123+
124+
this.toggleSampleHandler = function() {
125+
126+
$('.sample').on('click', function() {
127+
128+
_this.toggleSample($(this));
129+
130+
});
131+
132+
};
133+
134+
this.updateSampleList = function(samples) {
135+
136+
_sampleList = samples;
137+
138+
console.log(_sampleList);
139+
140+
};
141+
142+
this.updateBPM = function(bpm) {
143+
144+
_beatsPerMinute = bpm;
145+
146+
calculateBPM();
147+
148+
_this.stopAudio();
149+
_this.startAudio();
150+
151+
};
152+
153+
this.stopAudio = function() {
154+
155+
$_sampleBtn.removeClass('hit');
156+
157+
clearInterval(_isPlaying);
158+
159+
};
160+
161+
this.startAudio = function() {
162+
163+
_isPlaying = window.setInterval(function() {
164+
165+
_this.playAudio()
166+
167+
}, _stepDelay);
168+
169+
}
170+
171+
this.playAudio = function() {
172+
173+
if(_currentStep < _totalSteps) {
174+
175+
_currentStep++;
176+
177+
}else if(_currentStep >= _totalSteps){
178+
179+
_currentStep = 1;
180+
181+
}
182+
183+
$_sampleBtn.removeClass('hit');
184+
185+
for(var i = 1; i < _totalRows + 1; i++) {
186+
187+
var $_newSample = $('.sample[data-row="' + i + '"][data-column="' + _currentStep + '"]');
188+
189+
if($_newSample.hasClass('active')) {
190+
191+
$('#' + i)[0].currentTime = 0;
192+
193+
if(!$_newSample.hasClass('disabled')) {
194+
195+
$('#' + i)[0].play();
196+
197+
}else{
198+
199+
$('#' + i)[0].pause();
200+
201+
}
202+
203+
$_newSample.addClass('hit');
204+
205+
}
206+
207+
}
208+
209+
};
210+
211+
this.createMatrix = function(rows, columns) {
212+
213+
var sampleSize = $_containerWidth / columns;
214+
215+
for(var i = 1; i < rows + 1; i++) {
216+
217+
$('<div class="row" id="row-' + i + '"></div>').appendTo('.container');
218+
219+
$('<button class="enable-disable-row" id="toggle-row-' + i + '"></button>').prependTo('#row-' + i);
220+
221+
for(var k = 1; k < columns + 1; k++) {
222+
223+
$('<div class="column sample" data-row="' + i + '" data-column="' + k + '" style="height:' + (sampleSize - 8) + 'px;width:' + sampleSize + 'px"></div>').appendTo('#row-' + i);
224+
225+
}
226+
227+
}
228+
229+
$_toggleRowBtn = $('.enable-disable-row');
230+
$_sampleBtn = $('.sample');
231+
232+
calculateBPM();
233+
234+
};
235+
236+
this.toggleRowBtnHandler = function(button) {
237+
238+
button.toggleClass('disabled');
239+
240+
var rowID = button.attr('id').replace('toggle-row-', '');
241+
242+
$('.sample[data-row="' + rowID + '"]').toggleClass('disabled');
243+
244+
};
245+
246+
247+
/**
248+
* @function init()
249+
* @desc initiates the DrummerJS global function
250+
* creating an active instance of the script on the
251+
* current site.
252+
*/
253+
254+
this.init = function() {
255+
256+
// run functions here
257+
258+
_this.pageLoad();
259+
260+
_this.createMatrix(_totalRows, _totalSteps);
261+
_this.toggleSampleHandler();
262+
263+
$_playPauseBtn.on('click', function() {
264+
265+
_this.playPauseHandler($(this));
266+
267+
});
268+
269+
$_toggleRowBtn.on('click', function() {
270+
271+
_this.toggleRowBtnHandler($(this));
272+
273+
});
274+
275+
$_setBPM.on('change', function() {
276+
277+
_this.updateBPM($(this).val());
278+
279+
});
280+
281+
$_setSamplesBtn.on('change', function() {
282+
283+
_this.updateSampleList($(this).val());
284+
285+
});
286+
287+
// start the drum machine
288+
289+
$_playPauseBtn.click();
290+
291+
return this;
292+
293+
};
294+
295+
// initiate the script!
296+
return this.init();
297+
298+
}
299+
300+
// create a new handler object
301+
return new _handler();
302+
303+
}());
304+
305+
// assign DrummerJS to the global namespace
306+
}(window.DrummerJS = window.DrummerJS || {}, jQuery));

0 commit comments

Comments
 (0)