Compare commits

..

No commits in common. "rehersal_v1" 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,
body {
margin: 0;
padding: 0;
font-family: 'ACCchildrenfall';
}
canvas {
display: block;
}
.fullscreen {
.overlay-userinput {
display: grid;
justify-content: center;
align-items: center;
@ -25,55 +17,8 @@ canvas {
left: 0;
width: 100%;
height: 100%;
font-size: 3em;
}
#overlay-userinput {
/* display: none; */
background-color: rgba(255, 255, 255, 0.5);
color: white;
z-index: 2;
}
#announcements {
/* 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/Tone.min.js"></script>
<!-- css -->
<link type="text/css" rel="stylesheet" href="css/default.css">
<link type="text/css" rel="stylesheet" href="css/loading-animation.css" />
<!-- <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css"> -->
<link rel="stylesheet" href="css/default.css">
<!-- script -->
<script>
// const AudioContext = window.AudioContext || window.webkitAudioContext;
// let audioCtx;
const AudioContext = window.AudioContext || window.webkitAudioContext;
let audioCtx;
</script>
<script src="js/util.js"></script>
<script src="js/classes.js"></script>
</head>
<body>
<div id='overlay-userinput' class='fullscreen' onclick='initialize();'>
<div style='width:100%;'>
<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 class='overlay-userinput' onclick='initialize();'>
<div>터치하고-시작하기!</div>
</button>
<button id='scene-minok' onclick='scene=10;sceneChanger();'>
<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! -->
<audio controls crossorigin="anonymous" style="display:none;">
<!-- <source src="https://radio.dianaband.in:8000/stream" type="audio/aac" /> -->
</audio>
@ -62,6 +33,8 @@
let heading = 0;
let latitude = 37.574973;
let longitude = 126.925708;
// let latitude = 37.576774;
// let longitude = 126.931232;
// 맞는 결과 (예) : 작업실 -> 베지스
// p1 = [37.574973, 126.925708]
@ -75,15 +48,7 @@
let silence;
let clap;
let radio;
//scene
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
//all ready flag (not used)
let ready = false;
//clear all permissions
@ -94,237 +59,69 @@
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
// audioCtx = new AudioContext;
// audioCtx = Tone.getContext();
audioCtx = new AudioContext;
// some sounds for check-in
silence = (await AudioImport("./audio/_silence.wav")).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();
// clap.start();
// register sounders to the list
minok_sounds.push(new Sounder({
name: '주파수 구간',
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,
}));
// remove the veil
let veil = document.querySelector(".overlay-userinput");
veil.style.display = 'none';
wonjung_sounds.push(new Sounder({
name: '푸르지오 앞 데크길 밑 운동기구',
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');
// activate radio by adding source tag
const audiotag = document.querySelector('audio'); // N.B. assuming there's only 1 audio tag for streaming...
const sourcetag = document.createElement('source');
sourcetag.setAttribute('src', 'https://radio.dianaband.in:8000/stream');
sourcetag.setAttribute('type', 'audio/aac');
audiotag.appendChild(sourcetag);
audiotag.play();
//link a sounder object to radio streaming..
radio = new RadioSounder({
name: "베짜-📻",
location: [37.574973, 126.925708],
gain: 0,
spread: 90,
distmap: [0.01, 2, 0, -10], // (km) -> (dB)
//testing
volmin: -30,
});
radio.link(audiotag);
// audiotag.play(); // this doesn't work.. for some buggy iOS versions. another userinput needed..
// //link a sounder object to radio streaming..
// radio = new Sounder({
// // location: [37.576013, 126.927912],
// location: [37.574973, 126.935708],
// soundfile: "./audio/clap01.mp3",
// gain: 6,
// spread: 15,
// distmap: [0.005, 0.05, 0, -10],
// //testing
// volmin: -30,
// });
// // 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;
//
scene = 0;
sceneChanger();
}
async function sceneChanger() {
switch (scene) {
case 0:
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);
}
let compass_target;
let compass_north;
let sounds = [];
function setup() {
createCanvas(windowWidth, windowHeight);
compass_target = new Compass(200, ['#97FFFF', '#33A1DE', 'white']);
compass_north = new Compass(40, ['yellow', 'navy', 'white']);
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() {
@ -335,279 +132,82 @@
if (ready) {
//update sounders
scenes.wonjung_sounds.forEach(item => item.update_location());
scenes.minok_sounds.forEach(item => item.update_location());
sounds.forEach(async item => await item.update());
// radio.update();
//update radio
radio.update_location();
radio.pv.pan.value = 0;
radio.pv.volume.rampTo(radio.gain, radio.ramptime);
//
let target = sounds[0];
////main group
//a tabular compass closet.
let compass_table;
//(push)
push();
//scene logic
if (scene == 0) {
//compass (the North)
translate(20, 20, 0);
compass_target.heading = target.angerr; //target #0
compass_target.draw();
// tutorial stage
//(pop)
pop();
scenes.wonjung_sounds.forEach(item => item.update_panvol());
//
compass_table = [];
Sounder.allStart(scenes.wonjung_sounds);
Sounder.allStop(scenes.minok_sounds);
// draw sth.
push();
let sounder = scenes.wonjung_sounds[0];
let compass_target = new Compass(250, ['#003456', '#77AAAA', 'navy']);
compass_target.pointer = sounder.angerr;
translate((windowWidth - compass_target.size) / 2, (windowHeight - compass_target.size) / 2, 0);
compass_target.draw();
fill('white');
Textline.restart();
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();
//(push)
push();
//debug
fill('white');
translate(30, 200, 0);
Textline.restart();
Textline.put('heading');
Textline.put(heading);
Textline.put('ang');
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);
} else if (scene == 10) {
//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
// translate(0, 120, 0);
translate(0, 0, 0);
fill('white');
Textline.restart();
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));
pop(); // -2
}
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
//(pop)
pop();
////status-left group
push(); // +1
//(push)
push();
//
translate(20, windowHeight - 100, 0);
fill('white');
Textline.restart();
Textline.put('current location');
Textline.put(latitude.toFixed(6) + ', ' + longitude.toFixed(6));
Textline.put('scene');
Textline.put(scene);
pop(); // -1
Textline.put(latitude);
Textline.put(longitude);
//(pop)
pop();
////status-right group
push(); // +1
translate(windowWidth - 50, windowHeight - 100, 0);
let compass_north = new Compass(40, ['yellow', 'navy', 'white']);
compass_north.pointer = heading * -1; // the North pole azimuth is opposite of my heading.
//(push)
push();
//
translate(windowWidth - 50, windowHeight - 50, 0);
compass_north.heading = heading;
compass_north.draw();
translate(0, 40, 0);
fill('white');
Textline.restart();
Textline.put('N');
Textline.put(heading.toFixed(2));
pop(); // -1
//(pop)
pop();
}
}
</script>

View file

@ -1,7 +1,6 @@
// sounds
class Sounder {
constructor(args) {
this.name = args.name;
this.soundfile = args.soundfile;
this.gain = args.gain; // (dB)
this.latitude = args.location[0];
@ -10,30 +9,27 @@ class Sounder {
this.distmap = args.distmap;
this.volmin = args.volmin; // (dB)
this.ramptime = args.ramptime; // (seconds)
this.zone = 0;
}
async load() {
//start sound playback
this.pv = new Tone.PanVol(0, -99).toDestination();
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.start();
this.snd.loop = true;
}
update_location() {
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() {
//
//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~])
// arg #1 (inlet #3): width:
@ -41,35 +37,22 @@ class Sounder {
// -width/2 ~ width/2 -> cross fading
// +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_end = this.spread * (-0.5);
let panright_start = this.spread * (0.5);
let panright_end = this.spread * (1.5);
//pan & volume
//left fade-in
if (this.angerr > panleft_start && this.angerr < panleft_end) {
//left fade-in
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) {
//cross fading; //(dB)
this.pv.pan.value = map(this.angerr, panleft_end, panright_start, -1, 1);
this.pv.volume.rampTo(this.distvol + this.gain, this.ramptime); //(dB)
this.pv.pan.value = map(this.angerr, panleft_end, panright_start, -1, 1); // crossfade
this.pv.volume.rampTo(this.distvol + this.gain, this.ramptime)//right fade-out; //(dB)
} else if (this.angerr > panright_start && this.angerr < panright_end) {
//right fade-out
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 {
//slience
this.pv.volume.rampTo(-99, 10); //(dB)
}
}
@ -77,33 +60,11 @@ class Sounder {
draw() {
//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 {
constructor(args) {
super(args);
}
//do nothing
async load() {
;
@ -112,21 +73,15 @@ class RadioSounder extends Sounder {
link(audiotag) {
//start sound playback
this.pv = new Tone.PanVol(0, -99).toDestination();
//native webaudio
this.source = Tone.context.createMediaElementSource(audiotag);
this.snd = undefined;
this.gainnode = Tone.context.createGain();
this.gainnode.gain.value = 1; // 1 == max. volume
//a hacky native-to-Tonejs connection(?!)
this.source.connect(this.gainnode).connect(this.pv.input.input);
}
update() {
super.update();
// console.log('hi!');
let stream = Tone.context.createMediaElementSource(audiotag);
this.snd = Tone.context.createGain();
stream.connect(this.snd);
console.log(stream);
console.log(this.snd);
console.log(this.pv);
// this.snd.connect(this.pv.input.input); a hack ...
this.snd.gain.value = 1;
this.snd.connect(Tone.context.destination);
}
}
@ -135,7 +90,7 @@ class Compass {
constructor(size, colors) {
this.size = size;
this.colors = colors;
this.pointer = 0;
this.heading = 0;
}
draw() {
@ -151,7 +106,7 @@ class Compass {
circle(0, 0, 0.9);
//
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);
//
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
class Textline {
static #lines = 0;