How can I play multiple tracks simultaneously in SoundCloud JavaScript SDK 3.0.0? - soundcloud

How can I play multiple tracks simultaneously in JavaScript SDK 3.0.0 ?
SC.stream('/tracks/' + trackID1)
.then(function(player) {
player.play();
});
setTimeout(function() {
SC.stream('/tracks/' + trackID2)
.then(function(player) {
/*** track2 is played after stopping track1 ***/
player.play();
});
}, 5000);
I can do it in JavaScript SDK 2.0.0.
SC.stream('/tracks/' + trackID1, function(player) {
player.play();
});
setTimeout(function() {
SC.stream('/tracks/' + trackID2, function(player) {
/*** track2 is played without stopping track1 ***/
player.play();
});
}, 5000);

This is how:
var scplayers = [];
SC.stream("/tracks/"+sctrack.id, {autoLoad: true}).then(function(player){
player.options.debug = true;
player.options.useSinglePlayer = false;
//this sets a separate id for the same track so it gets handled as a
//separate track
player.options.soundId = 111; //ignore if the tracks are always different
scplayers[0] = player;
});
SC.stream("/tracks/"+sctrack.id, {autoLoad: true}).then(function(player){
player.options.debug = true;
player.options.useSinglePlayer = false;
//this sets a separate id for the same track so it gets handled as a
//separate track
player.options.soundId = 222; //ignore if the tracks are always different
scplayers[1] = player;
});
scplayers[0].play();
scplayers[1].play();
As an extra I added the soundId part. This allows you to play the same track multiple times with offset and what not.

Related

stop load items in pagination if items is refreshing

The main idea is downloading new item should not start if an update is currently in progress. So I created this code, and as I think, it should stop to load the new items if the refreshing is still processing.
void _onScroll() {
const isRefresh = true;
if (scrollController.position.pixels >=
scrollController.position.maxScrollExtent) {
if (isRefresh) {
_currentPlaceState.content([]);
}
_loadPlaces();
}
}
To perform what you want first thing make sure you take const isRefresh = true; out of the _onScroll function I personally use the upcoming flow
bool isRefresh = false;
_onscroll(){
if(isRefresh){
return;
}
isRefresh = true;
_loadPlaces().then(
(res){
isRefresh = false;
});
}

Subscribe and Unsubscribe Observable in ionic typescript

Using radio list where values are 5, 15, 20 and 30 mins. By default 15 mins are selected.
Now I need to constantly check function, when 5 seconds is selected.
when 15 seconds radio button is selected then unsubscribe observable of 5 second and start 15 second subsciber using Observable.
When app is in background I need to constantly check the above scenario which radio list value is selected and basis on value I need to start Observable.
I am using ionic framework (code below), When to subscribe and unsubscribe?
this.timerOneHourSubscription = Observable.interval(15000)
.subscribe((val) => {
}
Example below:
timerOneHourSubscription: Subscription;
constructor() {
this.showBadge();
}
}
/**
* This function allows to display badge on app icon
*/
showBadge() {
//by default one hour subscription
var refreshInterval =
localStore.getPersistedData(localApp.ISRADIOGROUP_KEY);
console.log('refreshInterval', refreshInterval);
this.timerOneHourSubscription = Observable.interval(refreshInterval)
.subscribe((val) => {
if (localStore.getPersistedData(localApp.ISRADIOGROUP_KEY) != null) {
if (localStore.getPersistedData(local.ISBADGE_ENABLED_KEY) != null) {
let badgeToggleEnable = local.getPersistedData(local.ISBADGE_ENABLED_KEY);
if (badgeToggleEnable) {
if (this.Items != null) {
if (localStore.getPersistedData(localApp.ITEMS_KEY) != null) {
this.Items = localStore.getPersistedData(localApp.ITEMS_KEY);
var count = 0;
for (let i = 0; i < this.Items.length; i++) {
var unRead= this.Items[i].unRead;
if (unRead) {
count++;
}
}
this.badge.set(unRead++);
}
}
}
else {
this.badge.clear();
}
}
}
});
}
You can use the following to clear your subscription and call a new subscription.
Observable.interval(15000).takeUntil(this.onDestroy$)
.subscribe(() => {
This will help you when you want to destroy the current subscription and start a new one.
To destroy the current one you can use below:-
this.onDestroy$.next();
You would have to declare the below at the top of you page:-
private onDestroy$ = new Subject<void>();
Instead of sending a static value in the Observable try sending a method and call the same method again and again.
I found my solution before selecting any radiobutton unsubscribe observable and start it again
unSubscribetimerhourSubscription() {
this.timerhourSubscription.unsubscribe();
}

Unity - Google cloud speech-to-text voice recognition, Unity freezes after successful result

A friend of mine and I are working on a VR project in Unity at the moment and we are trying to implement voice recognition as a feature. We are using Unity version 2018.3.3f1. The idea is that a user can say a word and the voice recognition will see if they pronounced it correctly. We have chosen to use the Google cloud speech-to-text service for this as it supports the target language (Norwegian). In addition, the application is also multiplayer and so we are trying to use the streaming version of Google cloud speech. Here is a link to their documentation: https://cloud.google.com/speech-to-text/docs/streaming-recognize
What we have done is to have a plugin that essentially runs the speech recognition for us. It is a modification of the example code given in the link above:
public Task<bool> StartSpeechRecognition()
{
return StreamingMicRecognizeAsync(20, "fantastisk");
}
static async Task<bool> StreamingMicRecognizeAsync(int inputTime, string inputWord)
{
bool speechSuccess = false;
Stopwatch timer = new Stopwatch();
Task delay = Task.Delay(TimeSpan.FromSeconds(1));
if (NAudio.Wave.WaveIn.DeviceCount < 1)
{
//Console.WriteLine("No microphone!");
return false;
}
var speech = SpeechClient.Create();
var streamingCall = speech.StreamingRecognize();
// Write the initial request with the config.
await streamingCall.WriteAsync(
new StreamingRecognizeRequest()
{
StreamingConfig = new StreamingRecognitionConfig()
{
Config = new RecognitionConfig()
{
Encoding =
RecognitionConfig.Types.AudioEncoding.Linear16,
SampleRateHertz = 16000,
LanguageCode = "nb",
},
InterimResults = true,
}
});
// Compare speech with the input word, finish if they are the same and speechSuccess becomes true.
Task compareSpeech = Task.Run(async () =>
{
while (await streamingCall.ResponseStream.MoveNext(
default(CancellationToken)))
{
foreach (var result in streamingCall.ResponseStream
.Current.Results)
{
foreach (var alternative in result.Alternatives)
{
if (alternative.Transcript.Replace(" ", String.Empty).Equals(inputWord, StringComparison.InvariantCultureIgnoreCase))
{
speechSuccess = true;
return;
}
}
}
}
});
// Read from the microphone and stream to API.
object writeLock = new object();
bool writeMore = true;
var waveIn = new NAudio.Wave.WaveInEvent();
waveIn.DeviceNumber = 0;
waveIn.WaveFormat = new NAudio.Wave.WaveFormat(16000, 1);
waveIn.DataAvailable +=
(object sender, NAudio.Wave.WaveInEventArgs args) =>
{
lock (writeLock)
{
if (!writeMore) return;
streamingCall.WriteAsync(
new StreamingRecognizeRequest()
{
AudioContent = Google.Protobuf.ByteString
.CopyFrom(args.Buffer, 0, args.BytesRecorded)
}).Wait();
}
};
waveIn.StartRecording();
timer.Start();
//Console.WriteLine("Speak now.");
//Delay continues as long as a match has not been found between speech and inputword or time that has passed since recording is lower than inputTime.
while (!speechSuccess && timer.Elapsed.TotalSeconds <= inputTime)
{
await delay;
}
// Stop recording and shut down.
waveIn.StopRecording();
timer.Stop();
lock (writeLock) writeMore = false;
await streamingCall.WriteCompleteAsync();
await compareSpeech;
//Console.WriteLine("Finished.");
return speechSuccess;
}
We made a small project in Unity to test if this was working with a cube GameObject that had this script:
private CancellationTokenSource tokenSource;
VR_VoiceRecognition.VoiceRecognition voice = new VR_VoiceRecognition.VoiceRecognition();
IDisposable speech;
// Use this for initialization
void Start() {
speech = Observable.FromCoroutine(WaitForSpeech).Subscribe();
}
// Update is called once per frame
void Update() {
}
IEnumerator WaitForSpeech()
{
tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
Debug.Log("Starting up");
Task<bool> t = Task.Run(() => voice.StartSpeechRecognition());
while (!(t.IsCompleted || t.IsCanceled))
{
yield return null;
}
if (t.Status != TaskStatus.RanToCompletion)
{
yield break;
}
else
{
bool result = t.Result;
UnityEngine.Debug.Log(t.Result);
yield return result;
}
}
void OnApplicationQuit()
{
print("Closing application.");
speech.Dispose();
}
We are also using a plugin that was recommended to us by Unity support that they thought might have a workaround called UniRx (https://assetstore.unity.com/packages/tools/integration/unirx-reactive-extensions-for-unity-17276).
At the moment it is working fine when you play it in the editor for the first time. When the voice recognition returns false then everything is fine (two cases when this happens is if it cannot find a microphone or if the user does not say the specific word). However, if it is a success then it still returns true, but if you exit play mode in the editor and try to play again then Unity will freeze. Unity support suspects that it might have something to do with the Google .dll files or Google API. We are not quite sure what to do from here and we hope that someone could point us to the right direction.

Unity3D UI button need multiple click to play or pause audio

Why does my play or pause button need multiple clicks to play or pause the audio? If the target is detected it will display a UI button and if clicked it will play a sound and when clicked again it will pause but I need multiple click to trigger the code.
any solutions? this is my code.
void playSound(string ss)
{
clipTarget = (AudioClip)Resources.Load(ss);
soundTarget.clip = clipTarget;
soundTarget.loop = false;
soundTarget.playOnAwake = false;
soundTarget.ignoreListenerPause = true;
}
if (name == "quezon")
{
if (Translate.GetComponent<Text>().text == "ENGLISH")
{
Narrator.gameObject.SetActive(true);
myGirl.gameObject.SetActive(false);
myBoy.enabled = false;
ButtonAction.GetComponent<Button().onClick.AddListener(delegate {
if (soundTarget.isPlaying)
{
soundTarget.Pause();
btn.image.overrideSprite = Play;
myBoy.enabled = false;
}
else if(!soundTarget.isPlaying)
{
soundTarget.Play();
playSound("sounds/English");
btn.image.overrideSprite = Pause;
myBoy.enabled = true;
}
});
TextDescription.GetComponent<Text>().text = "Manuel L. Quezon was born on August 19, 1878, and died on August 1, 1944. "
+ "He was a Filipino statesman, soldier, and politician who served as president of the Commonwealth of the "
+ "Philippines from 1935 to 1944.";
TextTargetName.GetComponent<Text>().text = name;
}
}
You have to define the button onClick behaviour only once. Like this:
void Awake ()
{
ButtonAction.GetComponent<Button>().onClick.AddListener (() => ToggleSound ());
}
private void ToggleSound ()
{
if (soundTarget.isPlaying)
{
soundTarget.Pause();
btn.image.overrideSprite = Play;
myBoy.enabled = false;
}
else
{
soundTarget.Play();
playSound("sounds/English");
btn.image.overrideSprite = Pause;
myBoy.enabled = true;
}
}
What I think is happening is since you are adding listeners everytime that routine happens it triggers first once, then twice, then thrice and so on.
Thats is the syntax I commonly use for adding behaviour to UI buttons, is easy, you can add parameters and looks clean. I recommend it.
Also if you dont have parameters you can do this and its easier.
ButtonAction.GetComponent<Button().onClick.AddListener (ToggleSound);

UI Thread issue with view model in MVVMCross

I am using MVVMCross with my cross-platform Windows Phone and Android app. In the core project's main view model, I am doing some background work using TPL and I want to make sure that in the callback, when I make changes to the properties of the view model which will trigger UI change, that the code is run on UI thread, how do I achieve this?
For code, here is how it likes
private MvxGeoLocation _currentLocation;
private Task<MvxGeoLocation> GetCurrentLocation()
{
return Task.Factory.StartNew(() =>
{
while (_currentLocation == null && !LocationRetrievalFailed)
{
}
return _currentLocation;
});
}
var location = await GetCurrentLocation();
if (LocationRetrievalFailed)
{
if (location == null)
{
ReverseGeocodingRequestFailed = true;
return;
}
// Show toast saying that we are using the last known location
}
Address = await GooglePlaceApiClient.ReverseGeocoding(location);
Did you try IMvxMainThreadDispatcher?
var dispatcher = Mvx.Resolve<IMvxMainThreadDispatcher>();
dispatcher.RequestMainThreadAction(()=> { .... });
See more on the implementation:
https://github.com/MvvmCross/MvvmCross/search?q=IMvxMainThreadDispatcher&type=Code
Usually I don't think you need this though.
Since you start the async processing from main thread, the async operations should return back to main thread.
Can you give an example of the async code you are doing?
Update on 24th August 2020:
As #claudio-redi has mentioned, ExecuteOnMainThreadAsync needs to be used. But Mvx.Resolve is now obsolete. So the latest snippet would be:
var mainThreadAsyncDispatcher = Mvx.IoCProvider.Resolve<IMvxMainThreadAsyncDispatcher>();
await mainThreadAsyncDispatcher.ExecuteOnMainThreadAsync( async ()=> { await SomeAsyncTask() });
Method RequestMainThreadAction is now obsolete. Today you have to do
var dispatcher = Mvx.Resolve<IMvxMainThreadAsyncDispatcher>();
await dispatcher.ExecuteOnMainThreadAsync(()=> { .... });