Saya mencoba memutar urutan daftar array audio tetapi ada beberapa kondisi. Pengguna akan memilih dropdown untuk pertanyaan acak dan durasi antara setiap pertanyaan pada awalnya. Dan klik tombol putar untuk menjalankan.

Saat playIndex meningkat menjadi 3, durasinya mulai bergantung pada dropdown pengguna. Tapi itu memberi saya tidak terdefinisi sekarang. Tapi itu berfungsi saat playIndex = 4. Mengapa ini?

Ketika playIndex meningkat menjadi 8 (setelah memainkan elemen ke-7) dan jumlah pertanyaan acak lebih besar dari 4, itu akan memanggil fungsi acak untuk menghasilkan nilai acak (angka 4 hingga 7) untuk playIndex dan bermain. Tetapi kode saya hanya melakukan ini sekali. Kenapa ini??

Saya perlu melakukan sebanyak yang diinginkan pengguna (dropdown 'numFollowUp') dan minus 4 karena pada putaran pertama, kode diputar dari elemen 0 hingga 7, yang tidak perlu saya hitung 4 kali pertama (elemen 4 ke 7).

Setelah memainkan semua pertanyaan acak, playIndex seharusnya

Tolong beri tahu saya jika saya membingungkan Anda. Terima kasih banyak atas bantuan Anda.

<select id="numFollowUp" name="numFollowUp" style=display:none>
            <option value="">Number of follow-up questions</option>
            <option value="4">4</option>
            <option value="5">5</option>
            <option value="6">6</option>
            <option value="7">7</option>
            <option value="8">8</option>
            <option value="9">9</option>
</select>
<select id="secFollowUp" name="secFollowUp" style=display:none>
            <option value="">Second between each question</option>
            <option value="10">10</option>
            <option value="11">11</option>
            <option value="12">12</option>
            <option value="13">13</option>
            <option value="14">14</option>
</select>

$("#ImageEnterVariables").on("click", function() {
        $('#ImageEnterVariables').hide();
        $("#numFollowUp").show();
        $("#secFollowUp").show();
        $("#subBut").show();
        $("#pause").hide();
    });

var intro_playList = [{
          "duration": 11,        // in seconds, real file duration
          "key": "1_hello",     
          "delayAfter": 6,    // in seconds, delay after file ended
          "stage": "intro",
          "runThrough": true,
          "random": false
        }, {
          "duration": 4,
          "key": "2_how_old",
          "delayAfter": 6,
          "stage": "intro",
          "runThrough": true,
          "random": false
        }, {
          "duration": 3,
          "key": "3_what_did_you_make",
          "delayAfter": 10,
          "stage": "intro",
          "runThrough": true,
          "random": false
        }, {
          // story_playlist
          "duration": 5,
          "key": "4_tell_me_a_story",
          "stage": "story",
          "runThrough": true,
          "random": false
        }, {
          "duration": 4,
          "key": "5_and_then_what",
          "stage": "story",
          "runThrough": true,
          "random": true
        }, {
          "duration": 2,
          "key": "6_why",
          "stage": "story",
          "runThrough": true,
          "random": true
        }, {
          "duration": 3,
          "key": "7_tell_me_more",
          "stage": "story",
          "runThrough": true,
          "random": true
        }, {
          "duration": 3,
          "key": "8_what_happened_next",
          "stage": "story",
          "runThrough": true,
          "random": true
        }, {
          "duration": 4,
          "key": "9_how_does_it_end",
          "stage": "ending",
          "runThrough": false,
          "random": false
        }, {
          "duration": 4,
          "key": "10_what_is_the_story_name",
          "stage": "ending",
          "runThrough": false,
          "random": false
        }, {
          "duration": 6,
          "key": "11_thank_you_goodbye",
          "stage": "ending",
          "runThrough": false,
          "random": false
        }];



$(document).ready(function() {
// Version 1
        var audioElement = document.createElement('audio');
        audioElement.addEventListener("ended", playAudio);

        var audioSrc = "sound/"
        var audioType = ".wav";
        var defaultNumFollowUp = 1; // default number of random question, if user this used the dropdown
        var defaultSecFollowUp = 10; // default delay (seconds) between random questions, if user this used the dropdown

        // Analyse the scenario by getting indexes in different arrays.
        var endingArr = [];
        var runThroughArr = [];
        var randomArr = [];

        for(i = 0; i < intro_playList.length ; i++){

            if(intro_playList[i].stage === "ending"){ endingArr.push(i); }
            if(intro_playList[i].runThrough){ runThroughArr.push(i); }
            if(intro_playList[i].random){ randomArr.push(i); }
        }

        function getAudio(n){
            audioElement.src = audioSrc + intro_playList[n].key + audioType;
            audioElement.load();
            audioElement.play();

            return intro_playList[n]; // return the object
        }

        // Onload indexes.
        var playIndex = 0;
        var randomplayCount = 0;
        var endingCount = 0;

        // Interval variables
        var playInterval;
        var time = new Date().getTime();
        console.log(time + " is old time");

        // User inputs
        var numFollowUp = parseInt($("#numFollowUp").val());
        if(isNaN(numFollowUp)){ numFollowUp = defaultNumFollowUp; }

        var secFollowUp = parseInt($("#secFollowUp").val());
        if(isNaN(secFollowUp)){ secFollowUp = defaultSecFollowUp; }

$("#play").on("click", playAudio);

function playAudio(){

            playInterval = setInterval(function(){ // Every 0.1 second, do setInterval
                var now = new Date().getTime();
                //console.log(now + " now time");

                if(now > time){
                    // First "run throught" plays all the audios in order, except the "ending" ones.
                    // playIndex = 0 in the first place
                    if(playIndex < runThroughArr.length){
                        var audioIndex = playIndex;
                        console.log("================================== RUN THROUGH!");
                        console.log("audioIndex is " + audioIndex);

                        playIndex++;

                    }else if (playIndex >= runThroughArr.length && randomplayCount <= numFollowUp){
                        var audioIndex = randomArr[ Math.floor(Math.random()*(randomArr.length - 1)) ];

                        console.log("================================== RUN random!");

                        // Increment index for next iteration
                        randomplayCount++;
                        console.log(randomplayCount);

                    }else if (randomplayCount >= defaultNumFollowUp && endingCount < endingArr.length ){
                        var audioIndex = endingArr[endingCount];

                        console.log("================================== RUN ending!");

                        // Increment index for next iteration
                        endingCount++;
                    }

                    // STOP INTERVAL!
                    if( endingCount === endingArr.length ){
                        clearInterval(playInterval);
                        console.log("=========== Interval stopped.");

                        // Reset onload indexes.
                        playIndex = 0;
                        randomplayCount = 0;
                        endingCount = 0;
                    }

                    // Prepare the audio file.
                    var audioObj = getAudio(audioIndex);

                    if(audioObj.stage === "intro"){
                    // set a new trigger time
                        time = new Date().getTime() + (audioObj.duration * 1000) + (audioObj.delayAfter * 1000);
                        console.log(time + " is time");

                    }else{

                        time = new Date().getTime() + (audioObj.duration * 1000) + (secFollowUp * 1000);
                    }

                    // Show what is actually playing
                    console.log("Playing "+ audioObj.key + " after " + audioObj.delayAfter + " seconds");
                    console.log("Stage: "+ audioObj.stage);

                } // if(now > time)

            }, 100); // playInterval, The interval duration of 0,1 second is to ensure accuracy if you set a duration or "delayAfter" using float seconds like 2.5.

        } // playAudio

        // Preload all audios to make sure they are available since timing is sometimes short.
        var preloadArr = [];

        for(i = 0; i < intro_playList.length; i++){

            var audioElementPreload = document.createElement('audio');
            audioElementPreload.src = audioSrc + intro_playList[i].key + audioType;
            audioElementPreload.load();
            preloadArr.push(audioElementPreload);
        }
});
1
Johnny 16 Agustus 2017, 06:20

2 jawaban

Jawaban Terbaik

Saya sepenuhnya menulis ulang kode Anda dari awal... Untuk kedua kalinya!
Saya pikir itu benar-benar proyek yang bagus... Dan tantangan pengkodean yang bagus.

Pada pelajaran kedua ini, saya melihat beberapa masalah dalam "konsep" penundaan pertama menggunakan setTimeout():

  1. Panjang audio lebih lama dari waktu tunda terpotong... Tidak menyisakan batas waktu di antara kedua file.
  2. Bahkan jika audio tidak lebih lama dari penundaan, penundaan ini sebagian "diserap" oleh panjang file.
  3. Mengubah "skenario", seperti dengan menambahkan lebih banyak pertanyaan acak, membutuhkan dua minggu dalam kode.
  4. "Akhir" yang akan dimainkan setelah "panggung" acak membutuhkan setTimeout() bersarang untuk setiap file akhir, yang mengerikan.

Jadi saya pikir menggunakan setInterval() untuk memeriksa "waktu aktual" dibandingkan dengan waktu yang ditetapkan skrip untuk memulai audio berikutnya (berdasarkan durasi file + penundaan) pada setiap iterasi... Akan menjadi ide.

Dan berhasil! Ini sangat menyederhanakan kode.
Dan semua info "skenario" sekarang ada di array objek.

pena kode

var audioSrc = "https://www.bessetteweb.com/SO/45704602/";    // Path to the audio files
var audioType = ".mp3";

var default_numFollowUp = 4;  // default number of random question, if user this used the dropdown
var default_secFollowUp = 10;  // default delai (seconds) between random questions, if user this used the dropdown

// Create the audio element
var audioElement = document.createElement('audio');

// Analyse the scenario by getting indexes in different arrays.
var endingArr = [];
var runThoughArr = [];
var randomArr = [];
for(i=0;i<intro_playList.length;i++){
  if(intro_playList[i].stage == "ending"){ endingArr.push(i); }
  if(intro_playList[i].runThough){ runThoughArr.push(i); }
  if(intro_playList[i].random){ randomArr.push(i); }
}

// Get an audio and play it
function getAudio(n){
  audioElement.src = audioSrc + intro_playList[n].key + audioType;
  audioElement.load();
  audioElement.play();
  console.log(JSON.stringify(intro_playList[n]));
  return intro_playList[n]; // return the object
}

// Onload indexes.
var playIndex = 0;
var randomplayCount = 0;
var endingCount = 0;

// Interval variables
var playInterval;
var time = new Date().getTime();


// Function to start the interval check to play a file
function playAudio(){

  // User inputs
  var numFollowUp = parseInt($("#numFollowUp").val() );
  if(isNaN(numFollowUp)){ numFollowUp = default_numFollowUp;}

  var secFollowUp = parseInt($("#secFollowUp").val() );
  if(isNaN(secFollowUp)){  secFollowUp = default_secFollowUp; }

  // Ensure no other interval runs...
  clearInterval(playInterval);

  // Set the interval.
  playInterval = setInterval(function(){

    var now = new Date().getTime();
    if(now > time){

      // First "run throught" plays all the audios in order, except the "ending" ones.
      if( playIndex < runThoughArr.length){
        var audioIndex = playIndex;
        console.log("==================================================================== RUN TROUGH!");

        // Increment index for next iteration
        playIndex++;
      }

      // Random!
      else if( playIndex >= runThoughArr.length && randomplayCount < numFollowUp ){
        //var audioIndex = getRandomIndex();
        var audioIndex = randomArr[ Math.floor(Math.random()*(randomArr.length-1)) ];
        console.log("==================================================================== RANDOM! ("+randomplayCount+"/"+numFollowUp+")");

        // Increment index for next iteration
        randomplayCount++;
      }

      // Ending
      else if( randomplayCount >= numFollowUp && endingCount < endingArr.length ){
        var audioIndex = endingArr[endingCount];
        console.log("==================================================================== ENDING!");

        // Increment index for next iteration
        endingCount++;
      }

      // STOP INTERVAL!
      if( endingCount == endingArr.length ){
        clearInterval(playInterval);
        console.log("=========== Interval stopped.");

        // Reset onload indexes.
        playIndex = 0;
        randomplayCount = 0;
        endingCount = 0;
      }

      // Prepare the audio file.
      var audioObj = getAudio(audioIndex);

      if(audioObj.stage == "intro"){
        // set a new trigger time
        time = new Date().getTime() + (audioObj.duration * 1000) + (audioObj.delayAfter * 1000);
      }else{
        time = new Date().getTime() + (audioObj.duration * 1000) + (secFollowUp * 1000);
      }
      // Show what is actually playing
      console.log("Playing "+ audioObj.key);
      console.log("Stage: "+ audioObj.stage);

    } // if(now > time)

  },100); // interval

} // playAudio()

// Preload all audios to make sure they are available since timing is sometimes short.
var preloadArr = [];
for(i=0;i<intro_playList.length;i++){
  var audioElementPreload = document.createElement('audio');
  audioElementPreload.src = audioSrc + intro_playList[i].key + audioType;
  audioElementPreload.load();
  preloadArr.push(audioElementPreload);
}

// Play button handler
$("#play").on("click", playAudio);
1
Louys Patrice Bessette 21 Agustus 2017, 19:30

Jika menafsirkan Pertanyaan dengan benar, Anda dapat menggunakan .queue() , .promise(), .then() dan penjadwalan berulang untuk melakukan tindakan pada larik penuh, while loop .splice() dan .splice() dengan Math.random() dan Math.floor() untuk mendapatkan elemen N dari larik asli sebagai larik baru, pilih elemen acak semu dari larik irisan, ulangi tugas asli, lalu ulangi tugas menggunakan larik asli untuk menyimpulkan prosedur.

var arr = [...Array(9).keys()],
  currentRandomTracks = [],
  notify = function notify(message) {
   $("body").append(message + "<br>")
  }
  
var player = $({});

function playTracks(tracks) {
  return player.queue("tracks", $.map(tracks, function(el, index) {
    return function(next) {
      return new Promise(function(resolve) {
        // do stuff 
        setTimeout(function() {
          resolve(el);
        }, Math.floor(Math.random() * 750))
      }).then(function(value) {
        notify(value);
        // call `next` when synchronous or asynchronous task completes
        return next()
      })
    }
  })).dequeue("tracks").promise("tracks")
}

function handleRandomQueue() {
    // select N elements from `arr`
    if (currentRandomTracks.length === 0) {
      currentRandomTracks = arr.slice(6);
      var randomTracks = [];
      // select random elements from `currentRandomTracks`
      while (currentRandomTracks.length) {
        randomTracks[randomTracks.length] = currentRandomTracks
          .splice(Math.floor(Math.random() * currentRandomTracks.length), 1)
          .pop();
      }
      notify("original playlist done playing, "
        + "starting playing random indexes " 
        + currentRandomTracks.toString() + " next"
      );
      return playTracks(randomTracks)
    } else {
      notify("random playback playlist complete, "
        + "stating playing original playlist " 
        + arr.toString()
      );
      // perform task on original array, again
      return playTracks(arr);
    }
  }
  
  function handleRepeatOriginalQueue() {
    notify("original and random playlist playback complete");
    return playTracks(arr);
  }
  
  function handleQueueComplete() {
    // procedure complete
    notify("original, random, "
      + "and second original playlist playback complete"
    );
  }

$(function() {

playTracks(arr)
  .then(handleRandomQueue)
  .then(handleRepeatOriginalQueue)
  .then(handleQueueComplete)
  .fail(function err(err) {
    console.error(err)
  })
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<body></body>
1
guest271314 16 Agustus 2017, 05:02