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.
Related
I would like to use react-svgmt to manipulate SVG's. These SVG's can be uploaded from the users. My problem is, that if the SVG has a gradient these parts of the SVG are not shown.
Has anybody a solution for my problem to reactivate these links after the import of the SVG via react-svgmt?
With the developertools of my browser I was be able the see that the elements are in the code, but the grandients will be linked to the elements and these links are broken.
I have seen that other people has the same problem with gradients and created an issue on github, but the developer did not respond.
I found a solution for my problem.
react-svgmt add to elements like linearGradients "-{nr}" to its id-names. Then this fill:url(#linear-gradient-2); does not work anymore in the style-tags, because it must be fill:url(#linear-gradient-2-{nr});.
So the first SVGProxy after loading is <SvgProxy selector="linearGradient" onElementSelected={handleGradients} ></ SvgProxy>
an the function handleGradients looks like following and saves the {nr}
const handleGradients = (gradients) => { if (typeof gradients.length !== 'undefined') { const output = gradients.map((g, i) => { nr = g.id.substring(g.id.lastIndexOf("-")+1); setNr(g.id.substring(g.id.lastIndexOf("-")+1)); if(g.href.baseVal.length > 0) { var base = g.href.baseVal; g.href.baseVal = base + '-' + nr; } return g; }); } else { nr = gradients.id.substring(gradients.id.lastIndexOf("-")+1); setNr(gradients.id.substring(gradients.id.lastIndexOf("-")+1)); if(gradients.href.baseVal.length > 0) { var base = gradients.href.baseVal; gradients.href.baseVal = base + '-' + nr; } } };
Then I had another SVGProxy
<SvgProxy selector="defs > style" onElementSelected={handleStyleElem} ></ SvgProxy>
with the following handlefunction which replaces all urls with the schema from above
const handleStyleElem = (svgStyle) => { var styleStr = svgStyle.outerHTML; styleStr = styleStr.replaceAll(/url\(#((\w|-)*)\);/g, 'url(#$1-'+ nr +');'); svgStyle.outerHTML = styleStr; };
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've been trying to create a system that automatically sets the slowmode in a channel to a certain amount depending on how many messages have been sent. Lua is my primary language, and not Node.js, therefore I'm having quite a bit of trouble as to how I would go about this. If anyone had any suggestions, please let me know.
Two ways to go about it:
Use discord.js's <TextChannel>.setRateLimitPerUser(number)
https://discord.js.org/#/docs/main/stable/class/TextChannel?scrollTo=setRateLimitPerUser
Not sure if this actually does what you want though, the other option is creating a session storage of the text channels msgCount and compare it to time, i found setRateLimitPerUser in the middle of writing the code so didn't finish it, be here's a start:
const { Client, Collection } = require("discord.js");
const client = new Client();
client.slowdown = new Collection();
client.on("message", msg => {
const id = msg.channel.id;
const attempt = client.slowdown.get(id);
//4 messages at most per second
const ratio = 4;
//look at last how many seconds
const timeSpace = 5;
//TODO: check if channel already has cooldown
if (attempt) {
attempt.msgCount++;
const currentTime = Date.now();
const timePassed = (currentTime - attempt.time) / 1000;
if (attempt.msgCount >= ratio && attempt.msgCount / timePassed >= ratio) {
//setCoolDown
}
if (timePassed >= timeSpace) {
attempt.time = currentTime;
attempt.msgCount = 0;
}
} else {
client.slowdown.set(id, {
time: Date.now(),
msgCount: 1
});
}
});
As I know this is Simple Approch to save it in a Photo Library. But It can save with custom filename.
var someImage = UIImage.FromFile("someImage.jpg");
someImage.SaveToPhotosAlbum((image, error) => {
var o = image as UIImage;
Console.WriteLine("error:" + error);
})
But I want to save it with filename.jpg in the Photo Library.
I try so much code but nothing is getting help to me.
Code 1 :
var imageName = "/" + dicomId.ToString() + ".jpg";
var documentsDirectory = Environment.GetFolderPath
(Environment.SpecialFolder.Personal);
string jpgFilename = System.IO.Path.Combine(documentsDirectory, imageName); // hardcoded filename, overwritten each time
NSData imgData = dicomImage.AsJPEG();
NSError err = null;
if (imgData.Save(jpgFilename, false, out err))
{
Console.WriteLine("saved as " + jpgFilename);
}
else
{
Console.WriteLine("NOT saved as " + jpgFilename + " because" + err.LocalizedDescription);
}
This code part goes to if condition but it can not save the Image.
Code 2 :
If using this part of Code
var documentsDirectoryPath = NSSearchPath.GetDirectories(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User, true)[0];
It give you don't have permission to save image.
I try lots of thing on google and SO but nothing could help to me.
Edit :
info.plist
Any Help would be Appreciated.
How about using UIImage.SaveToPhotosAlbum()?
Usage is something like:
image.SaveToPhotosAlbum((uiImage, nsError) =>
{
if (nsError != null)
// do something about the error..
else
// image should be saved
});
Make sure that you have requested permissions before you try to save.
PHPhotoLibrary.RequestAuthorization(status =>
{
switch (status)
{
case PHAuthorizationStatus.Restricted:
case PHAuthorizationStatus.Denied:
// nope you don't have permission
break;
case PHAuthorizationStatus.Authorized:
// yep it is ok to save
break;
}
});
Edit: if you want more control, you need to use PHPhotosLibrary, which is an awful API...
var library = PHPhotoLibrary.SharedPhotoLibrary;
var albumName = "MyPhotos";
var fetchOptions = new PHFetchOptions();
fetchOptions.Predicate = NSPredicate.FromFormat($"title = {albumName}");
var assetsCollections = PHAssetCollection.FetchAssetCollections(
PHAssetCollectionType.Album, PHAssetCollectionSubtype.Any, fetchOptions);
var collection = assetsCollections.firstObject as PHAssetCollection;
library.PerformChanges(() => {
var options = new PHAssetResourceCreationOptions();
options.OriginalFilename = "filename.jpg";
var createRequest = PHAssetCreationRequest.CreationRequestForAsset();
createRequest.AddResource(PHAssetResourceType.FullSizePhoto, image.AsJPEG(1), options);
// if you want to save to specific album... otherwise just remove these three lines
var placeholder = createRequest.PlaceholderForCreatedAsset;
var albumChangeRequest = PHAssetCollectionChangeRequest.ChangeRequest(collection);
albumChangeRequest.AddAssets(new PHObject[] { placeholder });
},
(ok, error) => {
if (error != null)
{
// someone set up us the bomb
}
});
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.