1

I have an html5 application that I have been working on. In the app, I want the j5 audio library to run AFTER the user has uploaded a file from their computer (because I want to use it to visualize the amplitudes on a canvas). However, I am confused about how I would go about solving this problem.

I need to import the item prior to preload, but the upload occurs only after the user has clicked the upload button. How can I understand this asynchronous problem?

var test, song, path, audio;
    function preload(){
      song = loadSound();
    }
    
    function setup(){
      createCanvas(200, 200);
    }
    
    function draw(){
      background(0);
    }
    
    document.querySelector('input[type="file"]').addEventListener('input', (e) => {
      if (e.target.files.length) {
        path = URL.createObjectURL(e.target.files[0])
        audio = new Audio(path);
        
        //HERE is where setup, etc show occur.
        //Create Canvas, etcetc
      }
    });
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width">
        <title>Mju</title>
        
        <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.min.js"></script>
        <script language="javascript" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/addons/p5.dom.js"></script>
        <script language="javascript" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/addons/p5.sound.js"></script>
    
        <link href="style.css" rel="stylesheet" type="text/css" />
      </head>
    
      <body>
        <h3>Upload Song:  <input onclick="this.style.display='none';" id="song" type="file" accept="audio/*"></h3>
      </body>

General structure of code: Take file from input -> preprocess the song so it is playable prior to the canvas loading. To run the code yourself: https://repl.it/@JacksonEnnis/Mju

Note

Interestingly enough, a previous attempt at the project I am doing has allowed me to succeed in doing this. But I cannot figure out how these two projects are different in a significant way: https://repl.it/@JacksonEnnis/MusicJournal

halfer
  • 19,824
  • 17
  • 99
  • 186
Jackson Ennis
  • 315
  • 2
  • 10
  • 2
    Have you used [`successCallback`](https://p5js.org/reference/#/p5.SoundFile) in `loadSound()`? – zero298 Jul 19 '19 at 14:57
  • I've tried "song = loadSound(path, console.log("OOF, Didn't load in time"), preload());" to ensure preloading before, but that sticks me with no shown errors, but stuck in loading... purgatory – Jackson Ennis Jul 19 '19 at 15:18

2 Answers2

2

Leverage async/await and promisify the callback API of p5.SoundFile().

const form = document.getElementById("audio-form");
const input = document.getElementById("audio-file");

form.addEventListener("submit", async e => {
  e.preventDefault();

  // Make ObjectURL
  const path = URL.createObjectURL(input.files[0]);

  // Promisify the callback function
  const sound = await new Promise((resolve, reject) => {
    new p5.SoundFile(path, s => resolve(s), err => reject(err));
  });

  // Do stuff with sound
  console.log(sound);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/addons/p5.sound.js"></script>

<form id="audio-form">
  <input type="file" id="audio-file" />
  <br />
  <button type="submit">Load audio</button>
</form>
zero298
  • 25,467
  • 10
  • 75
  • 100
0

You can use ajax and FormData to submit your file and jquery with the .change() method to start the upload when the user has selected the file, then if the upload success, you can setup your audio library.

Oshione
  • 88
  • 13