Task ExecuteSafe(Func <Task> execution, OnError errorAction, string errorMessage) { var task = new TaskCompletionSource <bool>(); AudioThread.Post(async() => { try { await execution(); task.TrySetResult(true); } catch (Exception ex) { if (errorAction == OnError.Throw) { task.TrySetException(ex); } else { await errorAction.Apply(ex, "Failed to play audio file"); task.TrySetResult(false); } } }); return(task.Task); }
public void TestThreads() { var a = new AudioThread(); var latency = 10; var cpuUsage = 1.0f; var underRuns = 1; var output = a.Update(TestHelper.Silence(1), out latency, out cpuUsage, out underRuns, false); float[] buf = new float[256]; Thread.Sleep(200); Assert.IsNotNull(output); Assert.IsTrue(a.PlayBuffer.BufferedSamples > 0); output.Read(buf, 0, buf.Length); Assert.AreEqual(TestHelper.GenerateBuffer(new[] { 1.0f }, 256), buf); output = a.Update(null, out latency, out cpuUsage, out underRuns, false); Thread.Sleep(200); Assert.IsNotNull(output); Assert.IsTrue(a.PlayBuffer.BufferedSamples == 0); output.Read(buf, 0, buf.Length); Assert.AreEqual(TestHelper.GenerateBuffer(new[] { 0.0f }, 256), buf); var input = TestHelper.Silence(2); output = a.Update(input, out latency, out cpuUsage, out underRuns, true); Thread.Sleep(200); Assert.IsNull(output); Assert.IsTrue(a.PlayBuffer.BufferedSamples > 0); Assert.IsTrue(((LevelProcessor)input.Processor).ReadPos > 0); Thread.Sleep(200); a.Dispose(); }
/// <summary> /// Constructs an AudioManager given a track resource store, and a sample resource store. /// </summary> /// <param name="trackStore">The resource store containing all audio tracks to be used in the future.</param> /// <param name="sampleStore">The sample store containing all audio samples to be used in the future.</param> public AudioManager(ResourceStore <byte[]> trackStore, ResourceStore <byte[]> sampleStore) { AudioDevice.ValueChanged += onDeviceChanged; trackStore.AddExtension(@"mp3"); sampleStore.AddExtension(@"wav"); sampleStore.AddExtension(@"mp3"); Thread = new AudioThread(Update, @"Audio"); Thread.Start(); scheduler.Add(() => { globalTrackManager = GetTrackManager(trackStore); globalSampleManager = GetSampleManager(sampleStore); try { setAudioDevice(); } catch { } }); scheduler.AddDelayed(delegate { updateAvailableAudioDevices(); checkAudioDeviceChanged(); }, 1000, true); }
private void StartRadioPlayerNew() { if (waveOut != null) { waveOut.Stop(); } tokenSource.Cancel(); tokenSource.Dispose(); Console.WriteLine("AudioThread.Wait(); start"); AudioThread.Wait(); Console.WriteLine("AudioThread.Wait(); end"); AudioThread.Dispose(); bufferedWaveProvider = null; waveOut = null; tokenSource = new CancellationTokenSource(); AudioThread = new Task(() => { StreamMp3(tokenSource.Token); }, tokenSource.Token); AudioThread.Start(); }
/// <summary> /// This method calls <see cref="Bass.Init(int, int, DeviceInitFlags, IntPtr, IntPtr)"/>. /// It can be overridden for unit testing. /// </summary> protected virtual bool InitBass(int device) { if (Bass.CurrentDevice == device) { return(true); } // reduce latency to a known sane minimum. Bass.Configure(ManagedBass.Configuration.DeviceBufferLength, 10); Bass.Configure(ManagedBass.Configuration.PlaybackBufferLength, 100); // this likely doesn't help us but also doesn't seem to cause any issues or any cpu increase. Bass.Configure(ManagedBass.Configuration.UpdatePeriod, 5); // without this, if bass falls back to directsound legacy mode the audio playback offset will be way off. Bass.Configure(ManagedBass.Configuration.TruePlayPosition, 0); // Enable custom BASS_CONFIG_MP3_OLDGAPS flag for backwards compatibility. Bass.Configure((ManagedBass.Configuration) 68, 1); // For iOS devices, set the default audio policy to one that obeys the mute switch. Bass.Configure(ManagedBass.Configuration.IOSMixAudio, 5); // ensure there are no brief delays on audio operations (causing stream STALLs etc.) after periods of silence. Bass.Configure(ManagedBass.Configuration.DevNonStop, true); return(AudioThread.InitDevice(device)); }
/// <summary> /// This method calls <see cref="Bass.Init(int, int, DeviceInitFlags, IntPtr, IntPtr)"/>. /// It can be overridden for unit testing. /// </summary> protected virtual bool InitBass(int device) { if (Bass.CurrentDevice == device) { return(true); } // reduce latency to a known sane minimum. Bass.Configure(ManagedBass.Configuration.DeviceBufferLength, 10); Bass.Configure(ManagedBass.Configuration.PlaybackBufferLength, 100); // this likely doesn't help us but also doesn't seem to cause any issues or any cpu increase. Bass.Configure(ManagedBass.Configuration.UpdatePeriod, 5); // without this, if bass falls back to directsound legacy mode the audio playback offset will be way off. Bass.Configure(ManagedBass.Configuration.TruePlayPosition, 0); // Enable custom BASS_CONFIG_MP3_OLDGAPS flag for backwards compatibility. Bass.Configure((ManagedBass.Configuration) 68, 1); // For iOS devices, set the default audio policy to one that obeys the mute switch. Bass.Configure(ManagedBass.Configuration.IOSMixAudio, 5); // ensure there are no brief delays on audio operations (causing stream STALLs etc.) after periods of silence. Bass.Configure(ManagedBass.Configuration.DevNonStop, true); // Always provide a default device. This should be a no-op, but we have asserts for this behaviour. Bass.Configure(ManagedBass.Configuration.IncludeDefaultDevice, true); // Disable BASS_CONFIG_DEV_TIMEOUT flag to keep BASS audio output from pausing on device processing timeout. // See https://www.un4seen.com/forum/?topic=19601 for more information. Bass.Configure((ManagedBass.Configuration) 70, false); return(AudioThread.InitDevice(device)); }
/// <summary> /// Constructs an AudioManager given a track resource store, and a sample resource store. /// </summary> /// <param name="audioThread">The host's audio thread.</param> /// <param name="trackStore">The resource store containing all audio tracks to be used in the future.</param> /// <param name="sampleStore">The sample store containing all audio samples to be used in the future.</param> public AudioManager(AudioThread audioThread, ResourceStore <byte[]> trackStore, ResourceStore <byte[]> sampleStore) { Thread = audioThread; Thread.RegisterManager(this); AudioDevice.ValueChanged += onDeviceChanged; trackStore.AddExtension(@"mp3"); sampleStore.AddExtension(@"wav"); sampleStore.AddExtension(@"mp3"); globalTrackManager = new Lazy <TrackManager>(() => GetTrackManager(trackStore)); globalSampleManager = new Lazy <SampleManager>(() => GetSampleManager(sampleStore)); scheduler.Add(() => { try { setAudioDevice(); } catch { } }); scheduler.AddDelayed(delegate { updateAvailableAudioDevices(); checkAudioDeviceChanged(); }, 1000, true); }
public void Init() { AudioThread.PreloadBass(); // Initialize bass with no audio to make sure the test remains consistent even if there is no audio device. Bass.Configure(ManagedBass.Configuration.UpdatePeriod, 5); Bass.Init(0); }
public void SetUp() { thread = new AudioThread(); store = new NamespacedResourceStore <byte[]>(new DllResourceStore(new AssemblyName("osu.Framework")), @"Resources"); manager = new AudioManager(thread, store, store); thread.Start(); }
public override void Stop() { tok.Cancel(); VideoThread?.CloseSocket(); AudioThread?.CloseSocket(); VideoThread?.Join(); AudioThread?.Join(); base.Stop(); }
protected override void Dispose(bool Managed) { if (!Managed) { return; } VideoThread?.Dispose(); AudioThread?.Dispose(); base.Dispose(Managed); }
public virtual void SetUp() { thread = new AudioThread(); var store = new NamespacedResourceStore <byte[]>(new DllResourceStore(@"osu.Framework.Tests.dll"), @"Resources"); Manager = new AudioManagerWithDeviceLoss(thread, store, store); thread.Start(); }
/// <summary> /// Fires up the engine. And then it makes noise. /// </summary> public static void Start(EngineMode engineMode) { #if DEBUG IsDebug = true; #endif AppId = 480; Mode = engineMode; LogService.ConfigureLoggers(); Process = Process.GetCurrentProcess(); PlatformId = PlatformId.Windows; PlatformType = PlatformType.Desktop; TempPath = Path.Combine(Path.GetTempPath(), "dEngine"); if (Directory.Exists(TempPath)) { ContentProvider.DeleteDirectory(TempPath); } // otherwise DeleteDirectory won't get called when stop debugging in VS. Directory.CreateDirectory(TempPath); Logger.Info("Log opened."); Logger.Info($"Command line args: {string.Join(" ", Environment.GetCommandLineArgs().Skip(1))})"); Logger.Info($"Base directory: {Environment.CurrentDirectory}"); Logger.Info($"Engine mode: {engineMode}"); Logger.Info($"Graphics mode: {RenderSettings.GraphicsMode}"); Logger.Info($"User: {Environment.UserName} on {Environment.MachineName}"); Logger.Info($"CPU: {DebugSettings.CpuName} ({Environment.ProcessorCount} processors)"); Logger.Info($"Memory: {((long)new ComputerInfo().TotalPhysicalMemory).ToPrettySize()}"); CancelTokenSource = new CancellationTokenSource(); Inst.Init(); Logger.Info("Starting GraphicsThread..."); StartThread(nameof(GraphicsThread), GraphicsThread.Start); GraphicsThread.Wait(); Logger.Info("GraphicsThread started."); Logger.Info("Starting AudioThread..."); StartThread(nameof(AudioThread), AudioThread.Start); AudioThread.Wait(); Logger.Info("AudioThread started."); Logger.Info("Starting GameThread..."); StartThread(nameof(GameThread), GameThread.Start); GameThread.Wait(); Logger.Info("GameThread started."); AppDomain.CurrentDomain.ProcessExit += (s, e) => Shutdown(0); }
public void SetUp() { Architecture.SetIncludePath(); thread = new AudioThread(); store = new NamespacedResourceStore <byte[]>(new DllResourceStore(@"osu.Framework.dll"), @"Resources"); manager = new AudioManager(thread, store, store); thread.Start(); }
/// <summary> /// Constructs an AudioStore given a track resource store, and a sample resource store. /// </summary> /// <param name="audioThread">The host's audio thread.</param> /// <param name="trackStore">The resource store containing all audio tracks to be used in the future.</param> /// <param name="sampleStore">The sample store containing all audio samples to be used in the future.</param> public AudioManager(AudioThread audioThread, ResourceStore <byte[]> trackStore, ResourceStore <byte[]> sampleStore) { thread = audioThread; thread.RegisterManager(this); AudioDevice.ValueChanged += onDeviceChanged; globalTrackStore = new Lazy <TrackStore>(() => { var store = new TrackStore(trackStore, TrackMixer); AddItem(store); store.AddAdjustment(AdjustableProperty.Volume, VolumeTrack); return(store); }); globalSampleStore = new Lazy <SampleStore>(() => { var store = new SampleStore(sampleStore, SampleMixer); AddItem(store); store.AddAdjustment(AdjustableProperty.Volume, VolumeSample); return(store); }); AddItem(TrackMixer = createAudioMixer(null, nameof(TrackMixer))); AddItem(SampleMixer = createAudioMixer(null, nameof(SampleMixer))); CancellationToken token = cancelSource.Token; scheduler.Add(() => { // sync audioDevices every 1000ms new Thread(() => { while (!token.IsCancellationRequested) { try { syncAudioDevices(); Thread.Sleep(1000); } catch { } } }) { IsBackground = true }.Start(); }); }
/// <summary> /// Constructs an AudioStore given a track resource store, and a sample resource store. /// </summary> /// <param name="audioThread">The host's audio thread.</param> /// <param name="trackStore">The resource store containing all audio tracks to be used in the future.</param> /// <param name="sampleStore">The sample store containing all audio samples to be used in the future.</param> public AudioManager(AudioThread audioThread, ResourceStore <byte[]> trackStore, ResourceStore <byte[]> sampleStore) { Thread = audioThread; Thread.RegisterManager(this); AudioDevice.ValueChanged += onDeviceChanged; globalTrackStore = new Lazy <TrackStore>(() => { var store = new TrackStore(trackStore); AddItem(store); store.AddAdjustment(AdjustableProperty.Volume, VolumeTrack); return(store); }); globalSampleStore = new Lazy <SampleStore>(() => { var store = new SampleStore(sampleStore); AddItem(store); store.AddAdjustment(AdjustableProperty.Volume, VolumeSample); return(store); }); // check for device validity every 100ms scheduler.AddDelayed(() => { try { if (!IsCurrentDeviceValid()) { setAudioDevice(); } } catch { } }, 100, true); // enumerate new list of devices every second scheduler.AddDelayed(() => { try { setAudioDevice(AudioDevice.Value); } catch { } }, 1000, true); }
/// <summary> /// This method calls <see cref="Bass.Init(int, int, DeviceInitFlags, IntPtr, IntPtr)"/>. /// It can be overridden for unit testing. /// </summary> protected virtual bool InitBass(int device) { if (Bass.CurrentDevice == device) { return(true); } // reduce latency to a known sane minimum. Bass.Configure(ManagedBass.Configuration.DeviceBufferLength, 10); Bass.Configure(ManagedBass.Configuration.PlaybackBufferLength, 100); // this likely doesn't help us but also doesn't seem to cause any issues or any cpu increase. Bass.Configure(ManagedBass.Configuration.UpdatePeriod, 5); // without this, if bass falls back to directsound legacy mode the audio playback offset will be way off. Bass.Configure(ManagedBass.Configuration.TruePlayPosition, 0); // Enable custom BASS_CONFIG_MP3_OLDGAPS flag for backwards compatibility. Bass.Configure((ManagedBass.Configuration) 68, 1); // For iOS devices, set the default audio policy to one that obeys the mute switch. Bass.Configure(ManagedBass.Configuration.IOSMixAudio, 5); // ensure there are no brief delays on audio operations (causing stream STALLs etc.) after periods of silence. Bass.Configure(ManagedBass.Configuration.DevNonStop, true); var didInit = Bass.Init(device); // If the device was already initialised, the device can be used without much fuss. if (Bass.LastError == Errors.Already) { Bass.CurrentDevice = device; // Without this call, on windows, a device which is disconnected then reconnected will look initialised // but not work correctly in practice. AudioThread.FreeDevice(device); didInit = Bass.Init(device); } if (didInit) { thread.RegisterInitialisedDevice(device); } return(didInit); }
/// <summary> /// Constructs an AudioStore given a track resource store, and a sample resource store. /// </summary> /// <param name="audioThread">The host's audio thread.</param> /// <param name="trackStore">The resource store containing all audio tracks to be used in the future.</param> /// <param name="sampleStore">The sample store containing all audio samples to be used in the future.</param> public AudioManager(AudioThread audioThread, ResourceStore <byte[]> trackStore, ResourceStore <byte[]> sampleStore) { Thread = audioThread; Thread.RegisterManager(this); AudioDevice.ValueChanged += onDeviceChanged; trackStore.AddExtension(@"mp3"); sampleStore.AddExtension(@"wav"); sampleStore.AddExtension(@"mp3"); globalTrackStore = new Lazy <TrackStore>(() => { var store = new TrackStore(trackStore); AddItem(store); store.AddAdjustment(AdjustableProperty.Volume, VolumeTrack); return(store); }); globalSampleStore = new Lazy <SampleStore>(() => { var store = new SampleStore(sampleStore); AddItem(store); store.AddAdjustment(AdjustableProperty.Volume, VolumeSample); return(store); }); scheduler.Add(() => { try { setAudioDevice(); } catch { } }); scheduler.AddDelayed(delegate { updateAvailableAudioDevices(); checkAudioDeviceChanged(); }, 1000, true); }
/// <summary> /// Constructs an AudioStore given a track resource store, and a sample resource store. /// </summary> /// <param name="audioThread">The host's audio thread.</param> /// <param name="trackStore">The resource store containing all audio tracks to be used in the future.</param> /// <param name="sampleStore">The sample store containing all audio samples to be used in the future.</param> public AudioManager(AudioThread audioThread, ResourceStore <byte[]> trackStore, ResourceStore <byte[]> sampleStore) { Thread = audioThread; Thread.RegisterManager(this); AudioDevice.ValueChanged += onDeviceChanged; globalTrackStore = new Lazy <TrackStore>(() => { var store = new TrackStore(trackStore); AddItem(store); store.AddAdjustment(AdjustableProperty.Volume, VolumeTrack); return(store); }); globalSampleStore = new Lazy <SampleStore>(() => { var store = new SampleStore(sampleStore); AddItem(store); store.AddAdjustment(AdjustableProperty.Volume, VolumeSample); return(store); }); // sync audioDevices every 200ms CancellationToken token = cancellationTokenSource.Token; Task.Factory.StartNew(() => { while (!token.IsCancellationRequested) { try { var task = Task.Delay(200, token); syncAudioDevices(); task.Wait(token); } catch { } } }, token, TaskCreationOptions.None, TaskScheduler.Default); }
public void ResetDevices() { // kill thread if (AudioThread != null) { ThreadRunning = false; AudioEvent.Set(); AudioThread.Join(2000); AudioThread = null; } // deconstruct all record/play streams if (Recorder != null) { Recorder.Dispose(); Recorder = null; } Players.ForEach(p => p.Dispose()); Players.SafeClear(); // will auto be recreated }
public AudioManagerWithDeviceLoss(AudioThread audioThread, ResourceStore <byte[]> trackStore, ResourceStore <byte[]> sampleStore) : base(audioThread, trackStore, sampleStore) { }
public override void Begin() { VideoThread?.Begin(); AudioThread?.Begin(); base.Begin(); }
public LevelAudioManager(AudioThread audioThread, ResourceStore <byte[]> trackStore, ResourceStore <byte[]> sampleStore) : base(audioThread, trackStore, sampleStore) { }