<commit_before>elation.require(['janusweb.janusbase'], function() {
  var soundcache = {};

  elation.component.add('engine.things.janussound', function() {
    this.postinit = function() {
      elation.engine.things.janussound.extendclass.postinit.call(this);
      this.defineProperties({
        sound_id: { type: 'string', set: this.updateSound },
        singleshot: { type: 'boolean', default: false },
        loop: { type: 'boolean', default: false },
        auto_play: { type: 'boolean', default: false },
        play_once: { type: 'boolean', default: false },
        dist: { type: 'float', default: 1.0, set: this.updateSound },
        pitch: { type: 'float', default: 1.0, set: this.updateSound },
        gain: { type: 'float', default: 1.0, set: this.updateSound },
        starttime: { type: 'float', default: 0.0, set: this.updateSound },
        distanceModel: { type: 'string', set: this.updateSound },
        rolloff: { type: 'float', default: 1.0, set: this.updateSound },
        rect: { type: 'string', set: this.updateSound }
      });
      this.playing = false;
      //Object.defineProperty(this, 'playing', { get: function() { if (this.audio) return this.audio.isPlaying; return false; } });
      this.playStarted = false;
      this.playDelayed = false;
      elation.events.add(this.room, 'janusweb_script_frame', elation.bind(this, this.checkBounds));
    }
    this.createObject3D = function() {
      return new THREE.Object3D();
    }
    this.createChildren = function() {
      elation.engine.things.janussound.extendclass.createChildren.call(this);

      this.updateSound();
      if (this.auto_play) {
        this.play();
      }
    }
    this.createAudio = async function(src, audionodes) {
      var sound = this.getAsset('sound', this.sound_id);
      if (!src) {
        this.currentsound = this.sound_id;
        if (sound && sound.src) {
          src = sound.getProxiedURL(sound.src);
        }
      }
      if (this.audio) {
        if (this.audio.isPlaying) {
          this.audio.stop();
        }
        this.objects['3d'].remove(this.audio);
      }
      //let listener = this.listener = this.engine.systems.sound.getRealListener();
      return new Promise(async (resolve, reject) => {
        if (!audionodes) {
          audionodes = await this.room.getAudioNodes();
        }
        if (!this.hasposition) {
          this.audio = new THREE.Audio(audionodes.listener);
        } else {
          this.audio = new THREE.PositionalAudio(audionodes.listener);
          if (this.properties.distanceModel) {
            this.audio.panner.distanceModel = this.properties.distanceModel;
          }
          //this.audio.panner.maxDistance = this.properties.distance;
          if (this.dist) {
            this.audio.setRefDistance(this.dist);
          } else {
            //this.audio.panner.distanceModel = 'linear';
          }
          this.audio.panner.panningModel = 'HRTF';
        }
        if (audionodes.gain) {
          // Route object's audio through the room's gain element
          //this.audio.disconnect();
          this.audio.gain.disconnect(audionodes.listener.getInput());
          //this.audio.setFilters([this.audio.gain, audionodes.gain]);
          this.audio.gain.connect(audionodes.gain);
        }
        this.audio.autoplay = this.auto_play || this.singleshot || this.playStarted;
        this.audio.setLoop(this.loop);
        this.audio.setVolume(this.gain);
        this.audio.setPlaybackRate(this.pitch);
        this.audio.offset = this.starttime;
        //this.seek(this.starttime);
        this.audio.onEnded = elation.bind(this, this.updatePlaying);
        elation.events.add(this.audio.buffer, 'playing,pause,ended', elation.bind(this, this.updatePlaying));
        if (src) {
          if (soundcache[src]) {
            this.audio.setBuffer(soundcache[src]);
            if (this.auto_play || this.singleshot || this.playStarted) {
              this.play();
            }
          } else {
            var loader = new THREE.AudioLoader();
            loader.load(src, elation.bind(this, function(buffer) {
              if (buffer) {
                soundcache[src] = buffer;
                this.audio.setBuffer(buffer);
                if ((this.auto_play || this.singleshot || this.playStarted) && this.room == this.janus.currentroom) {
                  this.play();
                }
              }
            }));
          }
        } else if (sound && sound.buffer) {
          soundcache[src] = sound.buffer;
          this.audio.setBuffer(sound.buffer);
        }
        this.objects['3d'].add(this.audio);
        this.updateSound();
        resolve(this.audio);
      });
    }
    this.load = function(url) {
      this.src = url;
      if (this.audio.isPlaying) {
        this.audio.stop();
      }
      this.createAudio(url);
    }
    this.play = async function() {
      if (!this.engine.systems.sound.canPlaySound) {
        if (!this.playDelayed) {
          this.playDelayed = true;
          elation.events.add(this.engine.systems.sound, 'sound_enabled', (ev) => { this.play(); });
          this.dispatchEvent({type: 'sound_delayed'});
        }
      } else {
        this.playStarted = true;
        if (!this.audio) {
          await this.createAudio();
        }
        if (this.audio && this.audio.buffer) { //this.audio.source && this.audio.source.buffer) {
          this.audio.setVolume(this.gain);
          if (this.audio.isPlaying) {
            this.audio.source.currentTime = 0;
          } else {
            this.seek(this.starttime);
            this.audio.play();<commit_msg>Stop sound before restarting if already playing<commit_after>elation.require(['janusweb.janusbase'], function() {
  var soundcache = {};

  elation.component.add('engine.things.janussound', function() {
    this.postinit = function() {
      elation.engine.things.janussound.extendclass.postinit.call(this);
      this.defineProperties({
        sound_id: { type: 'string', set: this.updateSound },
        singleshot: { type: 'boolean', default: false },
        loop: { type: 'boolean', default: false },
        auto_play: { type: 'boolean', default: false },
        play_once: { type: 'boolean', default: false },
        dist: { type: 'float', default: 1.0, set: this.updateSound },
        pitch: { type: 'float', default: 1.0, set: this.updateSound },
        gain: { type: 'float', default: 1.0, set: this.updateSound },
        starttime: { type: 'float', default: 0.0, set: this.updateSound },
        distanceModel: { type: 'string', set: this.updateSound },
        rolloff: { type: 'float', default: 1.0, set: this.updateSound },
        rect: { type: 'string', set: this.updateSound }
      });
      this.playing = false;
      //Object.defineProperty(this, 'playing', { get: function() { if (this.audio) return this.audio.isPlaying; return false; } });
      this.playStarted = false;
      this.playDelayed = false;
      elation.events.add(this.room, 'janusweb_script_frame', elation.bind(this, this.checkBounds));
    }
    this.createObject3D = function() {
      return new THREE.Object3D();
    }
    this.createChildren = function() {
      elation.engine.things.janussound.extendclass.createChildren.call(this);

      this.updateSound();
      if (this.auto_play) {
        this.play();
      }
    }
    this.createAudio = async function(src, audionodes) {
      var sound = this.getAsset('sound', this.sound_id);
      if (!src) {
        this.currentsound = this.sound_id;
        if (sound && sound.src) {
          src = sound.getProxiedURL(sound.src);
        }
      }
      if (this.audio) {
        if (this.audio.isPlaying) {
          this.audio.stop();
        }
        this.objects['3d'].remove(this.audio);
      }
      //let listener = this.listener = this.engine.systems.sound.getRealListener();
      return new Promise(async (resolve, reject) => {
        if (!audionodes) {
          audionodes = await this.room.getAudioNodes();
        }
        if (!this.hasposition) {
          this.audio = new THREE.Audio(audionodes.listener);
        } else {
          this.audio = new THREE.PositionalAudio(audionodes.listener);
          if (this.properties.distanceModel) {
            this.audio.panner.distanceModel = this.properties.distanceModel;
          }
          //this.audio.panner.maxDistance = this.properties.distance;
          if (this.dist) {
            this.audio.setRefDistance(this.dist);
          } else {
            //this.audio.panner.distanceModel = 'linear';
          }
          this.audio.panner.panningModel = 'HRTF';
        }
        if (audionodes.gain) {
          // Route object's audio through the room's gain element
          //this.audio.disconnect();
          this.audio.gain.disconnect(audionodes.listener.getInput());
          //this.audio.setFilters([this.audio.gain, audionodes.gain]);
          this.audio.gain.connect(audionodes.gain);
        }
        this.audio.autoplay = this.auto_play || this.singleshot || this.playStarted;
        this.audio.setLoop(this.loop);
        this.audio.setVolume(this.gain);
        this.audio.setPlaybackRate(this.pitch);
        this.audio.offset = this.starttime;
        //this.seek(this.starttime);
        this.audio.onEnded = elation.bind(this, this.updatePlaying);
        elation.events.add(this.audio.buffer, 'playing,pause,ended', elation.bind(this, this.updatePlaying));
        if (src) {
          if (soundcache[src]) {
            this.audio.setBuffer(soundcache[src]);
            if (this.auto_play || this.singleshot || this.playStarted) {
              this.play();
            }
          } else {
            var loader = new THREE.AudioLoader();
            loader.load(src, elation.bind(this, function(buffer) {
              if (buffer) {
                soundcache[src] = buffer;
                this.audio.setBuffer(buffer);
                if ((this.auto_play || this.singleshot || this.playStarted) && this.room == this.janus.currentroom) {
                  this.play();
                }
              }
            }));
          }
        } else if (sound && sound.buffer) {
          soundcache[src] = sound.buffer;
          this.audio.setBuffer(sound.buffer);
        }
        this.objects['3d'].add(this.audio);
        this.updateSound();
        resolve(this.audio);
      });
    }
    this.load = function(url) {
      this.src = url;
      if (this.audio.isPlaying) {
        this.audio.stop();
      }
      this.createAudio(url);
    }
    this.play = async function() {
      if (!this.engine.systems.sound.canPlaySound) {
        if (!this.playDelayed) {
          this.playDelayed = true;
          elation.events.add(this.engine.systems.sound, 'sound_enabled', (ev) => { this.play(); });
          this.dispatchEvent({type: 'sound_delayed'});
        }
      } else {
        this.playStarted = true;
        if (!this.audio) {
          await this.createAudio();
        }
        if (this.audio && this.audio.buffer) { //this.audio.source && this.audio.source.buffer) {
          if (this.audio.source) {
            this.audio.stop();
          }
          this.audio.setVolume(this.gain);
          if (this.audio.isPlaying) {
            this.audio.source.currentTime = 0;
          } else {
            this.seek(this.starttime);
            this.audio.play();
{'fraction_non_alphanumeric': 0.14407524613220815, 'fraction_numerical': 0.0026371308016877636, 'mean_word_length': 2.08654367878459, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1727598', 'n_tokens_mistral': 3448, 'n_tokens_neox': 3385, 'n_words': 582}