1

I'm working on an audio installation involving PiFM (https://github.com/oatmeal3000/pi2fm) that I want to play random audio files from a large selection of .wavs. My plan is to randomly select an audio file from this selection and then pass it to a function that will

A. Play it

B. Determine its length so that next random selection will play after the first one finishes..and so on (I expect maybe having 5 - 6 .wavs play after each other.

The below code does not include a random function as I am still figuring out the duration + setInterval. I am testing with just two audio files for now;

//this global variable
//allows me to assign
//length of audio1 track
//and use it in audioPlay();
var audio1Duration; 


//A function that plays audio 1 over pifm and also gets its length using SOX
function audio1(){


// gets child_process.exec for this function
var exec = require("child_process").exec

//plays pi2fm
exec("sudo -E /home/pi/Path/To audio1wav 103.50");

// gets audio duration via soxi command
exec("soxi -D /home/pi/Path/To audio1.wav", function(err, stdout){
    if (err){
         throw err;
}
//Globla Var is assigned value of stdout * 1000
audio1Duration = stdout * 1000; //converts seconds into milliseonds for SetTimeout 
console.log("This is audioDuration:" + audio1Duration);
});



}

function audio2(){
// gets child_process.exec for this function
var exec = require("child_process").exec

//plays pi2fm
exec("sudo -E /home/home/pi/Path/To audio2.wav 108.50");

// gets audio duration via soxi command
exec("soxi -D /home/pi/Path/audio.wav", function(err, stdout){
    if (err){
         throw err;
}

});

}

If I call either of the above functions on their own they will play no problem.

audio1();

or

audio2();

However when I try and trigger them using SetTimeout to play one after the other, they will either play at the same time or start when before they are meant to.

// this function should play audio1 first
//and then play audio2 based after 'audio1Duration' amount of milliseconds'
function audioPlay(){

audio1();
setTimeout(audio2, audioDuration);
}
audioPlay();

Any suggestions greatly appreciated

  • What's your code for playing audio? Are you using a library from npm? It might be the case that the audio library offers a callback when the audio is complete, rather than you needing to set a timeout of the same length. – Aurora0001 Jan 25 '18 at 20:01
  • @Aurora0001 I just updated my OP – heroZero Jan 26 '18 at 10:39
  • If you run pi2fm from the terminal, does it run synchronously until the broadcast ends (i.e. the program runs until the broadcast is complete)? If so, you might be able to use that to your advantage instead. – Aurora0001 Jan 26 '18 at 14:43
  • @Aurora0001 yes it does, can you elaborate please? – heroZero Jan 28 '18 at 17:05
  • @Aurora0001 just edited OP – heroZero Jan 31 '18 at 18:04
0

Since you said pi2fm runs synchronously, you should be able to use execSync() instead of exec(). exec() runs scripts asynchronously, which effectively means that the script launches in the background rather than your Node.js program waiting for the script to finish before moving on to the next one.

If you try something like this:

var child_process = require("child_process")
child_process.execSync("sudo -E /home/pi/Desktop/pi2fm/node/pi2fm audio1.wav 103.50")
child_process.execSync("sudo -E /home/pi/Desktop/pi2fm/node/pi2fm audio2.wav 103.50")

You should, hopefully, have the second audio file running after the first one is done. This relies on pi2fm exiting when it finishes broadcasting, and not earlier – if it does exit after broadcasting is finished, you can simply tell Node to wait for it to exit, and then you'll know that the file has definitely finished broadcasting.

Give the above code a test, and if it does work as expected, it should give you the building blocks to make the code work as you expect.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.