0

I am trying to mix multiple audios using jquery UI drag and drop. Means I will add tracks on the audio context dynamically which is dropped on a container. I am able to get track buffer after drop using XMLHttpRequest.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>jQuery UI Sortable - Connect lists</title>
  <style>
  body {
  font-family: Arial, Helvetica, sans-serif;
 }

 table {
  font-size: 1em;
 }

 .ui-draggable, .ui-droppable {
  background-position: top;
 }
  #sortable1, #sortable2 {
    border: 1px solid #eee;
    width: 142px;
    min-height: 20px;
    list-style-type: none;
    margin: 0;
    padding: 5px 0 0 0;
    float: left;
    margin-right: 10px;
  }
  #sortable1 li, #sortable2 li {
    margin: 0 5px 5px 5px;
    padding: 5px;
    font-size: 1.2em;
    width: 120px;
  }
  </style>
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  <script>
  
 var buffers = [];
  
 window.AudioContext = (window.AudioContext ||
        window.webkitAudioContext ||
        window.mozAudioContext ||
        window.oAudioContext ||
        window.msAudioContext);

    if (!AudioContext) alert('This site cannot be run in your Browser. Try a recent Chrome or Firefox. ');

    var audioContext = new AudioContext();
  
 $( function() {
  $( "#sortable1" ).droppable({
   helper: "clone",
   revert: "invalid",
   accept: ".ui-state-highlight",
   drop: function(e, ui){
    console.log(ui.draggable.data('url'));
    
   }
  }).disableSelection();


  $( "#sortable2").sortable({
   revert: true,
   connectWith: ".connectedSortable"
  }).disableSelection();

  
 function loadMusic(url) {
        var req = new XMLHttpRequest();
        req.open( "GET", url, true );
        req.responseType = "arraybuffer";
        req.onreadystatechange = function (e) {
            if (req.readyState == 4) {
                if(req.status == 200)
                    audioContext.decodeAudioData(req.response,
                        function(buffer) {
       var id = '_' + Math.random().toString(10).substr(2, 9)
                            buffers[id] = {
        buffer: buffer,
        start: 1, 
        to: 5       
       };
                        }, onDecodeError);
                else
                    alert('error during the load.Wrong url or cross origin issue');
            }
        };
        req.send();
    }
 
 // I have buffers array, how I can merge the dropped tracks by dynamic positions using start and end
  
  
 } );
 
  </script>
</head>
<body>
 
<ul id="sortable1" class="connectedSortable">
</ul>
 
<ul id="sortable2" class="connectedSortable">
  <li class="ui-state-highlight" data-url="https://twgljs.org/examples/sounds/DOCTOR%20VOX%20-%20Level%20Up.mp3">Song 1</li>
  <li class="ui-state-highlight" data-url="https://freesound.org/data/previews/449/449593_7037-lq.mp3">Song 1</li>
  <li class="ui-state-highlight" data-url="https://freesound.org/data/previews/449/449554_2454046-lq.mp3">Song 1</li>
</ul>
 
 
</body>
</html>

What I can do now to merge dropped tracks and play in real time? I am very new on javascript audio context.

Tareq Aziz
  • 341
  • 1
  • 10
  • 25

1 Answers1

-1

I would advise that the UI be more similar to this example:

https://jqueryui.com/droppable/#photo-manager

Yours may end up being more complex, yet this is a good example of how you can use Drag and Drop (DnD) features in a web app. Consider that users will need to perform certain tasks:

  • Move selections into a specific location
  • Adjust position of selections in that location
  • remove selections from location

Additionally, do you want them to slice an audio snippet? Make it smaller? Adjust other settings about the audio file?

Consider the following code.

var buffers = [];

window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.oAudioContext || window.msAudioContext;

if (!AudioContext) {
  alert('This site cannot be run in your Browser. Try a recent Chrome or Firefox.');
}

var audioCtx = new AudioContext();

$(function() {
  $("#output").sortable({
    revert: true,
    accept: ".clip",
    handle: ".handle",
    placeholder: "ui-state-highlight",
    receive: function(e, ui) {
      var clip = ui.item;
      console.log(clip.data("url"));
    },
    update: function(e, ui) {
      if (ui.item.find(".ui-icon-close").length < 1) {
        ui.item.append("<span class='ui-icon  ui-icon-grip-dotted-vertical handle left'></span>");
        ui.item.append("<span class='ui-icon ui-icon-close right'></span>");
        $("#output .ui-icon-close").click(function(e) {
          $(e.target).parent().remove();
        });
      }
    }
  }).disableSelection();

  $("#song-clips li").draggable({
    helper: "clone",
    revert: "invalid",
    connectToSortable: "#output"
  });

  /*
  function loadMusic(url, ac) {
    var req = $.ajax({
      cache: false,
      url: url,
      responseType: "arraybuffer",
      processData: false,
      success: function(response) {
        ac.decodeAudioData(response,
          function(buffer) {
            var id = '_' + Math.random().toString(10).substr(2, 9);
            buffers[id] = {
              buffer: buffer,
              start: 1,
              to: 5
            };
          }, onDecodeError);
      },
      error: function(xhr, error) {
        alert('Error during the load. ' + error);
      }
    });
  }
  */
});
body {
  font-family: Arial, Helvetica, sans-serif;
}

table {
  font-size: 1em;
}

.ui-draggable,
.ui-droppable {
  background-position: top;
}

.connectedSortable {
  width: 142px;
  min-height: 20px;
  list-style-type: none;
  margin: 0;
  padding: 5px 0 0 0;
}

.connectedSortable li {
  margin: 0 5px 5px 5px;
  padding: 5px;
  font-size: 1.2em;
  width: 120px;
}

.song-wrapper {
  width: 200px;
  margin-bottom: 3px;
}

.trash-wrapper {
  width: 200px;
  float: right;
}

#output {
  width: 100%;
  height: 48px;
  border: 1px solid #eee;
  padding: 5px 3px;
  overflow-x: scroll;
  white-space: nowrap;
}

#output li {
  min-height: 20px;
  margin: 0;
  padding: 5px;
  float: left;
  width: 120px;
}

#output .ui-icon-close:hover {
  background-color: #fff;
  border: 1px solid #999;
  border-radius: 3px;
}

#output .ui-icon-grip-dotted-vertical {
  cursor: move;
}

#output .handle {
  margin-top: 3px;
}

.left {
  float: left;
}

.right {
  float: right;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<div class="ui-helper-clearfix">
  <div class="ui-widget song-wrapper">
    <div class="ui-widget-header">Audio Clips</div>
    <div class="ui-widget-content">
      <ul id="song-clips" class="connectedSortable">
        <li class="ui-state-default clip" data-url="https://twgljs.org/examples/sounds/DOCTOR%20VOX%20-%20Level%20Up.mp3">Clip 1</li>
        <li class="ui-state-default clip" data-url="https://freesound.org/data/previews/449/449593_7037-lq.mp3">Clip 2</li>
        <li class="ui-state-default clip" data-url="https://freesound.org/data/previews/449/449554_2454046-lq.mp3">Clip 3</li>
      </ul>
    </div>
  </div>
</div>
<div class="ui-widget">
  <div class="ui-widget-header">Final Output</div>
  <div class="ui-widget-content">
    <ul id="output" class="connectedSortable">
    </ul>
  </div>
</div>
Twisty
  • 30,304
  • 2
  • 26
  • 45
  • Thanks for your ans bro. That helpful. But what about the merge dropped tracks and play in real time? – Tareq Aziz Dec 01 '18 at 05:52
  • @TareqAziz glad that helps. If it helps, upvote and mark it as the answer. How do you want it to play the tracks? Button click? Work on it and post another question if needed. – Twisty Dec 01 '18 at 06:03
  • I want to play a track by the button click. the answer is only about drag and drop I already know that bro. need play in real time is the main question after dropping multiple tracks. Like looplabs (https://looplabs.com) – Tareq Aziz Dec 01 '18 at 06:12
  • @TareqAziz I am not sure there is a good way to *mix* audio in the browser. Once the User has drAgged and dropped all the tracks, you can have a "Play" button that would trigger the play event via HTML5 ` – Twisty Dec 16 '19 at 18:59