diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2018-10-09 00:30:43 +0200 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2018-10-09 00:30:43 +0200 |
| commit | 8848bc387d62e1667cdfa684f36c058d2619e6b3 (patch) | |
| tree | 89c790f4bd6aa21fd12d3c943f4d5566a46bab28 /client | |
| parent | a411f4822a0b2fc72308bcd4af1bc3593aabd4ad (diff) | |
mass shooting sonification
Diffstat (limited to 'client')
| -rw-r--r-- | client/data.js | 2 | ||||
| -rw-r--r-- | client/index.js | 111 | ||||
| -rw-r--r-- | client/lib/midi.js | 20 |
3 files changed, 113 insertions, 20 deletions
diff --git a/client/data.js b/client/data.js index d48ccaa..d2a43aa 100644 --- a/client/data.js +++ b/client/data.js @@ -1,6 +1,6 @@ const files = [ // "gun_violence", - "mass_shootings", + "mass_shootings_lite", "gun_violence_by_month", ] const parse = require('csv-parse') diff --git a/client/index.js b/client/index.js index e9a0873..58185a5 100644 --- a/client/index.js +++ b/client/index.js @@ -8,13 +8,12 @@ import { midi_init, play_note, play_sequence, - play_interval_sequence, export_pattern_as_midi, note_values, MidiWriter, } from './lib/midi' import { - requestAudioContext, ftom, norm, dataURItoBlob, + requestAudioContext, norm, dataURItoBlob, get_bounds, get_diff_bounds, transpose, } from './lib/util' @@ -36,7 +35,16 @@ midi_init() /* initialization */ -let i = 0, datasets = {}, dataset = {}, bounds = {}, diff = [] +const mass_fields = [ + "date", "timestamp", + "fatalities", "injured", "total_victims", + "age", "case", "weapon_type", "weapon_details" +].reduce((a,b,i) => { + a[b] = i + return a +}, {}) + +let i = 0, mass_i = 0, datasets = {}, dataset = {}, bounds = {}, diff = [] let play_fn = play_sequence data.load().then(lists => { console.log(lists) @@ -48,12 +56,93 @@ data.load().then(lists => { name, h: [name], lines: [row.map(n => parseInt(n))], + play_fn: play_sequence, } }) + datasets["Mass Shootings"] = lists.mass_shootings_lite + datasets["Mass Shootings"].name = "Mass Shootings" + datasets["Mass Shootings"].play_fn = play_mass_shootings + const lines = datasets["Mass Shootings"].lines.reverse() + const [min_y, ...rest] = lines[0][mass_fields.date].split('/') + + datasets["Mass Shootings"].dates = lines.map(row => { + const [y, m, d] = row[mass_fields.date].split('/') + return (parseInt(y) - parseInt(min_y)) * 12 + parseInt(m) + }) + datasets["Mass Shootings"].lines = [lines.map(row => Math.log(row[mass_fields.total_victims]))] requestAudioContext(ready) }) -// +/* play function for mass shooting data w/ custom timing */ + +let mass_rest = 0 + +// export const note_values = [ +// [8, '8 measures', 8 * 512], +// [4, '4 measures', 4 * 512], +// [2, '2 measures', 2 * 512], +// [1, 'whole note', 512], +// [1/2, 'half note', 256], +// [1/3, 'third note', [170, 170, 171]], +// [1/4, 'quarter note', 128], +// [1/5, 'fifth note', [51,51,51,51,52]], +// [1/6, 'sixth note', [85, 85, 86, 85, 85, 86]], +// [1/8, 'eighth note', 64], +// [1/10, 'tenth note', [25,26,26,25,26,25,26,26,25,26]], +// [1/12, 'twelfth note', [21,21,22, 21,21,22, 21,21,22, 21,21,22]], +// [1/16, 'sixteenth note', 32], +// [1/32, 'thirtysecond note', 16], +// ] + +function play_mass_shootings(i, bounds, diff, note_time, channel="all", exporting) { + const { rows, min, max } = bounds + const y = 0 + const x = i % rows[0].length + const n = rows[y][x] + let notes = [], midi_notes = [] + console.log(i, mass_i, dataset.dates[mass_i]) + while (i === dataset.dates[mass_i]) { + notes.push(dataset.lines[mass_i]) + mass_i += 1 + } + switch (notes.length) { + default: + case 0: + mass_rest += 1 + break + case 1: + midi_notes.push(play_note( norm(n, min, max) * nx.multiply.value, 128, channel, exporting, mass_rest, 0)) + break + case 2: + midi_notes.push(play_note( norm(n, min, max) * nx.multiply.value, 64, channel, exporting, mass_rest, 0)) + midi_notes.push(play_note( norm(n, min, max) * nx.multiply.value, 64, channel, exporting, 0, 64)) + break + case 3: + midi_notes.push(play_note( norm(n, min, max) * nx.multiply.value, 43, channel, exporting, mass_rest)) + midi_notes.push(play_note( norm(n, min, max) * nx.multiply.value, 43, channel, exporting, 0, 43)) + midi_notes.push(play_note( norm(n, min, max) * nx.multiply.value, 42, channel, exporting, 0, 85)) + break + case 4: + midi_notes.push(play_note( norm(n, min, max) * nx.multiply.value, 32, channel, exporting, mass_rest)) + midi_notes.push(play_note( norm(n, min, max) * nx.multiply.value, 32, channel, exporting, 0, 32)) + midi_notes.push(play_note( norm(n, min, max) * nx.multiply.value, 32, channel, exporting, 0, 64)) + midi_notes.push(play_note( norm(n, min, max) * nx.multiply.value, 32, channel, exporting, 0, 96)) + break + } + if (mass_i > dataset.dates.length-1) { + mass_rest = 0 + mass_i = 0 + i = 0 + } else { + i += 1 + } + if (notes.length) { + mass_rest = 0 + return [i, midi_notes] + } + mass_rest += 128 + return [i, []] +} /* play next note according to sonification */ @@ -74,16 +163,12 @@ function play_next(){ function pick_dataset(key){ console.log('pick dataset:', key, datasets[key]) i = 0 + mass_i = 0 + mass_rest = 0 dataset = datasets[key] bounds = get_bounds(dataset) diff = get_diff_bounds(bounds.rows) -} -var behaviors = { - sequence: { name: 'Sequence', fn: play_sequence }, - interval: { name: 'Intervals', fn: play_interval_sequence }, -} -function pick_behavior(name){ - play_fn = behaviors[name].fn + play_fn = dataset.play_fn } /* build and bind the UI */ @@ -91,9 +176,7 @@ function pick_behavior(name){ function ready() { scales.build_options(document.querySelector('#scale')) build_options(document.querySelector('#dataset'), datasets, pick_dataset) - build_options(document.querySelector('#behavior'), behaviors, pick_behavior) - console.log(Nexus) const dial_size = [50, 50] Tone.Transport.bpm.value = DEFAULT_BPM @@ -184,7 +267,7 @@ function ready() { document.querySelector('.loading').classList.remove('loading') document.querySelector('#dataset').value = 'Surrenders' - pick_dataset('Surrenders') + pick_dataset('Mass Shootings') play_next() } diff --git a/client/lib/midi.js b/client/lib/midi.js index f2e0295..338526a 100644 --- a/client/lib/midi.js +++ b/client/lib/midi.js @@ -54,7 +54,7 @@ export function midi_init() { /* play a single note */ -export function play_note(index, duration, channel="all", exporting=false){ +export function play_note(index, duration, channel="all", exporting=false, defer=0){ // console.log(index) const scale = scales.current() const freq = scale.index(index + Math.round(nx.offset.value), nx.octave.value) @@ -71,9 +71,12 @@ export function play_note(index, duration, channel="all", exporting=false){ if (exporting || midiDevice) { duration = duration || 60000 / Tone.Transport.bpm.value if (! exporting) { - midiDevice.playNote(note, channel, { duration }) - if (sendPitchBend) { - midiDevice.sendPitchBend(cents, channel) + if (defer) { + setTimeout(() => { + play_midi_note(note, cents, channel, duration) + }, defer) + } else { + play_midi_note(note, cents, channel, duration) } } } else { @@ -82,6 +85,13 @@ export function play_note(index, duration, channel="all", exporting=false){ return note } +export function play_midi_note(note, cents, channel, duration) { + midiDevice.playNote(note, channel, { duration }) + if (sendPitchBend) { + midiDevice.sendPitchBend(cents, channel) + } +} + /* play the next note in sequence */ export function play_sequence(i, bounds, diff, note_time, channel="all", exporting) { @@ -90,7 +100,7 @@ export function play_sequence(i, bounds, diff, note_time, channel="all", exporti if (i >= count) i = 0 const y = Math.floor(i / rows[0].length) const x = i % rows[0].length - if (!x) console.log(y) + // if (!x) console.log(y) const n = rows[y][x] i += 1 if (i >= count) i = 0 |
