private void PlatformInitializeIeeeFloat( ReadOnlySpan <byte> data, int sampleRate, AudioChannels channels, int loopStart, int loopLength) { if (ALController.Get().SupportsFloat32) { var format = AudioLoader.GetSoundFormat(AudioLoader.FormatIeee, (int)channels, 32); SoundBuffer = ALBufferPool.Rent(); SoundBuffer.BufferData(data, format, sampleRate); } else { var floatData = MemoryMarshal.Cast <byte, float>(data); int byteCount = floatData.Length * sizeof(short); string bufferTag = nameof(PlatformInitializeIeeeFloat); using (var buffer = RecyclableMemoryManager.Default.GetBuffer(byteCount, bufferTag)) { var largeBuffer = buffer.Buffer; // If 32-bit IEEE float is not supported, convert to 16-bit signed PCM AudioLoader.ConvertSingleToInt16(floatData, MemoryMarshal.Cast <byte, short>(largeBuffer)); PlatformInitializePcm(largeBuffer, 16, sampleRate, channels, loopStart, loopLength); } } }
private void PlatformInitializeAdpcm( ReadOnlySpan <byte> data, int sampleRate, AudioChannels channels, int blockAlignment, int loopStart, int loopLength) { if (ALController.Get().SupportsAdpcm) { var format = AudioLoader.GetSoundFormat(AudioLoader.FormatMsAdpcm, (int)channels, 0); int sampleAlignment = AudioLoader.SampleAlignment(format, blockAlignment); // Buffer length must be aligned with the block alignment int alignedCount = data.Length - (data.Length % blockAlignment); data = data.Slice(0, alignedCount); SoundBuffer = ALBufferPool.Rent(); SoundBuffer.BufferData(data, format, sampleRate, sampleAlignment); } else { // If MS-ADPCM is not supported, convert to 16-bit signed PCM var pcmData = MemoryMarshal.AsBytes( AudioLoader.ConvertMsAdpcmToPcm(data, (int)channels, blockAlignment).AsSpan()); PlatformInitializePcm(pcmData, 16, sampleRate, channels, loopStart, loopLength); } }
private void PlatformInitializePcm( ReadOnlySpan <byte> data, int sampleBits, int sampleRate, AudioChannels channels, int loopStart, int loopLength) { byte[]? largeBuffer = null; string?bufferTag = null; try { if (sampleBits == 24) { // Convert 24-bit signed PCM to 16-bit signed PCM largeBuffer = AudioLoader.Convert24To16(data, out bufferTag, out int size); data = largeBuffer.AsSpan(0, size); sampleBits = 16; } var format = AudioLoader.GetSoundFormat(AudioLoader.FormatPcm, (int)channels, sampleBits); SoundBuffer = ALBufferPool.Rent(); SoundBuffer.BufferData(data, format, sampleRate); } finally { if (largeBuffer != null) { RecyclableMemoryManager.Default.ReturnBuffer(largeBuffer, bufferTag); } } }
private void PlatformSubmitBuffer <T>(ReadOnlySpan <T> data, AudioDepth depth) where T : unmanaged { // Bind the data ALFormat alFormat = ALHelper.GetALFormat(_channels, depth); var buffer = ALBufferPool.Rent(); buffer.BufferData(data, alFormat, _sampleRate); // Queue the buffer AL.SourceQueueBuffer(SourceId.Value, buffer.BufferId); ALHelper.CheckError("Failed to queue buffer."); lock (_queuedBuffers) _queuedBuffers.Enqueue(buffer); // If the source has run out of buffers, restart it var sourceState = AL.GetSourceState(SourceId.Value); if (_state == SoundState.Playing && sourceState == ALSourceState.Stopped) { AL.SourcePlay(SourceId.Value); ALHelper.CheckError("Failed to resume source playback."); } }
private void PlatformUpdateQueue() { // Get the completed buffers AL.GetSource(SourceId.Value, ALGetSourcei.BuffersProcessed, out int numBuffers); ALHelper.CheckError("Failed to get processed buffer count."); // Unqueue them if (numBuffers > 0) { AL.SourceUnqueueBuffers(SourceId.Value, numBuffers); ALHelper.CheckError("Failed to unqueue buffers."); lock (_queuedBuffers) { for (int i = 0; i < numBuffers; i++) { var buffer = _queuedBuffers.Dequeue(); ALBufferPool.Return(buffer); } } } // Raise the event for each removed buffer, if needed for (int i = 0; i < numBuffers; i++) { CheckBufferCount(); } }
private void PlatformStop() { AL.SourceStop(SourceId.Value); ALHelper.CheckError("Failed to stop the source."); // Remove all queued buffers AL.Source(SourceId.Value, ALSourcei.Buffer, 0); ALHelper.CheckError("Failed to unbind the buffer."); lock (_queuedBuffers) { while (_queuedBuffers.Count > 0) { var buffer = _queuedBuffers.Dequeue(); ALBufferPool.Return(buffer); } } }
private void PlatformDispose(bool disposing) { // SFXI disposal handles buffer detachment and source recycling base.Dispose(disposing); if (disposing) { lock (_queuedBuffers) { while (_queuedBuffers.Count > 0) { var buffer = _queuedBuffers.Dequeue(); ALBufferPool.Return(buffer); } } } DynamicSoundEffectInstanceManager.RemoveInstance(this); }
private void PlatformInitializeIma4( ReadOnlySpan <byte> data, int sampleRate, AudioChannels channels, int blockAlignment, int loopStart, int loopLength) { if (ALController.Get().SupportsIma4) { var format = AudioLoader.GetSoundFormat(AudioLoader.FormatIma4, (int)channels, 0); int sampleAlignment = AudioLoader.SampleAlignment(format, blockAlignment); SoundBuffer = ALBufferPool.Rent(); SoundBuffer.BufferData(data, format, sampleRate, sampleAlignment); } else { // If IMA4 is not supported, convert to 16-bit signed PCM data = MemoryMarshal.AsBytes( AudioLoader.ConvertIma4ToPcm(data, (int)channels, blockAlignment).AsSpan()); PlatformInitializePcm(data, 16, sampleRate, channels, loopStart, loopLength); } }