FileHardwareDevice.cs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. using Ryujinx.Audio.Integration;
  2. using System;
  3. using System.IO;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. namespace Ryujinx.Audio.Renderer.Utils
  7. {
  8. /// <summary>
  9. /// A <see cref="IHardwareDevice"/> that outputs to a wav file.
  10. /// </summary>
  11. public class FileHardwareDevice : IHardwareDevice
  12. {
  13. private FileStream _stream;
  14. private uint _channelCount;
  15. private uint _sampleRate;
  16. private const int HeaderSize = 44;
  17. public FileHardwareDevice(string path, uint channelCount, uint sampleRate)
  18. {
  19. _stream = File.OpenWrite(path);
  20. _channelCount = channelCount;
  21. _sampleRate = sampleRate;
  22. _stream.Seek(HeaderSize, SeekOrigin.Begin);
  23. }
  24. private void UpdateHeader()
  25. {
  26. var writer = new BinaryWriter(_stream);
  27. long currentPos = writer.Seek(0, SeekOrigin.Current);
  28. writer.Seek(0, SeekOrigin.Begin);
  29. writer.Write("RIFF"u8);
  30. writer.Write((int)(writer.BaseStream.Length - 8));
  31. writer.Write("WAVE"u8);
  32. writer.Write("fmt "u8);
  33. writer.Write(16);
  34. writer.Write((short)1);
  35. writer.Write((short)GetChannelCount());
  36. writer.Write(GetSampleRate());
  37. writer.Write(GetSampleRate() * GetChannelCount() * sizeof(short));
  38. writer.Write((short)(GetChannelCount() * sizeof(short)));
  39. writer.Write((short)(sizeof(short) * 8));
  40. writer.Write("data"u8);
  41. writer.Write((int)(writer.BaseStream.Length - HeaderSize));
  42. writer.Seek((int)currentPos, SeekOrigin.Begin);
  43. }
  44. public void AppendBuffer(ReadOnlySpan<short> data, uint channelCount)
  45. {
  46. _stream.Write(MemoryMarshal.Cast<short, byte>(data));
  47. UpdateHeader();
  48. _stream.Flush();
  49. }
  50. public void SetVolume(float volume)
  51. {
  52. // Do nothing, volume is not used for FileHardwareDevice at the moment.
  53. }
  54. public float GetVolume()
  55. {
  56. // FileHardwareDevice does not incorporate volume.
  57. return 0;
  58. }
  59. public uint GetChannelCount()
  60. {
  61. return _channelCount;
  62. }
  63. public uint GetSampleRate()
  64. {
  65. return _sampleRate;
  66. }
  67. public void Dispose()
  68. {
  69. Dispose(true);
  70. }
  71. protected virtual void Dispose(bool disposing)
  72. {
  73. if (disposing)
  74. {
  75. _stream?.Flush();
  76. _stream?.Dispose();
  77. _stream = null;
  78. }
  79. }
  80. }
  81. }