163 lines
4.2 KiB
JavaScript
163 lines
4.2 KiB
JavaScript
// sounds
|
|
class Sounder {
|
|
constructor(args) {
|
|
this.name = args.name;
|
|
this.soundfile = args.soundfile;
|
|
this.gain = args.gain; // (dB)
|
|
this.latitude = args.location[0];
|
|
this.longitude = args.location[1];
|
|
this.spread = args.spread; // (deg)
|
|
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);
|
|
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 sound pan/volume
|
|
//
|
|
|
|
// (from Pure Data patch "iamyou", [eqpan2~])
|
|
// arg #1 (inlet #3): width:
|
|
// -width*(1.5) ~ -width/2 -> left fade-in
|
|
// -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
|
|
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)
|
|
} 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)
|
|
} 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)
|
|
} else {
|
|
//slience
|
|
this.pv.volume.rampTo(-99, 10); //(dB)
|
|
}
|
|
}
|
|
|
|
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() {
|
|
;
|
|
}
|
|
|
|
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!');
|
|
}
|
|
}
|
|
|
|
//p5
|
|
class Compass {
|
|
constructor(size, colors) {
|
|
this.size = size;
|
|
this.colors = colors;
|
|
this.pointer = 0;
|
|
}
|
|
|
|
draw() {
|
|
push();
|
|
//
|
|
scale(this.size);
|
|
//
|
|
translate(0.5, 0.5);
|
|
//
|
|
noStroke();
|
|
//
|
|
fill(this.colors[0]);
|
|
circle(0, 0, 0.9);
|
|
//
|
|
fill(this.colors[1]);
|
|
rotate(this.pointer);
|
|
quad(0.1, 0.2, 0, -0.4, -0.1, 0.2, 0, 0.1);
|
|
//
|
|
fill(this.colors[2]);
|
|
circle(0, 0, 0.05);
|
|
//
|
|
pop();
|
|
}
|
|
}
|