protected virtual void Dispose(bool disposing) { if (!_isDisposed) { // Delete the buffer AL.DeleteBuffer(_bufferId); AL.DeleteSource(_sourceId); if (_context != ALContext.Null) { ALC.MakeContextCurrent(ALContext.Null); ALC.DestroyContext(_context); } _context = ALContext.Null; if (_device != IntPtr.Zero) { ALC.CloseDevice(_device); } _device = ALDevice.Null; _isDisposed = true; } }
private void Update() { ALC.MakeContextCurrent(_context); while (_stillRunning) { bool updateRequired = false; lock (_lock) { foreach (OpenALHardwareDeviceSession session in _sessions) { if (session.Update()) { updateRequired = true; } } } if (updateRequired) { _updateRequiredEvent.Set(); } // If it's not slept it will waste cycles. Thread.Sleep(10); } }
public void Destroy() { ALC.MakeContextCurrent(ALContext.Null); ALC.DestroyContext(_context); _context = ALContext.Null; ALC.CloseDevice(_device); _device = ALDevice.Null; }
private AudioContext() { var deviceName = findDeviceName(); device = ALC.OpenDevice(deviceName); ctx = ALC.CreateContext(device, (int[])null !); ALC.MakeContextCurrent(ctx); }
public static void Init() { string deviceName = ALC.GetString(ALDevice.Null, AlcGetString.DefaultDeviceSpecifier); var device = ALC.OpenDevice(deviceName); var context = ALC.CreateContext(device, (int[])null); ALC.MakeContextCurrent(context); }
public void Init() { _device = ALC.OpenDevice(null); _attributes = new ALContextAttributes(); _context = ALC.CreateContext(_device, _attributes); ALC.MakeContextCurrent(_context); _bufferId = AL.GenBuffers(1)[0]; _sourceId = AL.GenSources(1)[0]; //If data is byte, use ALFormat.Stereo16. For float use ALFormat.StereoFloat32Ext switch (Path.GetExtension(_fileName)) { case ".ogg": _oggSoundData = DecodeSound.LoadNVorbisData(_fileName); AL.BufferData(_bufferId, MapFormat(_oggSoundData.Format), _oggSoundData.BufferData, _oggSoundData.BufferData.Length * sizeof(float), _oggSoundData.SampleRate); break; case ".mp3": _mp3AndWaveSoundData = DecodeSound.LoadMP3SharpData(_fileName); AL.BufferData(_bufferId, MapFormat(_mp3AndWaveSoundData.Format), _mp3AndWaveSoundData.BufferData, _mp3AndWaveSoundData.BufferData.Length, _mp3AndWaveSoundData.SampleRate); break; case ".wav": _mp3AndWaveSoundData = DecodeSound.LoadWaveFile(_fileName); //Helpers.SaveData(_mp3AndWaveSoundData.BufferData, 4, @"C:\Temp\tone-data.csv"); // Sends the buffer data to the sound card AL.BufferData(_bufferId, MapFormat(_mp3AndWaveSoundData.Format), _mp3AndWaveSoundData.BufferData, _mp3AndWaveSoundData.BufferData.Length, _mp3AndWaveSoundData.SampleRate); break; } // Bind the buffer to the source AL.Source(_sourceId, ALSourcei.Buffer, _bufferId); }
public void Create() { if (_device == ALDevice.Null) { _device = ALC.OpenDevice(null); } if (_context == ALContext.Null) { _context = ALC.CreateContext(_device, (int[])null); } ALC.MakeContextCurrent(_context); }
public SoundManager(World world) { this.world = world; var audioDevice = ALC.OpenDevice(null); if (audioDevice.Handle != IntPtr.Zero) { var audioContext = ALC.CreateContext(audioDevice, new ALContextAttributes()); ALC.MakeContextCurrent(audioContext); } }
void Initialize() { device = ALC.OpenDevice(null); unsafe { context = ALC.CreateContext(device, (int *)null); ALC.MakeContextCurrent(context); } //Console.WriteLine(Alc.GetString(IntPtr.Zero, AlcGetString.AllDevicesSpecifier)); version = AL.Get(ALGetString.Version); vendor = AL.Get(ALGetString.Vendor); renderer = AL.Get(ALGetString.Extensions); }
public void Dispose() { if (context != ALContext.Null) { ALC.MakeContextCurrent(ALContext.Null); ALC.DestroyContext(context); } context = ALContext.Null; if (device != IntPtr.Zero) { ALC.CloseDevice(device); } device = ALDevice.Null; }
public OpenALBackend() { if (ALInstance != null) { throw new InvalidOperationException("Only one ALInstance can exist at a time."); } ALInstance = this; var audioDevice = ALC.OpenDevice(null); _context = ALC.CreateContext(audioDevice, new int[] { }); ALC.MakeContextCurrent(_context); _sourcePool = new ALSourcePool(); }
static OpenALContext() { //string deviceName = ALC.GetString(ALDevice.Null, AlcGetString.DefaultDeviceSpecifier); //foreach (var name in ALC.GetStringList(GetEnumerationStringList.DeviceSpecifier)) //{ // if (name.Contains("OpenAL Soft")) // { // deviceName = name; // } //} device = ALC.OpenDevice(null); context = ALC.CreateContext(device, (int[])null); ALC.MakeContextCurrent(context); }
/// <summary> /// Destroys the AL context and closes the device, when they exist. /// </summary> private void DestroyContexts() { ALC.MakeContextCurrent(IntPtr.Zero); if (_context != IntPtr.Zero) { ALC.DestroyContext(_context); _context = IntPtr.Zero; } if (Device != IntPtr.Zero) { ALC.CloseDevice(Device); Device = IntPtr.Zero; } }
public Window(GameWindowSettings settings, NativeWindowSettings nativeSettings) : base(settings, nativeSettings) { device = ALC.OpenDevice(""); context = ALC.CreateContext(device, new ALContextAttributes() { Frequency = 44100 }); ALC.MakeContextCurrent(context); Console.WriteLine("Version : " + AL.Get(ALGetString.Version)); Console.WriteLine("Vendor : " + AL.Get(ALGetString.Vendor)); Console.WriteLine("Renderer: " + AL.Get(ALGetString.Renderer)); _gameboy = new Gameboy(() => { return(new AudioEmitter()); }); string path = "Roms/Games/Mario Deluxe.gbc "; string[] args = Environment.GetCommandLineArgs(); if (args.Length > 1) { path = args[1]; } if (!File.Exists(path)) { Console.WriteLine(path); Console.WriteLine("Invalid usage... GBSharp [rom]"); foreach (string s in args) { Console.WriteLine("S: " + s); } throw new Exception(); } Cartridge cartridge = Cartridge.Load(path); //Cartridge cartridge = GetNextTestRom(); //CartridgeLoader.LoadDataIntoMemory(_mmu, GetNextTestRom(), 0x00); _gameboy.LoadCartridge(cartridge); thread = new Thread(new ThreadStart(_gameboy.Run)); _isAlive = true; thread.Start(); }
public bool Init() { try { var deviceName = ALC.GetString(ALDevice.Null, AlcGetString.DefaultDeviceSpecifier); OpenTkSound.device = ALC.OpenDevice(deviceName); var context = ALC.CreateContext(OpenTkSound.device, (int[])null); ALC.MakeContextCurrent(context); this.checkError(); this.initOpenALExtensions(); } catch (Exception e) { Com.Printf(e.Message + '\n'); return(false); } // set the master volume this.s_volume = Cvar.Get("s_volume", "0.7", Defines.CVAR_ARCHIVE); AL.GenBuffers(this.buffers.Length, this.buffers); var count = Channel.init(this.buffers, OpenTkSound.efxSlot); Com.Printf("... using " + count + " channels\n"); AL.DistanceModel(ALDistanceModel.InverseDistanceClamped); Cmd.AddCommand("play", () => { this.Play(); }); Cmd.AddCommand("stopsound", () => { this.StopAllSounds(); }); Cmd.AddCommand("soundlist", () => { this.SoundList(); }); Cmd.AddCommand("soundinfo", () => { this.SoundInfo_f(); }); OpenTkSound.num_sfx = 0; Com.Println("sound sampling rate: 44100Hz"); this.StopAllSounds(); Com.Println("------------------------------------"); return(true); }
private void PlaySound(MenuItem sender, EventArgs args) { if (_context != default && _soundSource != 0) { XPlane.Trace.WriteLine($"[OpenAL Sample] Playing sound ({_soundSource})"); var oldContext = ALC.GetCurrentContext(); ALC.MakeContextCurrent(_context); AL.Source(_soundSource, ALSourcef.Pitch, 1f); AL.SourcePlay(_soundSource); CheckError(); if (oldContext != default) { ALC.MakeContextCurrent(oldContext); } } }
public AudioPlayer() { audioDevice = ALC.OpenDevice(null); if (audioDevice == null) { Console.WriteLine("Unable to create audio device"); return; } audioContext = ALC.CreateContext(audioDevice, (int[])null); ALC.MakeContextCurrent(audioContext); audioSource = AL.GenSource(); AL.Listener(ALListener3f.Position, 0, 0, 0); AL.Listener(ALListener3f.Velocity, 0, 0, 0); var orientation = new Vector3(0, 0, 0); AL.Listener(ALListenerfv.Orientation, ref orientation, ref orientation); fastForward = false; audioDisabled = false; }
protected override void Init() { try { audioDevice = ALC.OpenDevice(null); audioContext = ALC.CreateContext(audioDevice, null); } catch (Exception e) { throw new AudioException("An issue occured during Audio initialization.", e); } if (!ALC.MakeContextCurrent(audioContext)) { throw new AudioException("An issue occured during Audio initialization: Unable to make the audio context current."); } CheckALErrors(); AL.DistanceModel(DistanceModel.LinearDistanceClamped); CheckALErrors(); }
internal SoundPlayer() { _alDevice = ALC.OpenDevice(null); var contextAttributes = new ALContextAttributes(); _alContext = ALC.CreateContext(_alDevice, contextAttributes); ALC.MakeContextCurrent(_alContext); _bufferedAudioSources = new BufferedAudioSource[4]; for (int i = 0; i < ChannelCount; i++) { _bufferedAudioSources[i] = new BufferedAudioSource(); } //noise and wave channel are panned left initially _bufferedAudioSources[2].SetPosition(SoundOutputTerminal.Left); _bufferedAudioSources[3].SetPosition(SoundOutputTerminal.Left); //TODO: Start/restart the sources synchronously }
private static void PrepareOpenAL() { audioDevice = ALC.OpenDevice(null); audioContext = ALC.CreateContext(audioDevice, null); if (!ALC.MakeContextCurrent(audioContext)) { throw new InvalidOperationException("Unable to make context current"); } Console.WriteLine("Created audio context."); CheckALErrors(); const string AudioFile = "Audio.raw"; if (!File.Exists(AudioFile)) { Console.WriteLine($"No {AudioFile} found."); return; } //Buffer AL.GenBuffer(out uint bufferId); byte[] data = File.ReadAllBytes(AudioFile); AL.BufferData(bufferId, BufferFormat.Stereo16, data, data.Length, 44100); //Source AL.GenSource(out uint sourceId); AL.Source(sourceId, SourceInt.Buffer, (int)bufferId); AL.Source(sourceId, SourceBool.Looping, true); AL.SourcePlay(sourceId); Console.WriteLine($"Played {AudioFile}."); }
public static bool InitDevice() { ALDevice audioDev = ALC.OpenDevice(null); AlcError err = ALC.GetError(audioDev); if (err != AlcError.NoError) { return(false); } ALContext aLContext = ALC.CreateContext(audioDev, new int[0]); bool makeRs = ALC.MakeContextCurrent(aLContext); err = ALC.GetError(audioDev); if (!makeRs || err != AlcError.NoError) { return(false); } //ALCdevice* inputDevice = alcCaptureOpenDevice(NULL, FREQ, AL_FORMAT_MONO16, FREQ / 2); ALCaptureDevice captureDev = ALC.CaptureOpenDevice(null, FREQ, ALFormat.Mono16, FREQ / 2); // FREQ ALC.CaptureStart(captureDev); err = ALC.GetError(audioDev); if (err != AlcError.NoError) { return(false); } int[] buffer = AL.GenBuffers(16); err = ALC.GetError(audioDev); if (err != AlcError.NoError) { return(false); } return(true); }
public static OpenALHost Open(Vector3 forward, Vector3 up) { var devices = ALC.GetStringList(GetEnumerationStringList.DeviceSpecifier); // Get the default device, then go though all devices and select the AL soft device if it exists. string deviceName = ALC.GetString(ALDevice.Null, AlcGetString.DefaultDeviceSpecifier); foreach (var d in devices) { if (d.Contains("OpenAL Soft")) { deviceName = d; } } var device = ALC.OpenDevice(deviceName); var context = ALC.CreateContext(device, new int[] { AlSoft.HRTF, AlSoft.Enable }); ALC.MakeContextCurrent(context); return(new OpenALHost(device, context, forward, up)); }
public AudioDevice() { device = ALC.OpenDevice(string.Empty); if (device.Equals(ALDevice.Null)) { return; } context = ALC.CreateContext(device, new ALContextAttributes()); ALC.MakeContextCurrent(context); var error = AL.GetError(); if (error != ALError.NoError) { throw new FailingSoundDeviceException($"Failed to open audio device. Error code: {error}."); } MusicSource = new MusicAudioSource(); IntenseMusicSource = new MusicAudioSource(); MiscSources = new GameAudioSource[miscSourceCount]; for (int i = 0; i < miscSourceCount; i++) { MiscSources[i] = new GameAudioSource(); } GameSources = new GameAudioSource[gameSourceCount]; for (int i = 0; i < gameSourceCount; i++) { GameSources[i] = new GameAudioSource(); } initialized = true; }
private unsafe float InitSound(float elapsedSinceLastCall, float elapsedTimeSinceLastFlightLoop, int counter) { CheckError(); var oldContext = ALC.GetCurrentContext(); if (oldContext == default) { XPlane.Trace.WriteLine("[OpenAL Sample] I found no OpenAL, I will be the first to init."); _device = ALC.OpenDevice(null); if (_device == null) { XPlane.Trace.WriteLine("[OpenAL Sample] Could not open the default OpenAL device."); return(0); } _context = ALC.CreateContext(_device, new ALContextAttributes()); if (_context == null) { ALC.CloseDevice(_device); _device = default; XPlane.Trace.WriteLine("[OpenAL Sample] Could not open the default OpenAL device."); return(0); } ALC.MakeContextCurrent(_context); XPlane.Trace.WriteLine("[OpenAL Sample] Created the Open AL context."); var hardware = ALC.GetString(_device, AlcGetString.DeviceSpecifier); var extensions = ALC.GetString(_device, AlcGetString.Extensions); var major = ALC.GetInteger(_device, AlcGetInteger.MajorVersion); var minor = ALC.GetInteger(_device, AlcGetInteger.MinorVersion); XPlane.Trace.WriteLine($"[OpenAL Sample] OpenAL version : {major}.{minor}"); XPlane.Trace.WriteLine($"[OpenAL Sample] OpenAL hardware : {hardware}"); XPlane.Trace.WriteLine($"[OpenAL Sample] OpenAL extensions: {extensions}"); CheckError(); } else { XPlane.Trace.WriteLine($"[OpenAL Sample] I found someone else's context: {(ulong)oldContext.Handle:X8}"); } var path = Path.Combine(Path.GetDirectoryName(PluginInfo.ThisPlugin.FilePath), "sound.wav"); // Generate 1 source and load a buffer of audio. _soundSource = AL.GenSource(); CheckError(); _soundBuffer = WavHelper.LoadWav(path); XPlane.Trace.WriteLine($"[OpenAL Sample] Loaded {_soundBuffer} from {path}."); // Basic initialization code to play a sound: specify the buffer the source is playing, as well as some // sound parameters. This doesn't play the sound - it's just one-time initialization. AL.Source(_soundSource, ALSourcei.Buffer, _soundBuffer); AL.Source(_soundSource, ALSourcef.Pitch, 1f); AL.Source(_soundSource, ALSourcef.Gain, 1f); AL.Source(_soundSource, ALSourceb.Looping, false); AL.Source(_soundSource, ALSource3f.Position, 0f, 0f, 0f); AL.Source(_soundSource, ALSource3f.Velocity, 0f, 0f, 0f); CheckError(); return(0); }
private float InitSound(float elapsedSinceLastCall, float elapsedTimeSinceLastFlightLoop, int counter) { CheckError(); // We have to save the old context and restore it later, so that we don't interfere with X-Plane // and other plugins. var oldContext = ALC.GetCurrentContext(); // Try to create our own default device and context. If we fail, we're dead, we won't play any sound. _device = ALC.OpenDevice(null); if (_device == null) { XPlane.Trace.WriteLine("[OpenAL Sample] Could not open the default OpenAL device."); return(0); } _context = ALC.CreateContext(_device, new ALContextAttributes()); if (_context == null) { if (oldContext != default) { ALC.MakeContextCurrent(oldContext); } ALC.CloseDevice(_device); _device = default; XPlane.Trace.WriteLine("[OpenAL Sample] Could not create a context."); return(0); } // Make our context current, so that OpenAL commands affect our, um, stuff. ALC.MakeContextCurrent(_context); var path = Path.Combine(Path.GetDirectoryName(PluginInfo.ThisPlugin.FilePath), "sound.wav"); // Generate 1 source and load a buffer of audio. AL.GenSource(out _soundSource); CheckError(); _soundBuffer = WavHelper.LoadWav(path); XPlane.Trace.WriteLine($"[OpenAL Sample] Loaded {_soundBuffer} from {path}."); // Basic initialization code to play a sound: specify the buffer the source is playing, as well as some // sound parameters. This doesn't play the sound - it's just one-time initialization. AL.Source(_soundSource, ALSourcei.Buffer, _soundBuffer); AL.Source(_soundSource, ALSourcef.Pitch, 1f); AL.Source(_soundSource, ALSourcef.Gain, 1f); AL.Source(_soundSource, ALSourceb.Looping, false); AL.Source(_soundSource, ALSource3f.Position, 0f, 0f, 0f); AL.Source(_soundSource, ALSource3f.Velocity, 0f, 0f, 0f); CheckError(); // Finally: put back the old context _if_ we had one. If old_ctx was null, X-Plane isn't using OpenAL. if (oldContext != default) { ALC.MakeContextCurrent(oldContext); } return(0); }
/// <summary> /// Open the sound device, sets up an audio context, and makes the new context /// the current context. Note that this method will stop the playback of /// music that was running prior to the game start. If any error occurs, then /// the state of the controller is reset. /// </summary> /// <returns>True if the sound controller was setup, and false if not.</returns> private bool Open() { lock (InitMutex) { try { Device = ALC.OpenDevice(string.Empty); } catch (DllNotFoundException) { throw; } catch (Exception ex) { throw new AudioHardwareException("OpenAL device could not be initialized.", ex); } ALCHelper.CheckError("Could not open OpenAL device."); if (Device == IntPtr.Zero) { return(false); } #if ANDROID // Attach activity event handlers so we can pause and resume all playing sounds MonoGameAndroidGameView.OnGameThreadPause += Activity_Paused; MonoGameAndroidGameView.OnGameThreadResume += Activity_Resumed; // Query the device for the ideal frequency and update buffer size so // we can get the low latency sound path. /* * The recommended sequence is: * * Check for feature "android.hardware.audio.low_latency" using code such as this: * import android.content.pm.PackageManager; * ... * PackageManager pm = getContext().getPackageManager(); * boolean claimsFeature = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY); * Check for API level 17 or higher, to confirm use of android.media.AudioManager.getProperty(). * Get the native or optimal output sample rate and buffer size for this device's primary output stream, using code such as this: * import android.media.AudioManager; * ... * AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); * String sampleRate = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)); * String framesPerBuffer = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)); * Note that sampleRate and framesPerBuffer are Strings. First check for null and then convert to int using Integer.parseInt(). * Now use OpenSL ES to create an AudioPlayer with PCM buffer queue data locator. * * See http://stackoverflow.com/questions/14842803/low-latency-audio-playback-on-android */ int frequency = DEFAULT_FREQUENCY; int updateSize = DEFAULT_UPDATE_SIZE; int updateBuffers = DEFAULT_UPDATE_BUFFER_COUNT; if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.JellyBeanMr1) { Android.Util.Log.Debug( "OAL", AndroidGameActivity.Instance.PackageManager.HasSystemFeature(PackageManager.FeatureAudioLowLatency) ? "Supports low latency audio playback." : "Does not support low latency audio playback."); if (AndroidGameActivity.Instance.GetSystemService(Context.AudioService) is AudioManager audioManager) { var result = audioManager.GetProperty(AudioManager.PropertyOutputSampleRate); if (!string.IsNullOrEmpty(result)) { frequency = int.Parse(result, CultureInfo.InvariantCulture); } result = audioManager.GetProperty(AudioManager.PropertyOutputFramesPerBuffer); if (!string.IsNullOrEmpty(result)) { updateSize = int.Parse(result, CultureInfo.InvariantCulture); } } // If 4.4 or higher, then we don't need to double buffer on the application side. // See http://stackoverflow.com/a/15006327 if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Kitkat) { updateBuffers = 1; } } else { Android.Util.Log.Debug("OAL", "Android 4.2 or higher required for low latency audio playback."); } Android.Util.Log.Debug( "OAL", "Using sample rate " + frequency + "Hz and " + updateBuffers + " buffers of " + updateSize + " frames."); // These are missing and non-standard ALC constants const int AlcFrequency = 0x1007; const int AlcUpdateSize = 0x1014; const int AlcUpdateBuffers = 0x1015; Span <int> attribute = stackalloc int[] { AlcFrequency, frequency, AlcUpdateSize, updateSize, AlcUpdateBuffers, updateBuffers, 0 }; #elif IOS AVAudioSession.SharedInstance().Init(); // NOTE: Do not override AVAudioSessionCategory set by the game developer: // see https://github.com/MonoGame/MonoGame/issues/6595 EventHandler <AVAudioSessionInterruptionEventArgs> handler = () => (sender, e) { switch (e.InterruptionType) { case AVAudioSessionInterruptionType.Began: AVAudioSession.SharedInstance().SetActive(false); ALC.MakeContextCurrent(IntPtr.Zero); ALC.SuspendContext(_context); break; case AVAudioSessionInterruptionType.Ended: AVAudioSession.SharedInstance().SetActive(true); ALC.MakeContextCurrent(_context); ALC.ProcessContext(_context); break; } }; AVAudioSession.Notifications.ObserveInterruption(handler); // Activate the instance or else the interruption handler will not be called. AVAudioSession.SharedInstance().SetActive(true); int[] attribute = Array.Empty <int>(); #else int[] attribute = Array.Empty <int>(); #endif _context = ALC.CreateContext(Device, attribute); ALCHelper.CheckError("Could not create OpenAL context."); if (_context != IntPtr.Zero) { ALC.MakeContextCurrent(_context); ALCHelper.CheckError("Could not make OpenAL context current."); SupportsIma4 = AL.IsExtensionPresent("AL_EXT_IMA4"); SupportsAdpcm = AL.IsExtensionPresent("AL_SOFT_MSADPCM"); SupportsEfx = AL.IsExtensionPresent("AL_EXT_EFX"); SupportsFloat32 = AL.IsExtensionPresent("AL_EXT_float32"); return(true); } return(false); } } #if ANDROID void Activity_Paused(MonoGameAndroidGameView view) { // Pause all currently playing sounds by pausing the mixer ALC.DevicePause(Device); } void Activity_Resumed(MonoGameAndroidGameView view) { // Resume all sounds that were playing when the activity was paused ALC.DeviceResume(Device); }
public static ALSourceState GetSourceState(int sid) { ALC.MakeContextCurrent(context); return(AL.GetSourceState(sid)); }
public void Shutdown() { ALC.MakeContextCurrent(ALContext.Null); ALC.CloseDevice(this.device); ALC.DestroyContext(this.context); }
public void MakeCurrent() { ALC.MakeContextCurrent(this.context); }
static void Main(string[] args) { Console.WriteLine("Starting OpenAL!"); var devices = ALC.GetStringList(GetEnumerationStringList.DeviceSpecifier); // Get the default device, then go though all devices and select the AL soft device if it exists. string deviceName = ALC.GetString(ALDevice.Null, AlcGetString.DefaultDeviceSpecifier); foreach (var d in devices) { if (d.Contains("OpenAL Soft")) { deviceName = d; } } var device = ALC.OpenDevice(deviceName); var context = ALC.CreateContext(device, (int[])null); ALC.MakeContextCurrent(context); CheckALError("Start"); // Playback the recorded data CheckALError("Before data"); AL.GenBuffer(out int alBuffer); AL.GenBuffer(out int backBuffer); AL.Listener(ALListenerf.Gain, 0.1f); AL.GenSource(out int alSource); AL.Source(alSource, ALSourcef.Gain, 1f); // var get samples from map var map = @"D:\H2vMaps\01a_tutorial.map"; var factory = new MapFactory(Path.GetDirectoryName(map)); var h2map = factory.Load(Path.GetFileName(map)); if (h2map is not H2vMap scene) { throw new NotSupportedException("Only Vista maps are supported in this tool"); } var soundMapping = scene.GetTag(scene.Globals.SoundInfos[0].SoundMap); var soundTags = scene.GetLocalTagsOfType <SoundTag>(); var maxSoundId = soundTags.Max(s => s.SoundEntryIndex); // TODO: multiplayer sounds are referencing the wrong ugh! tag var i = 0; foreach (var snd in soundTags) { var enc = snd.Encoding switch { EncodingType.ImaAdpcmMono => AudioEncoding.MonoImaAdpcm, EncodingType.ImaAdpcmStereo => AudioEncoding.StereoImaAdpcm, _ => AudioEncoding.Mono16, }; var sr = snd.SampleRate switch { Core.Tags.SampleRate.hz22k05 => Audio.SampleRate._22k05, Core.Tags.SampleRate.hz44k1 => Audio.SampleRate._44k1, _ => Audio.SampleRate._44k1 }; if (enc != AudioEncoding.Mono16) { continue; } var name = snd.Name.Substring(snd.Name.LastIndexOf("\\", snd.Name.LastIndexOf("\\") - 1) + 1).Replace('\\', '_'); Console.WriteLine($"[{i++}] {snd.Option1}-{snd.Option2}-{snd.Option3}-{snd.SampleRate}-{snd.Encoding}-{snd.Format2}-{snd.Unknown}-{snd.UsuallyMaxValue}-{snd.UsuallyZero} {name}"); var filenameFormat = $"{name}.{snd.SampleRate}-{snd.Encoding}-{snd.Format2}-{snd.Unknown}-{snd.UsuallyZero}-{snd.UsuallyMaxValue}.{{0}}.sound"; var soundEntry = soundMapping.SoundEntries[snd.SoundEntryIndex]; for (var s = 0; s < soundEntry.NamedSoundClipCount; s++) { var clipIndex = soundEntry.NamedSoundClipIndex + s; var clipInfo = soundMapping.NamedSoundClips[clipIndex]; var clipFilename = string.Format(filenameFormat, s); var clipSize = 0; for (var c = 0; c < clipInfo.SoundDataChunkCount; c++) { var chunk = soundMapping.SoundDataChunks[clipInfo.SoundDataChunkIndex + c]; clipSize += (int)(chunk.Length & 0x3FFFFFFF); } Span <byte> clipData = new byte[clipSize]; var clipDataCurrent = 0; for (var c = 0; c < clipInfo.SoundDataChunkCount; c++) { var chunk = soundMapping.SoundDataChunks[clipInfo.SoundDataChunkIndex + c]; var len = (int)(chunk.Length & 0x3FFFFFFF); var chunkData = scene.ReadData(chunk.Offset.Location, chunk.Offset, len); chunkData.Span.CopyTo(clipData.Slice(clipDataCurrent)); clipDataCurrent += len; } Interlocked.Exchange(ref backBuffer, Interlocked.Exchange(ref alBuffer, backBuffer)); AL.SourceStop(alSource); BufferData(enc, sr, clipData.Slice(96), alBuffer); CheckALError("After buffer"); AL.Source(alSource, ALSourcei.Buffer, alBuffer); AL.SourcePlay(alSource); while (AL.GetSourceState(alSource) == ALSourceState.Playing) { Thread.Sleep(100); } // Only play first variant break; } } ALC.MakeContextCurrent(ALContext.Null); ALC.DestroyContext(context); ALC.CloseDevice(device); Console.WriteLine("done"); Console.ReadLine(); }