Compare commits

..

No commits in common. "rehersal_v2" and "main" have entirely different histories.

25 changed files with 132 additions and 681 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
audio/delayecho.mp3 Normal file

Binary file not shown.

BIN
audio/minok01.mp3 Normal file

Binary file not shown.

BIN
audio/minok02.mp3 Normal file

Binary file not shown.

BIN
audio/minok03.mp3 Normal file

Binary file not shown.

BIN
audio/minok04.mp3 Normal file

Binary file not shown.

BIN
audio/minok1frequency.mp3 Normal file

Binary file not shown.

BIN
audio/minok2transpose.mp3 Normal file

Binary file not shown.

BIN
audio/minok3delay.mp3 Normal file

Binary file not shown.

BIN
audio/minok4eq.mp3 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,22 +1,14 @@
@font-face {
font-family: 'ACCchildrenfall';
src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_2112-2@1.0/ACCchildrenfall.woff') format('woff');
font-weight: normal;
font-style: normal;
}
html, html,
body { body {
margin: 0; margin: 0;
padding: 0; padding: 0;
font-family: 'ACCchildrenfall';
} }
canvas { canvas {
display: block; display: block;
} }
.fullscreen { .overlay-userinput {
display: grid; display: grid;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@ -25,55 +17,8 @@ canvas {
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
font-size: 3em;
}
#overlay-userinput {
/* display: none; */
background-color: rgba(255, 255, 255, 0.5); background-color: rgba(255, 255, 255, 0.5);
color: white; color: white;
z-index: 2; z-index: 2;
}
#announcements {
/* display: none; */ /* display: none; */
/* background-color: lime; */
color: white;
z-index: 1;
}
#radio {
position: fixed;
top: 20px;
left: 20px;
z-index: 1;
}
#radiostart-userinput {
position: fixed;
top: 50px;
right: 20px;
z-index: 1;
}
#scene-minok {
position: fixed;
top: 100px;
right: 20px;
z-index: 1;
}
#scene-wonjung {
position: fixed;
top: 150px;
right: 20px;
z-index: 1;
}
#scene-all {
position: fixed;
top: 200px;
right: 20px;
z-index: 1;
} }

View file

@ -1,46 +0,0 @@
/* Styles go here */
.animationStripes{
background-image: repeating-linear-gradient(-45deg, gold, gold 1em, blue 1em, blue 2em);
-webkit-animation:progress 2s linear infinite;
-moz-animation:progress 2s linear infinite;
-ms-animation:progress 2s linear infinite;
animation:progress 2s linear infinite;
background-size: 150% 100%;
display: none;
color: white;
z-index: 2;
}
@-webkit-keyframes progress{
0% {
background-position: 0 0;
}
100% {
background-position: -3em 0em;
}
}
@-moz-keyframes progress{
0% {
background-position: 0 0;
}
100% {
background-position: -3em 0em;
}
}
@-ms-keyframes progress{
0% {
background-position: 0 0;
}
100% {
background-position: -3em 0em;
}
}
@keyframes progress{
0% {
background-position: 0 0;
}
100% {
background-position: -2.8em 0em;
}
}

View file

@ -8,51 +8,22 @@
<script src="js/p5.min.js"></script> <script src="js/p5.min.js"></script>
<script src="js/Tone.min.js"></script> <script src="js/Tone.min.js"></script>
<!-- css --> <!-- css -->
<link type="text/css" rel="stylesheet" href="css/default.css"> <link rel="stylesheet" href="css/default.css">
<link type="text/css" rel="stylesheet" href="css/loading-animation.css" /> <!-- script -->
<!-- <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css"> -->
<script> <script>
// const AudioContext = window.AudioContext || window.webkitAudioContext; const AudioContext = window.AudioContext || window.webkitAudioContext;
// let audioCtx; let audioCtx;
</script> </script>
<script src="js/util.js"></script> <script src="js/util.js"></script>
<script src="js/classes.js"></script> <script src="js/classes.js"></script>
</head> </head>
<body> <body>
<div id='overlay-userinput' class='fullscreen' onclick='initialize();'> <button class='overlay-userinput' onclick='initialize();'>
<div style='width:100%;'> <div>터치하고-시작하기!</div>
<div style='text-align: left;'>터치하고-</div>
<div style='text-align: right;'>시작하기!</div>
</div>
</div>
<div id='loading-veil' class='fullscreen animationStripes'>
<div>로~~~~~딩⏳</div>
</div>
<div id='announcements' class='fullscreen announcements'>
<div></div>
</div>
<button id='radiostart-userinput' onclick='document.querySelector("#radio").play();'>
<span style='font-size:3em;'>📻</span>
</button> </button>
<button id='scene-minok' onclick='scene=10;sceneChanger();'> <audio controls crossorigin="anonymous" style="display:none;">
<span style='font-size:3em;'>🍇</span>
</button>
<button id='scene-wonjung' onclick='scene=20;sceneChanger();'>
<span style='font-size:3em;'>🥑</span>
</button>
<button id='scene-all' onclick='scene=scene+1;sceneChanger();'>
<span style='font-size:3em;'>🥥</span>
</button>
<audio id="radio" controls crossorigin="anonymous">
<!-- iOS bug... you must add <source> later! -->
<!-- <source src="https://radio.dianaband.in:8000/stream" type="audio/aac" /> --> <!-- <source src="https://radio.dianaband.in:8000/stream" type="audio/aac" /> -->
</audio> </audio>
@ -62,6 +33,8 @@
let heading = 0; let heading = 0;
let latitude = 37.574973; let latitude = 37.574973;
let longitude = 126.925708; let longitude = 126.925708;
// let latitude = 37.576774;
// let longitude = 126.931232;
// 맞는 결과 (예) : 작업실 -> 베지스 // 맞는 결과 (예) : 작업실 -> 베지스
// p1 = [37.574973, 126.925708] // p1 = [37.574973, 126.925708]
@ -75,15 +48,7 @@
let silence; let silence;
let clap; let clap;
let radio; let radio;
//scene //all ready flag (not used)
let scene = -1;
//sounders' list
let scenes = {};
let minok_sounds = [];
let wonjung_sounds = [];
scenes.minok_sounds = minok_sounds;
scenes.wonjung_sounds = wonjung_sounds;
//all ready flag
let ready = false; let ready = false;
//clear all permissions //clear all permissions
@ -94,237 +59,69 @@
requestOrientationPermission(); requestOrientationPermission();
} }
// remove the 'userinput' veil
document.querySelector("#overlay-userinput").style.display = 'none';
// show loading screen.
document.querySelector("#loading-veil").style.display = 'grid';
// unfreeze Tone.js with userinput
await Tone.start();
// start audiocontext // start audiocontext
// audioCtx = new AudioContext; audioCtx = new AudioContext;
// audioCtx = Tone.getContext();
// some sounds for check-in // some sounds for check-in
silence = (await AudioImport("./audio/_silence.wav")).toDestination(); silence = (await AudioImport("./audio/_silence.wav")).toDestination();
clap = (await AudioImport("./audio/clap01.mp3")).toDestination(); clap = (await AudioImport("./audio/clap01.mp3")).toDestination();
// start loading for all sounds
sounds.forEach(async item => await item.load());
// unfreeze audio playback for Tone.js
silence.start(); silence.start();
// clap.start();
// register sounders to the list // remove the veil
minok_sounds.push(new Sounder({ let veil = document.querySelector(".overlay-userinput");
name: '주파수 구간', veil.style.display = 'none';
location: [37.575451, 126.926939],
soundfile: "./audio/minok_01.mp3",
gain: 0,
spread: 20,
distmap: [0.01, 0.08, 0, -20], // (km) -> (dB)
//testing
volmin: -30,
}));
minok_sounds.push(new Sounder({
name: 'Transpose',
location: [37.575009, 126.926373],
soundfile: "./audio/minok_02.mp3",
gain: 0,
spread: 20,
distmap: [0.01, 0.08, 0, -20], // (km) -> (dB)
//testing
volmin: -30,
}));
minok_sounds.push(new Sounder({
name: 'Delay',
location: [37.574383, 126.925500],
soundfile: "./audio/minok_03.mp3",
gain: 0,
spread: 20,
distmap: [0.01, 0.08, 0, -20], // (km) -> (dB)
//testing
volmin: -30,
}));
minok_sounds.push(new Sounder({
name: 'EQ',
location: [37.573562, 126.924426],
soundfile: "./audio/minok_04.mp3",
gain: 0,
spread: 20,
distmap: [0.01, 0.08, 0, -20], // (km) -> (dB)
//testing
volmin: -30,
}));
minok_sounds.push(new Sounder({
name: '모든 효과가 다 섞인 뇌절 of 뇌절 트랙',
location: [37.572931, 126.923612],
soundfile: "./audio/minok_05.mp3",
gain: 0,
spread: 20,
distmap: [0.01, 0.08, 0, -20], // (km) -> (dB)
//testing
volmin: -30,
}));
minok_sounds.push(new Sounder({
name: '뇌절 트랙 (끝!)',
location: [37.571918, 126.922360],
soundfile: "./audio/minok_05.mp3",
gain: 0,
spread: 20,
distmap: [0.01, 0.08, 0, -20], // (km) -> (dB)
//testing
volmin: -30,
}));
wonjung_sounds.push(new Sounder({ // activate radio by adding source tag
name: '푸르지오 앞 데크길 밑 운동기구', const audiotag = document.querySelector('audio'); // N.B. assuming there's only 1 audio tag for streaming...
location: [37.576013, 126.927912],
soundfile: "./audio/01.mp3",
gain: 0,
spread: 20,
distmap: [0.01, 0.08, 0, -20], // (km) -> (dB)
//testing
volmin: -30,
}));
wonjung_sounds.push(new Sounder({
name: '연리지',
location: [37.574409, 126.925210],
soundfile: "./audio/02.mp3",
gain: 0,
spread: 20,
distmap: [0.01, 0.08, 0, -20], // (km) -> (dB)
//testing
volmin: -30,
}));
wonjung_sounds.push(new Sounder({
name: '폭우와 멜로디혼',
location: [37.573430, 126.923445],
soundfile: "./audio/03.mp3",
gain: 0,
spread: 20,
distmap: [0.01, 0.08, 0, -20], // (km) -> (dB)
//testing
volmin: -30,
}));
wonjung_sounds.push(new Sounder({
name: '농구대',
location: [37.573149, 126.922870],
soundfile: "./audio/04.mp3",
gain: 0,
spread: 20,
distmap: [0.01, 0.08, 0, -20], // (km) -> (dB)
//testing
volmin: -30,
}));
wonjung_sounds.push(new Sounder({
name: '물소리 조각',
location: [37.574623, 126.924903],
soundfile: "./audio/05.mp3",
gain: 0,
spread: 20,
distmap: [0.01, 0.08, 0, -20], // (km) -> (dB)
//testing
volmin: -30,
}));
wonjung_sounds.push(new Sounder({
name: '좌우패닝 벤치-지나가는 무게들',
location: [37.577172, 126.922993],
soundfile: "./audio/06.mp3",
gain: 0,
spread: 20,
distmap: [0.01, 0.08, 0, -20], // (km) -> (dB)
//testing
volmin: -30,
}));
wonjung_sounds.push(new Sounder({
name: '귀뚜라미',
location: [37.576753, 126.929252],
soundfile: "./audio/07.mp3",
gain: 0,
spread: 20,
distmap: [0.01, 0.08, 0, -20], // (km) -> (dB)
//testing
volmin: -30,
}));
// start loading for all soundfile-based sounders.
//N.B. for 'await', watch out 'forEach' ... https://stackoverflow.com/a/37576787
for (const item of scenes.wonjung_sounds) await item.load();
for (const item of scenes.minok_sounds) await item.load();
// activate radio by injecting <source> tag
const audiotag = document.querySelector('#radio');
const sourcetag = document.createElement('source'); const sourcetag = document.createElement('source');
sourcetag.setAttribute('src', 'https://radio.dianaband.in:8000/stream'); sourcetag.setAttribute('src', 'https://radio.dianaband.in:8000/stream');
sourcetag.setAttribute('type', 'audio/aac'); sourcetag.setAttribute('type', 'audio/aac');
audiotag.appendChild(sourcetag); audiotag.appendChild(sourcetag);
audiotag.play();
//link a sounder object to radio streaming.. // //link a sounder object to radio streaming..
radio = new RadioSounder({ // radio = new Sounder({
name: "베짜-📻", // // location: [37.576013, 126.927912],
location: [37.574973, 126.925708], // location: [37.574973, 126.935708],
gain: 0, // soundfile: "./audio/clap01.mp3",
spread: 90, // gain: 6,
distmap: [0.01, 2, 0, -10], // (km) -> (dB) // spread: 15,
//testing // distmap: [0.005, 0.05, 0, -10],
volmin: -30, // //testing
}); // volmin: -30,
radio.link(audiotag); // });
// audiotag.play(); // this doesn't work.. for some buggy iOS versions. another userinput needed.. // // radio.radiolink(audiotag);
// radio.load();
// remove loading screen.
document.querySelector("#loading-veil").style.display = 'none';
// remove loading screen.
document.querySelector("#announcements").style.display = 'grid';
// //
ready = true; ready = true;
//
scene = 0;
sceneChanger();
} }
async function sceneChanger() { let compass_target;
switch (scene) { let compass_north;
case 0: let sounds = [];
await fullscreenSplasher('<div>스테이지</div>', 1000); // some *splashes*
await fullscreenSplasher('<div>0</div>', 1000);
await fullscreenSplasher('<div>시작~~~</div>', 3000);
await fullscreenSplasher('', 0);
break;
case 10:
await fullscreenSplasher('<div>스테이지</div>', 1000); // some *splashes*
await fullscreenSplasher('<div>1</div>', 1000);
await fullscreenSplasher('<div>시작~~~</div>', 3000);
await fullscreenSplasher('', 0);
break;
case 20:
await fullscreenSplasher('<div>스테이지</div>', 1000); // some *splashes*
await fullscreenSplasher('<div>2</div>', 1000);
await fullscreenSplasher('<div>시작~~~</div>', 3000);
await fullscreenSplasher('', 0);
break;
case 30:
await fullscreenSplasher('<div>스테이지</div>', 1000); // some *splashes*
await fullscreenSplasher('<div>3</div>', 1000);
await fullscreenSplasher('<div>시작~~~</div>', 3000);
await fullscreenSplasher('', 0);
break;
default:
;
}
}
async function fullscreenSplasher(html, timeout) {
let element = document.querySelector('#announcements');
// element.style.display = 'grid';
element.innerHTML = html;
await asyncTimeout(timeout);
}
function setup() { function setup() {
createCanvas(windowWidth, windowHeight); createCanvas(windowWidth, windowHeight);
compass_target = new Compass(200, ['#97FFFF', '#33A1DE', 'white']);
compass_north = new Compass(40, ['yellow', 'navy', 'white']);
angleMode(DEGREES); angleMode(DEGREES);
// register sounders to the list
sounds.push(new Sounder({
location: [37.576774, 126.931232],
soundfile: "./audio/01.mp3",
gain: 6,
spread: 15,
distmap: [0.005, 0.05, 0, -10],
//testing
volmin: -30,
}));
} }
function draw() { function draw() {
@ -335,279 +132,82 @@
if (ready) { if (ready) {
//update sounders //update sounders
scenes.wonjung_sounds.forEach(item => item.update_location()); sounds.forEach(async item => await item.update());
scenes.minok_sounds.forEach(item => item.update_location()); // radio.update();
//update radio //
radio.update_location(); let target = sounds[0];
radio.pv.pan.value = 0;
radio.pv.volume.rampTo(radio.gain, radio.ramptime);
////main group ////main group
//a tabular compass closet. //(push)
let compass_table;
//scene logic
if (scene == 0) {
// tutorial stage
scenes.wonjung_sounds.forEach(item => item.update_panvol());
//
compass_table = [];
Sounder.allStart(scenes.wonjung_sounds);
Sounder.allStop(scenes.minok_sounds);
// draw sth.
push(); push();
let sounder = scenes.wonjung_sounds[0];
let compass_target = new Compass(250, ['#003456', '#77AAAA', 'navy']); //compass (the North)
compass_target.pointer = sounder.angerr; translate(20, 20, 0);
translate((windowWidth - compass_target.size) / 2, (windowHeight - compass_target.size) / 2, 0); compass_target.heading = target.angerr; //target #0
compass_target.draw(); compass_target.draw();
fill('white');
Textline.restart(); //(pop)
Textline.put(sounder.name);
Textline.put(sounder.latitude.toFixed(4) + ', ' + sounder.longitude.toFixed(4));
Textline.put(sounder.angerr.toFixed(2) + ', ' + (sounder.dist * 1000).toFixed(2));
Textline.put(sounder.pv.pan.value.toFixed(2) + ', ' + sounder.distvol.toFixed(2) + ', ' + sounder.pv.volume.value.toFixed(2));
Textline.put(sounder.zone);
pop(); pop();
} else if (scene == 10) { //(push)
push();
//no sound
//N.B. assumption: change all locations to 'trigger' locations!
//minok scene
// approaching to the spot. **before** reaching the first trigger location.
compass_table = scenes.minok_sounds;
Sounder.allSilent(scenes.minok_sounds);
Sounder.allStart(scenes.minok_sounds);
Sounder.allStop(scenes.wonjung_sounds);
//
let next = scenes.minok_sounds[0];
if (next.dist < 0.05) {
//fade-in
// console.log(next.snd.state);
next.pv.pan.value = 0;
next.pv.volume.rampTo(next.gain, next.ramptime);
scene = 11;
sceneChanger();
}
} else if (scene == 11) {
//minok scene
//listening to track #1
compass_table = scenes.minok_sounds;
//
let current = scenes.minok_sounds[0];
current.pv.volume.rampTo(current.gain, current.ramptime);
let next = scenes.minok_sounds[1];
if (next.dist < 0.05) {
//N.B. assumption: change location to 'playstart' location!
//cross-fade
current.pv.volume.rampTo(-99, current.ramptime);
next.pv.volume.rampTo(next.gain, next.ramptime);
scene = 12;
sceneChanger();
}
} else if (scene == 12) {
//minok scene
//listening to track #2
compass_table = scenes.minok_sounds;
//
let current = scenes.minok_sounds[1];
current.pv.volume.rampTo(current.gain, current.ramptime);
let next = scenes.minok_sounds[2];
if (next.dist < 0.05) {
//N.B. assumption: change location to 'playstart' location!
//cross-fade
current.pv.volume.rampTo(-99, current.ramptime);
next.pv.volume.rampTo(next.gain, next.ramptime);
scene = 13;
sceneChanger();
}
} else if (scene == 13) {
//minok scene
//listening to track #3
compass_table = scenes.minok_sounds;
//
let current = scenes.minok_sounds[2];
current.pv.volume.rampTo(current.gain, current.ramptime);
let next = scenes.minok_sounds[3];
if (next.dist < 0.05) {
//N.B. assumption: change location to 'playstart' location!
//cross-fade
current.pv.volume.rampTo(-99, current.ramptime);
next.pv.volume.rampTo(next.gain, next.ramptime);
scene = 14;
sceneChanger();
}
} else if (scene == 14) {
//minok scene
//listening to track #4
compass_table = scenes.minok_sounds;
//
let current = scenes.minok_sounds[3];
current.pv.volume.rampTo(current.gain, current.ramptime);
let next = scenes.minok_sounds[4];
if (next.dist < 0.05) {
//N.B. assumption: change location to 'playstart' location!
//cross-fade
current.pv.volume.rampTo(-99, current.ramptime);
next.pv.volume.rampTo(next.gain, next.ramptime);
scene = 15;
sceneChanger();
}
} else if (scene == 15) {
//minok scene
//listening to track #5
compass_table = scenes.minok_sounds;
//
let current = scenes.minok_sounds[4];
current.pv.volume.rampTo(current.gain, current.ramptime);
let next = scenes.minok_sounds[5]; // <-- dummy location, no sound. ending waypoint.
if (next.dist < 0.05) {
//N.B. assumption: change location to 'playstart' location!
//fade-out
current.pv.volume.rampTo(-99, current.ramptime);
next.pv.volume.rampTo(-99, next.ramptime);
scene = 16;
sceneChanger();
}
} else if (scene == 16) {
//minok scene
//No-no zone.
compass_table = [];
Sounder.allStop(scenes.minok_sounds);
Sounder.allStop(scenes.minok_sounds);
} else if (scene == 20) {
//wonjung scene
compass_table = scenes.wonjung_sounds;
Sounder.allStart(scenes.wonjung_sounds);
Sounder.allStop(scenes.minok_sounds);
scenes.wonjung_sounds.forEach(item => item.update_panvol());
} else {
//everything else
// nothing to show/playback.
compass_table = [];
Sounder.allStop(scenes.wonjung_sounds);
Sounder.allStop(scenes.minok_sounds);
}
//
push(); // +1
translate(20, 90, 0);
//
let compass_offsets = [
createVector(0, 0),
createVector(0, 110),
createVector(0, 220),
createVector(0, 330),
createVector(150, 0),
createVector(150, 110),
createVector(150, 220),
createVector(150, 330),
];
for (const [i, sounder] of compass_table.entries()) {
push(); // +2
translate(compass_offsets[i].x, compass_offsets[i].y, 0);
//compass targeting the location
// let compass_target = new Compass(120, ['#33A1DE', '#97FFFF', 'navy']);
let compass_target = new Compass(120, ['#003456', '#77AAAA', 'navy']);
compass_target.pointer = sounder.angerr;
compass_target.draw();
//debug //debug
// translate(0, 120, 0);
translate(0, 0, 0);
fill('white'); fill('white');
translate(30, 200, 0);
Textline.restart(); Textline.restart();
Textline.put(sounder.name); Textline.put('heading');
Textline.put(sounder.latitude.toFixed(4) + ', ' + sounder.longitude.toFixed(4)); Textline.put(heading);
Textline.put(sounder.angerr.toFixed(2) + ', ' + (sounder.dist * 1000).toFixed(2)); Textline.put('ang');
Textline.put(sounder.pv.pan.value.toFixed(2) + ', ' + sounder.distvol.toFixed(2) + ', ' + sounder.pv.volume.value.toFixed(2)); Textline.put(target.ang);
Textline.put('angerr');
Textline.put(target.angerr);
Textline.put('distance');
Textline.put(target.dist);
// Textline.put('pan');
// Textline.put(target.pv.pan.value);
// Textline.put('distvol');
// Textline.put(target.distvol);
// Textline.put('vol');
// Textline.put(target.pv.volume.value);
Textline.put('target_lat');
Textline.put(target.latitude);
Textline.put('target_lon');
Textline.put(target.longitude);
pop(); // -2 //(pop)
} pop();
pop(); // -1
// ////radio
// push(); // +2
// translate(windowWidth - 120, windowHeight - 200, 0);
//
// //compass targeting the location
// // let compass_target = new Compass(120, ['#33A1DE', '#97FFFF', 'navy']);
// let compass_radio = new Compass(120, ['#003456', '#77AAAA', 'navy']);
// compass_radio.pointer = radio.angerr;
// compass_radio.draw();
//
// //debug
// // translate(0, 120, 0);
// translate(0, 0, 0);
// fill('white');
// Textline.restart();
// Textline.put(radio.name);
// Textline.put(radio.latitude.toFixed(4) + ', ' + radio.longitude.toFixed(4));
// Textline.put(radio.angerr.toFixed(2) + ', ' + (radio.dist * 1000).toFixed(2));
// Textline.put(radio.pv.pan.value.toFixed(2) + ', ' + radio.distvol.toFixed(2) + ', ' + radio.pv.volume.value.toFixed(2));
//
// pop(); // -2
////status-left group ////status-left group
push(); // +1 //(push)
push();
//
translate(20, windowHeight - 100, 0); translate(20, windowHeight - 100, 0);
fill('white'); fill('white');
Textline.restart(); Textline.restart();
Textline.put('current location'); Textline.put('current location');
Textline.put(latitude.toFixed(6) + ', ' + longitude.toFixed(6)); Textline.put(latitude);
Textline.put('scene'); Textline.put(longitude);
Textline.put(scene);
pop(); // -1 //(pop)
pop();
////status-right group ////status-right group
push(); // +1 //(push)
translate(windowWidth - 50, windowHeight - 100, 0); push();
let compass_north = new Compass(40, ['yellow', 'navy', 'white']);
compass_north.pointer = heading * -1; // the North pole azimuth is opposite of my heading. //
translate(windowWidth - 50, windowHeight - 50, 0);
compass_north.heading = heading;
compass_north.draw(); compass_north.draw();
translate(0, 40, 0);
fill('white'); //(pop)
Textline.restart(); pop();
Textline.put('N');
Textline.put(heading.toFixed(2));
pop(); // -1
} }
} }
</script> </script>

View file

@ -1,7 +1,6 @@
// sounds // sounds
class Sounder { class Sounder {
constructor(args) { constructor(args) {
this.name = args.name;
this.soundfile = args.soundfile; this.soundfile = args.soundfile;
this.gain = args.gain; // (dB) this.gain = args.gain; // (dB)
this.latitude = args.location[0]; this.latitude = args.location[0];
@ -10,30 +9,27 @@ class Sounder {
this.distmap = args.distmap; this.distmap = args.distmap;
this.volmin = args.volmin; // (dB) this.volmin = args.volmin; // (dB)
this.ramptime = args.ramptime; // (seconds) this.ramptime = args.ramptime; // (seconds)
this.zone = 0;
} }
async load() { async load() {
//start sound playback //start sound playback
this.pv = new Tone.PanVol(0, -99).toDestination(); this.pv = new Tone.PanVol(0, -99).toDestination();
this.snd = await AudioImport(this.soundfile); // NOTE: url with spaces didn't work here. this.snd = await AudioImport(this.soundfile); // NOTE: url with spaces didn't work here.
// this.snd.connect(this.pv).start();
this.snd.connect(this.pv); this.snd.connect(this.pv);
this.snd.start();
this.snd.loop = true; this.snd.loop = true;
} }
update_location() { update() {
this.ang = getBearing(latitude, longitude, this.latitude, this.longitude); // (deg)
this.angerr = ((this.ang - heading + 360) % 360 + 180) % 360 - 180;
this.dist = getDistance(latitude, longitude, this.latitude, this.longitude); // (km)
//
this.distvol = map(this.dist, this.distmap[0], this.distmap[1], this.distmap[2], this.distmap[3], true); //(dB)
}
update_panvol() {
// console.log('pv');
// //
//update sound pan/volume //update sound pan/volume
// //
// this.ang = getBearing(latitude, longitude, this.latitude, this.longitude); (deg)
this.ang = getBearing(latitude, longitude, this.latitude, this.longitude); // (deg)
this.angerr = (heading - this.ang + 360) % 360;
this.dist = getDistance(latitude, longitude, this.latitude, this.longitude); // (km)
//
this.distvol = map(this.dist, this.distmap[0], this.distmap[1], this.distmap[2], this.distmap[3], true); //(dB)
// (from Pure Data patch "iamyou", [eqpan2~]) // (from Pure Data patch "iamyou", [eqpan2~])
// arg #1 (inlet #3): width: // arg #1 (inlet #3): width:
@ -41,35 +37,22 @@ class Sounder {
// -width/2 ~ width/2 -> cross fading // -width/2 ~ width/2 -> cross fading
// +width/2 ~ width*(1.5) -> right fade-out // +width/2 ~ width*(1.5) -> right fade-out
//if close enough. don't do pan/vol, but just playback with full volume.
this.zone = 0;
if (this.dist < 0.07) {
this.zone = 1;
this.pv.pan.rampTo(0, this.ramptime);
this.pv.volume.rampTo(this.gain, this.ramptime); //(dB)
return;
}
let panleft_start = this.spread * (-1.5); let panleft_start = this.spread * (-1.5);
let panleft_end = this.spread * (-0.5); let panleft_end = this.spread * (-0.5);
let panright_start = this.spread * (0.5); let panright_start = this.spread * (0.5);
let panright_end = this.spread * (1.5); let panright_end = this.spread * (1.5);
//pan & volume
if (this.angerr > panleft_start && this.angerr < panleft_end) {
//left fade-in //left fade-in
if (this.angerr > panleft_start && this.angerr < panleft_end) {
this.pv.pan.value = -1; //left-full this.pv.pan.value = -1; //left-full
this.pv.volume.rampTo(this.distvol + this.gain + map(this.angerr, panleft_start, panleft_end, this.volmin, 0), this.ramptime); //(dB) this.pv.volume.rampTo(this.distvol + this.gain + map(this.angerr, panleft_start, panleft_end, this.volmin, 0), this.ramptime)//cross fading; //(dB)
} else if (this.angerr > panleft_end && this.angerr < panright_start) { } else if (this.angerr > panleft_end && this.angerr < panright_start) {
//cross fading; //(dB) this.pv.pan.value = map(this.angerr, panleft_end, panright_start, -1, 1); // crossfade
this.pv.pan.value = map(this.angerr, panleft_end, panright_start, -1, 1); this.pv.volume.rampTo(this.distvol + this.gain, this.ramptime)//right fade-out; //(dB)
this.pv.volume.rampTo(this.distvol + this.gain, this.ramptime); //(dB)
} else if (this.angerr > panright_start && this.angerr < panright_end) { } else if (this.angerr > panright_start && this.angerr < panright_end) {
//right fade-out
this.pv.pan.value = 1; //right-full this.pv.pan.value = 1; //right-full
this.pv.volume.rampTo(this.distvol + this.gain + map(this.angerr, panright_start, panright_end, 0, this.volmin), this.ramptime); //(dB) this.pv.volume.rampTo(this.distvol + this.gain + map(this.angerr, panright_start, panright_end, 0, this.volmin), this.ramptime)//slience; //(dB)
} else { } else {
//slience
this.pv.volume.rampTo(-99, 10); //(dB) this.pv.volume.rampTo(-99, 10); //(dB)
} }
} }
@ -77,33 +60,11 @@ class Sounder {
draw() { draw() {
//draw sound location //draw sound location
} }
static allStart(array) {
array.forEach(item => {
if (item.snd.state != 'started') item.snd.start();
});
}
static allStop(array) {
array.forEach(item => {
if (item.snd.state != 'stopped') item.snd.stop();
});
}
static allSilent(array) {
array.forEach(item => {
item.pv.volume.rampTo(-99, item.ramptime);
});
}
} }
// //
class RadioSounder extends Sounder { class RadioSounder extends Sounder {
constructor(args) {
super(args);
}
//do nothing //do nothing
async load() { async load() {
; ;
@ -112,21 +73,15 @@ class RadioSounder extends Sounder {
link(audiotag) { link(audiotag) {
//start sound playback //start sound playback
this.pv = new Tone.PanVol(0, -99).toDestination(); this.pv = new Tone.PanVol(0, -99).toDestination();
let stream = Tone.context.createMediaElementSource(audiotag);
//native webaudio this.snd = Tone.context.createGain();
this.source = Tone.context.createMediaElementSource(audiotag); stream.connect(this.snd);
this.snd = undefined; console.log(stream);
this.gainnode = Tone.context.createGain(); console.log(this.snd);
this.gainnode.gain.value = 1; // 1 == max. volume console.log(this.pv);
// this.snd.connect(this.pv.input.input); a hack ...
//a hacky native-to-Tonejs connection(?!) this.snd.gain.value = 1;
this.source.connect(this.gainnode).connect(this.pv.input.input); this.snd.connect(Tone.context.destination);
}
update() {
super.update();
// console.log('hi!');
} }
} }
@ -135,7 +90,7 @@ class Compass {
constructor(size, colors) { constructor(size, colors) {
this.size = size; this.size = size;
this.colors = colors; this.colors = colors;
this.pointer = 0; this.heading = 0;
} }
draw() { draw() {
@ -151,7 +106,7 @@ class Compass {
circle(0, 0, 0.9); circle(0, 0, 0.9);
// //
fill(this.colors[1]); fill(this.colors[1]);
rotate(this.pointer); rotate(this.heading * -1);
quad(0.1, 0.2, 0, -0.4, -0.1, 0.2, 0, 0.1); quad(0.1, 0.2, 0, -0.4, -0.1, 0.2, 0, 0.1);
// //
fill(this.colors[2]); fill(this.colors[2]);

View file

@ -86,9 +86,6 @@ function AudioImport(url) {
}); });
} }
//promisified 'setTimeout' from https://stackoverflow.com/a/74004853
const asyncTimeout = ms => new Promise(resolve => setTimeout(resolve, ms));
// some p5 tools // some p5 tools
class Textline { class Textline {
static #lines = 0; static #lines = 0;