I have a flash mp3 player with a play, pause and next button on one frame.
The songs are stored in an array.Everything works fine except for the
pause button. It pauses the music and save the song position in a variable.
When i click on the pause button again the song is supposed to play
from the saved song position which it does. The problem is it also
play the first song in the array. Not the song that was paused. I have tried
to find a solution on Google. But the topics i could find where about mp3 players that only played one song.
Here is the code. Thanks.
var i:Number = 0;
var myMusic:Sound = new Sound();
var mySongs:Array = ["Kalimba.mp3","Sleep Away.mp3","Maid with the Flaxen Hair.mp3"];
var soundFile:URLRequest = new URLRequest(mySongs[i++]);
var channel:SoundChannel = new SoundChannel();
var sTransform:SoundTransform = new SoundTransform();
var songPosition:Number;
var myContext:SoundLoaderContext = new SoundLoaderContext(5000);
myMusic.load(soundFile, myContext);
btnPlay.addEventListener(MouseEvent.CLICK, playMusic);
btnNext.addEventListener(MouseEvent.CLICK, nextMusic);
btnPause.addEventListener(MouseEvent.CLICK, pauseMusic);
channel.addEventListener(Event.SOUND_COMPLETE, nextMusic);
function playMusic(evt:MouseEvent):void
{
channel = myMusic.play(songPosition);
channel.addEventListener(Event.SOUND_COMPLETE, nextMusic);
}
function nextMusic(evt:Event):void
{
channel.stop();
var myMusic:Sound = new Sound();
var mySongs:Array = ["Kalimba.mp3","Sleep Away.mp3","Maid with the Flaxen Hair.mp3"];
var soundFile:URLRequest = new URLRequest(mySongs[i]);
myMusic.load(soundFile, myContext);
channel = myMusic.play(i);
channel.addEventListener(Event.SOUND_COMPLETE, nextMusic);
if(i==mySongs.length-1) {
i=0;
}
else {
i++;
}
}
var Paused:Boolean = false;
function pauseMusic(evt:MouseEvent):void
{
if(Paused==false) {
songPosition = channel.position;
channel.stop();
Paused = true;
}
else if(Paused==true) {
channel = myMusic.play(songPosition);
Paused = false;
}
}
You shouldn't keep adding the channel.addEventListener(Event.SOUND_COMPLETE, nextMusic);
Beacuse SOUND_COMPLETE events get fired when you pause.
Adding this eventlistener just once should suffice anyway.
Related
I'm trying to play a set of audio files one after the other ( example Chime - Beep, Beep, Beep ), and this works quite well on localhost with no issues.
When I upload it to the server it has Promise Rejected issues, it seems to be that some of the sounds take too long to download and therefore don't get played before the timer moves on to the next sound.
playSoundPattern = (sounds, times, durations, index) => {
console.log("index = "+ index);
var sound = sounds[0];
var duration = durations[0];
if (index > times[0]) {
sound = sounds[1];
duration = durations[1];
}
console.log(sound);
console.log(this.player);
this.player.src = sound;
this.player.play();
var total = times[0] + times[1];
if (index < total) {
console.log("playing " + times);
setTimeout(this.playSoundPattern, duration, sounds, times, durations, index + 1);
}
}
Anyone have any ideas on how to solve the problem ?
If you don't have to many songs you can prepare all of them before and play when all are ready.
let songs = [];
[ "song_1", "song_2" ].forEach(function(filename) {
songs[filename] = new Audio();
songs[filename].src = "/path/to/songs/" + filename + ".";
songs[filename].addEventListener("load", function() {
songs[filename] = this;
});
});
Now inside songs there are only loaded songs.
I am using Recorder.js and MediaDevices to record audio. First few recordings are good but after some recordings (random as far as I can tell) the recorded audio is empty.
I can create the same issue if I Press Record and Stop in quick succession for some time.
Here is my code:
recordFunction=()=>{
// setup the recorder
var input;
var volume;
var AudioContext = window.AudioContext || window.webkitAudioContext;
this.audioContext = new AudioContext;
if(!this.state.isRecording){
this.setState({
isRecording:true
});
var constraints = {
audio: {
mandatory: {
googAutoGainControl: true,
googNoiseSuppression: false,
googHighpassFilter: false
}
},
video: false
}
// providing support for older Browsers
if(navigator.mediaDevices===null){
navigator.mediaDevices = {};
}
if(navigator.mediaDevices.getUserMedia===null){
navigator.mediaDevices.getUserMedia = (
navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia
)
}
navigator.mediaDevices.getUserMedia(constraints)
.then((stream)=> {
this.gumStream = stream;
input = this.audioContext.createMediaStreamSource(stream);
this.rec = new Recorder(input, {
numChannels: 1
})
this.rec.record();
}).catch((err) =>{
console.log("Error in recording: ",err);
});
}
else{
this.rec.stop();
this.gumStream.getAudioTracks()
.forEach( (track) => {
track.stop()
} );
this.gumStream.getVideoTracks().forEach((track)=> {
track.stop();
});
this.gumStream=null;
//create the wav blob and pass it on to createDownloadLink
this.rec.exportWAV(this.createDownloadLink);
}
}
recordFunction is called every time I press Record and Stop. Is my implementation incorrect?
If I wait for sometime (after an empty recording), say 5 sec the recorder starts working fine as before. I can't get my head around what I should try. I am fairly new to web development and sound recording.
Any suggestions would be appreciated.
In case someone has the same issue in the future.
The Problem was: I was creating a new AudioContext at each button Click. I tried running the App on a Phone where after pressing Record 6 times I got an error:
The number of hardware contexts provided (6) is greater than or equal
to the maximum bound (6)
I shifted these lines:
var AudioContext = window.AudioContext || window.
this.audioContext = new AudioContext;
Into Another file as:
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioContext = new AudioContext();
export default audioContext;
This Solved the Issue.
I am using the mp4Parser isoviewer-1.0-RC-35.jar to combine clips recorded with the android MediaRecorder. The clips seem to get combined correctly by listening to the audio tracks, but the video stays on one frame and the time code stays at zero on play back.
Media Recorder Code at time individual clips are created
mediaRecorder = new MediaRecorder();
myCamera.lock();
myCamera.unlock();
String clipLocation = file.getAbsolutePath();
_moviePaths.add(clipLocation);
// Please maintain sequence of following code.
// If you change sequence it will not work.
mediaRecorder.setCamera(myCamera);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
if (facingBack) {
mediaRecorder.setOrientationHint(90);
} else {
mediaRecorder.setOrientationHint(270);
}
// Log.v("cam","supported vid sizes: "+
// myCamera.getParameters().getSupportedVideoSizes());
CamcorderProfile profile = CamcorderProfile
.get(CamcorderProfile.QUALITY_720P);
// mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
//mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
// mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.setMaxDuration(g.kMaxVideoDurationInMiliseconds);// 15seconds
mediaRecorder.setProfile(profile);
mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
mediaRecorder.setOutputFile(path + filename);
mediaRecorder.prepare();
startTimer();
mediaRecorder.start();
}
Method i am using to combine the clips:
protected void combineClips() throws IOException{
for(int i=0; i<_moviePaths.size();i++){
Movie tm = MovieCreator.build(_moviePaths.get(i));
_clips.add(tm);
}
List<Track> videoTracks = new LinkedList<Track>();
List<Track> audioTracks = new LinkedList<Track>();
for (Movie m : _clips) {
for (Track t : m.getTracks()) {
if (t.getHandler().equals("soun")) {
audioTracks.add(t);
}
if (t.getHandler().equals("vide")) {
videoTracks.add(t);
}
}
}
Movie result = new Movie();
Log.v("cam", "adding:"+audioTracks.size()+" audio tracks and "+videoTracks.size()+" video tracks");
if (audioTracks.size() > 0) {
result.addTrack(new AppendTrack(audioTracks.toArray(new Track[audioTracks.size()])));
}
if (videoTracks.size() > 0) {
result.addTrack(new AppendTrack(videoTracks.toArray(new Track[videoTracks.size()])));
}
Container out = new DefaultMp4Builder().build(result);
FileChannel fc = new RandomAccessFile(String.format(videoFolder.getPath()+"/output.mp4"), "rw").getChannel();
out.writeContainer(fc);
fc.close();
}
Apparently the problem had something to do with the library: isoviewer-1.0-RC-35.jar. I replaced it with isoviewer-1.0-RC-27.jar and now everything is just dandy!
I have a set of movieclips setup as arrays in As3. I got the code to work were once a button is clicked a movieclip show on stage; but once the user clicks on another thumbnail the previous movieclip is still on stage. What I am trying to accomplish is I want the other arrays or movieclips to become hidden once the main array or clip that the user clicks becomes visible. I know I probably need a if loop for the arrays heres my code:
var soles:Array = [sle1,sle2,sle3,sle4];
var Slbtn_arr:Array = [sole,sole2,sole3,sole4];
for (var i= 0; i < Slbtn_arr.length; i++)
{
trace(i,Slbtn_arr[i]);
var temp_Slbtn = Slbtn_arr[i];
temp_Slbtn.addEventListener(MouseEvent.CLICK, btnCl);
temp_Slbtn.count = i;
soles[i].visible = false;
soles[0].visible = true;
}
function btnCl(e)
{
var num = e.target.count;
trace(e.target, e.target.count, soles[e.target.count]);
//hideAll()
soles[num].visible = true;
}
function hideAll()
{
for (var i= 0; i < soles.length; i++)
{
soles[i].visible = false;
}
}
Below is code that populates a menu. Everything seems to work great, with no errors thrown, except for one crucial part. My megaPages array has the values ["HOME","BABIES","BRIDALS","MISC","WEDDINGS","ABOUT"], but the actual text that displays on screen (which is produced by megaPages) is like this:
As you can see, some of the text is arbitrarily being truncated. I've traced the text strings as they get passed through the various functions at various stages of the menu-build, and they are always right, but somehow when each DisplayObject make it on screen, letters get ommitted (notice though that 'HOME' abd 'ABOUT' are fine). I don't even know where to start with this problem.
function buildMenu() {
var itemMCs = new Array();
for (var i = 0; i < megaPages.length; i++) {
megaPages[i] = megaPages[i].toUpperCase();
trace(megaPages[i]); // at each iteration, traces as follows "HOME","BABIES","BRIDALS","MISC","WEDDINGS","ABOUT"
var textMC = createText(megaPages[i]);
var itemMC = new MovieClip();
if (i!=0) {
var newLink = new PlateLink();
newLink.y = 0;
itemMC.addChild(newLink);
}
var newPlate = new Plate();
if (i==0) {
newPlate.y = 0;
} else {
newPlate.y = newLink.height - 2;
}
newPlate.x = 0;
newPlate.width = textMC.width + (plateMargin*2);
itemMC.addChild(newPlate);
if (i!=0) {
newLink.x = (newPlate.width/2) - (newLink.width/2);
}
textMC.x = plateMargin;
textMC.y = newPlate.y + .5;
itemMC.addChild(textMC);
itemMCs.push(itemMC);
itemMC.x = (homeplateref.x + (homeplateref.width/2)) - (itemMC.width/2);
if (i==0) {
itemMC.y = homeplateref.y;
} else {
itemMC.y = itemMCs[i-1].y + (itemMCs[i-1].height - 6);
}
menuRef.addChild(itemMC);
}
}
function createText(menuTitle) {
trace(menuTitle);
var textContainer : MovieClip = new MovieClip();
var myFont = new Font1();
var backText = instantText(menuTitle, 0x000000);
backText.x = 1;
backText.y = 1;
var frontText = instantText(menuTitle, 0xFFFFFF);
frontText.x = 0;
frontText.y = 0;
textContainer.addChild(backText);
textContainer.addChild(frontText);
return textContainer;
}
function instantText(textContent, color) {
trace(textContent); // again, traces the right text each time it is fired
var myFont = new Font1();
var myFormat:TextFormat = new TextFormat();
myFormat.size = 18;
myFormat.align = TextFormatAlign.CENTER;
myFormat.font = myFont.fontName;
var myText:TextField = new TextField();
myText.defaultTextFormat = myFormat;
myText.embedFonts = true;
myText.antiAliasType = AntiAliasType.ADVANCED;
myText.text = textContent;
myText.textColor = color;
myText.autoSize = TextFieldAutoSize.LEFT;
trace(myText.text);
return myText;
}
You need to embed all the necessary characters for the font you're using.
For textfields created in Flash:
Select the TextField, and hit the 'Embed' button in the properties panel.
For dynamically created textfields:
When you set the font to export (Font1 in your case) make sure to include all the characters you need.
You can choose to embed all uppercase characters, or just type in the ones you need for those specific menu items.