Stap 8: Moe van het maken van de beat drop? Laten we wat meer sensoren en geluiden toevoegen.
De vreugde van het maken van een bass drum kick van een fysieke knop drukt verdwijnt vrij snel, dus laten we het een beetje meer interessant. Cylon kunnen we gebruiken om de interface met een enorme hoeveelheid verschillende sensoren en apparaten. Tot nu toe hebben we vast voor het gebruik van een enkele knop push gebeurtenis te schoppen van de trommel. We willen nu, refactoring van de code van onze app.js om er een beetje makkelijker te meer knoppen toevoegen, evenals sommige analoge sensoren toevoegen.
Voordat u wijzigingen in de code, laten we Voeg een paar meer apparaten om mee te werken.
Voor dit instructable, koos ik aan kabellengte tot een totaal van 4 knoppen, een potentiometer en een fotocel. Hierdoor kunnen we meer parameters van de instrumenten van de Timbre.js met een groot bereik van waarden, in plaats van alleen de ON/OFF waarden uit onze knoppen bepalen.
Nu, laten we refactoring onze code ter ondersteuning van meer apparaten. Wij willen kunnen toestaan van onze opdrachtgever te luisteren naar specifieke knooppersen, en specifieke sensor lezingen, in plaats van met behulp van de gebeurtenis van een generieke 'knop'. We gaan twee verschillende gebeurtenissen, 'knop' en 'sensor', zenden met een hekje met een id van onze apparaat, alsmede de waarde die we willen sturen. We verwachten een 0 of een 1 voor knoppen, en voor analoge sensoren, verwachten we wat de waarde is van de sensorgegevens. De volgende wijzigingen aanbrengen in het bestand 'app.js'.
var express = require('express') var app = express() var server = require('http').Server(app) var cylon = require('cylon') var io = require('socket.io')(server) app.use(express.static(__dirname + '/public')) server.listen(8080) var socket = io .of('/soundsocket') .on('connection', function (socket) { console.log('client connected') }) var cylonReady = function(my) { io .of('/soundsocket') .on('connection', function (socket) { registerSocketHandlers(my, socket); }) } // this will be called each time a socket is opened, so each client will receive their own events when buttons are pushed. var registerSocketHandlers = function(my, socket) { buttons = [my.button0, my.button1, my.button2, my.button3] for (var i = 0; i < buttons.length; i++) { var button = buttons[i]; registerButtonHandler(socket, button, i); } analogSensors = [my.potentiometer, my.photocell] for (var i = 0; i < analogSensors.length; i++) { var sensor = analogSensors[i]; registerAnalogSensorHandler(socket, sensor, i); } } // convenience for button specific events var registerButtonHandler = function(socket, button, buttonID) { // on push, send button ID and value of 1 button.on('push', function() { socket.emit('button', { 'id': buttonID, 'value': 1 }) }) // on push, send button ID and value of 0 button.on('release', function() { socket.emit('button', { 'id': buttonID, 'value': 0 }) }) } // convenience for listening to analog read events and emitting sensor data messages var registerAnalogSensorHandler = function(socket, analogSensor, analogSensorID) { // on new data, send sensor ID and value of sensor reading analogSensor.on('analogRead', function() { // ask the sensor for it's value sensorValue = analogSensor.analogRead() socket.emit('sensor', { 'id': analogSensorID, 'value': sensorValue }) }) } // tell Cylon which devices we will be interfacing with var getDevices = function() { return { button0: { driver: 'button', pin: 2 }, button1: { driver: 'button', pin: 3 }, button2: { driver: 'button', pin: 4 }, button3: { driver: 'button', pin: 5 }, potentiometer: { driver: 'analogSensor', pin: 0, lowerLimit: 100, upperLimit: 900 }, photocell: { driver: 'analogSensor', pin: 1, lowerLimit: 100, upperLimit: 900 } } } // tell Cylon how we will be connecting to our devices var getConnections = function() { return { edison: { adaptor: 'intel-iot' } } } cylon.robot({ connections: getConnections(), // use our getConnections function to clean this up. devices: getDevices() // use our getDevices function to clean this up. }).on('ready', cylonReady) cylon.start()
Opmerking: Zorg ervoor dat uw analoge sensoren zijn aangesloten op de Analoge In -poorten van uw Edison.
Om te verbruiken deze veranderingen in onze klant, de volgende wijzigingen aanbrengen zodat uw 'playsounds.js' de volgende code geeft:
var BD var SD var HH1 var HH2 var CYM var drum var lead var env var arp var delay var inv T("audio").load("./drumkit.wav", function() { BD = this.slice( 0, 500).set({bang:false}) SD = this.slice( 500, 1000).set({bang:false}) HH1 = this.slice(1000, 1500).set({bang:false, mul:0.2}) HH2 = this.slice(1500, 2000).set({bang:false, mul:0.2}) CYM = this.slice(2000).set({bang:false, mul:0.2}) var scale = new sc.Scale([0,1,3,7,8], 12, "Pelog") var P1 = [ [BD, HH1], [HH1], [HH2], [], [BD, SD, HH1], [HH1], [HH2], [SD], ].wrapExtend(128) var P2 = sc.series(16) drum = T("lowshelf", {freq:110, gain:8, mul:0.6}, BD, SD, HH1, HH2, CYM).play() lead = T("saw", {freq:T("param")}) env = T("perc", {r:100}) arp = T("OscGen", {wave:"sin(15)", env:env, mul:0.5}) delay = T("delay", {time:"BPM128 L4", fb:0.65, mix:0.35}, T("pan", {pos:T("tri", {freq:"BPM64 L1", mul:0.8}).kr()}, arp) ).play(); inv = T("interval", {interval:"BPM128 L16"}, function(count) { var i = count % P1.length if (i === 0) CYM.bang() P1[i].forEach(function(p) { p.bang() }) if (Math.random() < 0.015) { var j = (Math.random() * P1.length)|0; P1.wrapSwap(i, j); P2.wrapSwap(i, j); } var noteNum = scale.wrapAt(P2.wrapAt(count)) + 60; if (i % 2 === 0) { lead.freq.linTo(noteNum.midicps() * 2, "100ms"); } arp.noteOn(noteNum + 24, 60) }).start() }) var socketConnection = io.connect('http://0.0.0.0:8080/soundsocket') socketConnection.on('connect', function () { console.log('connected to socket') }) socketConnection.on('button', function (data) { buttonID = data['id'] value = data['value'] switch (buttonID) { case 0: if (value == 1) { BD.bang() } break; case 1: if (value == 1) { CYM.bang() } break; case 2: value == 1 ? HH1.set({mul: 1}) : HH1.set({mul: 0.2}) break; case 3: value == 1 ? HH2.set({mul: 1}) : HH2.set({mul: 0.2}) break; default: } }) socketConnection.on('sensor', function (data) { sensorID = data['id'] value = data['value'] switch (sensorID) { case 0: inv.set({interval: value * 2 }) break; case 1: arp.set({mul: 10 / value }) break; default: } })
Plegen en uw wijzigingen duwen, trekken ze naar de Edison, en stormloop uw app. Als alles werkt zoals verwacht, u moet zitten kundig voor gebruik van de knoppen te raken van specifieke instrumenten en zitten kundig voor wijzigen van de vertraging en Opmerking compenseert met behulp van uw analoge sensoren.
Dit geeft u een voorbeeld van consumeren verschillende soorten gegevens, en ofwel spelen of aanpassen van de parameters van de instrumenten binnen de Timbre.js.